@charset "UTF-8";
/* ==========================================================================
   通用后台管理系统 - 设计系统
   科技极简商务风 / 无字体图标 / 无原生弹窗
   ========================================================================== */

:root {
    /* 主色（科技蓝紫） */
    --ui-primary: #2b5cf6;
    --ui-primary-dark: #1e46cc;
    --ui-primary-light: #e8efff;
    --ui-primary-soft: rgba(43, 92, 246, .09);

    /* 语义色 */
    --ui-success: #10b981;
    --ui-success-bg: #e7f8f1;
    --ui-warning: #f59e0b;
    --ui-warning-bg: #fef4e2;
    --ui-danger: #ef4444;
    --ui-danger-bg: #fdecec;
    --ui-info: #0ea5e9;
    --ui-info-bg: #e6f6fe;

    /* 中性色 */
    --ui-title: #0f172a;
    --ui-text: #334155;
    --ui-muted: #7c8798;
    --ui-line: #e6eaf2;
    --ui-line-soft: #f0f3f9;
    --ui-bg: #f4f6fb;
    --ui-card: #ffffff;

    /* 侧边栏（深色科技风） */
    --ui-side-bg: #0f1729;
    --ui-side-bg-2: #16203a;
    --ui-side-text: #a7b3c9;
    --ui-side-active: #ffffff;
    --ui-side-hover: rgba(255, 255, 255, .06);

    /* 尺寸 */
    /* 侧边栏宽度：尽量窄，把横向空间留给内容区。192px 下「4 字菜单 + 二级缩进」
       仍有约 100px 文字余量，更长的名称会自动省略号截断（见 .menu-link__text）。 */
    --ui-side-w: 192px;
    --ui-side-w-mini: 60px;
    --ui-head-h: 58px;
    --ui-tab-h: 42px;
    --ui-radius: 10px;
    --ui-radius-sm: 7px;
    --ui-radius-lg: 16px;

    /* 阴影 */
    --ui-shadow-sm: 0 1px 2px rgba(15, 23, 42, .05);
    --ui-shadow: 0 4px 16px rgba(15, 23, 42, .07);
    --ui-shadow-lg: 0 18px 44px rgba(15, 23, 42, .14);

    --ui-transition: .22s cubic-bezier(.4, 0, .2, 1);
}

/* ------------------------------ 基础重置 ------------------------------ */
* {
    box-sizing: border-box;
    -webkit-tap-highlight-color: transparent;
}

html, body {
    height: 100%;
}

/* 手机端禁止缩放（与模板里 <meta viewport> 的 maximum-scale=1 / user-scalable=no 配合）：
   · touch-action: manipulation 关掉「双击放大」（Android 与 iOS 13.4+ 都生效），
     单指滚动、表格横向滑动、侧边栏手势均不受影响；
   · text-size-adjust 关掉 iOS 横屏时自动放大字号（会把移动端布局撑歪）。
   iOS Safari 会忽略 viewport 里的缩放限制，捏合缩放由 admin.js 的 lockZoom 兜底。 */
html {
    touch-action: manipulation;
    -webkit-text-size-adjust: 100%;
    text-size-adjust: 100%;
}

body {
    margin: 0;
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Hiragino Sans GB",
        "Microsoft YaHei", "Helvetica Neue", Arial, sans-serif;
    font-size: 14px;
    line-height: 1.6;
    color: var(--ui-text);
    background: var(--ui-bg);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

a {
    color: var(--ui-primary);
    text-decoration: none;
    transition: color var(--ui-transition);
}

a:hover {
    color: var(--ui-primary-dark);
}

svg {
    display: inline-block;
    vertical-align: -0.15em;
    flex-shrink: 0;
}

::-webkit-scrollbar {
    width: 8px;
    height: 8px;
}

::-webkit-scrollbar-thumb {
    background: #c7d0de;
    border-radius: 8px;
}

::-webkit-scrollbar-thumb:hover {
    background: #a9b5c8;
}

::-webkit-scrollbar-track {
    background: transparent;
}

/* ==========================================================================
   通用组件
   ========================================================================== */

/* 卡片 */
.ui-card {
    background: var(--ui-card);
    border: 1px solid var(--ui-line);
    border-radius: var(--ui-radius);
    box-shadow: var(--ui-shadow-sm);
}

.ui-card__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 14px 18px;
    border-bottom: 1px solid var(--ui-line-soft);
}

.ui-card__title {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 15px;
    font-weight: 600;
    color: var(--ui-title);
}

.ui-card__body {
    padding: 18px;
}

/* 按钮 */
.ui-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    height: 36px;
    padding: 0 15px;
    border: 1px solid var(--ui-line);
    border-radius: var(--ui-radius-sm);
    background: #fff;
    color: var(--ui-text);
    font-size: 13.5px;
    font-family: inherit;
    line-height: 1;
    white-space: nowrap;
    cursor: pointer;
    transition: all var(--ui-transition);
    user-select: none;
}

.ui-btn:hover {
    color: var(--ui-primary);
    border-color: #bccdfb;
    background: #f8faff;
}

.ui-btn:active {
    transform: translateY(1px);
}

.ui-btn--primary {
    background: var(--ui-primary);
    border-color: var(--ui-primary);
    color: #fff;
    box-shadow: 0 4px 12px rgba(43, 92, 246, .24);
}

.ui-btn--primary:hover {
    background: var(--ui-primary-dark);
    border-color: var(--ui-primary-dark);
    color: #fff;
}

.ui-btn--danger {
    background: var(--ui-danger);
    border-color: var(--ui-danger);
    color: #fff;
}

.ui-btn--danger:hover {
    background: #d93b3b;
    border-color: #d93b3b;
    color: #fff;
}

.ui-btn--ghost {
    background: transparent;
    border-color: transparent;
    color: var(--ui-muted);
}

.ui-btn--ghost:hover {
    background: var(--ui-primary-soft);
    color: var(--ui-primary);
    border-color: transparent;
}

.ui-btn--link {
    height: auto;
    padding: 0;
    border: 0;
    background: none;
    color: var(--ui-primary);
    box-shadow: none;
}

.ui-btn--block {
    width: 100%;
}

.ui-btn--lg {
    height: 44px;
    padding: 0 22px;
    font-size: 15px;
}

.ui-btn--sm {
    height: 30px;
    padding: 0 11px;
    font-size: 12.5px;
}

.ui-btn[disabled],
.ui-btn.is-loading {
    opacity: .65;
    cursor: not-allowed;
    pointer-events: none;
}

.ui-btn.is-loading::before {
    content: "";
    width: 13px;
    height: 13px;
    border: 2px solid currentColor;
    border-top-color: transparent;
    border-radius: 50%;
    animation: ui-spin .7s linear infinite;
}

@keyframes ui-spin {
    to { transform: rotate(360deg); }
}

/* 表单 */
.ui-field {
    margin-bottom: 16px;
}

.ui-label {
    display: block;
    margin-bottom: 7px;
    font-size: 13px;
    font-weight: 500;
    color: var(--ui-title);
}

.ui-label .ui-required {
    color: var(--ui-danger);
    margin-left: 3px;
}

.ui-input,
.ui-select,
.ui-textarea {
    width: 100%;
    height: 38px;
    padding: 0 12px;
    border: 1px solid var(--ui-line);
    border-radius: var(--ui-radius-sm);
    background: #fff;
    color: var(--ui-title);
    font-size: 13.5px;
    font-family: inherit;
    outline: none;
    transition: border-color var(--ui-transition), box-shadow var(--ui-transition);
}

.ui-textarea {
    height: auto;
    min-height: 96px;
    padding: 10px 12px;
    line-height: 1.6;
    resize: vertical;
}

.ui-input:focus,
.ui-select:focus,
.ui-textarea:focus {
    border-color: var(--ui-primary);
    box-shadow: 0 0 0 3px var(--ui-primary-soft);
}

.ui-input::placeholder,
.ui-textarea::placeholder {
    color: #aab4c4;
}

.ui-input[readonly] {
    background: #f7f9fc;
    color: var(--ui-muted);
}

.ui-input.is-error,
.ui-select.is-error,
.ui-textarea.is-error {
    border-color: var(--ui-danger);
}

/* ==========================================================================
   Layui 下拉框：与设计系统对齐
   --------------------------------------------------------------------------
   原生 <select class="ui-select"> 由 admin.js 的 UI.renderSelects() 交给
   layui.form 渲染。原生 select 被 layui 隐藏、只保留 name 用于提交，
   界面上真正显示的是 .layui-form-select 这套结构，因此样式要落在这里。

   结构：
     .ui-select-wrap（隔离容器，唯一带 layui-form 的元素）
       ├─ select.ui-select           原生控件（display:none，负责取值/提交）
       └─ .layui-form-select
            ├─ .layui-select-title > input.layui-input + i.layui-edge
            └─ dl > dd                下拉面板（lay-append-to=body 时挂到 body）
   ========================================================================== */

/* 隔离容器：占满原有控件的位置 */
.ui-select-wrap {
    position: relative;
    display: block;
    width: 100%;
    min-width: 0;
}

.ui-select-wrap > .layui-form-select {
    width: 100%;
}

/* 触发区：与 .ui-input 完全一致（高度 / 圆角 / 描边 / 字号 / 过渡） */
.ui-select-wrap .layui-form-select .layui-select-title,
.ui-select-wrap .layui-form-select .layui-input {
    height: 38px;
    border-radius: var(--ui-radius-sm);
    font-size: 13.5px;
    font-family: inherit;
    line-height: 38px;
}

.ui-select-wrap .layui-form-select .layui-input {
    padding: 0 30px 0 12px;
    border: 1px solid var(--ui-line);
    background: #fff;
    color: var(--ui-title);
    cursor: pointer;
    transition: border-color var(--ui-transition), box-shadow var(--ui-transition);
}

.ui-select-wrap .layui-form-select .layui-input::placeholder {
    color: #aab4c4;
}

/* 聚焦 / 展开态：沿用主色描边光环 */
.ui-select-wrap .layui-form-select .layui-input:focus,
.ui-select-wrap .layui-form-select.layui-form-selected .layui-input {
    border-color: var(--ui-primary);
    box-shadow: 0 0 0 3px var(--ui-primary-soft);
}

/* 右侧箭头：颜色与位置对齐 .ui-select 的原生箭头 */
.ui-select-wrap .layui-form-select .layui-edge {
    right: 12px;
    border-top-color: #a8b3c4;
}

.ui-select-wrap .layui-form-select.layui-form-selected .layui-edge {
    border-top-color: var(--ui-primary);
}

/* 禁用态 */
.ui-select-wrap .layui-form-select.layui-select-disabled .layui-input,
.ui-select-wrap .layui-form-select .layui-input.layui-disabled {
    background: #f7f9fc;
    color: var(--ui-muted);
    cursor: not-allowed;
}

/* 校验错误态（UI.fieldError 会把 is-error 标到容器上） */
.ui-select-wrap.is-error .layui-form-select .layui-input,
.ui-select-wrap.is-error .layui-form-select.layui-form-selected .layui-input {
    border-color: var(--ui-danger);
}

.ui-select-wrap.is-error .layui-form-select.layui-form-selected .layui-input {
    box-shadow: 0 0 0 3px var(--ui-danger-bg);
}

/* 下拉面板：无论挂在容器内还是 body 上（lay-append-to）都套用同一套样式。
   z-index 必须高于弹窗（.ui-modal 9999）与底部操作条（9997），
   否则弹窗里的下拉会被遮罩挡住；同时低于 toast（99999）。 */
.ui-select-wrap .layui-form-select dl,
.layui-select-panel-wrap dl {
    padding: 5px;
    border: 1px solid var(--ui-line);
    border-radius: var(--ui-radius);
    background: #fff;
    box-shadow: 0 12px 30px rgba(2, 6, 23, .14);
    z-index: 10050;
    max-height: 306px;
}

/* 面板仍留在触发区内时（未挂到 body），相对输入框往下 100%
   —— 等价于 layui 默认的 top:42px，但不受输入框高度变化影响 */
.ui-select-wrap .layui-form-select dl {
    top: 100%;
    margin-top: 5px;
}

/* 挂到 body 的面板由 lay.position() 定位，间距已由它的 offset:[0,5] 给出，
   dl 只需填满面板容器（等价于 layui 自带的 .layui-select-panel-wrap dl{top:0}）。
   这里绝不能再写 top:100% —— 相对定位的百分比会再叠加一次自身高度的位移。 */
.layui-select-panel-wrap dl {
    top: 0;
}

/* 空间不足时 layui 会给面板容器加 .layui-form-selectup。
   但它自带的 .layui-form-selectup dl{bottom:42px} 是按「面板还在触发区内」
   写的（42px 正是触发区高度）；面板挂到 body 后，lay.position() 已经负责把
   整块翻到输入框上方，再叠加这 42px 上移，面板就正好压在输入框上。
   （layui 触发该 class 的判断对 append-to 场景存在重复计算，见 form.js）
   因此挂到 body 时统一按「面板填满容器」处理，把 up 态的影响清零。 */
.layui-select-panel-wrap.layui-form-selectup dl {
    top: 0;
    bottom: auto;
}

.ui-select-wrap .layui-form-select dl dd,
.layui-select-panel-wrap dl dd {
    height: 34px;
    padding: 0 10px;
    border-radius: 7px;
    font-size: 13.3px;
    line-height: 34px;
    color: var(--ui-text);
}

.ui-select-wrap .layui-form-select dl dd:hover,
.layui-select-panel-wrap dl dd:hover {
    background: #f4f7fd;
}

.ui-select-wrap .layui-form-select dl dd.layui-this,
.layui-select-panel-wrap dl dd.layui-this {
    background: var(--ui-primary-soft);
    color: var(--ui-primary);
    font-weight: 600;
}

.ui-select-wrap .layui-form-select dl dd.layui-select-tips,
.layui-select-panel-wrap dl dd.layui-select-tips {
    color: var(--ui-muted);
}

.ui-select-wrap .layui-form-select dl dt,
.layui-select-panel-wrap dl dt {
    padding: 0 10px;
    font-size: 12.4px;
    color: var(--ui-muted);
}

/* 搜索型下拉（给 select 加 lay-search 属性即启用） */
.ui-select-wrap .layui-form-select .layui-input:not([readonly]) {
    cursor: text;
}

/* ==========================================================================
   图片上传控件（预览 + 拖拽 + 粘贴）
   --------------------------------------------------------------------------
   模板里只写 <div class="ui-upload" data-name="xxx" data-value="...">，
   内部结构由 admin.js 的 UI.renderUploads() 生成。
   ========================================================================== */
.ui-upload {
    width: 100%;
}

.ui-upload__zone {
    position: relative;
    display: grid;
    place-items: center;
    width: 100%;
    min-height: 132px;
    padding: 10px;
    border: 1px dashed #d5dbe6;
    border-radius: var(--ui-radius);
    background: #fbfcfe;
    cursor: pointer;
    overflow: hidden;
    transition: border-color var(--ui-transition), background var(--ui-transition), box-shadow var(--ui-transition);
}

.ui-upload__zone:hover {
    border-color: #b9c6dd;
    background: #f7f9fd;
}

.ui-upload__zone:focus-visible {
    outline: none;
    border-color: var(--ui-primary);
    box-shadow: 0 0 0 3px var(--ui-primary-soft);
}

/* 占位态 */
.ui-upload__placeholder {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    color: var(--ui-muted);
    font-size: 12.8px;
    line-height: 1.5;
}

.ui-upload__placeholder svg {
    color: #aeb9cb;
}

/* 已上传：缩略图铺满，hover 出现轻微遮罩提示可点击 */
.ui-upload__zone.has-image {
    border-style: solid;
    padding: 0;
}

.ui-upload__img {
    display: block;
    width: 100%;
    height: 132px;
    object-fit: contain;
    background: #fff;
    cursor: zoom-in;
}

.ui-upload__zone.has-image::after {
    content: "";
    position: absolute;
    inset: 0;
    background: rgba(15, 23, 42, .04);
    opacity: 0;
    transition: opacity var(--ui-transition);
    pointer-events: none;
}

