/* ============================================================
   layout.css —— 页面骨架层（第 2 层）
   放「每个页面最外层长什么样」的那一层。统一后每个页面都是这个形状：

       <body class="page page-账号名">     ← 页面底板（背景 / 居中方式 / 留白）
         <div class="page-head">          ← 页头（有的页面没有）
         <div class="page-wrap">          ← 内容外框（多宽、多挤、居不居中）
           <section class="card">…        ← 内容卡片
   ------------------------------------------------------------
   ⚠️ 三条判据：

   ① **页面之间的差异只允许写在这一份文件里**，而且必须挂在 body 的页面类下
      （`body.page-xxx …`）。不带 `body.page-xxx` 前缀的规则会串到别的页面去。

   ② **`.page-head` 有两种位置，这是故意的，不是漏改：**
      · 在 `.page-wrap` 里面 —— 内容框是中性的（不带白底）时，页头要跟着一起受宽度限制：
        认证三页、登录后的新页（我的账号 / 操作记录 / 客户管理）
      · 在 `.page-wrap` 外面 —— 内容框本身就是那张白卡片时，页头必须在卡片外面：
        外壳、老后台（用户管理 / 数据库管理）、活动数据
      判断方法：看 `.page-wrap` 有没有白底。

   ③ **`.page-head` 自己不设任何样式**，它只是「页面的头部是哪一块」的统一挂点；
      外观一律写在各页参数里（认证页的品牌块是页头，老后台的顶栏也是页头）。

   ------------------------------------------------------------
   ⚠️ 盒模型：本文件同时被老页（border-box）和新页（content-box）引用。
      凡是可能被新页用到的规则，不要假设 padding 算在宽度里。
   ============================================================ */

/* ============================================================
   一、骨架基础 —— 所有页面共用，不含任何页面特有的数值
   ============================================================ */

/* 页面底板。⚠️ 这里不写 background：老页是蓝渐变、新页是浅灰、
   首页分流页没有背景、外壳靠舞台自己铺 —— 四种都不一样，各页参数里给。 */
body.page {
  margin: 0;
  padding: 0;
  min-height: 100vh;
  display: block;
}

/* 内容外框。
   ⚠️ 这里**故意不写任何属性** —— 它和 `.page-head` 一样只是个「角色挂点」。
      原因是两条：
      ① 宽度必须留给各页：老页是 border-box、新页是 content-box，
         在基础条里写 width:100% 会让新页在窄屏多溢出左右各 22px 的内边距；
      ② 更不能写 margin:0 auto：外壳和活动模块的 body 是 flex 容器，
         自动外边距会吸收剩余空间、把内容框压成内容宽度（实测 1384 → 847）。 */
/* .page-wrap 的宽度 / 居中 / 内边距一律在下面各页参数里给 */

/* 内容卡片。这两组页面（登录后新页 / 活动模块）的卡片共用这一份白底描边圆角，
   差别只在挤不挤（内边距 / 下间距）—— 那部分在各页参数里。 */
.card {
  background: #fff;
  border: 1px solid var(--grey);
  border-radius: var(--radius);
}

/* 页头里的标题与说明。
   ⚠️ `.page-sub` 不带页头前缀 —— 「我的账号」页把它借去当卡片内的小字说明用了。 */
.page-title {
  font-size: 1.28rem;
  color: var(--black);
  font-weight: 700;
  margin-bottom: 4px;
}
.page-sub {
  font-size: 0.88rem;
  color: var(--soft-black);
  margin-bottom: 22px;
}

/* ============================================================
   二、每页参数 —— 页面之间的差异只写在这里
   ============================================================ */

/* ------------------------------------------------------------
   A. 蓝渐变底 + 居中列
      index（首页分流）· login · forgot · admin · db
   ------------------------------------------------------------ */

