/* 后台管理 admin.dnwenhua.com 专用样式（不依赖前台 common.css，仅配合本地 Bootstrap 4） */

body.admin-body {
  background: #f4f6f9;
  font-size: 14px;
}

/* ===== 布局骨架：固定左侧栏 + 右侧内容 ===== */
.admin-wrapper { display: flex; min-height: 100vh; }

.admin-sidebar {
  width: 220px;
  flex: 0 0 220px;
  background: #343a40;
  color: #c2c7d0;
  display: flex;
  flex-direction: column;
}
.admin-sidebar .brand {
  color: #fff;
  font-weight: 700;
  font-size: 16px;
  padding: 18px 20px;
  border-bottom: 1px solid rgba(255,255,255,.08);
  letter-spacing: 1px;
}
.admin-sidebar .nav-link {
  color: #c2c7d0;
  padding: 11px 20px;
  display: block;
  border-left: 3px solid transparent;
}
.admin-sidebar .nav-link:hover { color: #fff; background: rgba(255,255,255,.05); }
.admin-sidebar .nav-link.active {
  color: #fff;
  background: rgba(255,255,255,.08);
  border-left-color: #007bff;
}
.admin-sidebar .nav-section {
  padding: 14px 20px 6px;
  font-size: 12px;
  color: #7a8290;
  text-transform: uppercase;
}
.admin-sidebar .sidebar-foot {
  margin-top: auto;
  padding: 12px 20px;
  font-size: 12px;
  color: #6c757d;
}

.admin-main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }
.admin-navbar {
  background: #fff;
  border-bottom: 1px solid #dee2e6;
  padding: 10px 24px;
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.admin-navbar .page-title { font-size: 17px; font-weight: 600; color: #343a40; }

.admin-content { padding: 24px; }

/* ===== 仪表盘统计卡片 ===== */
.stat-card { border: 0; box-shadow: 0 1px 3px rgba(0,0,0,.08); border-radius: 6px; }
.stat-card .stat-label { color: #6c757d; font-size: 13px; }
.stat-card .stat-value { font-size: 26px; font-weight: 700; color: #343a40; }
.stat-card .stat-sub { font-size: 12px; color: #6c757d; margin-top: 2px; }
.stat-card .stat-value.danger { color: #dc3545; }
.stat-card .stat-value.warn { color: #fd7e14; }

/* ===== 列表页通用 ===== */
.filter-bar {
  background: #fff;
  border-radius: 6px;
  padding: 14px 18px;
  margin-bottom: 16px;
  box-shadow: 0 1px 3px rgba(0,0,0,.06);
}
.table-card {
  background: #fff;
  border-radius: 6px;
  box-shadow: 0 1px 3px rgba(0,0,0,.06);
}
.table-card .card-header { background: #fff; border-bottom: 1px solid #eee; font-weight: 600; }
.table th { white-space: nowrap; font-size: 13px; color: #495057; }
.table td { vertical-align: middle; }

/* ===== 分页（Bootstrap 4 结构） =====
   后台 layout **只加载 bootstrap.min.css + admin.css**（不引前台 theme.css），
   所以这里必须自带一套皮肤：7 个列表页由驱动 app/paginator/Bootstrap4.php 输出，
   会员详情页充值时间轴（view/admin/member/detail.html）是手写 BS4 分页 —— 两者同吃这套规则。
   主色沿用后台既有强调色 #007bff（同侧栏 active 左边线 / .chart-tab.active）。
   特异性（CSSOM 实取）：`.pagination > .page-item > .page-link` = (0,3,0)，hover/active/disabled = (0,4,0)；
   BS4 侧是 `.pagination-sm .page-link` (0,2,0) 与 `.page-item.active/.disabled .page-link` (0,3,0)。
   颜色/底色/描边各项**不依赖加载顺序**（对照实测：把 bootstrap.min.css 的 <link> 挪到 admin.css 之后，
   下面四条规则的 bg/color/border 计算值完全不变）。
   ⚠️ 但 `.pagination-jump` 的**宽度依赖顺序**：`.form-inline > .pagination-jump` 与 BS4 在
   `@media(min-width:576px)` 里的 `.form-inline .form-control{width:auto}` 同为 (0,2,0)，
   靠 admin.css 后加载才拿到 4.5rem（对照实测：顺序对调后掉回 number 框默认 81.67px @根字号 16px）。 */
.pagination > .page-item > .page-link {
  color: #495057;
  background-color: #fff;
  border-color: #dee2e6;
}
.pagination > .page-item > .page-link:hover {
  color: #007bff;
  background-color: #eef4ff;
  border-color: #007bff;
}
.pagination > .page-item.active > .page-link {
  color: #fff;
  background-color: #007bff;
  border-color: #007bff;
}
.pagination > .page-item.disabled > .page-link {
  color: #adb5bd;
  background-color: #f8f9fa;
  border-color: #e9ecef;
}
/* 分页条压在 .card-footer.bg-white 里：去掉 BS4 的 margin-bottom 默认 1rem，居中摆放 */
.card-footer .pagination {
  margin-bottom: 0;
  justify-content: center;
}
/* 跳页输入框：与后台的 form-control-sm / btn-sm 同高同调。
   宽度用 `.form-inline >` 提档：BS4 的 @media(min-width:576px) `.form-inline .form-control{width:auto}`
   是 (0,2,0)，单写 `.pagination-jump` 会被压成 number 框默认的 50px */
.pagination-jump,
.form-inline > .pagination-jump {
  width: 4.5rem;
}

/* 状态徽章（与订单状态机对应） */
.badge-st-0 { background: #adb5bd; }   /* 待支付 */
.badge-st-1 { background: #17a2b8; }   /* 已支付 */
.badge-st-2 { background: #28a745; }   /* 已完成 */
.badge-st-3 { background: #6c757d; }   /* 已取消 */
.badge-st-4 { background: #dc3545; }   /* 金额异常 */
.badge-st-5 { background: #fd7e14; }   /* 待发货 */

/* ===== 登录页 ===== */
.login-page {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  background: linear-gradient(135deg, #343a40 0%, #495057 100%);
}
.login-box { width: 380px; }
.login-card { border: 0; border-radius: 8px; box-shadow: 0 10px 40px rgba(0,0,0,.3); }
.login-card .card-header {
  background: #fff;
  border-bottom: 0;
  text-align: center;
  padding-top: 28px;
  font-weight: 700;
  font-size: 18px;
}
.login-card .card-body { padding: 20px 32px 32px; }
.login-brand { color: #fff; text-align: center; margin-bottom: 18px; letter-spacing: 2px; }

/* 详情页信息组 */
.info-group dt { color: #6c757d; font-size: 13px; }
.info-group dd { margin-bottom: 12px; font-weight: 500; }

/* 空状态 */
.empty-tip { color: #868e96; text-align: center; padding: 40px 0; }

/* ===== 富文本编辑器容器（高度必须在 CSS 里，不能写 inline）=====
   ⚠️ 原先是 content/edit.html 上的 inline `style="height:400px"`。inline 样式
   媒体查询覆盖不了（除非 !important），窄屏就再也降不了高 ⇒ 挪到这里。
   桌面端 400px 观感不变；窄屏在下面的 @media 块里降到 240px。 */
.rich-editor { height: 400px; overflow-y: hidden; }

/* ===== 手机端适配（2026-10-08）=====
   ⚠️ 断点 991.98px 与既有侧栏断点、Bootstrap 4 的 lg 边界对齐：手机 + 平板竖屏同一档。
   ⚠️ 本块**之外**的规则一律不得改（桌面观感必须逐像素不变）；
      `tests/common/AdminMobileGuardTest::test_desktop_appearance_is_untouched` 钉住这条。
   ⚠️ 也别调整 layout.html 里 <link> 的先后顺序——admin.css 的 `.pagination-jump` 宽度
      依赖「admin.css 后加载」（见 docs/standards/frontend.md）。 */

/* 汉堡按钮：宽屏恒隐藏（display:none 在媒体查询之外，JS 就绪后才在窄屏显示）。
   三条横条用伪元素画——后台零 CDN 依赖，不引图标字体/外链图片。 */
.admin-menu-toggle {
  display: none;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  margin-right: 8px;
  padding: 0;
  border: 1px solid #ced4da;
  border-radius: 4px;
  background: #fff;
  cursor: pointer;
}
.admin-menu-toggle:hover { border-color: #007bff; }
.admin-menu-bars,
.admin-menu-bars::before,
.admin-menu-bars::after {
  display: block;
  width: 16px;
  height: 2px;
  background: #495057;
  content: '';
}
.admin-menu-bars { position: relative; }
.admin-menu-bars::before { position: absolute; top: -5px; }
.admin-menu-bars::after { position: absolute; top: 5px; }

/* 抽屉遮罩：默认不存在（display:none），由 body.admin-sidebar-open 打开 */
.admin-scrim {
  display: none;
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 1029;                 /* ⚠️ 必须 < 侧栏的 1030，否则盖住菜单 */
  background: rgba(0, 0, 0, .45);
}

/* ===== 内容管理按游戏父级手风琴（游戏名可点展开/折叠 5 类内容入口，配色对齐既有 nav-link） ===== */
.nav-group .nav-parent {
  display: block;
  padding: 11px 20px;
  color: #c2c7d0;
  cursor: pointer;
  font-size: 14px;
  border-left: 3px solid transparent;
  user-select: none;
}
.nav-group .nav-parent::before { content: '▸ '; color: #7a8290; }
.nav-group.open .nav-parent::before { content: '▾ '; }
.nav-group .nav-parent:hover { color: #fff; background: rgba(255,255,255,.05); }
.nav-group .nav-children { display: none; }
.nav-group.open .nav-children { display: block; }
.nav-group .nav-children .nav-link { padding-left: 28px; font-size: 13px; }
.nav-group .nav-parent.active { color: #fff; background: rgba(255,255,255,.08); border-left-color: #007bff; }

/* ===== 数据图表区（2026-09-07 数据可视化） ===== */
.chart-title { font-size: 13px; font-weight: 600; margin-bottom: 6px; }
.chart-box { width: 100%; height: 300px; }
.chart-empty { display: flex; align-items: center; justify-content: center; height: 300px; color: #6c757d; font-size: 13px; }

.chart-tabs { display: flex; gap: 6px; }
.chart-tab { padding: 3px 14px; border: 1px solid #ced4da; border-radius: 4px; background: #fff; font-size: 13px; color: #495057; cursor: pointer; }
.chart-tab.active { background: #007bff; border-color: #007bff; color: #fff; }

/* 统计时间筛选的「自定义区间」面板，由 admin-charts.js 插在 .card-header 与 .card-body **之间**。
   ⚠️ **承重规则，不是装饰**：面板不在 .card-body 里，拿不到那 20px 内边距 ——
   去掉 padding 它会紧贴卡头、下压统计卡（2026-10-16 用户实测反馈「上下都没有留白」）。
   flex-wrap 同样承重：两个 170px 的日期框在 375px 视口放不下，换行是第一性的修法
   （同 .chart-tabs 那条教训；min-width:0 让它们必要时还能收缩，而不是把面板撑出视口）。 */
.stats-range-panel { display: flex; flex-wrap: wrap; align-items: center;
  padding: 12px 20px; border-bottom: 1px solid #eee; background: #fafbfc; }
.stats-range-panel .form-control { min-width: 0; max-width: 100%; }

.stat-delta { font-size: 12px; }
.stat-delta.up { color: #28a745; }
.stat-delta.down { color: #dc3545; }
.stat-delta.zero { color: #6c757d; }

.skeleton { height: 84px; border-radius: 4px; background: linear-gradient(90deg, #f1f3f5 25%, #e9ecef 37%, #f1f3f5 63%); background-size: 400% 100%; animation: skeleton-loading 1.2s ease infinite; }
@keyframes skeleton-loading { 0% { background-position: 100% 50%; } 100% { background-position: 0 50%; } }

/* ===== 仪表盘游戏切换器（2026-09-08 手风琴） ===== */
.stat-acc { border-bottom: 1px solid #f0f0f0; }
.stat-acc-head { display: flex; justify-content: space-between; align-items: center; width: 100%; border: 0; background: none; padding: 10px 20px; font-size: 13px; font-weight: 600; color: #495057; cursor: pointer; text-align: left; }
.stat-acc-head:hover { background: #f8f9fa; }
.stat-acc-head .acc-arrow { color: #7a8290; font-size: 11px; transition: transform .15s; }
.stat-acc.collapsed .acc-arrow { transform: rotate(-90deg); }
.stat-acc-body { display: flex; flex-wrap: wrap; gap: 6px; padding: 2px 20px 12px; }
.stat-acc.collapsed .stat-acc-body { display: none; }
.stat-acc-item { padding: 3px 14px; border: 1px solid #ced4da; border-radius: 14px; background: #fff; font-size: 13px; color: #495057; cursor: pointer; }
.stat-acc-item:hover { border-color: #007bff; color: #007bff; }
.stat-acc-item.active { background: #007bff; border-color: #007bff; color: #fff; }

/* ============ 站内图库弹窗（admin-media-picker.js） ============ */
.media-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
  gap: 8px;
}
.media-item {
  cursor: pointer;
  border: 1px solid #dee2e6;
  border-radius: 4px;
  overflow: hidden;
  background: #f8f9fa;
}
.media-item:hover { border-color: #007bff; }
.media-item img {
  display: block;
  width: 100%;
  height: 90px;
  object-fit: cover;
  background: #fff;
}
.media-item-name {
  font-size: 11px;
  line-height: 1.3;
  padding: 2px 4px 0;
  color: #495057;
  word-break: break-all;
}
.media-item-size {
  font-size: 11px;
  padding: 0 4px 3px;
  color: #adb5bd;
}

/* ==========================================================================
   手机端适配（2026-10-08）—— 唯一的窄屏块，放在文件**最后**。
   ⚠️ 为什么必须在最后：它与前面同特异性的规则靠**加载顺序**决胜。
      例：`.nav-group .nav-parent` 的桌面 padding 写在上面（(0,2,0)），
      本条块里的 `.nav-group .nav-parent{padding:13px 20px}` 也是 (0,2,0)——
      块在文件中部时会被后面的桌面规则反压回去，放到最后才稳定生效。
   ⚠️ 断点 991.98px 与既有侧栏断点、Bootstrap 4 的 lg 边界对齐（手机 + 平板竖屏同一档）。
   ⚠️ 本块**之外**的规则一律不得改（桌面观感必须逐像素不变），
      `tests/common/AdminMobileGuardTest::test_desktop_appearance_is_untouched` 钉住这条。
   ⚠️ 也别调整 layout.html 里 <link> 的先后顺序——admin.css 的 `.pagination-jump` 宽度
      依赖「admin.css 后加载」（见 docs/standards/frontend.md）。
   ========================================================================== */
@media (max-width: 991.98px) {
  /* 侧栏抽屉：原断点规则 + 拉出时的投影 */
  .admin-sidebar { position: fixed; top: 0; bottom: 0; left: -220px; z-index: 1030; transition: left .2s; }
  .admin-sidebar.show { left: 0; box-shadow: 2px 0 12px rgba(0, 0, 0, .3); }

  /* 整页横向溢出兜底。只在窄屏：宽屏若也 hidden 会砍掉桌面端的横向滚动能力。 */
  body.admin-body { overflow-x: hidden; }

  /* 汉堡按钮：只有 JS 就绪后在窄屏显示（无 JS ⇒ 不出现点了没反应的死按钮） */
  body.admin-nav-ready .admin-menu-toggle { display: inline-flex; }
  body.admin-sidebar-open .admin-scrim { display: block; }

  /* 触摸目标加高（手指比鼠标粗）。⚠️ 必须排在上面 .nav-group 桌面规则**之后** */
  .admin-sidebar .nav-link { padding: 13px 20px; }
  .nav-group .nav-parent { padding: 13px 20px; }

  /* 顶栏与内容区收紧：375px 上 24px padding 吃掉太多宽度 */
  .admin-navbar { padding: 8px 12px; gap: 8px; }
  .admin-navbar .page-title { font-size: 15px; }
  .admin-content { padding: 12px; }
  .filter-bar { padding: 12px; }
  .card-body { padding: 14px; }
  .card-header { padding: 10px 14px; }
  .stats-range-panel { padding: 10px 14px; }   /* 与 .card-body 同档，窄屏别多占宽度 */
  /* 两个日期框各 170px 在 375px 上一行放不下：给出 130px 的 flex 基准让它们**并排收窄**
     （而不是各占一行把面板堆高）——实测并排后每个约 166px，日期文本仍完整可读。 */
  .stats-range-panel .form-control { flex: 1 1 130px; }

  /* 页头/卡头的「长说明文字 + 定宽控件」单行 d-flex 放不下——
     实测 /visit 溢出 +198px、/game-stats 溢出 +371px。允许折行是第一性的修法。
     ⚠️ 三处都要折，缺一不可（2026-10-08 实测教训）：
        ① 外层 `.d-flex.justify-content-between`（说明文字 vs 控件组）
        ② **内层控件组**（`<div class="d-flex align-items-center">`，装游戏选择器/档位/导出）
           ——只折外层时，内层仍 nowrap、被压到 351px：实测 `#j-days` 变 44px 宽
           （「近7天」竖排成 3 行）、`#j-export` 变 103px 宽（按钮文字变成一个词一行）。
        ③ `.card-header` 里的 d-flex
     选择器用 `> div[class*="d-flex"]` 而不是 `.d-flex`，是为了**只打直接子级**、
     不误伤更深层的内容块（如 `.stat-acc-body`、`.form-row` 等自带 flex 语义的容器）。 */
  .admin-content .d-flex.justify-content-between,
  .admin-navbar.d-flex,
  .admin-content .card-header.d-flex,
  .admin-content > div[class*="d-flex"].justify-content-between > div[class*="d-flex"],
  .admin-content .card-header > div[class*="d-flex"] { flex-wrap: wrap; }
  .admin-content .d-flex.justify-content-between { gap: 8px; }
  .admin-content .d-flex.justify-content-between > * { min-width: 0; }

  /* 工具栏里的定宽控件（inline width 有 150~260px 不等）在窄屏一律收成自适应。
     ⚠️ 必须 !important：目标是**覆盖 inline style 的宽度**，常规声明赢不了。 */
  .admin-content .card-header .form-control,
  .admin-content .d-flex .form-control,
  .filter-bar .form-control { width: auto !important; max-width: 100%; }
  .admin-content .btn-group { flex-wrap: wrap; }
  /* /game-stats 的 5 个 CSV 导出按钮：默认 flex 基准是内容宽，窄屏会被逐个挤成
     「一个字一行」的细条（实测 43px 宽、文字竖排）。给足基准宽让它两列铺开。 */
  .admin-content .btn-group > .btn { flex: 1 1 9rem; white-space: nowrap; }

  /* 筛选栏折行：一行两列，控件撑满 */
  .filter-bar .form-inline { display: flex; flex-wrap: wrap; }
  .filter-bar .form-inline > .form-group { flex: 1 1 calc(50% - 8px); margin-right: 8px !important; }
  .filter-bar .form-inline > .form-group > .form-control { width: 100% !important; }
  .filter-bar .form-inline > .btn { flex: 1 1 100%; }

  /* 统计卡数字降一档，免得 375px 上折行 */
  .stat-card .stat-value { font-size: 22px; }

  /* 图表降高（桌面 300px 不变）；echarts 由页面自己的 resize 钩子重算 */
  .chart-box,
  .chart-empty { height: 220px; }

  /* 档位选项卡换行：`.chart-tabs` 是 flex 且默认 nowrap，4 个档位（今日/近7/14/30 或
     最近24小时/3天/7天/自定义）在 375px 上放不下，实测把 /visit 整页撑出 +90px。
     `.chart-tab` 又不能收缩（按钮有内在最小宽度），所以必须允许**换行**而不是压缩。 */
  .chart-tabs { flex-wrap: wrap; }
  .admin-content .card-header .chart-tabs { justify-content: flex-start; }

  /* ⚠️ 「无容器 .row」：/visit、/game-stats 的统计卡行是 JS/模板直接放在内容区里的
     `<div class="row col-*">`，**外面没有 .card-body** ⇒ Bootstrap 的
     `.row{margin-left:-15px;margin-right:-15px}` 无人抵消，右边界比视口多出 6px。
     桌面端同样存在（只是视口宽、被滚动条兜住了），这里只修窄屏以保桌面像素不变。 */
  .admin-content > .row,
  .admin-content > #j-cards.row,
  .admin-content > #j-all .row,
  .admin-content > #j-one > .row { margin-left: 0; margin-right: 0; }
  .admin-content > .row > [class*="col-"],
  .admin-content > #j-cards.row > [class*="col-"],
  .admin-content > #j-one > .row > [class*="col-"] { padding-left: 0; padding-right: 0; }

  /* 表格横向滚动兜底：admin-visit.js / admin-game-stats.js 直接 .html('<table…>') 插进
     普通 div（`#j-compare`/`#j-silence`/`#j-paydepth`…），既没有 .table-responsive 包裹，
     也不是 .card-body 的直接子元素 ⇒ 只能由 CSS 给这些**裸表**开滚动。
     ⚠️ 选择器必须排除 `.table-responsive` 里的表（`:not(.table-responsive) > table.table`）：
        那些表本来就靠父容器滚动，若也套 `display:block;width:100%` 会被**压扁**——
        实测 `/log` 的详情列（`max-width:480px`）被挤成**一行一个字**，整表从自然 481px
        压到 349px。加了 `:not()` 后：`/log` 表保持 481px、父容器横滚；裸表仍 321px 不撑页。
     ⚠️ 三条声明是**无头浏览器逐组合对照实测**出来的（探针 `test_script/table_variants.mjs` 保留可复用）：
          `display:block` + `width:100%` + `overflow-x:auto`
          ⇒ 表宽=父宽、表内可滚、页面不被撑开（docW=375）。
        反例（都实测过，别改回去）：
          · 省掉 `width:100%`（= max-content）→ 表宽 535、**整页溢出 187px**；
          · `width:fit-content;min-width:100%` → 表宽 423、同样溢出；
          · 不加 `:not()` 而套到包裹表上 → `/log` 详情列被压成一行一字。 */
  .admin-content :not(.table-responsive) > table.table {
    display: block;
    width: 100%;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
  }

  /* 分页折行（`.card-footer .pagination` 是 flex，窄屏放不下时换行而不是溢出） */
  .card-footer .pagination { flex-wrap: wrap; }

  /* 登录页：固定 380px + .card-body 32px 内边距在 375px 视口必溢出 */
  .login-page { padding: 16px; }
  .login-box { width: min(100% - 24px, 380px); }
  .login-card .card-body { padding: 18px 18px 24px; }
  /* 「冬南文化 · 平台管理后台」在 375px 上会折成两行、贴到屏幕边缘 */
  .login-brand h4 { font-size: 1.15rem; }

  /* 站内图库网格：桌面 minmax(120px,1fr) 在窄屏一行放不下两张 */
  .media-grid { grid-template-columns: repeat(auto-fill, minmax(92px, 1fr)); }
  .media-item img { height: 72px; }

  /* 富文本编辑器：比桌面矮一截；工具栏窄屏放不下 ⇒ 横向滚动而不是换行堆高 */
  .rich-editor { height: 240px; }
  #j-toolbar { overflow-x: auto; white-space: nowrap; }

  /* 详情页 dl 堆叠后补点纵向间距（Bootstrap 的 col-md-6 窄屏已自动堆叠） */
  .info-group dt { margin-top: 6px; }
}