.ui-upload__zone.has-image:hover::after {
    opacity: 1;
}

/* 拖拽悬停态 */
.ui-upload.is-dragover .ui-upload__zone {
    border-color: var(--ui-primary);
    border-style: solid;
    background: var(--ui-primary-soft);
    box-shadow: 0 0 0 3px var(--ui-primary-soft);
}

.ui-upload.is-dragover .ui-upload__placeholder {
    color: var(--ui-primary);
}

/* 上传进度条：贴在框底部 */
.ui-upload__bar {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 3px;
    background: transparent;
    opacity: 0;
    transition: opacity var(--ui-transition);
}

.ui-upload__bar.is-active {
    opacity: 1;
    background: rgba(43, 92, 246, .16);
}

.ui-upload__bar > i {
    display: block;
    width: 0;
    height: 100%;
    background: var(--ui-primary);
    transition: width .18s ease;
}

/* 上传中：禁止重复触发 */
.ui-upload.is-uploading .ui-upload__zone {
    pointer-events: none;
    opacity: .85;
}

.ui-upload.is-uploading .ui-upload__zone::before {
    content: "";
    position: absolute;
    inset: 0;
    background: rgba(255, 255, 255, .45);
}

/* 底部说明与操作 */
.ui-upload__foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    flex-wrap: wrap;
    margin-top: 8px;
}

.ui-upload__hint {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
    font-size: 12px;
    color: var(--ui-muted);
    line-height: 1.5;
}

.ui-upload__hint-tip {
    color: #9aa6b8;
}

.ui-upload__ops {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-shrink: 0;
}

/* 还没有图片时，「预览 / 移除」弱化（点击会提示） */
.ui-upload:not(.has-value) [data-role="preview"],
.ui-upload:not(.has-value) [data-role="clear"] {
    opacity: .55;
}

/* 大图预览 */
.ui-upload-preview {
    display: grid;
    place-items: center;
    max-height: 66vh;
    overflow: auto;
}

.ui-upload-preview img {
    max-width: 100%;
    height: auto;
}

.ui-help {
    margin-top: 6px;
    font-size: 12px;
    color: var(--ui-muted);
    line-height: 1.5;
}

.ui-error-text {
    margin-top: 6px;
    font-size: 12px;
    color: var(--ui-danger);
}

/* 输入组（带图标） */
.ui-input-group {
    position: relative;
    display: flex;
    align-items: center;
}

.ui-input-group > svg {
    position: absolute;
    left: 12px;
    color: #9aa6b8;
    pointer-events: none;
}

.ui-input-group .ui-input {
    padding-left: 38px;
}

.ui-input-group .ui-input-group__suffix {
    position: absolute;
    right: 8px;
    display: flex;
    align-items: center;
    gap: 4px;
}

/* 开关 */
.ui-switch {
    position: relative;
    display: inline-block;
    width: 42px;
    height: 23px;
    flex-shrink: 0;
}

.ui-switch input {
    position: absolute;
    opacity: 0;
    width: 0;
    height: 0;
}

.ui-switch__slider {
    position: absolute;
    inset: 0;
    background: #cbd5e1;
    border-radius: 999px;
    cursor: pointer;
    transition: background var(--ui-transition);
}

.ui-switch__slider::after {
    content: "";
    position: absolute;
    top: 2.5px;
    left: 2.5px;
    width: 18px;
    height: 18px;
    border-radius: 50%;
    background: #fff;
    box-shadow: 0 1px 3px rgba(15, 23, 42, .25);
    transition: transform var(--ui-transition);
}

.ui-switch input:checked + .ui-switch__slider {
    background: var(--ui-primary);
}

.ui-switch input:checked + .ui-switch__slider::after {
    transform: translateX(19px);
}

.ui-switch input:focus-visible + .ui-switch__slider {
    box-shadow: 0 0 0 3px var(--ui-primary-soft);
}

/* 标签 / 徽标 */
.ui-badge {
    display: inline-flex;
    align-items: center;
    height: 22px;
    padding: 0 9px;
    border-radius: 999px;
    font-size: 12px;
    line-height: 1;
    background: #eef2f8;
    color: #64748b;
    white-space: nowrap;
}