/* 老后台与认证页共用的底板：蓝渐变 + 居中列，挂在 body 的页面类上 */
body.page-login,
body.page-forgot,
body.page-admin,
body.page-db {
  font-family: var(--font-stack);
  line-height: 1;
  margin: 16px;
  color: var(--black);
  background: var(--brand-grad);
  border-radius: var(--radius);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
  display: flex;
  flex-direction: column;
  align-items: center;
}

/* 首页分流页：不引 legacy.css，所以底板只有「整页居中」这一件事，没有渐变底 */
body.page-index {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 24px 16px 40px;
}

/* 登录 / 找回：内容外框自己占满一屏再居中。
   它是 border-box（引了 legacy.css 的 reset），所以 width:100% 含内边距。 */
body.page-login .page-wrap,
body.page-forgot .page-wrap {
  width: 100%;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 24px 16px 40px;
}

/* 认证三页的页头 = 品牌块（logo + 站名 + 副标题） */
body.page-index .page-head,
body.page-login .page-head,
body.page-forgot .page-head {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  margin-bottom: 22px;
  color: #fff;
}
body.page-index .page-head img,
body.page-login .page-head img,
body.page-forgot .page-head img {
  width: 54px;
  height: 54px;
}
body.page-index .page-head .ws-name,
body.page-login .page-head .ws-name,
body.page-forgot .page-head .ws-name {
  font-size: 1.6rem;
  font-weight: 700;
  letter-spacing: 1px;
}
body.page-index .page-head .tagline,
body.page-login .page-head .tagline,
body.page-forgot .page-head .tagline {
  font-size: 0.86rem;
  opacity: 0.82;
  letter-spacing: 0.5px;
}

/* 登录 / 找回的卡片 = 那张 400px 的登录框。
   白底由 .card 基础给；这里只改「多大、多圆、有没有描边」。 */
body.page-login .card,
body.page-forgot .card {
  width: 100%;
  max-width: 400px;
  border: 0;
  border-radius: 16px;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
  padding: 26px 28px 30px;
}
body.page-login .card h2,
body.page-forgot .card h2 {
  font-size: 1.16rem;
  color: var(--black);
  margin-bottom: 16px;
  font-weight: 700;
}

/* ------------------------------------------------------------
   B. 外层容器：100vh 舞台
      app（登录后外壳）
   ------------------------------------------------------------ */
body.page-app {
  display: flex;
  flex-direction: column;
  height: 100vh;
  height: 100dvh;
  overflow: hidden;
}

/* 外壳的页头 = 全局顶栏 */
body.page-app .page-head {
  box-sizing: border-box;
  flex: none;
  min-height: 48px;
  display: flex;
  align-items: center;
  /* 桌面/中屏：整条顶栏强制一行不换行 —— 空间不够时由时间条自动压缩（clocks.js 的
     fit() 选档），而不是让导航折到第二行。窄屏（≤920px）在 layout.css 的窄屏一节
     重新打开 flex-wrap，那里 logo 已整块隐藏、导航独自占第二行。 */
  flex-wrap: nowrap;
  gap: 4px;
  padding: 4px 16px;
  background: #fff;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
  position: relative;
  z-index: 2;
}
body.page-app .page-head .ws-brand {
  flex: none;
  margin-left: 14px;
  padding-left: 14px;
  border-left: 1px solid var(--grey);
}

/* 外壳的内容框 = iframe 舞台：每个页面一个 iframe，切换只做显隐 → 状态完整保留 */
body.page-app .page-wrap {
  position: relative;
  flex: 1 1 auto;
  min-height: 0;
  background: var(--soft-grey);
}
body.page-app .page-wrap iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0; /* 不设置0的话就会默认有1px的边框 */
  display: none;
}
body.page-app .page-wrap iframe.active { display: block; }

/* ------------------------------------------------------------
   C. 文档流：浅灰底 + 居中内容框
      account（我的账号）· audit（操作记录）· customers（客户管理）
   ------------------------------------------------------------ */
body.page-account,
body.page-audit,
body.page-customers {
  background: var(--soft-grey);
}

