/**
 * ================================================
 * 法律提示：本程序/代码仅限合法用途使用，您可以修改自用，请保留版权
 * ================================================
 * 使用限制：禁止用于非法用途，作者不承担任何使用责任
 * ================================================
 * Copy right 2026 网博士网络工作室， 保留所有权利。
 * ================================================
 * 官方网址: www.网博士.com   联系：QQ: 570830288
 * ================================================
 */
/* ==========================================================================
   优品商城系统 · 后台样式
   /assets/css/admin.css
   在 LayUI 2.8 之上做的一层克制的覆盖：扁平、留白、少描边、无渐变无阴影堆叠。
   ========================================================================== */

/* 全站 SVG 图标的基础尺寸：1em 跟着字号走，颜色用 currentColor 跟文字 */
.ico-svg{
    display:inline-block;width:1em;height:1em;
    vertical-align:-.125em;flex:none;
}

:root{
  --df-dark:#141414;
  --df-dark-2:#141C24;
  --df-dark-3:#262626;
  --df-accent:#2b6cff;
  --df-accent-2:#2b6cff;
  --df-accent-soft:#E9F2F5;
  --df-bg:#F2F5F7;
  --df-card:#FFFFFF;
  --df-text:#1B2733;
  --df-text-2:#41525F;
  --df-muted:#64778A;
  --df-line:#E5EAEE;
  --df-line-2:#EEF2F5;
  --df-ok:#2E7D5B;
  --df-warn:#B8862B;
  --df-danger:#B33A2B;
  --df-head-h:56px;
  --df-side-w:232px;
  --df-side-fold:58px;
  --df-radius:3px;
}