.ui-badge--primary { background: var(--ui-primary-light); color: var(--ui-primary-dark); }
.ui-badge--success { background: var(--ui-success-bg); color: #067a55; }
.ui-badge--warning { background: var(--ui-warning-bg); color: #a86205; }
.ui-badge--danger  { background: var(--ui-danger-bg);  color: #b91c1c; }
.ui-badge--info    { background: var(--ui-info-bg);    color: #0369a1; }

.ui-dot {
    display: inline-block;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: currentColor;
    margin-right: 5px;
    vertical-align: middle;
}

/* 表格 */
.ui-table-wrap {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
}

.ui-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 13.5px;
}

.ui-table th {
    padding: 12px 14px;
    background: #f8fafd;
    border-bottom: 1px solid var(--ui-line);
    color: #56637a;
    font-weight: 600;
    text-align: left;
    white-space: nowrap;
}

.ui-table td {
    padding: 12px 14px;
    border-bottom: 1px solid var(--ui-line-soft);
    color: var(--ui-text);
    vertical-align: middle;
}

.ui-table tbody tr {
    transition: background var(--ui-transition);
}

.ui-table tbody tr:hover {
    background: #fafbfe;
}

.ui-table tbody tr.is-selected {
    background: var(--ui-primary-soft);
}

.ui-table .ui-table__empty {
    padding: 54px 20px;
    text-align: center;
    color: var(--ui-muted);
}

/* 分页 */
.ui-pager {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
    padding: 14px 18px;
    border-top: 1px solid var(--ui-line-soft);
}

.ui-pager__info {
    font-size: 13px;
    color: var(--ui-muted);
}

.ui-pager__list {
    display: flex;
    align-items: center;
    gap: 5px;
    flex-wrap: wrap;
}

.ui-pager__item {
    min-width: 34px;
    height: 34px;
    padding: 0 9px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 1px solid var(--ui-line);
    border-radius: var(--ui-radius-sm);
    background: #fff;
    color: var(--ui-text);
    font-size: 13px;
    cursor: pointer;
    transition: all var(--ui-transition);
    user-select: none;
}

.ui-pager__item:hover:not(.is-disabled):not(.is-active) {
    color: var(--ui-primary);
    border-color: #bccdfb;
}

.ui-pager__item.is-active {
    background: var(--ui-primary);
    border-color: var(--ui-primary);
    color: #fff;
    font-weight: 600;
}

.ui-pager__item.is-disabled {
    color: #c3cbd8;
    cursor: not-allowed;
}

/* 空状态 */
.ui-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 10px;
    padding: 46px 20px;
    color: var(--ui-muted);
    text-align: center;
}

.ui-empty svg {
    color: #c9d3e2;
}

/* 工具条 */
/* 工具条：紧凑单行布局（PC），窄屏自动换行 */
.ui-toolbar {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 10px 16px;
    flex-wrap: wrap;
    padding: 12px 16px;
    border-bottom: 1px solid var(--ui-line-soft);
}

.ui-toolbar__left,
.ui-toolbar__right {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
}

.ui-toolbar__right {
    margin-left: auto;
    flex: 0 0 auto;
}

/* 搜索区：优先保持单行，空间不足时由关键字输入框让位 */
/*
 * 搜索区（工具条左侧）
 *
 * 关键点：flex-basis 设为 480px。
 * 在 flex-wrap: wrap 的容器中，换行判定依据 flex-basis 而非收缩后的宽度，
 * 因此当「搜索区 + 右侧按钮组」放不下时，会优先把**右侧按钮组**换到第二行，
 * 而不是把搜索区挤窄导致搜索/重置折行。
 */
.ui-search {
    display: flex;
    align-items: center;
    gap: 8px 10px;
    flex-wrap: nowrap;
    min-width: 0;
    flex: 1 1 480px;
}

.ui-search .ui-input,
.ui-search .ui-select {
    width: auto;
    height: 34px;
    font-size: 13px;
    padding: 0 10px;
}

/* layui 渲染后真正的弹性项是 .ui-select-wrap，尺寸规则要落到它身上 */
.ui-search .ui-select-wrap {
    width: 130px;
    height: 34px;
}

.ui-search .ui-select-wrap .layui-form-select .layui-select-title,
.ui-search .ui-select-wrap .layui-form-select .layui-input {
    height: 34px;
    font-size: 13px;
    line-height: 34px;
}

.ui-search .ui-select-wrap .layui-form-select .layui-input {
    padding: 0 26px 0 10px;
}

.ui-search .ui-select-wrap .layui-form-select .layui-edge {
    right: 9px;
}

/*
 * 关键字输入框：最小宽度压到 110px 并允许收缩，
 * 避免「刚好差几像素」就把搜索/重置按钮挤到第二行。
 */
.ui-search .ui-input[name="keyword"] {
    flex: 1 1 150px;
    width: auto;
    min-width: 96px;
    max-width: 280px;
}

.ui-search .ui-select,
.ui-search .ui-select-wrap {
    flex: 0 1 auto;
    min-width: 104px;
    max-width: 170px;
}

/* 日期区间控件：允许收缩，避免长占位挤掉按钮 */
.ui-search .ui-input[data-range] {
    flex: 1 1 170px;
    width: auto;
    min-width: 132px;
    max-width: 210px;
}

/* 搜索区内按钮紧凑排列，且不参与收缩 */
.ui-search > .ui-btn,
.ui-search .ui-search__actions {
    flex: 0 0 auto;
}

.ui-search > .ui-btn {
    height: 34px;
    padding: 0 13px;
}

/* 工具栏内普通按钮统一高度，视觉更整齐 */
.ui-toolbar .ui-btn {
    height: 34px;
}

/* --------------------------------------------------------------------------
   详情弹窗（UI.detailModal）：头部卡片 + 分组 + 标签/值列表
   -------------------------------------------------------------------------- */
.ui-detail { margin: -6px -4px -8px; }

/* 头部卡片 */
.ui-detail__hero {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 14px 16px;
    border-radius: var(--ui-radius);
    background: linear-gradient(135deg, #f4f7ff 0%, #eef3ff 60%, #f6f9ff 100%);
    border: 1px solid #e8eefc;
}
.ui-detail__avatar {
    flex: 0 0 auto;
    width: 44px; height: 44px;
    display: grid; place-items: center;
    border-radius: 50%;
    background: #fff;
    color: var(--ui-primary);
    font-size: 17px; font-weight: 650;
    box-shadow: 0 2px 8px rgba(43, 92, 246, .14);
    overflow: hidden;
}
.ui-detail__avatar .user-avatar { margin: 0; }
.ui-detail__hero-main { min-width: 0; }
.ui-detail__hero-title {
    display: flex; align-items: center; gap: 8px;
    font-size: 15.5px; font-weight: 650; color: var(--ui-title);
    line-height: 1.35;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ui-detail__hero-sub {
    margin-top: 3px;
    font-size: 12.6px; color: var(--ui-muted);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* 分组 */
.ui-detail__group { margin-top: 16px; }
.ui-detail__group-title {
    display: flex; align-items: center; gap: 7px;
    margin: 0 2px 8px;
    font-size: 12.6px; font-weight: 600; color: var(--ui-muted);
    letter-spacing: .3px;
}
.ui-detail__group-title::before {
    content: '';
    width: 3px; height: 12px; border-radius: 2px;
    background: var(--ui-primary);
}

/* 列表：标签左、值右 */
.ui-detail__list {
    border: 1px solid var(--ui-line);
    border-radius: var(--ui-radius-sm);
    background: #fff;
    overflow: hidden;
}
.ui-detail__item {
    display: flex;
    align-items: flex-start;
    gap: 16px;
    padding: 10px 13px;
    font-size: 13.4px;
    line-height: 1.6;
}
.ui-detail__item + .ui-detail__item { border-top: 1px solid #f1f4f9; }
.ui-detail__item:nth-child(odd) { background: #fcfdff; }
.ui-detail__label {
    flex: 0 0 92px;
    color: var(--ui-muted);
}
.ui-detail__value {
    flex: 1 1 auto;
    min-width: 0;
    color: var(--ui-text);
    word-break: break-word;
}
.ui-detail__empty { color: #c3c9d6; }
.ui-detail__strong { color: var(--ui-title); font-weight: 650; }
.ui-detail__code {
    display: inline-block;
    padding: 1px 6px;
    border-radius: 5px;
    background: #f3f5fa;
    color: #4a5568;
    font-size: 12.4px;
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}
.ui-detail__pre {
    margin: 0;
    max-height: 168px;
    overflow: auto;
    padding: 8px 10px;
    border-radius: 6px;
    background: #f7f9fc;
    color: #4a5568;
    font-size: 12.4px;
    line-height: 1.65;
    white-space: pre-wrap;
    word-break: break-all;
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}

/* 手机端：标签改为上、值在下，避免长值被挤 */
@media (max-width: 560px) {
    .ui-detail__item { display: block; padding: 9px 12px; }
    .ui-detail__label { display: block; flex: none; font-size: 12px; }
    .ui-detail__value { display: block; margin-top: 3px; }
    .ui-detail__hero { padding: 12px 14px; }
}

/* --------------------------------------------------------------------------
   响应式显示开关
   —— 手机端与桌面端用同一套模板，按视口切换「工作台」形态时用这两个类
   -------------------------------------------------------------------------- */
@media (max-width: 820px) {
    .is-desktop-only { display: none !important; }
}

@media (min-width: 821px) {
    .is-mobile-only { display: none !important; }
}

/* --------------------------------------------------------------------------
   移动端工作台（App 风格首页）
   与小屏 admin 的「工作台」页配合使用，桌面端不渲染
   -------------------------------------------------------------------------- */
.wf {
    display: flex;
    flex-direction: column;
    gap: 12px;
}

/* 顶部问候条 */
.wf__hero {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 16px 16px 18px;
    border-radius: var(--ui-radius);
    color: #fff;
    background: linear-gradient(135deg, #2b5cf6 0%, #4f7cff 55%, #6f9bff 100%);
    box-shadow: 0 10px 24px rgba(43, 92, 246, .22);
}
.wf__avatar {
    width: 42px; height: 42px; flex: 0 0 auto;
    display: grid; place-items: center;
    border-radius: 50%;
    background: rgba(255, 255, 255, .22);
    color: #fff; font-size: 16px; font-weight: 650;
    border: 1px solid rgba(255, 255, 255, .35);
}
.wf__hello { min-width: 0; flex: 1 1 auto; }
.wf__hello-title {
    font-size: 16px; font-weight: 650; line-height: 1.3;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.wf__hello-sub {
    margin-top: 3px; font-size: 12.2px; opacity: .86;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.wf__dot { margin: 0 5px; opacity: .6; }
.wf__notice {
    position: relative; flex: 0 0 auto;
    width: 40px; height: 40px;
    display: grid; place-items: center;
    border: 1px solid rgba(255, 255, 255, .3);
    border-radius: 12px;
    background: rgba(255, 255, 255, .14);
    color: #fff; cursor: pointer;
}
.wf__notice:active { background: rgba(255, 255, 255, .26); }
.wf__notice-dot {
    position: absolute; top: 8px; right: 8px;
    width: 8px; height: 8px; border-radius: 50%;
    background: #ff5b5b; border: 1.5px solid rgba(43, 92, 246, .9);
}

/* 关键数字：2×2 紧凑 */
.wf__stats {
    display: grid; gap: 10px;
    grid-template-columns: repeat(2, minmax(0, 1fr));
}
.wf__stat {
    padding: 14px 14px 13px;
    border-radius: var(--ui-radius);
    background: #fff;
    border: 1px solid var(--ui-line);
    display: flex; flex-direction: column;
}
.wf__stat-value { font-size: 21px; font-weight: 700; color: var(--ui-title); line-height: 1.1; }
.wf__stat-label { font-size: 12.4px; color: var(--ui-muted); }

/* 区块标题 */
.wf__section { margin-top: 4px; }
.wf__section-title {
    margin: 2px 2px 10px;
    font-size: 13.2px; font-weight: 600; color: var(--ui-title);
}

/* 功能宫格：一行 4 个，圆形图标 + 文案 */
.wf-tiles {
    display: grid;
    gap: 6px 4px;
    grid-template-columns: repeat(4, minmax(0, 1fr));
}
.wf-tile {
    display: flex; flex-direction: column; align-items: center; gap: 7px;
    padding: 12px 4px 10px;
    border: 0; background: transparent;
    font-family: inherit; cursor: pointer;
    border-radius: var(--ui-radius-sm);
    -webkit-tap-highlight-color: transparent;
}
.wf-tile:active { background: #f3f6fd; }
.wf-tile__icon {
    width: 44px; height: 44px;
    display: grid; place-items: center;
    border-radius: 14px;
    background: linear-gradient(180deg, #eef3ff, #e4ecff);
    color: var(--ui-primary);
}
.wf-tile__text {
    font-size: 12.2px; line-height: 1.25; color: var(--ui-text);
    text-align: center; max-width: 100%;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.wf-tiles-empty { text-align: center; padding: 26px 12px; color: var(--ui-muted); }
.wf-tiles-empty__icon {
    display: inline-grid; place-items: center; width: 44px; height: 44px;
    border-radius: 50%; background: #f1f3f9;
}
.wf-tiles-empty__text { margin-top: 10px; font-size: 13px; line-height: 1.7; }

/* --------------------------------------------------------------------------
   图标按钮：只有图标、没有文字（刷新 / 重置 / 列设置 / 导出）
   文字挪到 title 与 aria-label —— 鼠标悬停可见、读屏可读
   -------------------------------------------------------------------------- */
/* 选择器写成 .ui-btn.ui-btn--icon，权重与 .ui-search > .ui-btn 相同，
   靠位置在后覆盖掉它的左右内边距，图标才能真正居中 */
.ui-btn.ui-btn--icon,
.ui-search .ui-btn--icon,
.ui-toolbar .ui-btn--icon {
    width: 34px;
    padding: 0;
    flex: 0 0 auto;
}

/* 工具条内的辅助说明文字 */
.ui-toolbar__hint {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-size: 12.5px;
    color: var(--ui-muted);
    white-space: nowrap;
}

/* 表单栅格 */
.ui-row {
    display: flex;
    flex-wrap: wrap;
    margin: 0 -8px;
}

.ui-col {
    padding: 0 8px;
    width: 100%;
}

.ui-col--8 { width: 66.6667%; }
.ui-col--6 { width: 50%; }
.ui-col--4 { width: 33.3333%; }
.ui-col--3 { width: 25%; }

/* 描述列表 */
.ui-desc {
    display: grid;
    grid-template-columns: 108px 1fr;
    gap: 0;
}

.ui-desc dt {
    padding: 11px 0;
    color: var(--ui-muted);
    font-size: 13px;
    border-bottom: 1px dashed var(--ui-line);
}

.ui-desc dd {
    margin: 0;
    padding: 11px 0;
    color: var(--ui-title);
    font-size: 13.5px;
    border-bottom: 1px dashed var(--ui-line);
    word-break: break-all;
}

/* ==========================================================================
   附件上传控件（多文件 + 拖拽 + 进度 + 文件清单）
   --------------------------------------------------------------------------
   .ui-attach
     ├─ input[type=hidden]      表单值（JSON 文本：[{url,name,size,ext}]）
     ├─ .ui-attach__drop        选择/拖拽区
     │    ├─ .ui-attach__drop-main / __drop-tip
     │    └─ .ui-attach__bar > i   总进度
     ├─ .ui-attach__list
     │    └─ .ui-attach__item   单个文件（图标 / 名称 / 体积 / 下载 / 移除）
     └─ input[type=file]
   ========================================================================== */
.ui-attach {
    width: 100%;
}

.ui-attach__drop {
    position: relative;
    padding: 14px 16px;
    border: 1px dashed var(--ui-line);
    border-radius: var(--ui-radius);
    background: #fbfcfe;
    cursor: pointer;
    text-align: center;
    transition: border-color var(--ui-transition), background var(--ui-transition);
}

.ui-attach__drop:hover,
.ui-attach__drop:focus-visible {
    border-color: #bccdfb;
    background: #f7faff;
    outline: none;
}

.ui-attach.is-dragover .ui-attach__drop,
.ui-attach.is-uploading .ui-attach__drop {
    border-color: var(--ui-primary);
    background: var(--ui-primary-soft);
}

.ui-attach__drop-main {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    font-size: 13.3px;
    color: var(--ui-text);
}

.ui-attach__drop-main svg {
    color: var(--ui-primary);
}

.ui-attach__drop-tip {
    margin-top: 5px;
    font-size: 12.2px;
    color: var(--ui-muted);
    line-height: 1.5;
}

.ui-attach__bar {
    height: 3px;
    margin-top: 9px;
    border-radius: 2px;
    background: #e8eef8;
    overflow: hidden;
    opacity: 0;
    transition: opacity var(--ui-transition);
}

.ui-attach__bar.is-active {
    opacity: 1;
}

.ui-attach__bar > i {
    display: block;
    width: 0;
    height: 100%;
    background: var(--ui-primary);
    transition: width .18s linear;
}

.ui-attach__list {
    margin-top: 9px;
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.ui-attach__empty {
    padding: 8px 2px;
    font-size: 12.4px;
    color: var(--ui-muted);
    text-align: center;
}

.ui-attach__item {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 10px;
    border: 1px solid var(--ui-line-soft);
    border-radius: var(--ui-radius-sm);
    background: #fff;
    transition: border-color var(--ui-transition);
}

.ui-attach__item:hover {
    border-color: var(--ui-line);
}

.ui-attach__icon {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 34px;
    height: 34px;
    border-radius: 9px;
    background: var(--ui-primary-light);
    color: var(--ui-primary-dark);
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: .3px;
}

.ui-attach__main {
    flex: 1 1 auto;
    min-width: 0;
}

.ui-attach__name {
    font-size: 13.2px;
    color: var(--ui-title);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.ui-attach__meta {
    margin-top: 2px;
    font-size: 12px;
    color: var(--ui-muted);
}

.ui-attach__ops {
    display: flex;
    align-items: center;
    gap: 6px;
    flex: 0 0 auto;
}

/* ==========================================================================
   多图上传控件（车辆相册等）
   --------------------------------------------------------------------------
   .ui-images
     ├─ .ui-images__list          缩略图栅格 + 添加按钮
     │    ├─ .ui-images__item     单张（is-cover 为封面）
     │    │    ├─ img             点击看大图
     │    │    ├─ .ui-images__badge     封面角标（仅第一张）
     │    │    ├─ .ui-images__ascover   设为封面（仅非第一张）
     │    │    └─ .ui-images__del       删除
     │    └─ .ui-images__add      添加图片（含上传进度条）
     ├─ input[type=hidden]        表单值：JSON 数组字符串
     └─ input[type=file]          多选文件
   ========================================================================== */
.ui-images {
    width: 100%;
}

.ui-images__list {
    display: flex;
    flex-wrap: wrap;
    gap: 9px;
}

.ui-images__item {
    position: relative;
    flex: 0 0 auto;
    width: 104px;
    height: 78px;
    border: 1px solid var(--ui-line);
    border-radius: var(--ui-radius-sm);
    background: var(--ui-bg);
    overflow: hidden;
}

.ui-images__item.is-cover {
    border-color: var(--ui-primary);
    box-shadow: 0 0 0 2px var(--ui-primary-soft);
}

.ui-images__item img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    cursor: zoom-in;
    display: block;
}

/* 封面角标 / 设为封面：两种状态占同一位置，尺寸一致，切换时不跳 */
.ui-images__badge,
.ui-images__ascover {
    position: absolute;
    left: 0;
    bottom: 0;
    height: 22px;
    padding: 0 9px;
    border: 0;
    border-radius: 0 8px 0 0;
    font-size: 11.5px;
    line-height: 22px;
    font-family: inherit;
}

.ui-images__badge {
    background: var(--ui-primary);
    color: #fff;
}

.ui-images__ascover {
    background: rgba(15, 23, 42, .58);
    color: #fff;
    cursor: pointer;
    opacity: 0;
    transition: opacity var(--ui-transition);
}

.ui-images__item:hover .ui-images__ascover,
.ui-images__ascover:focus-visible {
    opacity: 1;
}

.ui-images__del {
    position: absolute;
    right: 3px;
    top: 3px;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    border: 0;
    border-radius: 50%;
    background: rgba(15, 23, 42, .58);
    color: #fff;
    cursor: pointer;
    transition: background var(--ui-transition);
}

.ui-images__del:hover {
    background: var(--ui-danger);
}

.ui-images__add {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 3px;
    flex: 0 0 auto;
    width: 104px;
    height: 78px;
    border: 1px dashed var(--ui-line);
    border-radius: var(--ui-radius-sm);
    background: #fbfcfe;
    color: var(--ui-muted);
    font-size: 12.2px;
    font-family: inherit;
    cursor: pointer;
    overflow: hidden;
    transition: border-color var(--ui-transition), color var(--ui-transition), background var(--ui-transition);
}

.ui-images__add:hover,
.ui-images__add:focus-visible {
    border-color: #bccdfb;
    background: #f7faff;
    color: var(--ui-primary);
    outline: none;
}

.ui-images__add svg {
    color: currentColor;
}

.ui-images__bar {
    position: absolute;
    left: 0;
    bottom: 0;
    display: block;
    width: 0;
    height: 3px;
    background: var(--ui-primary);
    transition: width .18s linear;
}

.ui-images__file {
    display: none;
}

/* 手机端缩略图排两列，手指点得准 */
@media (max-width: 820px) {
    .ui-images__item,
    .ui-images__add {
        width: calc(50% - 5px);
        height: 96px;
    }

    .ui-images__ascover {
        opacity: 1;
    }
}

/* ==========================================================================
   弹窗选择控件（选择用户 / 部门 / 任何列表数据）
   --------------------------------------------------------------------------
   .ui-picker
     ├─ input[type=hidden]        表单值（单选存 id，多选存逗号分隔 id）
     └─ .ui-picker__box           带标签展示的触发区
          ├─ .ui-picker__tags     已选项（标签可单个移除）
          └─ .ui-picker__ops      选择 / 清空
   ========================================================================== */
.ui-picker {
    width: 100%;
}

.ui-picker__box {
    display: flex;
    align-items: center;
    gap: 8px;
    min-height: 38px;
    padding: 4px 6px 4px 8px;
    border: 1px solid var(--ui-line);
    border-radius: var(--ui-radius-sm);
    background: #fff;
    cursor: pointer;
    transition: border-color var(--ui-transition), box-shadow var(--ui-transition);
}

.ui-picker__box:hover {
    border-color: #bccdfb;
}

.ui-picker__box:focus-visible {
    outline: none;
    border-color: var(--ui-primary);
    box-shadow: 0 0 0 3px var(--ui-primary-soft);
}

.ui-picker.is-error .ui-picker__box {
    border-color: var(--ui-danger);
}

.ui-picker__tags {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 6px;
    flex: 1 1 auto;
    min-width: 0;
    padding: 3px 0;
}

.ui-picker__placeholder {
    font-size: 13.5px;
    color: #aab4c4;
}

.ui-picker__tag {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    max-width: 100%;
    height: 24px;
    padding: 0 3px 0 9px;
    border-radius: 999px;
    background: var(--ui-primary-light);
    color: var(--ui-primary-dark);
    font-size: 12.4px;
}

.ui-picker__tag > span {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.ui-picker__tag > button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 18px;
    height: 18px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: transparent;
    color: inherit;
    opacity: .65;
    cursor: pointer;
}

.ui-picker__tag > button:hover {
    opacity: 1;
    background: rgba(43, 92, 246, .14);
}

.ui-picker__ops {
    display: flex;
    align-items: center;
    gap: 5px;
    flex: 0 0 auto;
}

/* 弹窗内的选择表格 */
.ui-picker-modal .ui-toolbar {
    padding: 0 0 12px;
    border-bottom: 0;
}

.ui-picker-modal__count {
    font-size: 12.5px;
    color: var(--ui-muted);
    white-space: nowrap;
}

.ui-picker__row {
    cursor: pointer;
}

.ui-picker__row.is-picked {
    background: var(--ui-primary-soft);
}

.ui-picker__row.is-picked td {
    font-weight: 500;
}

/* ==========================================================================
   日期 / 时间控件（laydate）：与设计系统对齐
   --------------------------------------------------------------------------
   结构（layui 默认皮肤）：
     .layui-laydate
       ├─ .layui-laydate-header     年月 + 左右箭头
       ├─ .layui-laydate-content    日期表格（td.layui-this = 选中）
       ├─ .layui-laydate-list       时间 / 年月列表（li.layui-this = 选中）
       ├─ .layui-laydate-shortcut   快捷选项（区间模式左侧一列）
       └─ .layui-laydate-footer     清空 / 现在 / 确定
   只覆盖配色与圆角，版式仍用 layui 自带的，避免把日历排坏。
   ========================================================================== */
.ui-date {
    width: 100%;
}

/* 只读是为了「手机上不弹系统键盘」，所以不能沿用 .ui-input[readonly] 的灰底禁用观感 */
.ui-date .ui-input[readonly] {
    background: #fff;
    color: var(--ui-title);
    cursor: pointer;
}

.ui-date .ui-input[readonly]:hover {
    border-color: #bccdfb;
}

.ui-date .ui-input[readonly]:focus {
    border-color: var(--ui-primary);
    box-shadow: 0 0 0 3px var(--ui-primary-soft);
    outline: none;
}

.ui-date.is-error .ui-input {
    border-color: var(--ui-danger);
}

.layui-laydate {
    border: 1px solid var(--ui-line);
    border-radius: var(--ui-radius);
    box-shadow: 0 12px 30px rgba(2, 6, 23, .14);
    font-family: inherit;
    color: var(--ui-text);
}

/* 头部：年月与翻页箭头 */
.layui-laydate-header {
    border-bottom: 1px solid var(--ui-line-soft);
}

.layui-laydate-header i {
    color: #9aa6b8;
}

.layui-laydate-header i:hover {
    color: var(--ui-primary);
}

/* 翻页箭头：laydate 用 layui 图标字体渲染（<i class="layui-icon laydate-prev-y">\e65a</i>），
   而本模板不提供字体文件（全站内联 SVG）。不处理的话箭头是空框，还会额外产生
   3 个字体文件 404（iconfont.woff2/woff/ttf）。这里把字形换成纯 CSS 画的箭头：
   既不依赖字体，也不影响点击区域。 */
.layui-laydate-header i.laydate-icon {
    width: 22px;
    height: 30px;
    padding: 0;
    /* layui 的 .layui-icon 用 !important 指定了图标字体；这里必须同样 !important
       覆盖掉，否则浏览器仍会去请求不存在的字体文件（3 个 404） */
    font-family: inherit !important;
    font-size: 0;          /* 屏蔽字体图标字形（PUA 码位不会显示成豆腐块） */
    color: transparent;
}

.layui-laydate-header i.laydate-icon::before {
    content: '';
    display: block;
    width: 8px;
    height: 8px;
    margin: 10px auto 0;
    border-left: 2px solid #9aa6b8;
    border-bottom: 2px solid #9aa6b8;
    transform: rotate(45deg);          /* 左箭头 */
}

.layui-laydate-header i.laydate-next-y::before,
.layui-laydate-header i.laydate-next-m::before {
    transform: rotate(-135deg);        /* 右箭头 */
}

.layui-laydate-header i.laydate-icon:hover::before {
    border-color: var(--ui-primary);
}

.laydate-set-ym span {
    color: var(--ui-title);
    font-weight: 500;
}

.laydate-set-ym span:hover {
    color: var(--ui-primary);
}

/* 日期表格 */
.layui-laydate-content th {
    color: var(--ui-muted);
    font-size: 12.5px;
}

.layui-laydate-content td,
.layui-laydate-content td > div {
    border-radius: 7px;
}

.layui-laydate-content td:hover > div {
    background: #f4f7fd;
    color: var(--ui-primary);
}

/* 选中态：layui 默认是绿色，这里换成主色 */
.layui-laydate .layui-this > div {
    background-color: var(--ui-primary) !important;
    color: #fff !important;
}

.layui-laydate-content .laydate-day-prev,
.layui-laydate-content .laydate-day-next {
    color: #c3ccda;
}

/* 时间 / 年月列表 */
.layui-laydate-list > li {
    border-radius: 7px;
}

.layui-laydate-list > li:hover {
    background: #f4f7fd;
    color: var(--ui-primary);
}

.layui-laydate-list > li.layui-this {
    background: var(--ui-primary-soft);
    color: var(--ui-primary);
    font-weight: 600;
}

/* 区间模式的快捷选项 */
.layui-laydate-shortcut {
    border-right: 1px solid var(--ui-line-soft);
}

.layui-laydate-shortcut li {
    border-radius: 7px;
    color: var(--ui-text);
    font-size: 13px;
}

.layui-laydate-shortcut li:hover {
    background: #f4f7fd;
    color: var(--ui-primary);
}

/* 底部：清空 / 现在 / 确定 */
.layui-laydate-footer {
    border-top: 1px solid var(--ui-line-soft);
}

.layui-laydate-footer span {
    border-radius: var(--ui-radius-sm);
    border-color: var(--ui-line);
    color: var(--ui-text);
    transition: all var(--ui-transition);
}

.layui-laydate-footer span:hover {
    color: var(--ui-primary);
    border-color: #bccdfb;
}

.layui-laydate-footer .laydate-btns-confirm {
    background-color: var(--ui-primary) !important;
    border-color: var(--ui-primary) !important;
    color: #fff !important;
}

.layui-laydate-footer .laydate-btns-confirm:hover {
    background-color: var(--ui-primary-dark) !important;
    border-color: var(--ui-primary-dark) !important;
}

.layui-laydate-footer .layui-laydate-preview {
    color: var(--ui-muted);
}

/* 区间面板固定 546px，手机（≤560px）放不下：允许面板内横向滚动，而不是溢出屏幕 */
@media (max-width: 560px) {
    .layui-laydate-range {
        max-width: calc(100vw - 12px);
        overflow-x: auto;
    }
}

/* ==========================================================================
   登录页
   ========================================================================== */
.login-page {
    position: relative;
    min-height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 28px 20px;
    overflow: hidden;
    background: #0b1224;
}

/* 科技感背景 */
.login-page::before {
    content: "";
    position: absolute;
    inset: 0;
    background:
        radial-gradient(900px 520px at 12% 8%, rgba(43, 92, 246, .38), transparent 62%),
        radial-gradient(760px 520px at 88% 92%, rgba(14, 165, 233, .28), transparent 60%),
        radial-gradient(620px 420px at 78% 12%, rgba(139, 92, 246, .22), transparent 62%),
        linear-gradient(150deg, #0b1224 0%, #101a33 48%, #0a1120 100%);
}

/* 网格纹理 */
.login-page::after {
    content: "";
    position: absolute;
    inset: 0;
    background-image:
        linear-gradient(rgba(148, 178, 255, .07) 1px, transparent 1px),
        linear-gradient(90deg, rgba(148, 178, 255, .07) 1px, transparent 1px);
    background-size: 46px 46px;
    mask-image: radial-gradient(circle at 50% 45%, #000 0%, transparent 78%);
    -webkit-mask-image: radial-gradient(circle at 50% 45%, #000 0%, transparent 78%);
}

.login-shell {
    position: relative;
    z-index: 2;
    display: grid;
    grid-template-columns: 1.05fr .95fr;
    width: 100%;
    max-width: 980px;
    min-height: 540px;
    border-radius: 22px;
    overflow: hidden;
    background: rgba(255, 255, 255, .045);
    border: 1px solid rgba(255, 255, 255, .1);
    box-shadow: 0 32px 80px rgba(2, 6, 23, .58);
    backdrop-filter: blur(14px);
    -webkit-backdrop-filter: blur(14px);
}

/* 左侧品牌区 */
.login-brand {
    padding: 48px 44px;
    color: #e8eeff;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    background: linear-gradient(160deg, rgba(43, 92, 246, .2), rgba(15, 23, 42, .05));
    border-right: 1px solid rgba(255, 255, 255, .07);
}

.login-brand__logo {
    display: flex;
    align-items: center;
    gap: 12px;
    font-size: 19px;
    font-weight: 650;
    letter-spacing: .4px;
}

.login-brand__mark {
    width: 42px;
    height: 42px;
    display: grid;
    place-items: center;
    border-radius: 12px;
    background: linear-gradient(140deg, #4d7cff, #2b5cf6);
    box-shadow: 0 8px 22px rgba(43, 92, 246, .45);
    color: #fff;
}

.login-brand__headline {
    margin: 34px 0 14px;
    font-size: 30px;
    line-height: 1.34;
    font-weight: 650;
    letter-spacing: .2px;
}

.login-brand__desc {
    margin: 0;
    max-width: 360px;
    font-size: 14px;
    line-height: 1.85;
    color: rgba(214, 226, 255, .74);
}

.login-brand__points {
    list-style: none;
    margin: 30px 0 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.login-brand__points li {
    display: flex;
    align-items: center;
    gap: 9px;
    font-size: 13.5px;
    color: rgba(206, 220, 255, .82);
}

.login-brand__points svg {
    color: #6f9bff;
}

/* 右侧表单区 */
.login-form {
    padding: 52px 46px;
    background: rgba(255, 255, 255, .97);
    display: flex;
    flex-direction: column;
    justify-content: center;
}

.login-form__title {
    margin: 0 0 6px;
    font-size: 23px;
    font-weight: 650;
    color: var(--ui-title);
}

.login-form__sub {
    margin: 0 0 28px;
    font-size: 13.5px;
    color: var(--ui-muted);
}

.login-form .ui-field {
    margin-bottom: 18px;
}

.login-form .ui-input {
    height: 44px;
    padding-left: 40px;
}

.login-form .ui-input-group > svg {
    left: 13px;
}

.login-captcha {
    display: flex;
    gap: 10px;
}

.login-captcha .ui-input-group {
    flex: 1;
    min-width: 0;
}

.login-captcha__img {
    width: 118px;
    height: 44px;
    flex-shrink: 0;
    border: 1px solid var(--ui-line);
    border-radius: var(--ui-radius-sm);
    cursor: pointer;
    object-fit: cover;
    background: #f4f7fc;
    transition: border-color var(--ui-transition);
}

.login-captcha__img:hover {
    border-color: var(--ui-primary);
}

.login-options {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    margin: 4px 0 22px;
    font-size: 13px;
}

.login-options label {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    color: var(--ui-muted);
    cursor: pointer;
    user-select: none;
}

.login-options input[type="checkbox"] {
    width: 15px;
    height: 15px;
    accent-color: var(--ui-primary);
    cursor: pointer;
}

.login-submit {
    width: 100%;
    height: 46px;
    border: 0;
    border-radius: var(--ui-radius-sm);
    background: linear-gradient(135deg, #3b6bff, #2b5cf6);
    color: #fff;
    font-size: 15px;
    font-weight: 600;
    font-family: inherit;
    letter-spacing: 1px;
    cursor: pointer;
    box-shadow: 0 10px 24px rgba(43, 92, 246, .3);
    transition: all var(--ui-transition);
}

.login-submit:hover {
    background: linear-gradient(135deg, #3161f5, #1e46cc);
    box-shadow: 0 12px 28px rgba(43, 92, 246, .38);
}

.login-submit:active {
    transform: translateY(1px);
}

.login-submit[disabled],
.login-submit.is-loading {
    opacity: .72;
    cursor: not-allowed;
}

.login-submit.is-loading::after {
    content: "";
    display: inline-block;
    width: 13px;
    height: 13px;
    margin-left: 8px;
    border: 2px solid #fff;
    border-top-color: transparent;
    border-radius: 50%;
    animation: ui-spin .7s linear infinite;
    vertical-align: -2px;
}

.login-tips {
    margin-top: 22px;
    padding-top: 18px;
    border-top: 1px dashed var(--ui-line);
    font-size: 12.5px;
    color: var(--ui-muted);
    line-height: 1.9;
}

.login-tips code {
    padding: 1px 6px;
    border-radius: 4px;
    background: #eef2f8;
    color: var(--ui-primary-dark);
    font-size: 12px;
}

/* ==========================================================================
   后台框架
   ========================================================================== */
.layout {
    display: flex;
    min-height: 100vh;
}

/* 侧边栏 */
.sidebar {
    position: fixed;
    top: 0;
    left: 0;
    bottom: 0;
    z-index: 1002;
    width: var(--ui-side-w);
    display: flex;
    flex-direction: column;
    background: linear-gradient(180deg, var(--ui-side-bg) 0%, var(--ui-side-bg-2) 100%);
    transition: width var(--ui-transition), transform var(--ui-transition);
    overflow: hidden;
}

.sidebar__brand {
    display: flex;
    align-items: center;
    gap: 9px;
    height: var(--ui-head-h);
    padding: 0 14px;
    flex-shrink: 0;
    border-bottom: 1px solid rgba(255, 255, 255, .06);
    color: #fff;
    overflow: hidden;
}

.sidebar__mark {
    width: 32px;
    height: 32px;
    flex-shrink: 0;
    display: grid;
    place-items: center;
    border-radius: 9px;
    background: linear-gradient(140deg, #4d7cff, #2b5cf6);
    box-shadow: 0 6px 16px rgba(43, 92, 246, .4);
    color: #fff;
}

.sidebar__name {
    font-size: 15px;
    font-weight: 600;
    white-space: nowrap;
    letter-spacing: .3px;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
}

.sidebar__scroll {
    flex: 1;
    overflow-y: auto;
    overflow-x: hidden;
    padding: 10px 0 20px;
}

.sidebar__scroll::-webkit-scrollbar {
    width: 5px;
}

.sidebar__scroll::-webkit-scrollbar-thumb {
    background: rgba(255, 255, 255, .14);
}

.sidebar__group {
    padding: 14px 14px 6px;
    font-size: 11.5px;
    letter-spacing: 1px;
    color: rgba(167, 179, 201, .5);
    text-transform: uppercase;
    white-space: nowrap;
}

.menu-item {
    position: relative;
}

.menu-link {
    display: flex;
    align-items: center;
    gap: 8px;
    height: 42px;
    padding: 0 14px;
    color: var(--ui-side-text);
    font-size: 13.8px;
    cursor: pointer;
    white-space: nowrap;
    transition: all var(--ui-transition);
    border: 0;
    background: none;
    width: 100%;
    font-family: inherit;
    text-align: left;
}

.menu-link:hover {
    color: #fff;
    background: var(--ui-side-hover);
}

.menu-link__icon {
    flex-shrink: 0;
    opacity: .85;
}

.menu-link__text {
    flex: 1;
    overflow: hidden;
    text-overflow: ellipsis;
}

.menu-link__arrow {
    flex-shrink: 0;
    opacity: .55;
    transition: transform var(--ui-transition);
}

/* 菜单数字角标（未读消息等）
   夹在文字与箭头之间：文字是 flex:1，所以角标自然靠右但不挤掉展开箭头 */
.menu-link__badge {
    flex-shrink: 0;
    min-width: 18px;
    height: 18px;
    padding: 0 5px;
    border-radius: 9px;
    background: var(--ui-danger);
    color: #fff;
    font-size: 11px;
    font-weight: 600;
    line-height: 18px;
    text-align: center;
    letter-spacing: 0;
    box-shadow: 0 2px 6px rgba(239, 68, 68, .45);
}

.menu-link__badge[hidden] {
    display: none;
}

/* 收起态只剩图标：角标脱离文档流贴在图标右上角，避免挤走图标 */
.layout.is-mini .menu-link__badge {
    position: absolute;
    top: 8px;
    left: calc(50% + 5px);
    min-width: 15px;
    height: 15px;
    padding: 0 4px;
    font-size: 10px;
    line-height: 15px;
    box-shadow: 0 0 0 2px var(--ui-side-bg);
}

.menu-item.is-open > .menu-link > .menu-link__arrow {
    transform: rotate(90deg);
}

.menu-item.is-active > .menu-link {
    color: #fff;
    background: linear-gradient(90deg, rgba(43, 92, 246, .34), rgba(43, 92, 246, .04));
}

.menu-item.is-active > .menu-link::before {
    content: "";
    position: absolute;
    left: 0;
    top: 8px;
    bottom: 8px;
    width: 3px;
    border-radius: 0 3px 3px 0;
    background: #4d7cff;
    box-shadow: 0 0 12px rgba(77, 124, 255, .9);
}

.menu-sub {
    overflow: hidden;
    max-height: 0;
    transition: max-height .28s ease;
    background: rgba(0, 0, 0, .16);
}

.menu-item.is-open > .menu-sub {
    max-height: 620px;
}

.menu-sub .menu-link {
    height: 38px;
    padding-left: 40px;
    font-size: 13.2px;
}

.menu-sub .menu-link::after {
    content: "";
    position: absolute;
    left: 24px;
    width: 5px;
    height: 5px;
    border-radius: 50%;
    background: rgba(167, 179, 201, .5);
    transition: background var(--ui-transition);
}

.menu-sub .menu-item.is-active > .menu-link::after {
    background: #4d7cff;
}

/* 侧边栏收起态 */
.layout.is-mini .sidebar {
    width: var(--ui-side-w-mini);
}

.layout.is-mini .sidebar__name,
.layout.is-mini .sidebar__group,
.layout.is-mini .menu-link__text,
.layout.is-mini .menu-link__arrow {
    display: none;
}

.layout.is-mini .menu-link,
.layout.is-mini .sidebar__brand {
    justify-content: center;
    padding: 0;
}

.layout.is-mini .menu-sub {
    display: none;
}

/* 主区域 */
.main {
    flex: 1;
    min-width: 0;
    margin-left: var(--ui-side-w);
    display: flex;
    flex-direction: column;
    transition: margin-left var(--ui-transition);
}

.layout.is-mini .main {
    margin-left: var(--ui-side-w-mini);
}

/* 顶栏 */
.header {
    position: sticky;
    top: 0;
    z-index: 1001;
    height: var(--ui-head-h);
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 0 18px;
    background: rgba(255, 255, 255, .92);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    border-bottom: 1px solid var(--ui-line);
}

.header__toggle {
    width: 36px;
    height: 36px;
    display: grid;
    place-items: center;
    border: 0;
    border-radius: var(--ui-radius-sm);
    background: transparent;
    color: var(--ui-text);
    cursor: pointer;
    transition: all var(--ui-transition);
}

.header__toggle:hover {
    background: var(--ui-primary-soft);
    color: var(--ui-primary);
}

.header__crumb {
    display: flex;
    align-items: center;
    gap: 7px;
    font-size: 14px;
    color: var(--ui-muted);
    min-width: 0;
}

.header__crumb strong {
    color: var(--ui-title);
    font-weight: 600;
}

.header__spacer {
    flex: 1;
}

.header__actions {
    display: flex;
    align-items: center;
    gap: 6px;
}

.header__btn {
    position: relative;
    width: 36px;
    height: 36px;
    display: grid;
    place-items: center;
    border: 0;
    border-radius: var(--ui-radius-sm);
    background: transparent;
    color: #5b6779;
    cursor: pointer;
    transition: all var(--ui-transition);
}

.header__btn:hover {
    background: var(--ui-primary-soft);
    color: var(--ui-primary);
}

.header__badge {
    position: absolute;
    top: 3px;
    right: 2px;
    min-width: 16px;
    height: 16px;
    padding: 0 4px;
    border-radius: 999px;
    background: var(--ui-danger);
    color: #fff;
    font-size: 10.5px;
    line-height: 16px;
    text-align: center;
    font-weight: 600;
    box-shadow: 0 0 0 2px #fff;
}

.header__badge[hidden] {
    display: none;
}

/* 用户下拉 */
.user-menu {
    position: relative;
}

.user-menu__trigger {
    display: flex;
    align-items: center;
    gap: 9px;
    height: 40px;
    padding: 0 10px 0 6px;
    border: 0;
    border-radius: 999px;
    background: transparent;
    cursor: pointer;
    font-family: inherit;
    transition: background var(--ui-transition);
}

.user-menu__trigger:hover {
    background: var(--ui-primary-soft);
}

.user-avatar {
    width: 30px;
    height: 30px;
    flex-shrink: 0;
    display: grid;
    place-items: center;
    border-radius: 50%;
    background: linear-gradient(140deg, #5b8bff, #2b5cf6);
    color: #fff;
    font-size: 13px;
    font-weight: 600;
}

/* 已上传头像时的图片形态（个人中心大图 + 顶栏小图） */
.user-avatar-img {
    display: block;
    width: 72px;
    height: 72px;
    margin: 0 auto 12px;
    border-radius: 50%;
    object-fit: cover;
    background: #f1f4f9;
    border: 2px solid #fff;
    box-shadow: 0 2px 10px rgba(15, 23, 42, .12);
}

.user-avatar-img--sm {
    width: 30px;
    height: 30px;
    margin: 0;
    flex-shrink: 0;
    border-width: 1px;
    box-shadow: none;
}

/* 侧边栏品牌 LOGO（系统设置里配置 site_logo 后生效） */
.sidebar__logo {
    display: block;
    width: 28px;
    height: 28px;
    flex-shrink: 0;
    border-radius: 8px;
    object-fit: contain;
    background: rgba(255, 255, 255, .08);
}

.user-menu__name {
    font-size: 13.5px;
    color: var(--ui-title);
    font-weight: 500;
    max-width: 110px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.user-dropdown {
    position: absolute;
    top: calc(100% + 8px);
    right: 0;
    z-index: 1200;
    min-width: 210px;
    padding: 6px;
    border-radius: var(--ui-radius);
    background: #fff;
    border: 1px solid var(--ui-line);
    box-shadow: var(--ui-shadow-lg);
    opacity: 0;
    visibility: hidden;
    transform: translateY(-6px);
    transition: all var(--ui-transition);
}

.user-dropdown.is-open {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
}

.user-dropdown__head {
    padding: 10px 12px 12px;
    border-bottom: 1px solid var(--ui-line-soft);
    margin-bottom: 6px;
}

.user-dropdown__head strong {
    display: block;
    color: var(--ui-title);
    font-size: 14px;
}

.user-dropdown__head span {
    font-size: 12.5px;
    color: var(--ui-muted);
}

.user-dropdown__item {
    display: flex;
    align-items: center;
    gap: 9px;
    width: 100%;
    padding: 9px 12px;
    border: 0;
    border-radius: var(--ui-radius-sm);
    background: none;
    color: var(--ui-text);
    font-size: 13.5px;
    font-family: inherit;
    text-align: left;
    cursor: pointer;
    transition: all var(--ui-transition);
}

.user-dropdown__item:hover {
    background: var(--ui-primary-soft);
    color: var(--ui-primary);
}

.user-dropdown__item--danger:hover {
    background: var(--ui-danger-bg);
    color: var(--ui-danger);
}

.user-dropdown__divider {
    height: 1px;
    margin: 6px 4px;
    background: var(--ui-line-soft);
}

/* 标签页导航 */
/* 标签页整行：左侧标签横向滚动，右侧「关闭全部」按钮固定 */
.tabs-bar {
    display: flex;
    align-items: stretch;
    height: var(--ui-tab-h);
    padding-right: 8px;
    background: #fff;
    border-bottom: 1px solid var(--ui-line);
}

.tabs {
    display: flex;
    align-items: center;
    gap: 4px;
    flex: 1;
    min-width: 0;
    height: var(--ui-tab-h);
    padding: 0 12px;
    overflow-x: auto;
    overflow-y: hidden;
}

/* 关闭全部标签页：整条分隔线 + 满高点击区，和单个标签上的小叉区分开 */
.tabs__action {
    flex-shrink: 0;
    display: grid;
    place-items: center;
    width: 42px;
    border: 0;
    border-left: 1px solid var(--ui-line);
    background: transparent;
    color: #8695ab;
    cursor: pointer;
    transition: all var(--ui-transition);
}

.tabs__action:hover:not(:disabled) {
    color: var(--ui-primary);
    background: var(--ui-primary-soft);
}

.tabs__action:disabled {
    opacity: .35;
    cursor: not-allowed;
}

.tabs::-webkit-scrollbar {
    height: 0;
}

.tab {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    height: 30px;
    padding: 0 10px 0 13px;
    border-radius: var(--ui-radius-sm);
    background: #f3f6fc;
    color: #5b6779;
    font-size: 13px;
    white-space: nowrap;
    cursor: pointer;
    transition: all var(--ui-transition);
    user-select: none;
}

.tab:hover {
    color: var(--ui-primary);
    background: var(--ui-primary-soft);
}

.tab.is-active {
    background: var(--ui-primary);
    color: #fff;
    box-shadow: 0 3px 10px rgba(43, 92, 246, .26);
}

.tab__close {
    display: grid;
    place-items: center;
    width: 16px;
    height: 16px;
    border-radius: 50%;
    opacity: .6;
    transition: all var(--ui-transition);
}

.tab__close:hover {
    background: rgba(0, 0, 0, .16);
    opacity: 1;
}

/* 内容区 */
.content {
    flex: 1;
    min-height: 0;
    position: relative;
}

.content__frame {
    display: block;
    width: 100%;
    height: 100%;
    border: 0;
    background: var(--ui-bg);
}

/* 页面容器（iframe 内部使用） */
.page {
    padding: 18px;
}

.page__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
    margin-bottom: 16px;
}

.page__title {
    margin: 0;
    font-size: 18px;
    font-weight: 650;
    color: var(--ui-title);
}

.page__desc {
    margin: 4px 0 0;
    font-size: 13px;
    color: var(--ui-muted);
}

/* ==========================================================================
   UI Kit：Toast / Modal / Confirm / Loading / Dropdown
   ========================================================================== */
.ui-toast-wrap {
    position: fixed;
    top: 20px;
    left: 50%;
    transform: translateX(-50%);
    z-index: 99999;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 10px;
    pointer-events: none;
    width: max-content;
    max-width: calc(100vw - 32px);
}

.ui-toast {
    display: flex;
    align-items: center;
    gap: 10px;
    min-width: 200px;
    max-width: 460px;
    padding: 12px 18px;
    border-radius: var(--ui-radius);
    background: #fff;
    border: 1px solid var(--ui-line);
    box-shadow: var(--ui-shadow-lg);
    font-size: 13.8px;
    color: var(--ui-title);
    pointer-events: auto;
    animation: ui-toast-in .28s cubic-bezier(.2, .9, .3, 1.2);
}

.ui-toast.is-leaving {
    animation: ui-toast-out .22s ease forwards;
}

.ui-toast__icon {
    display: grid;
    place-items: center;
    width: 22px;
    height: 22px;
    border-radius: 50%;
    flex-shrink: 0;
    color: #fff;
}

.ui-toast--success .ui-toast__icon { background: var(--ui-success); }
.ui-toast--error   .ui-toast__icon { background: var(--ui-danger); }
.ui-toast--warning .ui-toast__icon { background: var(--ui-warning); }
.ui-toast--info    .ui-toast__icon { background: var(--ui-info); }

.ui-toast--success { border-left: 3px solid var(--ui-success); }
.ui-toast--error   { border-left: 3px solid var(--ui-danger); }
.ui-toast--warning { border-left: 3px solid var(--ui-warning); }
.ui-toast--info    { border-left: 3px solid var(--ui-info); }

.ui-toast__msg {
    flex: 1;
    line-height: 1.55;
    word-break: break-word;
}

@keyframes ui-toast-in {
    from { opacity: 0; transform: translateY(-16px) scale(.96); }
    to   { opacity: 1; transform: translateY(0) scale(1); }
}

@keyframes ui-toast-out {
    to { opacity: 0; transform: translateY(-12px) scale(.97); }
}

/* 遮罩 */
.ui-mask {
    position: fixed;
    inset: 0;
    z-index: 9998;
    background: rgba(15, 23, 42, .48);
    backdrop-filter: blur(2px);
    -webkit-backdrop-filter: blur(2px);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 20px;
    animation: ui-fade-in .18s ease;
}

@keyframes ui-fade-in {
    from { opacity: 0; }
    to   { opacity: 1; }
}

/* 弹窗 */
.ui-modal {
    width: 100%;
    max-width: 620px;
    max-height: calc(100vh - 40px);
    display: flex;
    flex-direction: column;
    background: #fff;
    border-radius: var(--ui-radius-lg);
    box-shadow: var(--ui-shadow-lg);
    overflow: hidden;
    animation: ui-modal-in .26s cubic-bezier(.2, .9, .3, 1.1);
}

.ui-modal--sm { max-width: 440px; }
.ui-modal--lg { max-width: 880px; }
.ui-modal--full { max-width: 1080px; }

@keyframes ui-modal-in {
    from { opacity: 0; transform: translateY(18px) scale(.97); }
    to   { opacity: 1; transform: translateY(0) scale(1); }
}

.ui-modal__head {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 16px 20px;
    border-bottom: 1px solid var(--ui-line-soft);
    flex-shrink: 0;
}

.ui-modal__title {
    flex: 1;
    margin: 0;
    font-size: 16px;
    font-weight: 650;
    color: var(--ui-title);
    display: flex;
    align-items: center;
    gap: 9px;
}

.ui-modal__close {
    width: 32px;
    height: 32px;
    display: grid;
    place-items: center;
    border: 0;
    border-radius: var(--ui-radius-sm);
    background: transparent;
    color: var(--ui-muted);
    cursor: pointer;
    transition: all var(--ui-transition);
}

.ui-modal__close:hover {
    background: var(--ui-danger-bg);
    color: var(--ui-danger);
}

.ui-modal__body {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    padding: 20px;
}

.ui-modal__body--flush {
    padding: 0;
}

.ui-modal__foot {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 10px;
    padding: 14px 20px;
    border-top: 1px solid var(--ui-line-soft);
    background: #fbfcfe;
    flex-shrink: 0;
}

/* 确认框 */
.ui-confirm {
    width: 100%;
    max-width: 400px;
    padding: 26px 24px 20px;
    border-radius: var(--ui-radius-lg);
    background: #fff;
    text-align: center;
    box-shadow: var(--ui-shadow-lg);
    animation: ui-modal-in .26s cubic-bezier(.2, .9, .3, 1.1);
}

.ui-confirm__icon {
    width: 52px;
    height: 52px;
    margin: 0 auto 14px;
    display: grid;
    place-items: center;
    border-radius: 50%;
    background: var(--ui-warning-bg);
    color: var(--ui-warning);
}

.ui-confirm--danger .ui-confirm__icon {
    background: var(--ui-danger-bg);
    color: var(--ui-danger);
}

.ui-confirm--info .ui-confirm__icon {
    background: var(--ui-info-bg);
    color: var(--ui-info);
}

.ui-confirm__title {
    margin: 0 0 8px;
    font-size: 16.5px;
    font-weight: 650;
    color: var(--ui-title);
}

.ui-confirm__msg {
    margin: 0 0 22px;
    font-size: 13.6px;
    color: var(--ui-muted);
    line-height: 1.7;
    word-break: break-word;
}

.ui-confirm__actions {
    display: flex;
    gap: 10px;
}

.ui-confirm__actions .ui-btn {
    flex: 1;
    height: 40px;
}

/* 加载 */
.ui-loading {
    position: fixed;
    inset: 0;
    z-index: 9999;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 12px;
    background: rgba(255, 255, 255, .62);
    backdrop-filter: blur(1.5px);
    -webkit-backdrop-filter: blur(1.5px);
    color: var(--ui-muted);
    font-size: 13px;
}

.ui-loading__spin {
    width: 34px;
    height: 34px;
    border: 3px solid rgba(43, 92, 246, .16);
    border-top-color: var(--ui-primary);
    border-radius: 50%;
    animation: ui-spin .78s linear infinite;
}

/* 下拉菜单（通用） */
.ui-dropdown {
    position: absolute;
    z-index: 1200;
    min-width: 148px;
    padding: 6px;
    border-radius: var(--ui-radius);
    background: #fff;
    border: 1px solid var(--ui-line);
    box-shadow: var(--ui-shadow-lg);
    animation: ui-dropdown-in .16s ease;
}

@keyframes ui-dropdown-in {
    from { opacity: 0; transform: translateY(-4px); }
    to   { opacity: 1; transform: translateY(0); }
}

.ui-dropdown__item {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    padding: 8px 11px;
    border: 0;
    border-radius: var(--ui-radius-sm);
    background: none;
    color: var(--ui-text);
    font-size: 13.2px;
    font-family: inherit;
    text-align: left;
    cursor: pointer;
    transition: all var(--ui-transition);
}

.ui-dropdown__item:hover {
    background: var(--ui-primary-soft);
    color: var(--ui-primary);
}

.ui-dropdown__item--danger {
    color: var(--ui-danger);
}

.ui-dropdown__item--danger:hover {
    background: var(--ui-danger-bg);
    color: var(--ui-danger);
}

/* 表格行内操作 */
.ui-actions {
    display: flex;
    align-items: center;
    gap: 4px;
    flex-wrap: wrap;
}

.ui-action {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    height: 26px;
    padding: 0 8px;
    border: 0;
    border-radius: 6px;
    background: transparent;
    color: var(--ui-primary);
    font-size: 12.8px;
    font-family: inherit;
    cursor: pointer;
    transition: all var(--ui-transition);
    white-space: nowrap;
}

.ui-action:hover {
    background: var(--ui-primary-soft);
}

.ui-action--danger {
    color: var(--ui-danger);
}

.ui-action--danger:hover {
    background: var(--ui-danger-bg);
}

.ui-action--muted {
    color: var(--ui-muted);
}

.ui-action--muted:hover {
    background: #eef2f8;
    color: var(--ui-text);
}

/* 只显示图标的行内操作（查看 / 编辑 / 删除）：文字进 title，悬停有原生提示 */
.ui-action--icon-only {
    width: 28px;
    padding: 0;
    justify-content: center;
}
.ui-action--icon-only .ui-action__text {
    position: absolute;
    width: 1px; height: 1px;
    margin: -1px; padding: 0; border: 0;
    overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap;
}

/* 复选框 */
.ui-check {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    cursor: pointer;
    user-select: none;
    font-size: 13.3px;
    color: var(--ui-text);
}

.ui-check input[type="checkbox"] {
    width: 15px;
    height: 15px;
    accent-color: var(--ui-primary);
    cursor: pointer;
    margin: 0;
}

/* 树形选择（角色授权用） */
.ui-tree {
    font-size: 13.5px;
}

.ui-tree__node {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 8px;
    border-radius: var(--ui-radius-sm);
    transition: background var(--ui-transition);
}

.ui-tree__node:hover {
    background: #f7f9fd;
}

.ui-tree__toggle {
    width: 18px;
    height: 18px;
    display: grid;
    place-items: center;
    border: 0;
    background: none;
    color: var(--ui-muted);
    cursor: pointer;
    flex-shrink: 0;
    padding: 0;
}

.ui-tree__toggle svg {
    transition: transform var(--ui-transition);
}

.ui-tree__node.is-open > .ui-tree__toggle svg {
    transform: rotate(90deg);
}

.ui-tree__toggle.is-leaf {
    visibility: hidden;
}

.ui-tree__children {
    margin-left: 22px;
    border-left: 1px dashed var(--ui-line);
    padding-left: 8px;
    display: none;
}

.ui-tree__node.is-open + .ui-tree__children {
    display: block;
}

.ui-tree__label {
    display: inline-flex;
    align-items: center;
    gap: 6px;
}

.ui-tree__type {
    font-size: 11px;
    padding: 1px 6px;
    border-radius: 4px;
    background: #eef2f8;
    color: var(--ui-muted);
}

.ui-tree__type--menu { background: var(--ui-primary-light); color: var(--ui-primary-dark); }
.ui-tree__type--button { background: var(--ui-warning-bg); color: #a86205; }

/* 统计卡片 */
.stat-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
    gap: 14px;
}

/* 工作台统计卡：列数固定为卡片数的因数
   （auto-fit 在「算得下 3 列」的宽度区间会让 4 张卡排成 3+1，最后一排右侧空一大片、
   和上排对不齐）。4 张卡 → 宽屏 4 列、窄屏 2 列，永远填满；用 ID 选择器提高优先级，
   加卡片时记得同步改列数或保持 4 的倍数。 */
#statGrid {
    grid-template-columns: repeat(4, minmax(0, 1fr));
}

/* 工作台同一行的卡片必须等高：flex 行默认只拉伸「列」不拉伸卡片，
   于是左边图表卡与右边「我的信息」卡底边一高一低 */
.dash-row > .ui-col {
    display: flex;
}

.dash-row > .ui-col > .ui-card {
    display: flex;
    flex-direction: column;
    width: 100%;
}

.dash-row > .ui-col > .ui-card > .ui-card__body {
    flex: 1 1 auto;
}

/* 图表跟随卡片一起长高，避免拉伸后底部留一块空白 */
.dash-row .chart-bars {
    height: 100%;
    min-height: 190px;
}

/* 平板区间（桌面形态从 821px 起）：两栏并排太挤，直接上下堆叠 */
@media (max-width: 1100px) {
    .dash-row > .ui-col {
        width: 100%;
    }
}

@media (max-width: 1180px) {
    #statGrid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

.stat-card {
    position: relative;
    padding: 18px;
    border-radius: var(--ui-radius);
    background: #fff;
    border: 1px solid var(--ui-line);
    box-shadow: var(--ui-shadow-sm);
    overflow: hidden;
    transition: all var(--ui-transition);
}

.stat-card:hover {
    transform: translateY(-2px);
    box-shadow: var(--ui-shadow);
}

.stat-card::after {
    content: "";
    position: absolute;
    right: -28px;
    top: -28px;
    width: 92px;
    height: 92px;
    border-radius: 50%;
    opacity: .12;
    background: currentColor;
}

.stat-card__top {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    margin-bottom: 10px;
}

.stat-card__label {
    font-size: 13px;
    color: var(--ui-muted);
}

.stat-card__icon {
    width: 34px;
    height: 34px;
    display: grid;
    place-items: center;
    border-radius: 9px;
    background: currentColor;
    color: #fff;
    opacity: .92;
}

.stat-card__icon svg {
    color: #fff;
}

.stat-card__value {
    font-size: 27px;
    font-weight: 700;
    line-height: 1.1;
    color: var(--ui-title);
    letter-spacing: -.5px;
}

.stat-card__extra {
    margin-top: 7px;
    font-size: 12.5px;
    color: var(--ui-muted);
}

.stat-card--blue   { color: #2b5cf6; }
.stat-card--violet { color: #8b5cf6; }
.stat-card--green  { color: #10b981; }
.stat-card--amber  { color: #f59e0b; }
.stat-card--rose   { color: #f43f5e; }
.stat-card--cyan   { color: #06b6d4; }

/* 简易柱状图 */
.chart-bars {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: 10px;
    height: 190px;
    padding: 12px 4px 0;
}

.chart-bars__item {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    height: 100%;
    justify-content: flex-end;
}

.chart-bars__bars {
    display: flex;
    align-items: flex-end;
    justify-content: center;
    gap: 4px;
    width: 100%;
    flex: 1;
}

.chart-bars__bar {
    width: 12px;
    min-height: 3px;
    border-radius: 4px 4px 0 0;
    background: linear-gradient(180deg, #5b8bff, #2b5cf6);
    transition: height .5s cubic-bezier(.2, .9, .3, 1);
    position: relative;
}

.chart-bars__bar--alt {
    background: linear-gradient(180deg, #7dd3fc, #0ea5e9);
}

.chart-bars__label {
    font-size: 11.5px;
    color: var(--ui-muted);
    white-space: nowrap;
}

.chart-legend {
    display: flex;
    align-items: center;
    gap: 16px;
    font-size: 12.5px;
    color: var(--ui-muted);
}

.chart-legend span {
    display: inline-flex;
    align-items: center;
    gap: 6px;
}

.chart-legend i {
    width: 10px;
    height: 10px;
    border-radius: 3px;
    display: inline-block;
}

/* 消息列表 */
.msg-list {
    display: flex;
    flex-direction: column;
}

.msg-item {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    padding: 15px 18px;
    border-bottom: 1px solid var(--ui-line-soft);
    transition: background var(--ui-transition);
}

.msg-item:hover {
    background: #fafbfe;
}

.msg-item.is-unread {
    background: #f7faff;
}

.msg-item.is-unread .msg-item__title {
    font-weight: 650;
}

.msg-item__icon {
    width: 36px;
    height: 36px;
    flex-shrink: 0;
    display: grid;
    place-items: center;
    border-radius: 9px;
    background: var(--ui-info-bg);
    color: var(--ui-info);
}

.msg-item__icon--success { background: var(--ui-success-bg); color: var(--ui-success); }
.msg-item__icon--warning { background: var(--ui-warning-bg); color: var(--ui-warning); }
.msg-item__icon--danger  { background: var(--ui-danger-bg);  color: var(--ui-danger); }

.msg-item__main {
    flex: 1;
    min-width: 0;
}

.msg-item__title {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 14px;
    color: var(--ui-title);
    margin-bottom: 4px;
}

.msg-item__dot {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--ui-danger);
    flex-shrink: 0;
}

.msg-item__content {
    font-size: 13px;
    color: var(--ui-muted);
    line-height: 1.65;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.msg-item__meta {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-top: 7px;
    font-size: 12.2px;
    color: #9aa6b8;
}

.msg-item__actions {
    display: flex;
    align-items: center;
    gap: 4px;
    flex-shrink: 0;
}

/* 通知弹层 */
.notice-panel {
    position: absolute;
    top: calc(100% + 8px);
    right: 0;
    z-index: 1200;
    width: 330px;
    max-width: calc(100vw - 24px);
    border-radius: var(--ui-radius);
    background: #fff;
    border: 1px solid var(--ui-line);
    box-shadow: var(--ui-shadow-lg);
    overflow: hidden;
    opacity: 0;
    visibility: hidden;
    transform: translateY(-6px);
    transition: all var(--ui-transition);
}

.notice-panel.is-open {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
}

.notice-panel__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 12px 15px;
    border-bottom: 1px solid var(--ui-line-soft);
    font-size: 13.5px;
    font-weight: 600;
    color: var(--ui-title);
}

.notice-panel__body {
    max-height: 320px;
    overflow-y: auto;
}

.notice-panel__item {
    display: block;
    padding: 12px 15px;
    border-bottom: 1px solid var(--ui-line-soft);
    transition: background var(--ui-transition);
    cursor: pointer;
}

.notice-panel__item:hover {
    background: #f7faff;
}

.notice-panel__item strong {
    display: block;
    font-size: 13.3px;
    color: var(--ui-title);
    font-weight: 600;
    margin-bottom: 3px;
}

.notice-panel__item span {
    font-size: 12px;
    color: var(--ui-muted);
}

.notice-panel__foot {
    padding: 10px 15px;
    text-align: center;
    border-top: 1px solid var(--ui-line-soft);
    background: #fbfcfe;
}

.notice-panel__foot a {
    font-size: 13px;
}

/* 设置分组标签 */
.setting-tabs {
    display: flex;
    gap: 4px;
    flex-wrap: wrap;
    border-bottom: 1px solid var(--ui-line);
    padding: 0 18px;
}

.setting-tab {
    position: relative;
    padding: 12px 14px;
    border: 0;
    background: none;
    color: var(--ui-muted);
    font-size: 13.8px;
    font-family: inherit;
    cursor: pointer;
    transition: color var(--ui-transition);
}

.setting-tab:hover {
    color: var(--ui-primary);
}

.setting-tab.is-active {
    color: var(--ui-primary);
    font-weight: 600;
}

.setting-tab.is-active::after {
    content: "";
    position: absolute;
    left: 12px;
    right: 12px;
    bottom: -1px;
    height: 2px;
    border-radius: 2px;
    background: var(--ui-primary);
}

.setting-panel {
    display: none;
    padding: 20px 18px;
}

.setting-panel.is-active {
    display: block;
}

/* 设置表单的栅格
   通用 .ui-row 是 flex 两列：同一排若有高矮差异很大的字段（图片上传 vs 单行输入框），
   矮字段那一列下方会空出一大块，第二排又只剩左列，看起来「不整齐」。
   这里改用 CSS grid，并让高字段跨两行（.is-tall），短字段就会自动填到它右侧两行。 */
.setting-panel .setting-row {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0 18px;
    margin: 0;
    align-items: start;
}

.setting-panel .setting-row > .ui-col {
    width: auto;
    padding: 0;
}

.setting-panel .setting-row > .ui-col.is-tall {
    grid-row: span 2;
}

/* 骨架屏 */
.ui-skeleton {
    background: linear-gradient(90deg, #eef1f7 25%, #f6f8fc 37%, #eef1f7 63%);
    background-size: 400% 100%;
    animation: ui-skeleton 1.3s ease infinite;
    border-radius: 6px;
}

@keyframes ui-skeleton {
    0%   { background-position: 100% 50%; }
    100% { background-position: 0 50%; }
}

/* 移动端遮罩 */
.sidebar-mask {
    position: fixed;
    inset: 0;
    z-index: 1001;
    background: rgba(15, 23, 42, .46);
    opacity: 0;
    visibility: hidden;
    transition: all var(--ui-transition);
}

/* ==========================================================================
   响应式：平板与手机
   ========================================================================== */
@media (max-width: 1100px) {
    .login-shell {
        grid-template-columns: 1fr;
        max-width: 480px;
        min-height: auto;
    }

    .login-brand {
        display: none;
    }

    .login-form {
        padding: 40px 32px;
    }
}

@media (max-width: 900px) {
    .ui-col--4,
    .ui-col--3 {
        width: 50%;
    }
}

@media (max-width: 820px) {
    :root {
        --ui-head-h: 54px;
    }

    /* 侧边栏改为抽屉：宽度独立于桌面变量，保证触控区足够宽 */
    .sidebar {
        transform: translateX(-100%);
        box-shadow: var(--ui-shadow-lg);
        width: min(78vw, 248px) !important;
    }

    .layout.is-mobile-open .sidebar {
        transform: translateX(0);
    }

    .layout.is-mobile-open .sidebar-mask {
        opacity: 1;
        visibility: visible;
    }

    .main,
    .layout.is-mini .main {
        margin-left: 0;
    }

    /* 移动端忽略收起态 */
    .layout.is-mini .sidebar__name,
    .layout.is-mini .sidebar__group,
    .layout.is-mini .menu-link__text,
    .layout.is-mini .menu-link__arrow {
        display: block;
    }

    .layout.is-mini .sidebar__name {
        display: inline;
    }

    .layout.is-mini .sidebar__group {
        display: block;
    }

    .layout.is-mini .menu-link {
        justify-content: flex-start;
        padding: 0 18px;
    }

    .layout.is-mini .menu-sub {
        display: block;
    }

    .page {
        padding: 12px;
    }

    .user-menu__name {
        display: none;
    }

    .header {
        padding: 0 12px;
        gap: 8px;
    }

    .header__crumb {
        font-size: 13.5px;
    }

    .ui-toolbar {
        padding: 12px;
    }

    .ui-search {
        width: 100%;
        gap: 8px;
        flex-wrap: wrap;
    }

    .ui-search .ui-input,
    .ui-search .ui-select,
    .ui-search .ui-select-wrap {
        flex: 1 1 calc(50% - 4px);
        min-width: 0;
        max-width: none;
        width: auto;
    }

    /* 关键字输入独占一行，便于输入；搜索按钮组也独占一行 */
    .ui-search .ui-input[name="keyword"],
    .ui-search .ui-input[data-range] {
        flex: 1 1 100%;
        max-width: none;
    }

    .ui-toolbar__right {
        width: 100%;
    }

    .ui-toolbar__right .ui-btn {
        flex: 1;
    }

    .ui-modal {
        max-width: 100% !important;
        max-height: calc(100vh - 24px);
        border-radius: var(--ui-radius);
    }

    .ui-mask {
        padding: 12px;
        align-items: flex-end;
    }

    .ui-modal,
    .ui-confirm {
        animation: ui-sheet-in .26s cubic-bezier(.2, .9, .3, 1.05);
    }

    @keyframes ui-sheet-in {
        from { opacity: 0; transform: translateY(34px); }
        to   { opacity: 1; transform: translateY(0); }
    }

    .ui-modal__foot {
        padding: 12px;
    }

    .ui-modal__foot .ui-btn {
        flex: 1;
    }

    .ui-pager {
        justify-content: center;
        padding: 12px;
    }

    .ui-pager__info {
        width: 100%;
        text-align: center;
    }

    /* 表格 -> 卡片列表 */
    .ui-table--responsive thead {
        display: none;
    }

    .ui-table--responsive tbody,
    .ui-table--responsive tr,
    .ui-table--responsive td {
        display: block;
        width: 100%;
    }

    .ui-table--responsive tr {
        margin-bottom: 12px;
        border: 1px solid var(--ui-line);
        border-radius: var(--ui-radius);
        padding: 6px 4px;
        background: #fff;
    }

    .ui-table--responsive td {
        display: flex;
        align-items: flex-start;
        justify-content: space-between;
        gap: 12px;
        padding: 8px 12px;
        border-bottom: 1px dashed var(--ui-line-soft);
        text-align: right;
    }

    .ui-table--responsive td:last-child {
        border-bottom: 0;
    }

    .ui-table--responsive td::before {
        content: attr(data-label);
        flex-shrink: 0;
        color: var(--ui-muted);
        font-size: 12.5px;
        text-align: left;
    }

    .ui-table--responsive td[data-label=""]::before {
        display: none;
    }

    .ui-desc {
        grid-template-columns: 1fr;
        gap: 0;
    }

    .ui-desc dt {
        padding-bottom: 0;
        border-bottom: 0;
    }

    .ui-desc dd {
        padding-top: 2px;
    }

    .stat-grid {
        grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
        gap: 10px;
    }

    .stat-card {
        padding: 14px;
    }

    .stat-card__value {
        font-size: 22px;
    }

    .notice-panel {
        width: calc(100vw - 20px);
        right: -8px;
    }

    .chart-bars {
        height: 156px;
    }
}

@media (max-width: 560px) {
    .ui-col--8,
    .ui-col--6,
    .ui-col--4,
    .ui-col--3 {
        width: 100%;
    }

    /* 设置表单在窄屏退回单列，跨行也不再需要 */
    .setting-panel .setting-row {
        grid-template-columns: 1fr;
    }

    .setting-panel .setting-row > .ui-col.is-tall {
        grid-row: auto;
    }

    .page__head {
        margin-bottom: 12px;
    }

    .page__title {
        font-size: 16.5px;
    }

    .login-form {
        padding: 32px 22px;
    }

    .login-form__title {
        font-size: 20px;
    }

    .login-captcha__img {
        width: 96px;
    }

    .msg-item {
        padding: 12px;
    }
}

/* 打印隐藏交互元素 */
@media print {
    .sidebar,
    .header,
    .tabs-bar,
    .ui-toolbar,
    .ui-pager {
        display: none !important;
    }

    .main {
        margin-left: 0 !important;
    }
}

/* 减少动画偏好 */
@media (prefers-reduced-motion: reduce) {
    * {
        animation-duration: .01ms !important;
        transition-duration: .01ms !important;
    }
}

/* ==========================================================================
   数据表格：表头吸顶 + 左侧列固定 + 排序 + 导出
   ========================================================================== */

/* 滚动容器：同时承担横向与纵向滚动，sticky 才生效 */
.ui-table-wrap {
    overflow: auto;
    max-height: var(--ui-table-max-h, 620px);
}

.ui-table--fixed {
    table-layout: fixed;
    min-width: var(--ui-table-min-w, auto);
}

/* 吸顶表头 */
.ui-table--sticky thead th {
    position: sticky;
    top: 0;
    z-index: 3;
    background: #f8fafd;
    box-shadow: inset 0 -1px 0 var(--ui-line);
}

/* 左侧固定列（勾选框 / 首列 / 次列） */
.ui-table--sticky th.is-pin,
.ui-table--sticky td.is-pin {
    position: sticky;
    z-index: 2;
    background: #fff;
}

.ui-table--sticky thead th.is-pin {
    z-index: 4;
    background: #f8fafd;
}

.ui-table--sticky .is-pin-1 { left: 0; }
/* 默认偏移由 crud.js 按表头实测宽度写入；这里的值只作兜底（勾选框列 44px） */
.ui-table--sticky .is-pin-2 { left: var(--pin-1-w, 44px); }
.ui-table--sticky .is-pin-3 { left: var(--pin-left-3, 204px); }

/* 右侧固定列（操作列）：始终贴住滚动容器右缘 */
.ui-table--sticky .is-pin-right {
    right: 0;
    left: auto;
    z-index: 5;
}

/* 右侧固定列左侧投影 */
.ui-table--sticky .is-pin-right::after {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    bottom: -1px;
    width: 6px;
    transform: translateX(-100%);
    background: linear-gradient(90deg, transparent, rgba(15, 23, 42, .07));
    pointer-events: none;
}

/* 表头右侧固定列层级最高 */
.ui-table--sticky thead th.is-pin-right {
    z-index: 6;
}

/* 固定列右侧投影，滚动时体现层次 */
.ui-table--sticky .is-pin-last::after {
    content: "";
    position: absolute;
    top: 0;
    right: 0;
    bottom: -1px;
    width: 6px;
    transform: translateX(100%);
    background: linear-gradient(90deg, rgba(15, 23, 42, .07), transparent);
    pointer-events: none;
}

.ui-table--sticky tbody tr:hover td.is-pin {
    background: #fafbfe;
}

/* 排序表头 */
.ui-table th.is-sortable {
    cursor: pointer;
    user-select: none;
    white-space: nowrap;
}

.ui-table th.is-sortable:hover {
    color: var(--ui-primary);
    background: #f1f5fd;
}

.ui-table th .ui-sort {
    display: inline-flex;
    align-items: center;
    gap: 3px;
}

.ui-table th .ui-sort__icon {
    display: inline-flex;
    flex-direction: column;
    line-height: 0;
    opacity: .38;
    transition: opacity var(--ui-transition);
}

.ui-table th.is-sortable:hover .ui-sort__icon {
    opacity: .7;
}

.ui-table th.is-sort-asc .ui-sort__icon,
.ui-table th.is-sort-desc .ui-sort__icon {
    opacity: 1;
    color: var(--ui-primary);
}

.ui-table th.is-sort-asc .ui-sort__up,
.ui-table th.is-sort-desc .ui-sort__down {
    opacity: 1;
}

.ui-table th .ui-sort__up,
.ui-table th .ui-sort__down {
    opacity: .45;
}

/* 列显示设置面板 */
.ui-col-panel {
    position: absolute;
    z-index: 1200;
    min-width: 170px;
    max-height: 320px;
    overflow-y: auto;
    padding: 8px;
    border-radius: var(--ui-radius);
    background: #fff;
    border: 1px solid var(--ui-line);
    box-shadow: var(--ui-shadow-lg);
    animation: ui-dropdown-in .16s ease;
}

.ui-col-panel__title {
    padding: 4px 8px 8px;
    font-size: 12.5px;
    color: var(--ui-muted);
    border-bottom: 1px solid var(--ui-line-soft);
    margin-bottom: 6px;
}

.ui-col-panel__item {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 8px;
    border-radius: var(--ui-radius-sm);
    font-size: 13px;
    color: var(--ui-text);
    cursor: pointer;
    user-select: none;
}

.ui-col-panel__item:hover {
    background: var(--ui-primary-soft);
}

/* 移动端取消固定列与吸顶（卡片模式更合适） */
@media (max-width: 820px) {
    .ui-table-wrap {
        max-height: none;
        overflow-x: visible;
    }

    .ui-table--sticky thead th,
    .ui-table--sticky th.is-pin,
    .ui-table--sticky td.is-pin {
        position: static;
    }

    .ui-table--sticky .is-pin-last::after {
        display: none;
    }
}

/* 小屏隐藏按钮文字，仅保留图标 */
@media (max-width: 560px) {
    .hide-sm { display: none; }
}

/* ==========================================================================
   图标管理：卡片网格
   ========================================================================== */
.icon-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
    gap: 12px;
}

.icon-card {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    padding: 14px 10px 10px;
    border: 1px solid var(--ui-line);
    border-radius: var(--ui-radius);
    background: #fff;
    transition: all var(--ui-transition);
}

.icon-card:hover {
    border-color: #bccdfb;
    box-shadow: var(--ui-shadow);
    transform: translateY(-2px);
}

.icon-card.is-disabled {
    opacity: .5;
}

.icon-card__preview {
    display: grid;
    place-items: center;
    width: 52px;
    height: 52px;
    border-radius: 12px;
    background: var(--ui-primary-soft);
    color: var(--ui-primary);
}

.icon-card__name {
    width: 100%;
    text-align: center;
    font-size: 12.5px;
    color: var(--ui-title);
    font-family: ui-monospace, Menlo, Consolas, monospace;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.icon-card__meta {
    font-size: 11.5px;
}

.icon-card__actions {
    display: flex;
    gap: 2px;
    opacity: 0;
    transition: opacity var(--ui-transition);
}

.icon-card:hover .icon-card__actions {
    opacity: 1;
}

@media (max-width: 560px) {
    .icon-grid {
        grid-template-columns: repeat(auto-fill, minmax(104px, 1fr));
        gap: 8px;
    }

    .icon-card__actions {
        opacity: 1;
    }
}

/* 设置页：标签栏与右侧操作按钮同一行 */
.setting-bar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
    padding: 0 16px;
    border-bottom: 1px solid var(--ui-line);
}

.setting-bar .setting-tabs {
    flex: 1 1 auto;
    min-width: 0;
    border-bottom: 0;
    padding: 0;
}

.setting-bar__actions {
    display: flex;
    align-items: center;
    gap: 8px;
    flex: 0 0 auto;
    margin-left: auto;
}

@media (max-width: 820px) {
    .setting-bar {
        padding: 0 12px 10px;
    }

    .setting-bar .setting-tabs {
        flex: 1 1 100%;
    }

    .setting-bar__actions {
        flex: 1 1 100%;
        margin-left: 0;
    }

    .setting-bar__actions .ui-btn {
        flex: 1;
    }
}

/* 搜索按钮组：始终相邻，窄屏也不被拆开 */
.ui-search__actions {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    flex-shrink: 0;
}

/* 固定表格：单行单元格超出时省略，避免挤压相邻列 */
.ui-table--fixed td.is-nowrap,
.ui-table--fixed th.is-nowrap {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* 固定表格中的普通单元格也做省略处理，防止文字溢出列边界 */
.ui-table--fixed td {
    overflow: hidden;
    text-overflow: ellipsis;
}

.ui-table--fixed td .ui-actions,
.ui-table--fixed td .ui-badge {
    overflow: visible;
}

@media (max-width: 820px) {
    .ui-search__actions {
        width: 100%;
    }

    .ui-search__actions .ui-btn {
        flex: 1;
    }
}

/* --------------------------------------------------------------------------
   搜索区紧凑模式：容器较窄时进一步收缩，避免搜索/重置被挤到第二行
   -------------------------------------------------------------------------- */
@media (min-width: 821px) and (max-width: 1500px) {
    .ui-search .ui-input[name="keyword"] {
        max-width: 220px;
    }

    .ui-search .ui-select,
    .ui-search .ui-select-wrap {
        min-width: 96px;
        max-width: 140px;
    }

    .ui-search > .ui-btn {
        padding: 0 10px;
    }
}

@media (min-width: 821px) and (max-width: 1280px) {
    .ui-search .ui-input[name="keyword"] {
        max-width: 190px;
    }

    .ui-search .ui-select,
    .ui-search .ui-select-wrap {
        min-width: 90px;
        max-width: 126px;
    }
}

/* 极窄窗口：搜索区内部横向滚动，也不把按钮挤到第二行 */
@media (min-width: 821px) {
    .ui-search {
        overflow-x: auto;
        overflow-y: hidden;
        scrollbar-width: none;
    }

    .ui-search::-webkit-scrollbar {
        height: 0;
    }
}

/* ==========================================================================
   移动端方案（≤820px）
   --------------------------------------------------------------------------
   设计目标：手机端「像 App 一样好用」，而不只是把 PC 布局压窄。

   四条主线：
     1. 折叠筛选   —— 列表优先，筛选项默认收起，需要时展开
     2. 卡片列表   —— 每条记录一张卡片：主信息突出、字段可换行、操作独立成行
     3. 批量操作条 —— 选中后从底部浮出，不必回滚到顶部找按钮
     4. 触控与安全区 —— 所有可点区域 ≥44px，适配刘海/底部横条/动态视口
   ========================================================================== */

:root {
    /* 安全区内边距（非全面屏浏览器为 0，不影响 PC） */
    --ui-safe-top: env(safe-area-inset-top, 0px);
    --ui-safe-bottom: env(safe-area-inset-bottom, 0px);
    --ui-safe-left: env(safe-area-inset-left, 0px);
    --ui-safe-right: env(safe-area-inset-right, 0px);
    /* 移动端触控最小高度（Material / HIG 建议 44px 左右） */
    --ui-touch: 44px;
}

@media (max-width: 820px) {

    /* ------------------------------------------------------------------
     * 1. 框架与安全区
     * ---------------------------------------------------------------- */
    .layout {
        min-height: 100vh;
        min-height: 100dvh;          /* 支持动态视口的浏览器优先 */
    }

    .sidebar {
        padding-top: var(--ui-safe-top);
        padding-bottom: var(--ui-safe-bottom);
        padding-left: var(--ui-safe-left);
        /* 宽度统一在上面「侧边栏改为抽屉」处声明，这里只补安全区与滚动手感 */
        box-shadow: 0 0 40px rgba(2, 6, 23, .45);
        /* iOS 惯性滚动 */
        -webkit-overflow-scrolling: touch;
    }

    .sidebar__scroll {
        -webkit-overflow-scrolling: touch;
        padding-bottom: 24px;
    }

    /* 抽屉内的关闭按钮（桌面端不显示） */
    .sidebar__close {
        display: grid;
        place-items: center;
        width: 36px;
        height: 36px;
        margin-left: auto;
        flex-shrink: 0;
        border: 0;
        border-radius: 9px;
        background: rgba(255, 255, 255, .08);
        color: #cbd5e1;
        cursor: pointer;
    }

    .sidebar__close:active {
        background: rgba(255, 255, 255, .18);
    }

    .header {
        height: calc(var(--ui-head-h) + var(--ui-safe-top));
        padding-top: var(--ui-safe-top);
        padding-left: calc(12px + var(--ui-safe-left));
        padding-right: calc(12px + var(--ui-safe-right));
    }

    .tabs {
        -webkit-overflow-scrolling: touch;
        scrollbar-width: none;
        padding-left: calc(12px + var(--ui-safe-left));
    }

    .tabs-bar {
        padding-right: calc(8px + var(--ui-safe-right));
    }

    .tabs::-webkit-scrollbar {
        display: none;
    }

    .page {
        padding: 10px calc(10px + var(--ui-safe-right)) calc(10px + var(--ui-safe-bottom)) calc(10px + var(--ui-safe-left));
    }

    /* 触控目标：头部按钮加大 */
    .header__toggle,
    .header__btn {
        width: var(--ui-touch);
        height: var(--ui-touch);
    }

    .header__crumb {
        font-size: 14.5px;
        font-weight: 600;
        color: var(--ui-title);
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }

    /* ------------------------------------------------------------------
     * 2. 折叠筛选：列表优先
     * ---------------------------------------------------------------- */
    .ui-toolbar {
        padding: 10px 12px;
        gap: 8px;
    }

    .ui-search {
        flex-direction: column;
        align-items: stretch;
        gap: 8px;
        overflow: visible;      /* 移动端不需要内部滚动 */
        flex-basis: auto;
    }

    /* 关键字输入常驻，占满一行 */
    .ui-search .ui-input[name="keyword"] {
        flex: 1 1 100%;
        max-width: none;
        height: 40px;
    }

    /* 其余筛选项：仅当搜索区带「筛选」开关（.is-collapsible，由 JS 标记）时
       才默认收起，否则筛选条件会变得无法访问 */
    .ui-search.is-collapsible > .ui-select,
    .ui-search.is-collapsible > .ui-select-wrap,
    .ui-search.is-collapsible > .ui-input:not([name="keyword"]) {
        display: none;
        width: 100%;
        max-width: none;
        height: 40px;
    }

    .ui-search.is-collapsible.is-filter-open > .ui-select,
    .ui-search.is-collapsible.is-filter-open > .ui-select-wrap,
    .ui-search.is-collapsible.is-filter-open > .ui-input:not([name="keyword"]) {
        display: block;
    }

    /* 手机端渲染后的下拉触发区同样要占满整行 */
    .ui-search .ui-select-wrap,
    .ui-search.is-collapsible.is-filter-open > .ui-select-wrap {
        flex: 0 0 auto;
        width: 100%;
        max-width: none;
        height: var(--ui-touch);
    }

    .ui-search .ui-select-wrap .layui-form-select .layui-select-title,
    .ui-search .ui-select-wrap .layui-form-select .layui-input {
        height: var(--ui-touch);
        font-size: 16px;
        line-height: var(--ui-touch);
    }

    /* 图片上传：手机端整块加大，操作按钮等分便于点按 */
    .ui-upload__zone {
        min-height: 160px;
    }

    .ui-upload__img {
        height: 160px;
    }

    .ui-upload__foot {
        flex-direction: column;
        align-items: stretch;
        gap: 8px;
    }

    .ui-upload__ops {
        width: 100%;
    }

    .ui-upload__ops .ui-btn {
        flex: 1;
        justify-content: center;
        min-height: var(--ui-touch);
    }

    /* 操作按钮行：筛选 / 搜索 / 重置 三等分 */
    .ui-search__actions {
        width: 100%;
        gap: 8px;
    }

    .ui-search__actions .ui-btn {
        flex: 1 1 0;
        min-width: 0;
        height: var(--ui-touch);
        padding: 0 6px;
        font-size: 14px;
    }

    /* 重置只有图标：保持方形，剩余宽度让给「搜索」 */
    .ui-search__actions .ui-btn--icon {
        flex: 0 0 auto;
        width: var(--ui-touch);
        padding: 0;
    }

    .ui-search__toggle {
        display: inline-flex !important;
        position: relative;
    }

    /* 没有可收起的筛选项时，不显示「筛选」开关 */
    .ui-search__toggle.is-hidden {
        display: none !important;
    }

    .ui-search__toggle.is-active {
        color: var(--ui-primary);
        border-color: #bccdfb;
        background: var(--ui-primary-soft);
    }

    .ui-search__badge {
        position: absolute;
        top: -6px;
        right: -4px;
        min-width: 17px;
        height: 17px;
        padding: 0 4px;
        border-radius: 999px;
        background: var(--ui-danger);
        color: #fff;
        font-size: 10.5px;
        font-style: normal;
        line-height: 17px;
        text-align: center;
    }

    /* 工具栏右侧按钮组：整行铺满 + 三列网格，避免每个按钮独占一行 */
    .ui-toolbar__right {
        width: 100%;
        margin-left: 0;
        gap: 8px;
    }

    .ui-toolbar__right .ui-btn {
        flex: 1 1 calc(33.333% - 6px);
        min-width: 0;
        height: 40px;
        padding: 0 6px;
        font-size: 13px;
    }

    /* 移动端「新增」按钮突出显示，独占一行并置顶 */
    .ui-toolbar__right .ui-btn--primary {
        flex: 1 1 100%;
        order: -1;
        height: var(--ui-touch);
        font-size: 14.5px;
    }

    /* 批量删除已由底部「批量操作条」承担，工具栏里不再重复占位 */
    .ui-toolbar__right .ui-btn--danger {
        display: none;
    }

    /* ------------------------------------------------------------------
     * 3. 卡片列表：主信息突出 + 字段可换行 + 操作独立成行
     * ---------------------------------------------------------------- */
    .ui-table-wrap {
        max-height: none !important;
        overflow: visible;
        background: transparent;
    }

    .ui-table--responsive {
        display: block;
        min-width: 0 !important;
        table-layout: auto !important;
        background: transparent;
    }

    .ui-table--responsive colgroup,
    .ui-table--responsive thead {
        display: none;
    }

    .ui-table--responsive tbody {
        display: block;
    }

    .ui-table--responsive tr {
        position: relative;
        display: flex;
        flex-direction: column;
        margin: 0 0 10px;
        padding: 0;
        border: 1px solid var(--ui-line);
        border-radius: 12px;
        background: #fff;
        box-shadow: 0 1px 2px rgba(15, 23, 42, .04);
        overflow: hidden;
    }

    /* 主信息永远排在最前，其余字段按原列序跟随 */
    .ui-table--responsive td[data-primary] {
        order: -1;
    }

    .ui-table--responsive tr:active {
        background: #fafbfe;
    }

    /* 主信息单元格：卡片标题 */
    .ui-table--responsive td[data-primary] {
        display: block;
        padding: 13px 46px 11px 14px;
        text-align: left;
        white-space: normal !important;
        overflow: visible !important;
        text-overflow: clip !important;
        background: linear-gradient(180deg, #fbfcff, #f7f9fd);
        border-bottom: 1px solid var(--ui-line);
        font-size: 15px;
    }

    .ui-table--responsive td[data-primary]::before {
        display: none;
    }

    /* 卡片模式下固定列全部失效；尤其要清掉 .is-pin-1 的 left:0，
       否则下面那个「绝对定位的勾选框单元格」会被 left+right 同时约束，
       横向铺满整张卡片并盖住卡片标题 */
    .ui-table--responsive th.is-pin,
    .ui-table--responsive td.is-pin {
        position: static;
        left: auto;
        right: auto;
        z-index: auto;
    }

    /* 勾选框：浮动到卡片右上角，触控区 40×40 */
    .ui-table--responsive td[data-label=""] {
        position: absolute;
        top: 6px;
        right: 6px;
        left: auto;
        bottom: auto;
        z-index: 2;
        display: block;
        width: auto;
        height: auto;
        padding: 0;
        border: 0;
        background: transparent;
    }

    .ui-table--responsive td[data-label=""] .ui-check {
        display: grid;
        place-items: center;
        width: 40px;
        height: 40px;
        gap: 0;
    }

    .ui-table--responsive td[data-label=""]::before {
        display: none;
    }

    .ui-table--responsive td[data-label=""] input[type="checkbox"] {
        width: 22px;
        height: 22px;
    }

    /* 普通字段：左标签右值，允许换行，不再裁切 */
    .ui-table--responsive td {
        display: flex;
        align-items: baseline;
        justify-content: space-between;
        gap: 14px;
        width: 100%;
        min-height: 40px;
        padding: 10px 14px;
        border-bottom: 1px solid var(--ui-line-soft);
        text-align: right;
        font-size: 13.5px;
        white-space: normal !important;
        overflow: visible !important;
        text-overflow: clip !important;
    }

    .ui-table--responsive td::before {
        content: attr(data-label);
        flex: 0 0 auto;
        color: var(--ui-muted);
        font-size: 12.5px;
        line-height: 1.7;
        text-align: left;
    }

    .ui-table--responsive td > * {
        min-width: 0;
    }

    /* 值过长时换行，不截断 */
    .ui-table--responsive td > :not(.ui-actions):not(.ui-badge) {
        word-break: break-word;
    }

    /* 操作单元格：卡片底部按钮行（触控友好） */
    .ui-table--responsive td.is-actions-cell {
        display: flex;
        justify-content: flex-end;
        gap: 8px;
        padding: 9px 10px calc(9px + var(--ui-safe-bottom) * 0);
        border-top: 1px solid var(--ui-line);
        border-bottom: 0;
        background: #fbfcfe;
    }

    .ui-table--responsive td.is-actions-cell::before {
        display: none;
    }

    .ui-table--responsive td.is-actions-cell .ui-actions {
        width: 100%;
        gap: 8px;
    }

    .ui-table--responsive td.is-actions-cell .ui-action {
        flex: 1;
        justify-content: center;
        min-height: 40px;
        padding: 0 8px;
        border: 1px solid var(--ui-line);
        background: #fff;
        font-size: 13.5px;
    }

    /* 触屏没有 hover：图标按钮在手机端恢复文字，方便辨认 */
    .ui-table--responsive td.is-actions-cell .ui-action--icon-only {
        width: auto;
    }
    .ui-table--responsive td.is-actions-cell .ui-action--icon-only .ui-action__text {
        position: static;
        width: auto; height: auto;
        margin: 0; overflow: visible; clip: auto;
    }

    .ui-table--responsive td.is-actions-cell .ui-action--danger {
        border-color: #f6c9c9;
        background: #fdf6f6;
    }

    .ui-table--responsive td.is-actions-cell .ui-action:active {
        background: var(--ui-primary-soft);
    }

    /* 树形表格（菜单 / 部门）的展开收起按钮：PC 上是 13px 图标，
       手机端必须放大到可点区域，否则 21×26 根本点不准 */
    .ui-table--responsive td [data-action="toggle"] {
        flex: 0 0 auto;
        justify-content: center;
        min-width: 40px;
        min-height: 40px;
        margin-left: -8px;
        padding: 0 !important;
        border: 1px solid var(--ui-line);
        border-radius: 9px;
        background: #fff;
        color: var(--ui-text);
    }

    .ui-table--responsive td [data-action="toggle"]:active {
        background: var(--ui-primary-soft);
        border-color: #bccdfb;
    }

    /* 卡片标题行（树形节点名）允许换行，长层级名不撑破卡片 */
    .ui-table--responsive td[data-primary] > div {
        flex-wrap: wrap;
    }

    /* 卡片间的空状态与骨架 */
    .ui-table--responsive .ui-empty {
        padding: 40px 16px;
    }

    /* ------------------------------------------------------------------
     * 4. 批量操作条：选中后从底部浮出
     * ---------------------------------------------------------------- */
    .ui-batch-bar {
        position: fixed;
        left: calc(10px + var(--ui-safe-left));
        right: calc(10px + var(--ui-safe-right));
        bottom: calc(10px + var(--ui-safe-bottom));
        z-index: 9997;
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 12px;
        padding: 10px 12px;
        border-radius: 14px;
        background: rgba(15, 23, 42, .96);
        color: #e2e8f0;
        box-shadow: 0 14px 34px rgba(2, 6, 23, .4);
        backdrop-filter: blur(10px);
        -webkit-backdrop-filter: blur(10px);
        animation: ui-batch-in .22s cubic-bezier(.2, .9, .3, 1.1);
    }

    .ui-batch-bar[hidden] {
        display: none;
    }

    .ui-batch-bar__info {
        font-size: 13.5px;
        white-space: nowrap;
    }

    .ui-batch-bar__info strong {
        color: #fff;
        font-size: 15px;
    }

    .ui-batch-bar__actions {
        display: flex;
        gap: 8px;
    }

    .ui-batch-bar__actions .ui-btn {
        height: 38px;
        border-color: rgba(255, 255, 255, .22);
        background: rgba(255, 255, 255, .1);
        color: #e2e8f0;
    }

    .ui-batch-bar__actions .ui-btn--danger {
        border-color: transparent;
        background: var(--ui-danger);
        color: #fff;
    }

    @keyframes ui-batch-in {
        from { opacity: 0; transform: translateY(20px); }
        to   { opacity: 1; transform: translateY(0); }
    }

    /* ------------------------------------------------------------------
     * 5. 分页：精简为大按钮
     * ---------------------------------------------------------------- */
    .ui-pager {
        flex-direction: column;
        gap: 10px;
        padding: 12px;
    }

    .ui-pager__info {
        width: 100%;
        text-align: center;
        font-size: 12.5px;
    }

    .ui-pager__list {
        width: 100%;
        justify-content: center;
        gap: 6px;
    }

    .ui-pager__item {
        min-width: var(--ui-touch);
        height: var(--ui-touch);
        font-size: 14px;
    }

    /* 页码过多时隐藏中间页，只保留首末与相邻（由 JS 已做窗口，这里兜底） */
    .ui-pager__list .ui-pager__item:nth-child(n+7):not(:nth-last-child(-n+3)) {
        display: none;
    }

    /* ------------------------------------------------------------------
     * 6. 弹窗：底部弹出 + 安全区
     * ---------------------------------------------------------------- */
    .ui-mask {
        align-items: flex-end;
        padding: 0;
    }

    .ui-modal {
        width: 100%;
        max-width: 100% !important;
        max-height: 92vh;
        max-height: 92dvh;
        border-radius: 18px 18px 0 0;
        padding-bottom: var(--ui-safe-bottom);
        animation: ui-sheet-in .26s cubic-bezier(.2, .9, .3, 1.05);
    }

    .ui-modal__head {
        padding: 14px 16px;
        position: relative;
    }

    /* 顶部拖拽提示条 */
    .ui-modal__head::before {
        content: "";
        position: absolute;
        top: 6px;
        left: 50%;
        transform: translateX(-50%);
        width: 38px;
        height: 4px;
        border-radius: 999px;
        background: #d7dee9;
    }

    .ui-modal__body {
        padding: 16px;
    }

    .ui-modal__foot {
        padding: 12px 14px calc(12px + var(--ui-safe-bottom));
        gap: 10px;
    }

    .ui-modal__foot .ui-btn {
        flex: 1;
        height: var(--ui-touch);
        font-size: 15px;
    }

    .ui-modal__close {
        width: var(--ui-touch);
        height: var(--ui-touch);
    }

    /* 表单控件加大，避免 iOS 输入聚焦时自动放大 */
    .ui-input,
    .ui-select,
    .ui-textarea,
    .ui-select-wrap .layui-form-select .layui-select-title,
    .ui-select-wrap .layui-form-select .layui-input {
        font-size: 16px;
        min-height: var(--ui-touch);
    }

    /* 手机端下拉面板：行高抬到 44px，方便点选 */
    .ui-select-wrap .layui-form-select dl dd,
    .layui-select-panel-wrap dl dd {
        height: 44px;
        font-size: 15px;
        line-height: 44px;
    }

    .ui-textarea {
        min-height: 96px;
        font-size: 15px;
    }

    .ui-switch {
        width: 50px;
        height: 30px;
    }

    .ui-switch__slider::after {
        width: 24px;
        height: 24px;
        top: 3px;
        left: 3px;
    }

    .ui-switch input:checked + .ui-switch__slider::after {
        transform: translateX(20px);
    }

    /* 确认框同样适配 */
    .ui-confirm {
        border-radius: 18px 18px 0 0;
        max-width: 100%;
        padding: 24px 20px calc(18px + var(--ui-safe-bottom));
    }

    .ui-confirm__actions .ui-btn {
        height: var(--ui-touch);
        font-size: 15px;
    }

    /* 抽屉式详情 */
    .ui-mask .ui-modal[style*="height:100%"] {
        border-radius: 0;
    }

    /* ------------------------------------------------------------------
     * 7. 列表与卡片类页面
     * ---------------------------------------------------------------- */
    .ui-card {
        border-radius: 12px;
    }

    .ui-card__head {
        padding: 13px 14px;
    }

    .ui-card__body {
        padding: 14px;
    }

    /* 消息列表：图标 + 正文占满整行，操作独立成一行；
       否则标题会被挤成「每行一个字」的竖排 */
    .msg-item {
        display: grid;
        grid-template-columns: 36px minmax(0, 1fr);
        grid-template-areas:
            "icon main"
            ".    actions";
        align-items: start;
        gap: 10px 12px;
        padding: 14px;
    }

    .msg-item__icon { grid-area: icon; }

    .msg-item__main { grid-area: main; }

    .msg-item__title {
        flex-wrap: wrap;
        line-height: 1.45;
    }

    .msg-item__actions {
        grid-area: actions;
        width: 100%;
        flex-direction: row;
        gap: 8px;
        margin-top: 2px;
    }

    .msg-item__actions .ui-action {
        flex: 1;
        justify-content: center;
        min-height: 40px;
        padding: 0 8px;
        border: 1px solid var(--ui-line);
        background: #fff;
    }

    .msg-item__actions .ui-action--danger {
        border-color: #f6c9c9;
        background: #fdf6f6;
    }

    /* 设置页：标签横向滚动，按钮整行 */
    .setting-bar {
        padding: 0 12px;
    }

    .setting-bar .setting-tabs {
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
        scrollbar-width: none;
    }

    .setting-bar .setting-tabs::-webkit-scrollbar {
        display: none;
    }

    .setting-tab {
        padding: 13px 12px;
        font-size: 14px;
        white-space: nowrap;
    }

    .setting-panel {
        padding: 16px 14px;
    }

    /* 图标网格 */
    .icon-grid {
        grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
        gap: 8px;
    }

    .icon-card {
        padding: 12px 6px 8px;
    }

    .icon-card__actions {
        opacity: 1;
        gap: 4px;
    }

    /* 图标卡片操作按钮：PC 上是紧凑小按钮，手机端要够大才好点 */
    .icon-card__actions .ui-action {
        flex: 1;
        justify-content: center;
        min-height: 38px;
        padding: 0 4px;
        border: 1px solid var(--ui-line);
        background: #fff;
        font-size: 12.5px;
    }

    .icon-card__actions .ui-action--danger {
        border-color: #f6c9c9;
        background: #fdf6f6;
    }

    /* 小号按钮在移动端抬高到可点高度 */
    .ui-btn--sm {
        height: 40px;
        padding: 0 12px;
        font-size: 13px;
    }

    /* 工作台统计卡片 */
    .stat-grid {
        grid-template-columns: repeat(2, 1fr);
        gap: 10px;
    }

    .stat-card {
        padding: 13px;
        border-radius: 12px;
    }

    .stat-card__value {
        font-size: 21px;
    }

    .chart-bars {
        height: 150px;
        gap: 6px;
    }

    .chart-bars__bar {
        width: 9px;
    }

    /* 双列/三列布局在移动端一律改为单列。
       注意不能用 `.page .ui-row`：部分页面（如工作台）没有 .page 外壳，
       漏掉后图表与「我的信息」会并排挤压成竖排文字 */
    .ui-row > .ui-col {
        width: 100% !important;
    }

    /* 通知面板铺满 */
    .notice-panel {
        position: fixed;
        top: calc(var(--ui-head-h) + var(--ui-safe-top) + 6px);
        left: 10px;
        right: 10px;
        width: auto;
        max-width: none;
    }
}

/* 小屏手机（≤390px）进一步收紧 */
@media (max-width: 390px) {
    /* 统计卡片保持两列：单列会把首屏拉得很长，数字本身很短 */
    .stat-card {
        padding: 11px;
    }

    .stat-card__value {
        font-size: 19px;
    }

    .stat-card__label {
        font-size: 12px;
    }

    /* 三列网格在超窄屏略微收窄内边距，保证「刷新 / 列设置 / 导出」仍在同一行 */
    .ui-toolbar__right .ui-btn {
        padding: 0 2px;
        font-size: 12.5px;
    }

    .ui-search__actions .ui-btn {
        padding: 0 4px;
        font-size: 13px;
    }

    .ui-batch-bar__info {
        font-size: 12.5px;
    }
}

/* 桌面端隐藏移动端专属元素 */
@media (min-width: 821px) {
    .sidebar__close {
        display: none;
    }

    .ui-search__toggle {
        display: none !important;
    }

    .ui-batch-bar {
        display: none !important;
    }
}

/* 横屏手机：压缩纵向留白 */
@media (max-width: 820px) and (orientation: landscape) {
    .ui-modal {
        max-height: 96vh;
        max-height: 96dvh;
    }

    .stat-grid {
        grid-template-columns: repeat(4, 1fr);
    }
}

/* 设置项说明（输入框下方的小字提示，数据来自 sys_settings.tip） */
.ui-form-tip {
    margin-top: 6px;
    color: var(--ui-muted);
    font-size: 12px;
    line-height: 1.6;
}