body.page-account .page-wrap,
body.page-audit .page-wrap,
body.page-customers .page-wrap {
  max-width: 980px;
  margin: 0 auto;
  padding: 26px 22px 60px;
}
/* 操作记录页要放表格，内容框单独放宽 */
body.page-audit .page-wrap { max-width: 1180px; }

/* 这三页的卡片比活动模块的松一档 */
body.page-account .card,
body.page-audit .card,
body.page-customers .card {
  padding: 20px 22px;
  margin-bottom: 18px;
}

/* ------------------------------------------------------------
   D. 蓝渐变底 + 一张大白卡
      admin（用户管理）· db（数据库管理）
   ------------------------------------------------------------ */

/* 页头 = 老后台自己的顶栏（白字压在渐变上）。被外壳嵌进去时会整条隐藏。 */
body.page-admin .page-head,
body.page-db .page-head {
  width: 100%;
  max-width: 1200px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 30px;
  color: #fff;
}
body.page-admin .page-head .brand,
body.page-db .page-head .brand {
  font-size: 1.2rem;
  font-weight: 700;
  letter-spacing: 0.5px;
}
body.page-admin .page-head nav,
body.page-db .page-head nav {
  display: flex;
  gap: 16px;
  align-items: center;
  font-size: 0.95rem;
}
body.page-admin .page-head a,
body.page-db .page-head a {
  color: #fff;
  text-decoration: none;
  opacity: 0.92;
}
body.page-admin .page-head a:hover,
body.page-db .page-head a:hover {
  opacity: 1;
  text-decoration: underline;
}
body.page-admin .page-head .user-chip,
body.page-db .page-head .user-chip {
  background: rgba(255, 255, 255, 0.18);
  padding: 6px 14px;
  border-radius: 999px;
  backdrop-filter: blur(4px);
}

/* 内容框 = 那张大白卡本身（这两页没有内层卡片） */
body.page-admin .page-wrap,
body.page-db .page-wrap {
  width: 100%;
  max-width: 600px;
  background: #fff;
  border-radius: 16px;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
  padding: 60px 40px;
  text-align: center;
  animation: fadeInUp 0.8s ease-out;
}
body.page-admin .page-wrap { max-width: 1200px; }
body.page-db .page-wrap {
  max-width: 1180px;
  text-align: left;
  padding: 36px 28px;
}

body.page-admin .page-wrap .tab-hint {
  font-size: 0.8rem;
  line-height: 1.8;
  color: var(--dark-grey);
  text-align: left;
  margin: 0 0 16px;
}
body.page-db .page-wrap h1 { font-size: 2rem; }

/* ------------------------------------------------------------
   E. 内嵌浮卡：四周留 10px、整块浮在舞台上
      activity（活动数据模块）
   ------------------------------------------------------------ */
body.page-activity {
  margin: 10px 5%;
  /* 同 page-manage：视口高度扣掉上下外边距做定高，body 不再跟随内容滚动 */
  height: calc(100vh - 20px);
  height: calc(100dvh - 20px);
  min-height: auto; /* 覆盖基线的 min-height:100vh —— 它有 10px 外边距，撑满会产生滚动 */
  display: flex;
  flex-direction: column;
  overflow: hidden; /* body 自身不滚动，滚动交给 .page-wrap */
  background: var(--soft-grey);
  color: var(--black);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
  border: 1px solid var(--grey);
  border-radius: 30px;
  font-family: var(--font-stack);
  font-size: 14px;
}

/* 页头 = 模块自己的标题条 + 子页签，贴在顶部 */
body.page-activity .page-head {
  flex: none;
  background: #fff;
  border-bottom: 1px solid var(--grey);
  border-radius: 30px 30px 0 0;
  padding: 4px 10px 0;
  position: sticky;
  top: 0;
  z-index: 20; 
}