*{box-sizing:border-box;}
html,body{height:100%;}
body{
  margin:0;background:var(--df-bg);color:var(--df-text);
  font:14px/1.65 -apple-system,BlinkMacSystemFont,"Segoe UI","PingFang SC","Hiragino Sans GB","Microsoft YaHei",sans-serif;
  -webkit-font-smoothing:antialiased;
}
a{color:var(--df-accent);text-decoration:none;transition:color .15s;}
a:hover{color:var(--df-accent-2);}
::selection{background:var(--df-accent);color:#fff;}

/* 滚动条 ---------------------------------------------------------------- */
::-webkit-scrollbar{width:8px;height:8px;}
::-webkit-scrollbar-thumb{background:#C9D3DA;border-radius:4px;}
::-webkit-scrollbar-thumb:hover{background:#AEBCC6;}
::-webkit-scrollbar-track{background:transparent;}

/* ==========================================================================
   顶栏
   ========================================================================== */
.df-header{
  position:fixed;top:0;left:0;right:0;height:var(--df-head-h);z-index:1000;
  background:var(--df-dark);display:flex;align-items:center;
  padding:0 18px 0 0;
  border-bottom:1px solid #000;
  box-shadow:0 1px 0 rgba(255,255,255,.04), 0 4px 14px rgba(0,0,0,.28);
}
.df-logo{
  width:var(--df-side-w);height:var(--df-head-h);flex:0 0 auto;
  display:flex;align-items:center;gap:9px;padding-left:20px;
  color:#fff;font-size:16px;font-weight:600;letter-spacing:.3px;
  background:linear-gradient(180deg, #0E141B 0%, #141414 100%);
  transition:width .22s cubic-bezier(.4,0,.2,1);overflow:hidden;white-space:nowrap;
}
/* 左上角 logo 图标（assets/images/admin_logo.svg）：21×21（比原来那颗字体图标大一号），
   display:block 去掉 img 底部的行内空隙，免得和右边的站点名对不齐 */
.df-logo img{width:21px;height:21px;flex:0 0 auto;display:block;}
.df-logo span{transition:opacity .18s;}

.df-head-left{display:flex;align-items:center;gap:2px;}
.df-head-right{margin-left:auto;display:flex;align-items:center;gap:2px;}

.df-hbtn{
  height:36px;min-width:36px;padding:0 11px;border:0;background:transparent;
  color:#8FA3B2;border-radius:var(--df-radius);cursor:pointer;
  display:inline-flex;align-items:center;justify-content:center;gap:6px;
  font-size:13px;transition:background .15s,color .15s;
}
.df-hbtn:hover{background:rgba(255,255,255,.07);color:#fff;}
.df-hbtn i{font-size:16px;}

/* 顶栏待审核提醒（有用户未审核 / 有商品未审核）：右上角挂个会呼吸的红点 */
.df-hbtn-alert{position:relative;color:#F5B98C;background:rgba(235,124,52,.14);}
.df-hbtn-alert:hover{background:rgba(235,124,52,.26);color:#FFD8B0;}
.df-hdot{
  position:absolute;top:5px;right:4px;width:7px;height:7px;
  border-radius:50%;background:#FF4D4F;
  box-shadow:0 0 0 2px rgba(10,14,18,.9);
}
/* 扩散出去的光圈（伪元素，不占位置），纯装饰 */
.df-hdot::after{
  content:'';position:absolute;left:50%;top:50%;width:7px;height:7px;
  margin:-3.5px 0 0 -3.5px;border-radius:50%;border:1px solid #FF4D4F;
  animation:df-hdot-pulse 1.9s ease-out infinite;
}
@keyframes df-hdot-pulse{
  0%{transform:scale(1);opacity:.65;}
  70%,100%{transform:scale(2.6);opacity:0;}
}
@media (prefers-reduced-motion:reduce){
  .df-hdot::after{animation:none;opacity:0;}
}

.df-admin-chip{
  display:flex;align-items:center;gap:8px;padding:0 10px 0 6px;height:36px;
  border-radius:var(--df-radius);color:#C7D3DC;font-size:13px;cursor:pointer;
  transition:background .15s;
}
.df-admin-chip:hover{background:rgba(255,255,255,.07);}
.df-avatar{
  width:26px;height:26px;border-radius:50%;background:var(--df-accent);
  color:#fff;display:flex;align-items:center;justify-content:center;
  font-size:12px;font-weight:600;flex:0 0 auto;
}

/* ==========================================================================
   侧边菜单
   ========================================================================== */
.df-side{
  position:fixed;top:var(--df-head-h);bottom:0;left:0;width:var(--df-side-w);z-index:999;
  background:var(--df-dark);overflow-y:auto;overflow-x:hidden;
  padding:10px 0 60px;
  transition:width .22s cubic-bezier(.4,0,.2,1),transform .22s cubic-bezier(.4,0,.2,1);
}
.df-side::-webkit-scrollbar{width:5px;}
.df-side::-webkit-scrollbar-thumb{background:#2C3A48;border-radius:3px;}
.df-side::-webkit-scrollbar-thumb:hover{background:#3D4E5E;}

.df-menu-group{margin-bottom:1px;}
.df-menu-item{
  display:flex;align-items:center;gap:10px;height:42px;padding:0 18px;
  color:#B6C5D2;font-size:14px;cursor:pointer;position:relative;white-space:nowrap;
  transition:background .15s,color .15s;
}
.df-menu-item:hover{background:var(--df-dark-2);color:#fff;}
.df-menu-item > i:first-child{font-size:16px;width:18px;text-align:center;flex:0 0 auto;color:#a9a9a9;}
.df-menu-item:hover > i:first-child{color:var(--df-accent-2);}
.df-menu-item .df-mtext{flex:1;overflow:hidden;text-overflow:ellipsis;}
.df-menu-item .df-arrow{
  font-size:12px;color:#5D7385;transition:transform .22s;flex:0 0 auto;
}
.df-menu-group.open > .df-menu-item .df-arrow{transform:rotate(90deg);}
.df-menu-group.open > .df-menu-item{color:#fff;}

.df-sub{
  overflow:hidden;max-height:0;transition:max-height .26s cubic-bezier(.4,0,.2,1);
  background:#181818;
}
.df-menu-group.open > .df-sub{max-height:900px;}

.df-sub a{
  display:flex;align-items:center;height:38px;padding:0 18px 0 47px;
  color:#8e8f91;font-size:13.5px;position:relative;white-space:nowrap;
  transition:background .15s,color .15s,padding .15s;
}
.df-sub a::before{
  content:"";position:absolute;left:29px;top:50%;width:4px;height:4px;margin-top:-2px;
  border-radius:50%;background:#3C5566;transition:background .15s;
}
.df-sub a:hover{background:var(--df-dark-2);color:#fff;}
.df-sub a:hover::before{background:var(--df-accent-2);}
.df-sub a.active{background:var(--df-dark-3);color:#fff;}
.df-sub a.active::before{background:var(--df-accent-2);box-shadow:0 0 0 3px rgba(30,111,140,.18);}
.df-sub a.active::after{
  content:"";position:absolute;left:0;top:0;bottom:0;width:2px;background:var(--df-accent-2);
}

.df-menu-item.single.active{
  background:var(--df-dark-3);color:#fff;
  box-shadow:inset 3px 0 0 var(--df-accent-2);
}
.df-menu-item.single.active::after{
  content:"";position:absolute;left:0;top:0;bottom:0;width:2px;background:var(--df-accent-2);
}

.df-side-tip{
  padding:14px 18px 6px;color:#4E657600;font-size:11px;
}

/* 收起态 ---------------------------------------------------------------- */
body.df-fold .df-logo{width:var(--df-side-fold);padding-left:0;justify-content:center;}
body.df-fold .df-logo span{opacity:0;width:0;overflow:hidden;}
body.df-fold .df-side{width:var(--df-side-fold);}
body.df-fold .df-side .df-mtext,
body.df-fold .df-side .df-arrow{opacity:0;width:0;flex:0 0 0;overflow:hidden;}
/* 收起态：清除 gap，让 18px 图标在 58px 侧栏中由 justify-content 精确居中((58-18)/2=20px) */
body.df-fold .df-menu-item{justify-content:center;padding:0;gap:0;}
body.df-fold .df-sub{display:none;}
body.df-fold .df-main{margin-left:var(--df-side-fold);}

/* 收起态：当前弹出二级菜单的一级图标高亮 */
body.df-fold .df-menu-item.pop-on{background:var(--df-dark-2);color:#fff;}
body.df-fold .df-menu-item.pop-on > i:first-child{color:var(--df-accent-2);}

/* 收起态二级菜单浮层（挂在 body 下，定位到图标右侧） -------------------- */
.df-fold-pop{
  position:fixed;z-index:1100;min-width:160px;display:none;
  padding:5px 0;
  background:var(--df-dark);
  border:1px solid rgba(255,255,255,.07);
  border-radius:6px;
  box-shadow:0 12px 32px rgba(0,0,0,.45);
}
.df-fold-pop.show{display:block;animation:df-pop-in .12s ease;}
@keyframes df-pop-in{
  from{opacity:0;transform:translateX(-4px);}
  to{opacity:1;transform:none;}
}
.df-fold-pop-t{
  padding:7px 16px 8px;margin-bottom:4px;
  font-size:12px;color:#6E8294;white-space:nowrap;
  border-bottom:1px solid rgba(255,255,255,.06);
}
.df-fold-pop-bd a{
  display:block;padding:8px 18px;
  color:#B6C5D2;font-size:13.5px;white-space:nowrap;
  transition:background .15s,color .15s;
}
.df-fold-pop-bd a:hover{background:var(--df-dark-2);color:#fff;}
.df-fold-pop-bd a.active{background:var(--df-dark-3);color:#fff;}

/* ==========================================================================
   主体
   ========================================================================== */
.df-main{
  margin-left:var(--df-side-w);padding-top:var(--df-head-h);min-height:100vh;
  transition:margin-left .22s cubic-bezier(.4,0,.2,1);
}
.df-body{padding:18px 20px 30px;}

/* 后台公共版权信息：所有页面底部居中 */
.df-admin-copy{
  text-align:center;padding:18px 0 22px;
  font-size:12px;color:var(--df-muted);
}
.df-admin-copy a{color:inherit;text-decoration:none;}
.df-admin-copy a:hover{color:var(--df-accent);}

.df-crumb{
  display:flex;align-items:center;gap:8px;color:var(--df-muted);font-size:13px;
  margin-bottom:14px;
}
.df-crumb b{color:var(--df-text);font-weight:600;font-size:15px;}
.df-crumb i{font-size:12px;color:#AEBCC6;}

.df-card{
  background:var(--df-card);border:1px solid var(--df-line);border-radius:var(--df-radius);
  margin-bottom:16px;
}
.df-card-hd{
  height:48px;padding:0 16px;display:flex;align-items:center;gap:10px;
  border-bottom:1px solid var(--df-line-2);
}
.df-card-hd h3{margin:0;font-size:14.5px;font-weight:600;color:var(--df-text);}
.df-card-hd .df-hd-sub{color:var(--df-muted);font-size:12.5px;}
.df-card-hd .df-hd-right{margin-left:auto;display:flex;gap:8px;align-items:center;}
.df-card-bd{padding:16px;}
.df-card-bd.nopad{padding:0;}

/* df-table-fit：表格统一外观（分隔线 + 隔行换色 + 悬停提亮），
   后台所有列表页的表格容器都加它，风格跟订单列表一致。 */
/* 列特别多、内容又长的表格（订单那种）再额外加 .df-nowrap：
   单元格统一单行省略，鼠标悬停看全文（templet 里都带了 title）。
   默认不开启，免得公告、文章、邮件模板这类内容型列表被截成省略号 */
.df-table-fit.df-nowrap .layui-table-cell{
  overflow:hidden;
  text-overflow:ellipsis;
  white-space:nowrap;
}

/* 列表一多就分不清上下两条：行间一条清晰分隔线，隔行换色，
   鼠标划过时整行提亮并在行首亮出一条主题色，方便横向对着看 */
/* 注意：admin.css 里有一条「.layui-table td{border-color:...!important}」把单元格边框色锁死了，
   这里必须同样用 !important 才盖得住，否则改了等于没改 */
.df-table-fit .layui-table tbody tr td{
  border-bottom:1px solid #D8E4F0!important;
}
.df-table-fit .layui-table tbody tr:nth-child(even) td{
  background:#F5F9FD;
}
.df-table-fit .layui-table tbody tr:hover td{
  background:#DCE8FA;
}
.df-table-fit .layui-table tbody tr:hover td:first-child{
  box-shadow:inset 3px 0 0 var(--df-accent);
}
.df-table-fit .layui-table tbody tr:hover td .df-tag{
  box-shadow:0 0 0 2px #fff;
}
/* 列表里跳前台的那些链接（商品名 / 店铺名，都是新窗口打开）：
   平时跟正文同色不抢戏，鼠标划过才变主色 + 下划线，提示点得动 */
.df-table-fit .g-name{color:inherit;}
.df-table-fit .g-name:hover{color:var(--df-accent);text-decoration:underline;}

/* 统计卡片 -------------------------------------------------------------- */
.df-stats{
  display:grid;grid-template-columns:repeat(6,minmax(0,1fr));gap:14px;margin-bottom:16px;
}
.df-stat{
  background:var(--df-card);border:1px solid var(--df-line);border-radius:6px;
  padding:14px 16px 12px 18px;position:relative;overflow:hidden;
  box-shadow:0 1px 2px rgba(27,39,51,.04);
  transition:border-color .18s,box-shadow .18s;
}
/* 左侧 3px 状态色条：无状态类=中性灰，有 is-* 跟随状态色 */
.df-stat::before{
  content:"";position:absolute;left:0;top:9px;bottom:9px;width:3px;border-radius:0 3px 3px 0;
  background:#AEBBC7;
}
.df-stat.is-warn::before{background:var(--df-warn);}
.df-stat.is-doing::before{background:#3A71B8;}
.df-stat.is-ok::before{background:var(--df-ok);}
.df-stat.is-danger::before{background:var(--df-danger);}
.df-stat.is-accent::before{background:var(--df-accent);}
/* 悬停只提亮边框+轻浮影，不做位移（后台统计区求稳） */
.df-stat:hover{border-color:#D2DCE4;box-shadow:0 5px 16px rgba(27,39,51,.09);}
.df-stat .df-stat-t{color:var(--df-muted);font-size:12.5px;display:flex;align-items:center;gap:6px;}
.df-stat .df-stat-t i{font-size:14px;color:#97A5B2;}
.df-stat.is-warn .df-stat-t i{color:var(--df-warn);}
.df-stat.is-doing .df-stat-t i{color:#3A71B8;}
.df-stat.is-ok .df-stat-t i{color:var(--df-ok);}
.df-stat.is-danger .df-stat-t i{color:var(--df-danger);}
.df-stat.is-accent .df-stat-t i{color:var(--df-accent);}
.df-stat .df-stat-v{
  font-size:25px;font-weight:600;letter-spacing:-.5px;margin-top:8px;color:var(--df-text);
  font-variant-numeric:tabular-nums;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.df-stat .df-stat-v small{font-size:13px;font-weight:400;color:var(--df-muted);margin-left:2px;}
.df-stat .df-stat-f{margin-top:6px;font-size:12px;color:var(--df-muted);}
.df-stat.is-accent .df-stat-v{color:var(--df-accent);}
.df-stat.is-warn .df-stat-v{color:var(--df-warn);}
.df-stat.is-danger .df-stat-v{color:var(--df-danger);}
.df-stat.is-ok .df-stat-v{color:var(--df-ok);}
.df-stat-skeleton{
  height:25px;width:60%;margin-top:8px;border-radius:3px;
  background:linear-gradient(90deg,#EEF2F5 25%,#E3EAEF 37%,#EEF2F5 63%);
  background-size:400% 100%;animation:df-shimmer 1.3s ease infinite;
}
@keyframes df-shimmer{0%{background-position:100% 50%;}100%{background-position:0 50%;}}

/* 筛选条 ---------------------------------------------------------------- */
.df-filter{
  display:flex;flex-wrap:wrap;gap:10px;align-items:center;
  padding:14px 16px;border-bottom:1px solid var(--df-line-2);
}
.df-filter .layui-input,.df-filter .layui-select{height:34px;}
.df-filter .df-f-item{display:flex;align-items:center;gap:7px;}
.df-filter .df-f-item > label{color:var(--df-muted);font-size:13px;white-space:nowrap;}
.df-filter .df-f-item .layui-input{width:158px;}
.df-filter .df-f-tail{margin-left:auto;display:flex;gap:8px;}

/* ==========================================================================
   LayUI 覆盖
   ========================================================================== */
.layui-btn{
  height:34px;line-height:32px;padding:0 15px;border-radius:var(--df-radius);
  font-size:13.5px;font-weight:400;border:1px solid transparent;transition:all .16s;
}
.layui-btn:not(.layui-btn-primary){background-color:var(--df-accent);}
.layui-btn:not(.layui-btn-primary):hover{background-color:var(--df-accent-2);opacity:1;}
.layui-btn-primary{border-color:#D6DEE4;background:#fff;color:var(--df-text-2);}
.layui-btn-primary:hover{border-color:var(--df-accent);color:var(--df-accent);background:#fff;}
.layui-btn-danger{background-color:var(--df-danger)!important;}
.layui-btn-danger:hover{background-color:#C4432F!important;}
.layui-btn-warm{background-color:var(--df-warn)!important;}
.layui-btn-normal{background-color:var(--df-accent)!important;}
.layui-btn-sm{height:30px;line-height:28px;padding:0 11px;font-size:12.5px;}
.layui-btn-xs{height:24px;line-height:22px;padding:0 8px;font-size:12px;}
.layui-btn.layui-btn-disabled,.layui-btn[disabled]{opacity:.55;cursor:not-allowed;}

.layui-input,.layui-textarea,.layui-select{
  border-color:#D8E0E6;border-radius:var(--df-radius);color:var(--df-text);
  transition:border-color .16s,box-shadow .16s;
}
.layui-input:focus,.layui-textarea:focus,.layui-select:focus{
  border-color:var(--df-accent)!important;box-shadow:0 0 0 2px rgba(30,111,140,.10)!important;
}
.layui-input::placeholder,.layui-textarea::placeholder{color:#A7B5C0;}
.layui-form-label{
  width:104px;padding:9px 12px 9px 0;text-align:right;color:var(--df-text-2);font-weight:400;
}
.layui-input-block{margin-left:104px;}
.layui-form-item{margin-bottom:16px;}
.layui-form-mid{color:var(--df-muted);font-size:12.5px;}
.df-tip{color:var(--df-muted);font-size:12.5px;line-height:1.6;margin-top:6px;}
/* 表单里没有输入框、只放一句话的行（比如「自营平台编辑」里的「前台页面」）：
   上下各留 9px、行高 20px，跟 .layui-form-label 的盒模型一模一样，
   这样这句话跟左边的标签在同一水平线上，不会比标签高出半行 */
.df-fi-plain{padding:9px 0;line-height:20px;color:var(--df-muted);font-size:13px;}

.layui-form-switch{margin-top:5px;border-color:#D8E0E6;}
.layui-form-onswitch{border-color:var(--df-accent);background-color:var(--df-accent);}
.layui-form-checked[lay-skin=primary] i{border-color:var(--df-accent)!important;background-color:var(--df-accent);}

/* 表格 ------------------------------------------------------------------ */
.layui-table-view{border:0;margin:0;}
.layui-table-header{background:#F7F9FB;}
.layui-table th{
  background:#F7F9FB!important;color:var(--df-text-2);font-weight:600;font-size:13px;
  border-color:var(--df-line-2)!important;
}
.layui-table td{border-color:var(--df-line-2)!important;font-size:13.5px;color:var(--df-text-2);}
.layui-table-cell{height:auto;line-height:30px;padding:0 14px;}
.layui-table-box .layui-table tbody tr:hover{background:#F6FAFB;}
.layui-table-view .layui-table[lay-even] tr:nth-child(even){background:#FCFDFE;}
.layui-table-page{border-top:1px solid var(--df-line-2);padding:12px 14px 6px;height:auto;}
.layui-laypage a,.layui-laypage span{height:30px;line-height:30px;border-radius:var(--df-radius);border-color:#DDE4EA;}
.layui-laypage .layui-laypage-curr .layui-laypage-em{background-color:var(--df-accent);border-radius:var(--df-radius);}
.layui-table-tool{border:0;background:#fff;padding:10px 14px;min-height:auto;}
.layui-none{color:var(--df-muted);padding:44px 0;font-size:13.5px;}
.layui-table-grid-down{border-color:var(--df-line-2);}

/* 自定义客服：左边名称、右边内容，两个框并排；窄屏放不下就上下排 */
.df-kf2{display:flex;gap:10px;}
.df-kf2 .layui-input{flex:1 1 0;min-width:0;}
.df-kf2 .layui-input:first-child{flex:0 0 34%;}
@media (max-width:575px){
  .df-kf2{flex-direction:column;gap:8px;}
  .df-kf2 .layui-input:first-child{flex:1 1 auto;}
}

/* 分页条左下角操作区（表格容器加 .df-page-left 生效）
   layui 的 pagebar 默认 float:right，这里改成 flex，按钮排最左，分页条靠右 */
.df-page-left .layui-table-page{display:flex;align-items:center;flex-wrap:wrap;gap:8px;}
.df-page-left .layui-table-page>div{height:auto;}
.df-page-left .layui-table-page .layui-table-pagebar{float:none;order:-1;margin-right:auto;line-height:30px;}
.df-page-left .layui-table-page .layui-table-pagebar .layui-btn{margin-top:0;}

/* 表内小元素 ------------------------------------------------------------ */
.df-dot{display:inline-flex;align-items:center;gap:6px;cursor:pointer;text-decoration:none;}
.df-dot:hover{opacity:0.8;}
.df-dot::before{content:"";width:6px;height:6px;border-radius:50%;background:#C3CED6;}
.df-dot.on::before{background:var(--df-ok);}
.df-dot.off::before{background:#C3CED6;}
.df-dot.warn::before{background:var(--df-warn);}
.df-dot.danger::before{background:var(--df-danger);}
/* 状态文字跟着圆点一起变色：st-on 绿色（正常），st-off 红色（停用） */
.df-dot.st-on{color:#0b8b16;}
.df-dot.st-on::before{background:#0b8b16;}
.df-dot.st-off{color:var(--df-danger);}
.df-dot.st-off::before{background:var(--df-danger);}

.df-tag{
  display:inline-block;padding:1px 8px;border-radius:2px;font-size:12px;line-height:19px;
  background:#EEF2F5;color:var(--df-text-2);
}
.df-tag.ok{background:#E7F3EE;color:var(--df-ok);}
.df-tag.warn{background:#FAF2E2;color:var(--df-warn);}
.df-tag.danger{background:#FBEAE7;color:var(--df-danger);}
.df-tag.info{background:var(--df-accent-soft);color:var(--df-accent);}
/* 可点的审核标签（商品列表「审核」列） */
.df-tag.g-audit{cursor:pointer;transition:opacity .15s;}
.df-tag.g-audit:hover{opacity:.78;}

/* 商品列表「状态」列：点一下切换上架 / 下架。上架绿色，下架灰色 */
.df-st-btn{
  display:inline-flex;align-items:center;
  padding:2px 10px;border:1px solid #DCE3E8;border-radius:11px;
  background:#F2F5F7;color:#7B838C;font-size:12px;line-height:18px;
  cursor:pointer;user-select:none;transition:.15s;
}
/* 状态两色已经够区分了，前面的小圆点去掉 */
.df-st-btn:hover{border-color:#C3CED6;color:#41525F;}
.df-st-btn.on{background:#E9F6EE;border-color:#B7E0C6;color:#0B8B16;}
.df-st-btn.on:hover{background:#DFF1E7;border-color:#9AD4AF;}

/* 商品审核：通过 / 驳回 + 驳回原因（列表弹窗和编辑弹窗共用一套） */
.df-audit-box{width:100%;}
.df-audit-btns{display:flex;gap:10px;flex-wrap:wrap;}
.df-audit-opt{
  display:inline-flex;align-items:center;gap:6px;
  padding:7px 20px;border:1px dashed #C3CED6;border-radius:4px;
  background:#fff;color:var(--df-muted);font-size:13px;line-height:19px;
  cursor:pointer;user-select:none;transition:.15s;
}
.df-audit-opt i{font-size:14px;}
.df-audit-opt:hover{border-color:var(--df-accent);color:var(--df-accent);}
.df-audit-opt.pass:hover{border-color:#12A83B;color:#0B8B16;}
.df-audit-opt.reject:hover{border-color:#D92E20;color:var(--df-danger);}
.df-audit-opt.pass.on{
  border-style:solid;border-color:#12A83B;background:#E9F6EE;
  color:#0B8B16;font-weight:600;
}
.df-audit-opt.reject.on{
  border-style:solid;border-color:#D92E20;background:#FDEDEC;
  color:var(--df-danger);font-weight:600;
}

/* 驳回原因框：只有选中「驳回」才滑出来 */
.df-audit-reason{
  display:none;margin-top:12px;padding:12px 14px;
  border:1px solid var(--df-line);border-radius:4px;background:#FAFCFD;
}
.df-audit-reason textarea{min-height:76px;font-size:13px;}
.df-audit-fast{
  display:flex;flex-wrap:wrap;align-items:center;gap:6px;
  margin-top:8px;font-size:12px;color:#8A97A3;
}
.df-audit-fast span{
  display:inline-block;padding:2px 9px;border:1px solid #DCE3E8;border-radius:11px;
  background:#fff;color:var(--df-muted);cursor:pointer;transition:.15s;
}
.df-audit-fast span:hover{border-color:var(--df-accent);color:var(--df-accent);}

/* 商品列表点「审核」弹出的小窗 */
.df-audit-pop{padding:16px 18px 6px;}
.df-audit-pop .ap-name{
  margin-bottom:12px;font-size:13px;color:var(--df-text-2);line-height:1.7;
}
.df-audit-pop .ap-name b{color:var(--df-text);}
.df-audit-pop .ap-foot{
  margin-top:14px;padding-top:12px;border-top:1px solid var(--df-line-2);text-align:right;
}
.df-audit-pop .ap-foot .layui-btn{margin-left:8px;}

.df-thumb{width:34px;height:34px;border-radius:2px;object-fit:cover;background:#EEF2F5;vertical-align:middle;}
.df-thumb-pv{cursor:zoom-in;}
.df-img-pv{position:fixed;z-index:99999;padding:5px;background:#fff;border:1px solid #D8E0E6;border-radius:4px;box-shadow:0 8px 26px rgba(31,45,61,.18);pointer-events:none;}
.df-img-pv-img{display:block;border-radius:2px;}
.df-img-pv-err{width:240px;padding:26px 18px;text-align:center;color:#E05E5E;font-size:14px;line-height:1.6;box-sizing:border-box;}
.df-img-pv-err span{display:block;margin-top:8px;color:#9AA7B2;font-size:12px;word-break:break-all;}
.df-num{font-variant-numeric:tabular-nums;}
.df-money{font-variant-numeric:tabular-nums;color:var(--df-danger);}
.df-mono{font-family:Consolas,Menlo,monospace;font-size:12.5px;}

.df-ops a{margin-right:12px;font-size:13px;}
.df-ops a:last-child{margin-right:0;}
.df-ops a.del{color:var(--df-danger);}
.df-ops a.del:hover{color:#C4432F;}

/* 订单列表：单号右边的复制图标 / 「有投诉」链接 -------------------------- */
.o-copy{
  display:inline-flex;align-items:center;margin-left:6px;vertical-align:-1px;
  color:#A7B5C0;transition:color .15s;
}
.o-copy:hover{color:var(--df-accent);}
.o-copy.copied{color:var(--df-ok);cursor:default;}
.o-complain.has{color:var(--df-danger);font-weight:600;text-decoration:underline dotted;}
.o-complain.has:hover{color:#C4432F;}

/* 投诉详情弹窗里的每一条投诉 ------------------------------------------- */
.df-cp-item{
  border:1px solid var(--df-line);border-radius:var(--df-radius);
  padding:13px 14px;margin-bottom:12px;background:#FBFCFD;
}
.df-cp-item:last-child{margin-bottom:0;}
.df-cp-hd{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-bottom:9px;}
.df-cp-lab{color:var(--df-muted);font-size:12.5px;}
.df-cp-row{
  display:flex;gap:10px;font-size:13px;color:var(--df-text-2);line-height:1.9;
}
.df-cp-row > span:first-child{
  width:66px;flex:0 0 66px;color:var(--df-muted);
}
.df-cp-block{margin-top:9px;}
.df-cp-block > span{display:block;color:var(--df-muted);font-size:12.5px;margin-bottom:4px;}
.df-cp-body{
  background:#fff;border:1px solid var(--df-line);border-radius:2px;padding:9px 11px;
  font-size:13.5px;line-height:1.85;color:var(--df-text);word-break:break-all;
  max-height:190px;overflow:auto;
}

/* 选项卡 ---------------------------------------------------------------- */
.layui-tab-title{border-bottom:1px solid var(--df-line);height:44px;}
.layui-tab-title li{
  height:44px;line-height:44px;font-size:13.5px;color:var(--df-text-2);min-width:auto;padding:0 17px;
  transition:color .15s;
}
.layui-tab-title li:hover{color:var(--df-accent);}
.layui-tab-title .layui-this{color:var(--df-accent);font-weight:600;}
.layui-tab-title .layui-this:after{border:0;border-bottom:2px solid var(--df-accent);height:44px;border-radius:0;}
.layui-tab-content{padding:20px 4px 4px;}
.df-tab-vertical{display:flex;gap:0;}
.df-tab-vertical .df-tab-nav{
  width:168px;flex:0 0 168px;border-right:1px solid var(--df-line);padding:8px 0;
}
.df-tab-vertical .df-tab-nav a{
  display:block;padding:0 16px;height:38px;line-height:38px;font-size:13.5px;
  color:var(--df-text-2);border-left:2px solid transparent;transition:all .15s;
}
.df-tab-vertical .df-tab-nav a:hover{background:#F7F9FB;color:var(--df-accent);}
.df-tab-vertical .df-tab-nav a.active{
  color:var(--df-accent);border-left-color:var(--df-accent);background:var(--df-accent-soft);font-weight:600;
}
.df-tab-vertical .df-tab-panes{flex:1;min-width:0;padding:20px 22px;}
.df-pane{display:none;animation:df-fade .22s ease;}
.df-pane.active{display:block;}
@keyframes df-fade{from{opacity:0;transform:translateY(4px);}to{opacity:1;transform:none;}}

.df-sub-title{
  font-size:13px;color:var(--df-muted);font-weight:600;letter-spacing:.4px;
  padding:4px 0 12px;margin:14px 0 12px;border-bottom:1px dashed var(--df-line);
}
.df-sub-title:first-child{margin-top:0;}

/* 模板选项里的单选按钮组（取代原来的下拉框）：
   每个候选值一颗虚线边框的按钮，选中后变主题色实线 + 淡底 */
.df-radio-group{display:flex;flex-wrap:wrap;gap:8px;padding-top:2px;}
.df-radio{
  position:relative;display:inline-flex;align-items:center;justify-content:center;gap:6px;
  min-width:62px;height:34px;padding:0 14px;box-sizing:border-box;
  border:1px dashed #C6D0D9;border-radius:var(--df-radius,3px);
  background:#fff;color:var(--df-text-2,#41525F);font-size:13px;line-height:1;
  cursor:pointer;user-select:none;transition:all .16s;
}
/* 按钮里那颗小圆点：没选中是空心灰圈，选中了变主题色圈 + 中间实心
   （不用浏览器自带的 radio —— 它又大又各浏览器长得不一样，还容易被 layui 藏掉） */
.df-radio-dot{
  flex:none;width:12px;height:12px;box-sizing:border-box;border-radius:50%;
  border:1px solid #B9C4CE;background:#fff;transition:all .16s;
}
.df-radio:hover .df-radio-dot{border-color:var(--df-accent);}
.df-radio.on .df-radio-dot{
  border-color:var(--df-accent);background:var(--df-accent);
  box-shadow:inset 0 0 0 2px #fff;              /* 描边留白，中间留出一颗实心 */
}
/*
 * 真正的单选框不当外观用，只当「点击靶子」：透明铺满整颗按钮，
 * 点文字、点边框、点留白都落在它身上，浏览器自己就会勾上。
 * 不能让它 display:none —— layui 有一条
 *   .layui-form input[type=radio]{display:none}
 * 权重压过了 .df-radio input，一旦被藏掉，点文字就成了点空气。
 * 所以这里把权重抬上去再显式 display:block 顶回来；
 * 就算哪天 CSS 没加载上，页面里的 JS 也会手动勾中它，不会失灵。
 */
.df-radio > input[type=radio],
.layui-form .df-radio input[type=radio]{
  display:block;position:absolute;left:0;top:0;width:100%;height:100%;
  margin:0;padding:0;border:0;appearance:none;-webkit-appearance:none;
  background:transparent;opacity:0;cursor:pointer;
}
/* 键盘 Tab 过来时给个看得见的框，别让人找不到焦点在哪 */
.df-radio:focus-within{box-shadow:0 0 0 2px rgba(43,108,255,.18);}
/* 保险：万一还有 layui 生成的那颗大圆点（layui-form-radio）残留，直接抹掉，
   只留我们自己这颗 12px 的小圆点 */
.df-radio .layui-form-radio{display:none !important;}
.df-radio:hover{border-color:var(--df-accent);color:var(--df-accent);}
.df-radio.on{
  border-style:solid;border-color:var(--df-accent);
  background:#EEF4FF;color:var(--df-accent);font-weight:600;
}
.df-radio.on:hover{color:var(--df-accent);}

/* 弹层 ------------------------------------------------------------------ */

/*
 * TinyMCE 的浮动层（下拉菜单、插图/链接对话框、全屏）是挂在 body 上的，
 * 它自己的 z-index 只有 1100 上下，而 layui 弹窗是从 19891014 起跳的，
 * 不抬上去的话编辑器在弹窗里一点菜单就被弹窗盖住，看着像没反应。
 * 这里统一抬到比 layui 更高的一层。
 */
.tox.tox-tinymce-aux{z-index:198910150 !important;}
.tox .tox-dialog-wrap{z-index:198910151 !important;}
.tox.tox-fullscreen{z-index:198910152 !important;}

/* 表单里的编辑器：跟下面的提示文字留点距离 */
.layui-form-item .tox-tinymce{margin-bottom:2px;}

.layui-layer{border-radius:4px;box-shadow:0 6px 32px rgba(12,26,38,.14);}
.layui-layer-title{
  height:50px;line-height:50px;background:#fff;border-bottom:1px solid var(--df-line-2);
  color:var(--df-text);font-size:14.5px;font-weight:600;padding:0 20px;border-radius:4px 4px 0 0;
}
.layui-layer-setwin{top:17px;right:18px;}
.layui-layer-btn{
  padding:12px 18px;border-top:1px solid var(--df-line-2);text-align:right;background:#FCFDFE;
}
.layui-layer-btn a{
  height:32px;line-height:30px;border-radius:var(--df-radius);font-size:13.5px;padding:0 16px;
  margin-left:8px;border:1px solid #D6DEE4;background:#fff;color:var(--df-text-2);
}
.layui-layer-btn .layui-layer-btn0{
  background:var(--df-accent);border-color:var(--df-accent);color:#fff;
}
.layui-layer-btn .layui-layer-btn0:hover{background:var(--df-accent-2);border-color:var(--df-accent-2);}
/*
 * 对话框（alert / confirm，以及带图标的 layer.msg）统一白底深字。
 *
 * 要排除 .layui-layer-hui：layer.msg 不带图标时用的是 layui 的深色胶囊皮肤
 * （背景 rgba(0,0,0,.6)），这里再套上深灰文字就成了“深底 + 深字”，看不见。
 */
.layui-layer-dialog:not(.layui-layer-hui) .layui-layer-content{
  padding:24px 20px 22px 20px;font-size:14px;line-height:1.7;color:var(--df-text-2);
}

/*
 * 带图标的提示框（layer.msg 的 icon:1 成功 / icon:2 失败 那种）。
 *
 * layui 用 .layui-layer-padding 给内容留 55px 左边距放图标，
 * 但上面那条规则的 padding 把它覆盖掉了，图标就直接压在文字上。
 * 这里把左边距补回来，并让图标垂直居中。
 */
.layui-layer-dialog .layui-layer-content.layui-layer-padding{
    padding:22px 26px 22px 62px;
    min-height:34px;
}

/*
 * 图标元素。
 * 这个 layui 版本用的是 .layui-layer-face（字体图标 layui-icon-success 之类），
 * 老版本用 .layui-layer-ico（雪碧图），两个都覆盖上，换版本也不会跑掉。
 *
 * 关键是 line-height 要等于 height：字体图标默认继承外层的 line-height:1.7，
 * 撑出来的行高比图标本身高，视觉上就是"图标往下掉了一点"。
 */
.layui-layer-dialog .layui-layer-content .layui-layer-face,
.layui-layer-dialog .layui-layer-content .layui-layer-ico{
    position:absolute;
    left:20px;
    top:50%;
    width:30px;
    height:30px;
    margin-top:-15px;
    line-height:30px;
    font-size:30px;
    text-align:center;
    display:block;
}
.layui-layer-page .layui-layer-content{padding:0;overflow:visible;}
.layui-layer-msg{border-radius:4px;}

/*
 * 中性提示（DF.tip，例如点“刷新”后的“已刷新”）。
 *
 * 跟成功 / 失败提示保持同一套外观：白底、浅边框、深字、同一个阴影和圆角。
 * admin.js 里通过 skin: 'df-layer-tip' 挂上，并在文字前拼一个 <i class="layui-icon ...">，
 * 这里给它留出左边的位置，让图标和成功/失败提示的图标落在同一条竖线上。
 */
.layui-layer.df-layer-tip{
  background:#fff;border:1px solid var(--df-line);box-shadow:0 6px 24px rgba(12,26,38,.14);
}
.layui-layer.df-layer-tip .layui-layer-content{
  padding:22px 26px 22px 62px;min-height:34px;text-align:left;
  font-size:14px;line-height:1.7;color:var(--df-text-2);
}
/* 图标绝对定位后就不占文字流了，所以左边距靠上面的 padding 撑开 */
.layui-layer.df-layer-tip .layui-layer-content .layui-icon{
  position:absolute;left:20px;top:50%;width:30px;height:30px;margin-top:-15px;
  line-height:30px;font-size:30px;text-align:center;display:block;
  color:var(--df-accent);
}
.df-layer-form .layui-form-item:last-child{margin-bottom:0;}

/* 库存告急右下角弹窗 ---------------------------------------------------- */
.df-stock-pop{
  position:fixed;right:20px;bottom:20px;width:300px;z-index:1200;
  background:#fff;border:1px solid var(--df-line);border-radius:4px;
  box-shadow:0 6px 26px rgba(12,26,38,.13);overflow:hidden;
  transform:translateY(16px);opacity:0;pointer-events:none;
  transition:transform .28s cubic-bezier(.4,0,.2,1),opacity .28s;
}
.df-stock-pop.show{transform:none;opacity:1;pointer-events:auto;}
.df-stock-pop .hd{
  height:42px;padding:0 12px;display:flex;align-items:center;gap:7px;
  border-bottom:1px solid var(--df-line-2);font-size:13.5px;font-weight:600;color:var(--df-danger);
}
.df-stock-pop .hd i{font-size:15px;}
.df-stock-pop .hd .close{margin-left:auto;color:#A7B5C0;cursor:pointer;font-size:14px;}
.df-stock-pop .hd .close:hover{color:var(--df-text);}
.df-stock-pop .bd{max-height:210px;overflow-y:auto;padding:4px 0;}
.df-stock-pop .row{
  display:flex;align-items:center;gap:8px;padding:7px 12px;font-size:13px;
}
.df-stock-pop .row:hover{background:#F7F9FB;}
.df-stock-pop a.row{text-decoration:none;color:inherit;cursor:pointer;}
.df-stock-pop .row .n{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--df-text-2);}
.df-stock-pop .row .s{color:var(--df-danger);font-variant-numeric:tabular-nums;}
.df-stock-pop .row .go{color:var(--df-accent);font-size:12px;flex:0 0 auto;}
.df-stock-pop .ft{padding:9px 12px;border-top:1px solid var(--df-line-2);text-align:right;}

/* 登录页 ---------------------------------------------------------------- */
.df-login-wrap{
  min-height:100vh;display:flex;align-items:center;justify-content:center;
  /* 只放底色，背景图单独做一层（见 ::after），这样才能整体调透明度 */
  background:var(--df-dark);
  position:relative;overflow:hidden;padding:20px;
}
/* 背景图独立一层：opacity 只作用于这一层，不会把登录卡片一起弄透明。
   原图 2560x109，缩到一半（1280x55）平铺；嫌大就调小 1280px，想更淡就调小 0.7 */
.df-login-wrap::after{
  content:"";position:absolute;inset:0;z-index:0;pointer-events:none;
  background:url(../images/bg.png) repeat left top;
  background-size:1280px auto;
  opacity:.5;
}
/* 层级：背景图 0 < 光晕 1 < 登录卡片 2 */
.df-login-wrap::before{
  content:"";position:absolute;inset:0;z-index:1;pointer-events:none;
  background:radial-gradient(900px 500px at 72% 18%,rgba(30,111,140,.30),transparent 62%);
}
.df-login-box{
  position:relative;z-index:2;width:376px;max-width:100%;background:#fff;border-radius:5px;
  padding:34px 34px 28px;box-shadow:0 18px 60px rgba(0,0,0,.28);
  animation:df-rise .4s cubic-bezier(.2,.7,.3,1);
}
@keyframes df-rise{from{opacity:0;transform:translateY(16px);}to{opacity:1;transform:none;}}
/* 标题两行都居中，图标已去掉 */
.df-login-box h1{
  margin:0 0 4px;font-size:19px;font-weight:600;text-align:center;
}
.df-login-box .sub{color:var(--df-muted);font-size:13px;margin-bottom:24px;text-align:center;}
.df-login-box .layui-form-item{margin-bottom:15px;}
.df-login-box .layui-input{height:42px;line-height:42px;padding-left:38px;}
.df-login-field{position:relative;}
.df-login-field > i{
  position:absolute;left:13px;top:50%;transform:translateY(-50%);
  color:#A7B5C0;font-size:15px;z-index:1;
}
.df-login-cap{display:flex;gap:10px;}
.df-login-cap .layui-input{flex:1;}
/* 验证码那一格：输入框外面多套了一层放图标，flex 要让这层撑开、输入框铺满 */
.df-login-cap .df-login-cap-in{position:relative;flex:1;min-width:0;}
.df-login-cap .df-login-cap-in .layui-input{width:100%;padding-left:38px;}
.df-login-cap img{
  width:112px;height:42px;border:1px solid #D8E0E6;border-radius:var(--df-radius);
  cursor:pointer;background:#F7F9FB;flex:0 0 auto;
}
.df-login-btn{width:100%;height:42px;line-height:40px;font-size:14.5px;margin-top:6px;}
.df-login-foot{margin-top:20px;text-align:center;color:#9AAAB6;font-size:12px;}
.df-login-foot a{color:#9AAAB6;text-decoration:none;transition:color .18s;}
.df-login-foot a:hover{color:var(--df-accent);}
.df-login-err{
  background:#FBEAE7;color:var(--df-danger);border-radius:var(--df-radius);
  padding:9px 12px;font-size:13px;margin-bottom:14px;display:none;
}

/* 上传 ------------------------------------------------------------------ */
.df-upload{display:flex;align-items:center;gap:12px;}
.df-upload .pv{
  width:74px;height:74px;border:1px dashed #D2DBE2;border-radius:var(--df-radius);
  display:flex;align-items:center;justify-content:center;background:#FAFCFD;
  overflow:hidden;cursor:pointer;transition:border-color .16s;flex:0 0 auto;
}
.df-upload .pv:hover{border-color:var(--df-accent);}
.df-upload .pv img{width:100%;height:100%;object-fit:cover;}
.df-upload .pv i{color:#B7C4CD;font-size:20px;}

/* 实名资料弹窗里的证件照：预览别占满弹窗，能看清又不撑高弹窗 */
.u-idc-pics{display:flex;gap:16px;flex-wrap:wrap;}
.u-idc-pic .u-idc-t{font-size:12.5px;color:#64778A;margin-bottom:6px;}
/* 说明文字放在预览图下面，横着放会被挤成两行、跟上传框抢宽度 */
.u-idc-pic .df-upload{flex-direction:column;align-items:flex-start;gap:6px;}
.u-idc-pic .pv{width:170px;height:108px;background:#F4F7F9;}
.u-idc-pic .pv img{object-fit:contain;}
.u-idc-pic .u-idc-tip{font-size:12px;color:#8A9099;line-height:1.7;}

/* 空态与加载 ------------------------------------------------------------ */
.df-empty{padding:52px 0;text-align:center;color:var(--df-muted);}
.df-empty i{font-size:36px;color:#CBD6DE;display:block;margin-bottom:10px;}
.df-loading{padding:44px 0;text-align:center;color:var(--df-muted);font-size:13px;}

/* JSON 编辑器 ----------------------------------------------------------- */
.df-json{
  width:100%;min-height:360px;font-family:Consolas,Menlo,monospace;font-size:13px;
  line-height:1.75;padding:14px;border:1px solid #D8E0E6;border-radius:var(--df-radius);
  resize:vertical;color:#26333F;background:#FCFDFE;
}
.df-json:focus{border-color:var(--df-accent);outline:none;box-shadow:0 0 0 2px rgba(30,111,140,.10);}

/* 遮罩(移动端菜单) ------------------------------------------------------ */
.df-mask{
  position:fixed;inset:0;background:rgba(12,26,38,.42);z-index:998;
  opacity:0;pointer-events:none;transition:opacity .22s;
}
body.df-side-open .df-mask{opacity:1;pointer-events:auto;}

/* ==========================================================================
   三端自适应
   ========================================================================== */
@media (max-width:1400px){
  .df-stats{grid-template-columns:repeat(3,minmax(0,1fr));}
}
@media (max-width:1023px){      /* 平板 */
  .df-stats{grid-template-columns:repeat(3,minmax(0,1fr));gap:12px;}
  .df-body{padding:16px 16px 26px;}
  .df-logo{width:var(--df-side-fold);padding-left:0;justify-content:center;}
  .df-logo span{display:none;}
  .df-side{width:var(--df-side-w);transform:translateX(-100%);}
  body.df-side-open .df-side{transform:none;}
  .df-main{margin-left:0;}
  body.df-fold .df-main{margin-left:0;}
}
@media (max-width:767px){       /* 手机 */
  .df-stats{grid-template-columns:repeat(2,minmax(0,1fr));gap:10px;}
  .df-stat{padding:13px 13px 11px;}
  .df-stat .df-stat-v{font-size:21px;}
  .df-body{padding:12px 12px 24px;}
  .df-card-hd{height:auto;padding:12px;flex-wrap:wrap;}
  .df-card-hd .df-hd-right{margin-left:0;width:100%;}
  .df-card-bd{padding:12px;}
  .df-filter{padding:12px;}
  .df-filter .df-f-item{width:100%;}
  .df-filter .df-f-item .layui-input{width:100%;}
  .df-filter .df-f-tail{margin-left:0;width:100%;}
  .df-filter .df-f-tail .layui-btn{flex:1;}
  .df-head-right .df-hbtn span{display:none;}
  .df-tab-vertical{display:block;}
  .df-tab-vertical .df-tab-nav{
    width:100%;flex:none;border-right:0;border-bottom:1px solid var(--df-line);
    display:flex;overflow-x:auto;padding:0;
  }
  .df-tab-vertical .df-tab-nav a{
    border-left:0;border-bottom:2px solid transparent;white-space:nowrap;padding:0 14px;
  }
  .df-tab-vertical .df-tab-nav a.active{border-left:0;border-bottom-color:var(--df-accent);background:transparent;}
  .df-tab-vertical .df-tab-panes{padding:16px 12px;}
  .layui-form-label{width:auto;float:none;display:block;text-align:left;padding:0 0 6px;}
  .layui-input-block{margin-left:0;}
  .df-stock-pop{left:12px;right:12px;width:auto;bottom:12px;}
  /* 手机上菜单抽屉打开时先把库存弹窗让开 */
  body.df-side-open .df-stock-pop{opacity:0;pointer-events:none;}
}

/* 打印 ------------------------------------------------------------------ */
@media print{
  .df-header,.df-side,.df-filter,.df-ops,.layui-table-tool{display:none!important;}
  .df-main{margin:0;padding:0;}
}

/* =========================================================================
 * 弹窗自适应
 *
 * 各页面调 layer.open 时写的都是固定像素宽度，手机上会撑出屏幕。
 * admin.js 里已经把宽度夹到屏幕以内了，这里补两件事：
 *   1. 内容太长时在弹窗内部滚动，不要把弹窗顶出可视区
 *   2. 窄屏下表单标签和输入框改成上下排，横排在 375px 宽的手机上挤不下
 * ====================================================================== */

.layui-layer{
    max-width:calc(100vw - 24px) !important;
    border-radius:6px;
}

/*
 * 弹窗内容超长就自己滚，别把按钮顶到屏幕外面去。
 *
 * 注意这里排除了 msg / dialog / loading / tips 这几类提示框：
 * 它们的高度本来就由内容撑开，套上 max-height + overflow 之后
 * 右侧会冒出滚动条，左边的图标（icon:1/2 那个圆圈）也会被挤错位。
 */
/*
 * 滚动交给我们自己的内层容器，不要动 layui 的 .layui-layer-content。
 *
 * 动它的话会跟 layui 自己算的 inline height 打架，出现双滚动条；
 * 而且用 JS 算高度在手机上会被输入法坑（键盘一弹 innerHeight 骤降）。
 * CSS 的 vh 是按初始视口算的，键盘弹出不影响，所以限高放在这里最稳。
 */
.df-layer-form,
.df-layer-scroll{
    max-height:68vh;
    overflow-y:auto;
    overflow-x:hidden;
    -webkit-overflow-scrolling:touch;   /* iOS 上滚动跟手 */
}
.df-layer-scroll{padding:18px 20px;}

/* 提示框保持 layui 原样：不限高、不滚动，图标才不会跑位 */
.layui-layer-dialog .layui-layer-content,
.layui-layer-msg .layui-layer-content,
.layui-layer-loading .layui-layer-content,
.layui-layer-tips .layui-layer-content{
    max-height:none !important;
    overflow:visible !important;
}

/* 弹窗里的表单留点内边距，贴边很难点 */
.df-layer-form{padding:18px 20px 4px;}

/* 弹窗里的长内容（卡密、JSON、报文）不要横向撑破 */
.layui-layer-content pre,
.layui-layer-content .df-mono,
.layui-layer-content textarea{
    max-width:100%;
    white-space:pre-wrap;
    word-break:break-all;
}
.layui-layer-content table{width:100% !important;}

/* iframe 型弹窗（商品编辑那种） */
.layui-layer-iframe{max-height:92vh !important;}
.layui-layer-iframe iframe{max-height:92vh;}

/* ---------- 平板 ---------- */
@media (max-width:1023px){
    .df-layer-form,
    .df-layer-scroll{max-height:64vh;}
}

/* ---------- 手机 ---------- */
@media (max-width:767px){
    .layui-layer{
        max-width:calc(100vw - 16px) !important;
        border-radius:8px;
    }
    .df-layer-form,
    .df-layer-scroll{max-height:60vh;}

    .df-layer-form{padding:14px 14px 2px;}

    /* 标签和输入框改成上下排。横排在窄屏上标签占掉一半宽度，输入框就没法用了 */
    .df-layer-form .layui-form-item{margin-bottom:14px;}
    .df-layer-form .layui-form-label{
        position:static;
        float:none;
        display:block;
        width:auto !important;
        padding:0 0 6px;
        text-align:left;
        font-size:13.5px;
        color:#41525F;
        line-height:1.6;
    }
    .df-layer-form .layui-input-block,
    .df-layer-form .layui-input-inline{
        margin-left:0 !important;
        width:100% !important;
        display:block;
        float:none;
    }
    .df-layer-form .layui-input-inline + .layui-input-inline{margin-top:8px;}
    .df-layer-form .layui-form-mid{
        display:block;
        float:none;
        padding:6px 0 0;
        line-height:1.6;
        font-size:12.5px;
        color:#64778A;
    }
    /* 弹窗里那些写死宽度的输入框（style="max-width:200px" 之类）也放开 */
    .df-layer-form .layui-input,
    .df-layer-form .layui-textarea,
    .df-layer-form .layui-select,
    .df-layer-form select{max-width:100% !important;}

    /* 底部按钮加大，手指点得中 */
    .layui-layer-btn{padding:10px 14px 14px;text-align:right;}
    .layui-layer-btn a{
        height:36px;
        line-height:36px;
        padding:0 18px;
        font-size:14px;
        margin-left:8px;
    }

    /* 弹窗里的表格横向可滚，不要撑破弹窗 */
    .layui-layer-content .layui-table-view,
    .layui-layer-content .layui-table-box{overflow-x:auto;}

    /* 权限勾选树、规格编辑这类多列布局，窄屏下改单列 */
    .layui-layer-content .sku-row{flex-wrap:wrap;}
    .layui-layer-content .sku-row .col,
    .layui-layer-content .sku-row .col.sm,
    .layui-layer-content .sku-row .col.xs{flex:1 1 46%;min-width:0;}
}

/* ---------- 很窄的屏（iPhone SE 之类） ---------- */
@media (max-width:400px){
    .layui-layer{max-width:calc(100vw - 10px) !important;}
    .df-layer-form,
    .df-layer-scroll{max-height:56vh;}
    .layui-layer-title{font-size:14.5px;padding:0 50px 0 14px;}
    .df-layer-form{padding:12px 12px 2px;}
}

/* 库存告急浮窗：小屏上别占满宽度、别挡住表格右侧的操作列 */
@media (max-width:767px){
    .df-stock-pop{
        left:10px;
        right:10px;
        bottom:10px;
        width:auto !important;
        max-width:none;
        max-height:44vh;
        overflow-y:auto;
    }
}


/* 提示框（layer.msg / alert）保持 layui 原样的自适应宽度 */
.layui-layer-dialog,
.layui-layer-msg,
.layui-layer-loading,
.layui-layer-tips{
    max-width:calc(100vw - 32px) !important;
    min-width:0;
}
.layui-layer-msg .layui-layer-content,
.layui-layer-dialog .layui-layer-content{
    word-break:break-word;
}

/* ---------- 长任务等待层（备份 / 恢复）：转圈图标 + 下方文字 ---------- */
.df-busy-layer{
    background:transparent;
    box-shadow:none;
    border-radius:10px;
}
.df-busy-layer .layui-layer-content{
    background:#fff;
    border-radius:10px;
    box-shadow:0 8px 30px rgba(0,0,0,.22);
    overflow:hidden;
}
/* admin.js 会给内容自动套一层 .df-layer-scroll，这里不需要它的内边距和滚动 */
.df-busy-layer .df-layer-scroll{
    padding:0;
    max-height:none;
    overflow:visible;
}
.df-busy{
    padding:26px 30px 22px;
    text-align:center;
    min-width:200px;
}
.df-busy .layui-icon{
    display:inline-block;
    font-size:34px;
    line-height:1;
    color:#1E6F8C;
}
.df-busy .df-busy-tip{
    margin-top:13px;
    font-size:13.5px;
    line-height:1.7;
    color:#4A5A6A;
}

/*
 * 手机键盘弹出时的弹窗形态。
 * 键盘占掉大半屏幕，弹窗改成贴顶显示、内容区压缩，
 * 这样标题和正在输入的那个框还在视野里。
 */
.layui-layer-page.df-kb-open{
    top:8px !important;
}
.layui-layer-page.df-kb-open .df-layer-form,
.layui-layer-page.df-kb-open .df-layer-scroll{
    max-height:38vh;
}

/* 键盘态下让弹窗高度重新由内容决定，否则 layui 写在行内的固定高度会让它压不下来 */
.layui-layer-page.df-kb-open{height:auto !important;}
.layui-layer-page.df-kb-open > .layui-layer-content{height:auto !important;}

/* =========================================================================
 * 控制台的统计卡片与图表
 * ====================================================================== */

.df-stats-4{grid-template-columns:repeat(4,minmax(0,1fr));}

/* 统计卡列数变体：页面按卡片实际数量挂 df-stats-3/4/5。
   卡片视觉（色条/图标色/圆角/阴影）统一走基础 .df-stat，不再按列数重复。 */
.df-stats-3{grid-template-columns:repeat(3,minmax(0,1fr));}
.df-stats-5{grid-template-columns:repeat(5,minmax(0,1fr));gap:12px;}
@media (max-width:680px){
  /* 5 卡极窄屏依然不换行：横向滑动卡条，单卡固定紧凑宽度，露出半截暗示可滑 */
  .df-stats-5{
    display:flex;flex-wrap:nowrap;overflow-x:auto;
    margin-bottom:12px;padding-bottom:2px;gap:8px;
    -webkit-overflow-scrolling:touch;scrollbar-width:none;
  }
  .df-stats-5::-webkit-scrollbar{display:none;}
  .df-stats-5 .df-stat{flex:0 0 108px;padding:11px 12px 10px 14px;}
  .df-stats-5 .df-stat .df-stat-v{font-size:19px;}
}

.df-grid-2{
    display:grid;
    grid-template-columns:1fr 1fr;
    gap:16px;
    margin-bottom:16px;
}
.df-grid-2 > .df-card{margin-bottom:0;}

.df-chart{min-height:250px;}
/* 明确给高度，只写 max-height 的话 SVG 会按自身比例缩成一小块，容器两边空一大片 */
.df-svg{width:100%;height:230px;display:block;}

/* 趋势图图例 */
.df-legend{
    display:flex;gap:20px;justify-content:center;
    margin-top:6px;font-size:12.5px;color:#64778A;
}
.df-legend i{
    display:inline-block;width:11px;height:11px;border-radius:2px;
    margin-right:5px;vertical-align:-1px;
}

/* 环形图 */
.df-pie-wrap{display:flex;align-items:center;gap:18px;width:100%;flex-wrap:wrap;}
.df-pie{width:200px;height:200px;flex:0 0 200px;}
.df-pie-legend{flex:1;min-width:170px;font-size:13px;}
.df-pie-legend > div{
    display:flex;align-items:center;gap:8px;
    padding:6px 0;border-bottom:1px dashed #EEF2F5;
}
.df-pie-legend > div:last-child{border-bottom:0;}
.df-pie-legend i{
    display:inline-block;width:11px;height:11px;border-radius:2px;flex:0 0 11px;
}
.df-pie-legend .n{flex:1;color:#41525F;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.df-pie-legend .v{font-weight:600;color:#1B2733;}
.df-pie-legend .c{color:#A7B5C0;font-size:12px;width:52px;text-align:right;}

@media (max-width:1200px){
    .df-stats-4{grid-template-columns:repeat(2,minmax(0,1fr));}
}
@media (max-width:1023px){
    .df-grid-2{grid-template-columns:1fr;}
    .df-pie-wrap{justify-content:center;}
}
@media (max-width:640px){
    .df-stats-4{grid-template-columns:1fr;}
    .df-chart{min-height:200px;}
    .df-pie{width:170px;height:170px;flex:0 0 170px;}
    .df-pie-legend{min-width:100%;}
}

/* ==========================================================================
 * 主题设置 · 导航菜单编辑器
 * 一棵看得见的两级菜单：卡片加、改、删、排序，数据写回隐藏域。
 * ======================================================================== */
.df-nav-builder{
    display:flex;flex-wrap:wrap;gap:14px;
    padding:14px;border:1px solid #E4EAEF;border-radius:10px;background:#FBFCFD;
}
.df-nav-builder .df-nav-empty{color:#9AA8B4;font-size:13px;}

.df-nav-col{
    /* 一列一个一级菜单，宽度给够（至少 400px），不然菜单名和链接挤在一起看不清 */
    flex:1 1 400px;max-width:100%;min-width:400px;
    border:1px solid #E1E8EE;border-radius:9px;background:#FFFFFF;overflow:hidden;
}
.df-nav-item{
    display:flex;align-items:center;gap:10px;
    padding:9px 12px;border-bottom:1px solid #F0F3F6;
}
.df-nav-item:last-child{border-bottom:0;}
.df-nav-item-top{background:#F7FAFD;}
.df-nav-item-sub{padding-left:14px;background:#FFFFFF;}

.df-nav-title{
    flex:1;min-width:0;display:flex;align-items:center;gap:8px;
    font-size:14px;color:#2C3A47;
}
.df-nav-title b{font-weight:600;}
.df-nav-title span{color:#5A6B7A;}
.df-nav-title i{color:#7A8A99;font-size:15px;flex:0 0 auto;}
.df-nav-title code{
    flex:0 0 auto;max-width:170px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
    padding:1px 6px;border-radius:4px;background:#F1F4F7;color:#8494A4;
    font-family:Consolas,Menlo,monospace;font-size:12px;
}
.df-nav-tag{
    flex:0 0 auto;padding:1px 6px;border-radius:3px;background:#EAF2FF;color:#2F6BFF;font-size:11px;font-style:normal;
}
.df-nav-sort{
    flex:0 0 54px;width:54px;height:28px;padding:0 6px;
    border:1px solid #DFE6EC;border-radius:5px;background:#FFFFFF;
    color:#5A6B7A;font-size:12px;text-align:center;
}
.df-nav-ops{flex:0 0 auto;display:flex;gap:6px;}
.df-nav-btn{
    height:28px;padding:0 10px;border:1px solid #DFE6EC;border-radius:5px;
    background:#FFFFFF;color:#5A6B7A;font-size:12.5px;cursor:pointer;transition:.15s;
}
.df-nav-btn:hover{color:#1B6BFF;border-color:#9CBEFF;background:#F5F9FF;}
.df-nav-btn.del:hover{color:#D23B2E;border-color:#F3ABA3;background:#FFF5F4;}

.df-nav-add{
    flex:0 0 auto;align-self:stretch;min-height:82px;
    display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;
    padding:0 18px;border:1.5px dashed #BFCEDC;border-radius:9px;
    color:#7A8A99;font-size:13px;cursor:pointer;transition:.15s;
}
.df-nav-add:hover{border-color:#2F6BFF;color:#2F6BFF;background:#F5F9FF;}

/* 弹窗：只在主题设置页用，输入框不带 name，不会被表单收集到 */
.df-modal{position:fixed;inset:0;z-index:9999;display:flex;align-items:center;justify-content:center;}
.df-modal[hidden]{display:none;}
.df-modal-mask{position:absolute;inset:0;background:rgba(15,30,45,.42);}
.df-modal-box{
    position:relative;width:calc(100% - 40px);max-width:460px;
    background:#FFFFFF;border-radius:12px;box-shadow:0 20px 60px rgba(15,30,45,.25);overflow:hidden;
}
.df-modal-hd{
    display:flex;align-items:center;padding:15px 18px;border-bottom:1px solid #EDF1F5;font-size:15.5px;
}
.df-modal-hd b{flex:1;}
.df-modal-x{font-size:22px;line-height:1;color:#9AA8B4;cursor:pointer;padding:0 4px;}
.df-modal-x:hover{color:#41525F;}
.df-modal-bd{padding:16px 18px;max-height:64vh;overflow-y:auto;}
.df-modal-ft{padding:0 18px 18px;text-align:right;}
.df-modal-ft .layui-btn{margin-left:8px;}
.df-fr{margin-bottom:12px;}
.df-fr:last-child{margin-bottom:0;}
.df-fr > label{display:block;margin-bottom:6px;color:#5A6B7A;font-size:13px;}
.df-fr .layui-input{width:100%;}
.df-fr .df-tip{margin-top:6px;}

/* ==========================================================================
 * 主题设置 · 移动底部菜单
 * 顶部导航那套的基础上多一个图标，卡排得更窄一点（一行能塞两三个）
 * ======================================================================== */
.df-nav-builder-tab{padding:12px;}
.df-nav-builder-tab .df-nav-col{flex:1 1 280px;min-width:280px;}

.df-tab-ico{
    flex:0 0 auto;width:26px;height:26px;border-radius:6px;background:#F1F4F7;
    display:inline-flex;align-items:center;justify-content:center;
    color:#41525F;font-size:17px;
}
.df-tab-ico.none{color:#B6C4CE;font-size:15px;}
.df-tab-ico.big{width:38px;height:38px;background:#FFFFFF;border:1px solid #DFE6EC;border-radius:8px;font-size:22px;}

.df-tab-pick{display:flex;align-items:center;gap:8px;}
.df-tab-pick .layui-btn{flex:0 0 auto;}
/* 输入框排在按钮后面，撑满剩下的宽度 */
.df-tab-pick .layui-input{flex:1 1 auto;min-width:0;max-width:none;}

/* 图标选择窗：宽一点能多排几个 */
.df-modal-wide{max-width:720px;}
/* 顶上的两栏切换（字体图标 / 矢量图标）。
   之前这两个 button 一个样式都没有，是浏览器裸按钮，点了连"当前在哪一栏"都看不出来，
   用起来就像点了没反应——这里补成胶囊标签的样子。 */
.df-icon-tabs{display:flex;gap:8px;margin-bottom:10px;}
.df-icon-tabs button{
    -webkit-appearance:none;appearance:none;cursor:pointer;
    padding:7px 16px;border:1px solid #DFE6EC;border-radius:20px;background:#FFFFFF;
    color:#5A6B7B;font-size:13px;line-height:1;transition:.15s;
}
.df-icon-tabs button:hover{border-color:#2F6BFF;color:#1B6BFF;}
.df-icon-tabs button.on{
    border-color:#2F6BFF;background:#2F6BFF;color:#FFFFFF;font-weight:600;
    box-shadow:0 4px 10px rgba(47,107,255,.22);
}
.df-icon-grid{
    display:grid;grid-template-columns:repeat(auto-fill,minmax(74px,1fr));
    gap:8px;margin-top:12px;
}
.df-icon-cell{
    display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;
    height:72px;padding:6px 4px;border:1px solid #E6ECF1;border-radius:8px;background:#FFFFFF;
    cursor:pointer;overflow:hidden;transition:.15s;
}
/* 当前选中的那个：编辑框里已经有图标时，一眼能看出选的是哪一格 */
.df-icon-cell.on{border-color:#2F6BFF;background:#F5F9FF;box-shadow:0 0 0 2px rgba(47,107,255,.12) inset;}
.df-icon-cell.on i.df-i,.df-icon-cell.on svg.ico-svg{color:#1B6BFF;}
.df-icon-cell:hover{border-color:#2F6BFF;background:#F5F9FF;}
.df-icon-cell i.df-i{font-size:22px;color:#2C3A47;line-height:1;}
.df-icon-cell:hover i.df-i{color:#1B6BFF;}
/* 矢量图标：格子里的 SVG 跟字体图标一样大，颜色也跟着 hover 变 */
.df-icon-cell svg.ico-svg{width:22px;height:22px;color:#2C3A47;}
.df-icon-cell:hover svg.ico-svg{color:#1B6BFF;}
.df-icon-cell em{
    max-width:100%;font-style:normal;font-size:11px;line-height:1.2;
    color:#8494A4;text-align:center;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}

/* ==========================================================================
 * 主题设置 · 前台链接清单
 * ======================================================================== */
.df-link-tb{width:100%;border-collapse:collapse;}
.df-link-tb th,.df-link-tb td{
    padding:10px 14px;border-bottom:1px solid #F0F3F6;vertical-align:middle;text-align:left;
}
.df-link-tb thead th{
    background:#F7F9FB;color:#5A6B7A;font-size:13px;font-weight:600;white-space:nowrap;
}
.df-link-tb tbody tr:last-child td{border-bottom:0;}
.df-link-tb tbody tr:hover td{background:#FAFCFE;}
.df-link-tb .col-name{width:220px;color:#2C3A47;font-size:13.5px;}
.df-link-tb td:not(.col-name){font-size:13px;}
.df-link-tb .df-link-tb-actions{white-space:nowrap;}
.df-link-url{
    display:inline-block;max-width:100%;padding:2px 6px;margin-right:6px;
    border-radius:4px;background:#F1F4F7;color:#3C4E5E;
    word-break:break-all;vertical-align:middle;
}
.df-link-tb .layui-btn-xs{margin:0;}
.df-link-group td{
    padding:9px 14px;background:#FBFCFD;color:#8494A4;font-size:12.5px;font-weight:600;
    border-bottom:1px solid #EEF2F6;
}
.df-link-group:hover td{background:#FBFCFD;}

@media (max-width:767px){
    .df-link-tb .col-name{width:auto;}
    .df-link-url{display:block;margin:0 0 6px;width:100%;}
}

/* 用户列表：账号左边带头像，昵称 / 手机用两行小字 */
.df-mcell{display:flex;align-items:center;gap:8px;padding:2px 0;}
.df-mcell .u-av{
    width:30px;height:30px;flex:0 0 auto;border-radius:50%;object-fit:cover;
    background:#EEF2F6;display:block;
}
.df-mcell .txt{min-width:0;}
.df-mcell .l1{line-height:16px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
.df-mcell .l2{
    line-height:15px;margin-top:2px;font-size:12px;color:#8A9099;
    white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
/* 头像角标：绑了 QQ 登录挂右上、绑了微信登录挂右下，白底圆片压在头像边上 */
.df-mcell .u-av-wrap{position:relative;flex:0 0 auto;line-height:0;}
.df-mcell .u-av-b{
    position:absolute;width:13px;height:13px;border-radius:50%;background:#fff;
    box-shadow:0 0 0 1px rgba(0,0,0,.12);
    display:flex;align-items:center;justify-content:center;
}
.df-mcell .u-av-b img{width:9px;height:9px;display:block;}
.df-mcell .u-av-b.q{top:-2px;right:-3px;}
.df-mcell .u-av-b.w{bottom:-2px;right:-3px;}