body.page-activity .page-wrap {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto; /* 子页内容在此内部滚动（body 不再滚） */
  overscroll-behavior: contain;
  padding: 14px 3% 40px;
  border-radius: 30px;
}

/* 网站监控独立页（/monitor.html）：之前漏了 body.page-monitor 布局规则，
   导致 .page-wrap 没有内边距、内容顶到屏幕两边。这里补上（浅灰底 + 居中列）。 */
body.page-monitor { background: var(--soft-grey); }
body.page-monitor .page-wrap {
  max-width: 1180px;
  margin: 0 auto;
  padding: 26px 22px 60px;
}
body.page-monitor .card { padding: 20px 22px; margin-bottom: 18px; }

/* 活动模块的卡片 */
body.page-activity .card {
  padding: 14px 16px;
  margin-bottom: 14px;
}
body.page-activity .card.pad0 { padding: 0; overflow: hidden; }

/* ------------------------------------------------------------
   F. 内嵌浮卡：四周留 10px、整块浮在舞台上
       manage（网站管理聚合板）
   ------------------------------------------------------------ */
body.page-manage {
  margin: 10px 24px;
  /* 用视口高度扣掉上下外边距做定高：这样 body 是固定高度的弹性列，
     内部 .page-wrap 才能 overflow 滚动，而不是整个 body 跟着内容撑高去滚。 */
  height: calc(100vh - 20px);
  height: calc(100dvh - 20px);
  min-height: auto; /* 覆盖基线的 min-height:100vh —— 它有外边距，撑满会产生滚动 */
  display: flex;
  flex-direction: column;
  overflow: hidden; /* body 自身不滚动，滚动交给 .page-wrap */
  background: var(--soft-grey);
  color: var(--black);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
  border: 1px solid var(--grey);
  border-radius: 30px;
  font-family: var(--font-stack);
  font-size: 14px;
}

body.page-manage .page-head {
  flex: none;
  background: #fff;
  border-bottom: 1px solid var(--grey);
  border-radius: 30px 30px 0 0;
  padding: 10px 18px 0;
  position: sticky;
  top: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
}

body.page-manage .page-wrap {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto; /* 所有子页面内容在此内部滚动（body 不再滚） */
  overscroll-behavior: contain;
  padding: 14px 20px 40px;
  position: relative;
}

/* ============================================================
   三、公共件 —— 跨页面共用的东西（目前只有按钮）

   全站按钮类名只有一套 .btn，这里是它唯一的定义处。角色（不是尺寸）：
     .btn           空心（白底描边）    次要操作
     .btn.primary   实心（品牌色）      主操作
     .btn.danger    红描边 / 悬停填红    危险操作
     .btn.on        浅蓝底选中态
   类名写在 HTML / JS 里；要换颜色改 base.css 的变量。

   ⚠️ 用 inline-flex + height 定高，不让 emoji（🔄 🗑 ⬇）把按钮撑高。
   全站一个尺寸；要局部做小，在对应页面那一份里覆写 height / padding / font-size。
   ============================================================ */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 4px;
  padding: 4px 8px;
  border: 1px solid var(--grey);
  border-radius: var(--radius);
  background: var(--grey);
  color: var(--soft-black);
  font-family: inherit;
  font-size: 0.85rem;
  font-weight: 400;
  line-height: 1;
  white-space: nowrap;
  cursor: pointer;
  transition: border-color 0.15s, color 0.15s, background 0.15s;
}
.btn:hover:not(:disabled) { 
  background: var(--brand-4);
  border-color: var(--brand-4);
  color: var(--white);
}
.btn:disabled { opacity: 0.4; cursor: not-allowed; }

.btn.primary {
  background: var(--brand-4);
  border-color: var(--brand-4);
  color: var(--white);
}
.btn.primary:hover:not(:disabled) {
  background: var(--brand-5);
  border-color: var(--brand-5);
  color: var(--white);
}

.btn.danger { 
  background-color: #f13f3f;
  color: #ffffff;
  font-weight: 300; 
}
.btn.danger:hover:not(:disabled) {
  background: var(--red);
  border-color: var(--red);
  color: var(--white);
}

.btn.on {
  background: var(--brand-4);
  border-color: var(--brand-4);
  color: var(--white);
}

/* 大号按钮：卡片主操作（仪表盘导出 / 一键导入这类成排的主动作），可与 primary 叠用 */
.btn.lg {
  height: 36px;
  padding: 0 16px;
  font-size: 0.92rem;
  gap: 6px;
}

/* ============================================================
   四、窄屏（≤920px）
   ============================================================ */
@media (max-width: 920px) {
  /* 外壳顶栏：由一行折成两行。
     选 920 是因为：账号块 + 导航 + 品牌(logo+站名) 三者加在一起约 720px，
     加上最窄档(nano)时钟约 140px，一行至少需要 ~886px 内容宽（≈918px 视口）才放得下；
     低于这个宽度就算把时钟压到 nano 也会被 flex 挤窄裁切，所以更早折行：
     折行后品牌整块隐藏、时钟独占整行（budget 给满行宽），既不裁切也不压到导航。 */
  body.page-app .page-head {
    height: auto;
    flex-wrap: wrap;
    padding: 7px 10px;
    gap: 6px 8px;
  }
  /* 品牌图标收进第一行最右 */
  body.page-app .page-head .ws-brand {
    order: 2;
    margin-left: auto;
    padding-left: 0;
    border-left: 0;
  }

  /* 老后台的白卡收一收内边距、放开宽度 */
  body.page-admin .page-wrap,
  body.page-db .page-wrap { padding: 32px 16px; }
  body.page-admin .page-wrap { max-width: 100%; }
}

/* ═══ 表格十字高亮（js/common.js 挂类）═══
 * 行/列染高饱和蓝（颜色浓度加深、非压低明度）、交叉格提亮变浅。用 inset box-shadow 叠半透明层，
 * 不动单元格本来的背景色（身份列、过期底色那些不受影响），文字照常显示。 */
/* 行/列高亮：用高饱和的品牌蓝叠加，提高饱和度、加深颜色浓度（而非压低明度变灰）。
   ⚠️ 不是 rgba(30,60,100,0.055) 那种低饱和暗蓝（白底上只压明度、显灰暗），
   改用 --brand-3 同色相（rgb(57,132,254)）提 alpha，读作「染蓝」而非「变暗」。*/
td.xh-row, td.xh-col { box-shadow: inset 0 0 0 9999px rgba(57, 132, 254, 0.16); }
th.xh-col { box-shadow: inset 0 0 0 9999px rgba(57, 132, 254, 0.22); }
td.xh-cell { box-shadow: inset 0 0 0 9999px rgba(255, 255, 255, 0.55); }

/* ═══ 表格拖动多选（js/common.js 挂类）═══
 * 拖拽圈选的数据单元格高亮；选区优先于十字高亮显示（本块在其后，同特异度下生效）。*/
td.x-sel { box-shadow: inset 0 0 0 9999px rgba(33, 118, 230, 0.20); }
body.x-sel-dragging { user-select: none; cursor: cell; }

/* ═══ 版本号徽章（js/common.js 拉 /api/version 填充）═══ */
.js-ver { font-size: 11px; color: var(--dark-grey); white-space: nowrap; cursor: default; }

/* ═══ 拖文件上传的提示层（js/common.js enableFileDrop 挂）═══ */
.drop-mask {
  position: absolute; inset: 0; z-index: 99;
  display: flex; align-items: center; justify-content: center;
  background: rgba(238, 244, 252, 0.88);
  border: 2px dashed var(--brand-2); border-radius: inherit;
  pointer-events: none; /* 不挡住底下元素的 dragenter / dragleave / drop 判定 */
}
.drop-mask-t { font-size: 0.95rem; font-weight: 600; color: var(--brand-4); }
