/* =====================================================
   校园午餐·请假管理 — 视觉样式 v3
   ===================================================== */
:root {
  --bg: #f4f6fb;
  --card: #ffffff;
  --primary: #3a5bf6;
  --primary-2: #6b5df7;
  --primary-soft: #eef2ff;
  --danger: #e5484d;
  --danger-soft: #fdecec;
  --success: #12a150;
  --success-soft: #e7f7ee;
  --warn: #d97706;
  --warn-soft: #fff5e5;
  --text: #141a26;
  --muted: #78849b;
  --line: #e8ecf3;
  --radius: 16px;
  --grad: linear-gradient(135deg, #5570ff 0%, #3a4ff0 55%, #6b5df7 100%);
  --shadow-sm: 0 1px 2px rgba(20, 26, 38, .04), 0 6px 16px -8px rgba(20, 26, 38, .12);
  --shadow-md: 0 2px 6px rgba(20, 26, 38, .05), 0 16px 34px -16px rgba(20, 26, 38, .18);
  /* v25.43：只做浅色主题，阻止微信/系统对页面做智能反色（背景变黑、字变白） */
  color-scheme: light;
}
* { box-sizing: border-box; margin: 0; padding: 0; -webkit-tap-highlight-color: transparent; }
html {
  /* v25.43：禁止微信/手机浏览器的字体自动缩放（Font Boosting），避免文字被放大撑破卡片 */
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  background: var(--bg);
}
body {
  font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei", "Helvetica Neue", sans-serif;
  color: var(--text); font-size: 15px; line-height: 1.55;
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
}
/* v25.43：顶部渐变光晕改用固定定位层，替代 background-attachment:fixed
   —— iOS / 微信内置内核对 fixed 背景会错位拉伸，换成这一层后视觉一致且不影响滚动 */
body::before {
  content: "";
  position: fixed;
  top: 0; left: 0; right: 0; bottom: 0;
  z-index: -1;
  background: radial-gradient(1100px 460px at 50% -8%, #e4ebff 0%, rgba(228, 235, 255, 0) 62%);
  pointer-events: none;
}
/* v25.43：dvh = 动态视口高度，微信内有地址栏/工具栏时按可视高度算，底部不会被截掉 */
#app { max-width: 900px; margin: 0 auto; padding: 12px 14px 64px; min-height: 100vh; min-height: 100dvh; }

.boot-loading { display: flex; flex-direction: column; align-items: center; padding: 90px 0; color: var(--muted); }
.spinner { width: 34px; height: 34px; border: 3px solid var(--line); border-top-color: var(--primary); border-radius: 50%; animation: spin .8s linear infinite; margin-bottom: 12px; }
@keyframes spin { to { transform: rotate(360deg); } }

/* ---------- v25.16 下拉刷新提示条（贴顶固定，不占文档流也不推动页面） ---------- */
.pull-hint {
  position: fixed; left: 0; right: 0; top: 0; z-index: 60;
  display: flex; align-items: flex-end; justify-content: center;
  height: 0; overflow: hidden; pointer-events: none;
  background: linear-gradient(180deg, rgba(58, 91, 246, .16), rgba(58, 91, 246, .05));
  color: var(--primary); font-size: 13px; font-weight: 700;
  transition: height .08s linear;
}
.pull-hint span { padding-bottom: 8px; }
/* 手机端表头空间紧张：刷新按钮只留图标 */
.userchip #btn-refresh { padding: 5px 8px; }
@media (max-width: 640px) {
  .userchip #btn-refresh .rt { display: none; }
}
/* v25.16 企业微信「同步/发送失败」与「🩺 自检」的结果框：长文案要能留住看懂，不能只靠 toast */
.wx-check { margin-top: 10px; padding: 10px 12px; border-radius: 12px; font-size: 13px; line-height: 1.65; }
.wx-check.err-box { background: #fff2f2; border: 1px solid #ffc9c9; color: var(--danger); }
.wx-check.chk-box { background: #f4f8ff; border: 1px solid #d9e3ff; color: var(--text); }
.wx-check.chk-box b { color: var(--text); }
.wx-check .muted { margin-top: 4px; }
.draft-box { margin-top: 10px; padding: 10px 12px; border-radius: 12px; font-size: 13px; line-height: 1.7;
  background: #f7f9fb; border: 1px solid #e3e8ef; color: var(--text);
  white-space: pre-wrap; word-break: break-all; max-height: 260px; overflow: auto; user-select: all; }
/* 「放行可信IP」操作台：把要加的 IP 摆在最显眼的位置，配按钮直接操作 */
.ipfix { margin-top: 10px; padding: 10px 12px; border-radius: 10px; background: #fffaf0; border: 1px dashed #f0b429; }
.ipfix-lbl { font-size: 12px; color: #8a6100; margin-bottom: 4px; }
.ipfix-ip {
  font-family: ui-monospace, SFMono-Regular, Consolas, monospace;
  font-size: 17px; font-weight: 700; letter-spacing: .5px; color: #1a1a1a;
  background: #fff; border: 1px solid #e6d3a3; border-radius: 8px;
  padding: 8px 10px; margin-bottom: 8px; word-break: break-all; user-select: all;
}
.ipfix .btn-row { margin-top: 0; }

/* ---------- 顶栏 ---------- */
.topbar {
  position: sticky; top: 0; z-index: 30;
  /* v25.44：minmax(0,1fr) 替代 1fr —— 否则按钮组会把列撑破、溢出到圆角框外（微信内核常见） */
  display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); align-items: center; gap: 8px;
  padding: 12px 16px; margin-bottom: 16px;
  background: rgba(255, 255, 255, .88); backdrop-filter: blur(12px);
  border: 1px solid var(--line); border-radius: 18px; box-shadow: var(--shadow-sm);
}
.topbar .brand { grid-column: 2; justify-self: center; display: flex; align-items: center; gap: 10px; }
.brand-logo {
  width: 40px; height: 40px; border-radius: 12px; background: var(--grad); color: #fff;
  display: flex; align-items: center; justify-content: center; font-size: 19px;
  box-shadow: 0 6px 14px -6px rgba(58, 79, 240, .7);
}
img.brand-logo { background: #fff; object-fit: contain; padding: 2px; }
/* v24：标题两行严格左对齐（以前 b/small 渲染差异总有一两像素的错位感） */
.brand-txt { text-align: left; }
.brand-txt b { font-size: 20px; font-weight: 800; letter-spacing: -.3px; display: block; line-height: 1.15; }
.brand-txt small { display: block; margin-top: 2px; font-size: 12px; line-height: 1.2; color: var(--muted); font-weight: 400; }
.userchip { grid-column: 3; justify-self: end; display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--muted); flex-wrap: wrap; justify-content: flex-end; min-width: 0; }

/* v25.44 窄屏（含微信内）：顶栏改为两行——品牌一行、按钮组一行，彻底杜绝按钮被挤出框外 */
@media (max-width: 430px) {
  .topbar { grid-template-columns: minmax(0, 1fr); gap: 10px; padding: 10px 12px; }
  /* v25.47：窄屏顶栏两行时，品牌名居中、按钮组居中，不再贴左也不再溢出 */
  .topbar .brand { grid-column: 1; justify-self: center; }
  .userchip { grid-column: 1; justify-self: stretch; justify-content: center; }
}
.userchip .uname { font-weight: 600; color: var(--text); }
/* v25.47：名字过长时自己压缩并省略，避免把整行撑出顶栏 */
.userchip .uname { max-width: 6.5em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.userchip { overflow: hidden; }
.role-badge { padding: 3px 10px; border-radius: 99px; font-size: 12px; background: var(--primary-soft); color: var(--primary); font-weight: 700; }
.role-badge.admin { background: var(--warn-soft); color: var(--warn); }
.role-badge.staff { background: var(--success-soft); color: var(--success); }

/* ---------- 卡片 ---------- */
.card {
  background: var(--card); border: 1px solid #eef1f7; border-radius: var(--radius);
  box-shadow: var(--shadow-sm); padding: 18px; margin-bottom: 14px;
}
.card h3 {
  font-size: 15.5px; font-weight: 700; margin-bottom: 14px;
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
}
.card h3::before { content: ""; width: 4px; height: 15px; border-radius: 3px; background: var(--grad); flex: none; }
.card h3 .sub { font-size: 12.5px; color: var(--muted); font-weight: 400; margin-left: 2px; }

/* ---------- 表单 ---------- */
label.fld { display: block; margin-bottom: 14px; font-size: 13px; color: var(--muted); font-weight: 500; }
label.fld input, label.fld select, label.fld textarea {
  display: block; width: 100%; margin-top: 6px; padding: 12px 14px; font-size: 15px;
  border: 1.5px solid var(--line); border-radius: 12px; background: #fbfcfe; color: var(--text);
  outline: none; transition: .15s; font-family: inherit;
}
label.fld input:focus, label.fld select:focus, label.fld textarea:focus {
  border-color: var(--primary); background: #fff; box-shadow: 0 0 0 4px rgba(58, 91, 246, .12);
}
textarea { resize: vertical; min-height: 130px; line-height: 1.7; }
.btn-row input, .btn-row select, .imp-map select {
  padding: 11px 12px; font-size: 14px; border: 1.5px solid var(--line); border-radius: 11px;
  background: #fbfcfe; color: var(--text); outline: none; font-family: inherit; max-width: 100%;
}
.btn-row input:focus, .btn-row select:focus, .imp-map select:focus { border-color: var(--primary); background: #fff; }
.form-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(165px, 1fr)); gap: 0 12px; }

/* ---------- 按钮 ---------- */
.btn {
  display: inline-block; border: none; border-radius: 12px; padding: 12px 20px; font-size: 15px;
  background: var(--grad); color: #fff; cursor: pointer; font-weight: 600; font-family: inherit;
  box-shadow: 0 6px 16px -8px rgba(58, 79, 240, .9); transition: .15s;
}
.btn:hover { transform: translateY(-1px); box-shadow: 0 8px 20px -8px rgba(58, 79, 240, .95); }
.btn:active { transform: translateY(0); opacity: .92; }
.btn.block { width: 100%; }
.btn.ghost { background: #fff; color: var(--primary); border: 1.5px solid #cfd8ff; box-shadow: none; }
.btn.light { background: var(--primary-soft); color: var(--primary); box-shadow: none; }
.btn.light:hover { background: #e3eaff; }
.btn.small { padding: 7px 13px; font-size: 13px; border-radius: 10px; box-shadow: none; font-weight: 600; }
.btn.small:hover { transform: none; }
.btn.danger { background: linear-gradient(135deg, #f5615f, #d93a3f); box-shadow: 0 6px 16px -8px rgba(217, 58, 63, .8); }
.btn.success { background: linear-gradient(135deg, #2ec27e, #0f9752); box-shadow: 0 6px 16px -8px rgba(15, 151, 82, .7); }
.btn:disabled { opacity: .5; cursor: not-allowed; transform: none; }
.btn-row { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; margin-top: 12px; }
.btn-row > input, .btn-row > select { flex: 1; min-width: 120px; }
.linklike { background: none; border: none; color: var(--primary); cursor: pointer; font-size: 13px; padding: 4px 6px; font-family: inherit; }
.linklike:hover { text-decoration: underline; }
.err-msg { background: var(--danger-soft); color: var(--danger); padding: 11px 14px; border-radius: 12px; font-size: 13.5px; margin: 12px 0; border: 1px solid #fbdada; }
.ok-msg { background: var(--success-soft); color: var(--success); padding: 11px 14px; border-radius: 12px; font-size: 13.5px; margin: 12px 0; border: 1px solid #cfeedd; }
.hint { font-size: 12.5px; color: var(--muted); margin-top: 10px; line-height: 1.7; }

/* ---------- 登录 ---------- */
.auth-wrap { max-width: 440px; margin: 46px auto 0; animation: fadeUp .45s ease; }
@keyframes fadeUp { from { opacity: 0; transform: translateY(14px); } }
.auth-hero { text-align: center; margin-bottom: 20px; }
.auth-mark {
  width: 74px; height: 74px; margin: 0 auto 14px; border-radius: 22px; background: var(--grad);
  display: flex; align-items: center; justify-content: center; font-size: 36px;
  box-shadow: 0 14px 30px -12px rgba(58, 79, 240, .75);
}
.auth-hero h1 { font-size: 23px; font-weight: 800; letter-spacing: -.5px; }
.auth-hero p { color: var(--muted); font-size: 13.5px; margin-top: 6px; }
.auth-card { padding: 24px; box-shadow: var(--shadow-md); }
/* v25.47：登录卡标题居中 */
.auth-card-title { font-size: 16px; font-weight: 700; margin-bottom: 16px; text-align: center; }
.auth-feats { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 16px; justify-content: center; }
.auth-feats span { background: #f5f7fc; border: 1px solid var(--line); border-radius: 99px; padding: 5px 12px; font-size: 12px; color: var(--muted); }
.auth-tabs { display: flex; background: #eef1f7; border-radius: 13px; padding: 4px; margin-bottom: 16px; }
.auth-tabs button { flex: 1; border: none; background: none; padding: 9px; border-radius: 10px; font-size: 14px; cursor: pointer; color: var(--muted); font-weight: 600; }
.auth-tabs button.on { background: #fff; color: var(--primary); box-shadow: var(--shadow-sm); }

/* ---------- 统计卡 ---------- */
.stat-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px; }
.stat-grid.three { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.stat-grid.two { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.stat-grid.four { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.stat {
  background: var(--card); border: 1px solid var(--line); border-radius: var(--radius);
  box-shadow: var(--shadow-sm); padding: 15px 10px; text-align: center; transition: .15s;
}
.stat:hover { transform: translateY(-2px); box-shadow: var(--shadow-md); }
.stat .ico {
  width: 34px; height: 34px; border-radius: 11px; margin: 0 auto 8px; font-size: 17px;
  display: flex; align-items: center; justify-content: center; background: var(--primary-soft);
}
.stat .num { font-size: 26px; font-weight: 800; letter-spacing: -.6px; color: var(--primary); line-height: 1.15; }
.stat .num.money { color: var(--danger); }
.stat .lbl { font-size: 12px; color: var(--muted); margin-top: 3px; }

/* ---------- 日历 ---------- */
/* v25.44：改 nowrap —— 月份标题自己收缩，‹ › 永远留在同一行 */
.cal-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 14px; gap: 10px; flex-wrap: nowrap; }
.cal-head .m-title { font-size: 16.5px; font-weight: 700; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cal-nav { display: flex; gap: 8px; flex: 0 0 auto; }
.cal-nav button {
  border: 1.5px solid var(--line); background: #fff; border-radius: 11px; width: 36px; height: 36px;
  font-size: 17px; cursor: pointer; color: var(--text); transition: .15s;
}
.cal-nav button:hover { border-color: var(--primary); color: var(--primary); }
.cal-grid { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 7px; }
/* v25.45：grid 子项默认 min-width:auto，内容（日期+"休"）会把格子撑出轨道 3px，
   表现为周日那一列（3/10/17…）有一半跑到白色区域外面 —— 强制归零即可 */
.cal-grid > *, .stat-grid > *, .topbar > * { min-width: 0; }
.cal-dow { text-align: center; font-size: 12px; color: var(--muted); padding: 5px 0; font-weight: 600; }
.cal-cell {
  /* v25.45：宽度锁死为网格轨道宽 —— aspect-ratio 会反向把格子撑宽 3~4px，
     导致周日列（3/10/17…）越过日历白色区域边界 */
  width: 100%; max-width: 100%;
  /* v25.48：align-self:start 才能让 aspect-ratio 生效（默认 stretch 会把格子拉成行高，变成扁的） */
  align-self: start;
  aspect-ratio: 1; border-radius: 13px; display: flex; flex-direction: column; align-items: center; justify-content: center;
  font-size: 15px; position: relative; background: #fff; border: 1.5px solid var(--line); user-select: none; transition: .14s;
  /* v25.44：内核不支持 aspect-ratio 时（老 X5 / iOS<15），格子会高度塌陷导致日期和"休"溢出到格子外，
     这里给一个兜底高度；支持 aspect-ratio 的浏览器会由下面 @supports 还原成正方形 */
  min-height: 46px;
}
/* 注：aspect-ratio 在本布局里会被内容最小高度压住（宽>内容高时仍按内容高），
   因此正方形由 app.js 的 fixCalSquare() 用 JS 精确设置 height=width，兼容所有内核 */
.cal-cell .d, .cal-cell .tag { overflow: hidden; max-width: 100%; }
.cal-cell .d { font-weight: 600; }
.cal-cell.off { background: #f5f7fa; color: #adb5c4; border-color: transparent; }
.cal-cell.off .d { font-weight: 400; }
.cal-cell.leave {
  background: linear-gradient(135deg, #ff7176, #e5484d); color: #fff; border-color: transparent;
  box-shadow: 0 6px 14px -6px rgba(229, 72, 77, .6);
}
.cal-cell.markable { cursor: pointer; }
.cal-cell.markable:hover { transform: translateY(-2px); box-shadow: var(--shadow-sm); border-color: var(--primary); }
.cal-cell.markable:active { transform: scale(.94); }
.cal-cell.past { opacity: .45; }
.cal-cell.today { box-shadow: 0 0 0 2.5px var(--primary) inset; }
.cal-cell.today.leave { box-shadow: 0 0 0 2.5px #fff inset, 0 6px 14px -6px rgba(229, 72, 77, .6); }
.cal-cell .tag { font-size: 9px; color: var(--muted); line-height: 1; }
.cal-cell.leave .tag { color: rgba(255, 255, 255, .9); }
.legend { display: flex; gap: 14px; font-size: 12px; color: var(--muted); margin-top: 12px; flex-wrap: wrap; }
.legend i { display: inline-block; width: 13px; height: 13px; border-radius: 4px; margin-right: 5px; vertical-align: -2px; }

/* ---------- 表格 ---------- */
.tbl-wrap { overflow-x: auto; margin: 0 -4px; padding: 0 4px; }
table.tbl { width: 100%; border-collapse: separate; border-spacing: 0; font-size: 13.5px; min-width: 640px; }
.tbl th {
  text-align: left; padding: 11px 12px; background: #f7f9fc; color: var(--muted); font-weight: 600;
  white-space: nowrap; font-size: 12.5px; border-bottom: 1px solid var(--line);
}
.tbl th:first-child { border-top-left-radius: 10px; }
.tbl th:last-child { border-top-right-radius: 10px; }
.tbl td { padding: 11px 12px; border-bottom: 1px solid #f1f4f9; white-space: nowrap; }
.tbl tbody tr:hover td { background: #fafbfe; }
.tbl tr.total td { font-weight: 700; background: #f7f9fc; border-top: 1px solid var(--line); border-bottom: none; }
.pill { padding: 3px 10px; border-radius: 99px; font-size: 12px; font-weight: 700; display: inline-block; }
.pill.ok { background: var(--success-soft); color: var(--success); }
.pill.wait { background: var(--warn-soft); color: var(--warn); }
.pill.no { background: #f1f3f7; color: var(--muted); }
.pill.warn { background: var(--danger-soft); color: var(--danger); }
.pill.tap { cursor: pointer; }
.pill.tap:hover { filter: brightness(.95); }

/* ---------- 缴费：收款码 + 付款截图 ---------- */
.pay-qr-box { display: flex; gap: 14px; align-items: flex-start; flex-wrap: wrap; }
.pay-qr { flex: 0 0 140px; }
.pay-qr img { width: 140px; height: 140px; object-fit: contain; background: #fff; border: 1.5px solid var(--line); border-radius: 14px; padding: 5px; }
.pay-qr img, .qr-prev img { cursor: zoom-in; -webkit-touch-callout: default; }
/* v25.1：收款码可点击 → 跳到学校配好的付款链接 */
.pay-qr.has-link img { cursor: pointer; }
.pay-qr-go {
  display: block; margin-top: 7px; text-align: center; font-size: 12.5px; font-weight: 700;
  color: #fff; background: var(--primary); border-radius: 9px; padding: 5px 0; line-height: 1.5;
}
.pay-qr-only-link {
  width: 140px; height: 140px; border-radius: 14px; border: 1.5px solid var(--line);
  background: linear-gradient(160deg, #f4f7ff, #e6edff); cursor: pointer;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 9px;
}
.pay-qr-big { font-size: 34px; line-height: 1; }
.pay-qr-only-link .pay-qr-go { width: 76%; margin-top: 0; }
.pay-qr-txt { flex: 1; min-width: 130px; }
.pay-tip {
  background: #f4f7ff; border: 1px solid #dfe6fb; border-radius: 12px;
  padding: 10px 12px; margin: 10px 0; font-size: 13px; line-height: 1.75;
}
.pay-tip b { color: var(--primary); }
/* v25.0：确认单 vs 缴费「两件事」的说明条，比普通提示更醒目 */
.pay-tip.split-tip {
  background: #fff8ec; border-color: #f6ddb4; border-left: 4px solid var(--warn, #e8a33d);
}
.pay-tip.split-tip b { color: #b6720a; }
.pay-tip.split-tip .muted { color: var(--muted); font-size: 12px; }
.pay-qr-txt b { font-size: 15px; }
.pay-amt { font-size: 23px; font-weight: 800; color: var(--danger); margin: 4px 0 6px; }
.pay-done { background: var(--success-soft); color: var(--success); border-radius: 11px; padding: 9px 12px; font-size: 14px; font-weight: 600; margin: 10px 0; display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; }
.pay-todo { background: var(--warn-soft); color: var(--warn); border-radius: 11px; padding: 9px 12px; font-size: 14px; font-weight: 600; margin: 10px 0; }
.qr-pick { display: flex; align-items: center; gap: 10px; margin: 6px 0; flex-wrap: wrap; }
.qr-prev img { max-width: 170px; max-height: 170px; border-radius: 12px; border: 1.5px solid var(--line); margin-top: 8px; background: #fff; padding: 4px; }
@media (max-width: 900px) {
  .pay-qr { flex: 0 0 116px; }
  .pay-qr img { width: 116px; height: 116px; }
  .pay-qr-only-link { width: 116px; height: 116px; }
  .pay-qr-big { font-size: 27px; }
  .pay-amt { font-size: 20px; }
}

/* ---------- 确认单 ---------- */
.confirm-card { border: 1px solid var(--line); border-radius: 15px; padding: 16px; margin-bottom: 12px; background: #fff; box-shadow: var(--shadow-sm); }
.confirm-card.pending { border-color: #ffd9a8; background: linear-gradient(180deg, #fffaf2, #fff); }
.confirm-card h4 { font-size: 15px; margin-bottom: 10px; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.confirm-rows { display: grid; grid-template-columns: 1fr 1fr; gap: 7px 16px; font-size: 13.5px; margin-bottom: 10px; }
.confirm-rows b { color: var(--danger); font-size: 15px; }
.leave-dates { font-size: 12.5px; color: var(--muted); margin-bottom: 12px; }
/* v25.26：本月未就餐 / 0 元确认单 */
.cf-zero { background: var(--success-soft); color: var(--success); border-radius: 10px; padding: 10px 12px; font-size: 15px; font-weight: 700; margin-bottom: 10px; }
.cf-zero.big { font-size: 17px; padding: 13px 14px; }
.pill.zero { background: var(--success-soft); color: var(--success); }
/* v25.27：往期确认单折叠卡 + 餐费统计 */
.conf-history { padding: 0; }
.conf-h-sum { display: flex; align-items: center; gap: 10px; padding: 13px 14px; cursor: pointer; list-style: none; }
.conf-h-sum::-webkit-details-marker { display: none; }
.conf-h-sum .ch-t { font-weight: 700; font-size: 14.5px; }
.conf-h-sum .sub { flex: 1; color: var(--muted); font-size: 12.5px; }
.conf-history[open] .conf-h-sum .pc-arrow { transform: rotate(90deg); }
.conf-history .confirm-card { margin: 0 12px 10px; }
.conf-title-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.conf-stat-btn { flex: 0 0 auto; width: auto; margin: 0; padding: 7px 13px; font-size: 12.5px; font-weight: 700; }
.stat-range { display: flex; gap: 10px; margin-bottom: 6px; }
.stat-range .fld { flex: 1; }
.st-rows { max-height: 46vh; overflow-y: auto; }
.st-row { display: flex; align-items: center; gap: 10px; padding: 8px 4px; border-bottom: 1px solid var(--line, #eef1f7); font-size: 13.5px; }
.st-row span:first-child { flex: 1; }
.st-row b { color: var(--danger); }
.st-row i { font-style: normal; font-size: 12px; font-weight: 700; border-radius: 6px; padding: 2px 7px; }
.st-row i.ok { background: var(--success-soft); color: var(--success); }
.st-row i.wait { background: #fff4e0; color: #b46b00; }

/* ---------- 管理端 tab ---------- */
.subtabs { display: flex; gap: 6px; overflow-x: auto; margin-bottom: 16px; padding: 4px; background: #eef1f7; border-radius: 14px; }
.subtabs button {
  border: none; background: transparent; padding: 9px 16px; border-radius: 11px; font-size: 13.5px;
  cursor: pointer; white-space: nowrap; color: var(--muted); font-weight: 600; transition: .15s; font-family: inherit;
}
.subtabs button:hover { color: var(--primary); }
.subtabs button.on { background: #fff; color: var(--primary); box-shadow: var(--shadow-sm); }
.ov-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 10px; }
.ov-item { background: #fafbfe; border: 1px solid var(--line); border-radius: 12px; padding: 12px 14px; }
.ov-item .n { font-size: 20px; font-weight: 800; color: var(--primary); letter-spacing: -.4px; }
.ov-item .t { font-size: 12.5px; color: var(--muted); }

/* ---------- 导入区 ---------- */
.import-tabs { display: inline-flex; gap: 6px; background: #eef1f7; padding: 4px; border-radius: 13px; margin-bottom: 14px; }
.import-tabs button { border: none; background: transparent; padding: 8px 15px; border-radius: 10px; font-size: 13px; font-weight: 600; color: var(--muted); cursor: pointer; font-family: inherit; transition: .15s; }
.import-tabs button.on { background: #fff; color: var(--primary); box-shadow: var(--shadow-sm); }
.drop-zone {
  border: 2px dashed #c8d3f2; border-radius: 16px; padding: 28px 18px; text-align: center; cursor: pointer;
  background: #fafcff; transition: .15s;
}
.drop-zone:hover, .drop-zone.over { border-color: var(--primary); background: #f1f4ff; }
.dz-icon { font-size: 32px; line-height: 1; }
.dz-title { font-weight: 700; margin-top: 8px; font-size: 14.5px; }
.dz-sub { color: var(--muted); font-size: 12.5px; margin-top: 5px; }
.imp-meta { font-size: 13px; color: var(--muted); margin: 14px 0 4px; }
.imp-meta b { color: var(--primary); font-size: 15px; }
.imp-map { display: flex; gap: 12px; flex-wrap: wrap; margin: 10px 0 4px; }
.imp-map .m-item { font-size: 12px; color: var(--muted); display: flex; flex-direction: column; gap: 4px; }
.imp-map .m-item b { font-weight: 600; color: var(--text); }

/* ---------- toast ---------- */
#toast-box { position: fixed; left: 50%; bottom: 32px; transform: translateX(-50%); z-index: 99; display: flex; flex-direction: column; gap: 8px; align-items: center; width: max-content; max-width: 90vw; }
.toast {
  background: rgba(24, 30, 44, .94); color: #fff; padding: 11px 20px; border-radius: 13px; font-size: 14px;
  box-shadow: 0 10px 30px -8px rgba(0, 0, 0, .35); animation: pop .22s ease; max-width: 90vw;
  backdrop-filter: blur(6px);
}
.toast.err { background: linear-gradient(135deg, #f5615f, #d93a3f); }
.toast.ok { background: linear-gradient(135deg, #2ec27e, #0f9752); }
@keyframes pop { from { opacity: 0; transform: translateY(10px); } }

.section-title { font-size: 16.5px; font-weight: 800; margin: 22px 0 10px; letter-spacing: -.3px; }
.muted { color: var(--muted); font-size: 13px; }
.mt8 { margin-top: 8px; } .mt16 { margin-top: 16px; }
code.inline { background: var(--primary-soft); color: var(--primary); padding: 2px 7px; border-radius: 7px; font-size: 12.5px; font-weight: 600; }

@keyframes cardIn { from { opacity: 0; transform: translateY(10px); } }
#admin-body > .card, .stat { animation: cardIn .25s ease both; }

/* ---------- 顶栏多孩切换 / 确认进度 ---------- */
/* 孩子切换：表头里一排孩子名，选中的蓝底白字，点另一个就切过去
   v24.1：孩子多时限高滚动（手机约 3 行），别把日历顶出屏幕、看起来像卡住 */
.kid-switch {
  grid-column: 1 / -1; justify-self: center;
  display: flex; gap: 8px; flex-wrap: wrap; justify-content: center;
  max-height: 118px; overflow-y: auto; -webkit-overflow-scrolling: touch;
  scrollbar-width: none; padding: 1px;
}
.kid-switch::-webkit-scrollbar { display: none; }
.kid-chip {
  display: flex; align-items: baseline; gap: 6px; padding: 6px 14px; border-radius: 99px;
  border: 1.5px solid var(--line); background: #fff; cursor: pointer; font-family: inherit;
  font-size: 13.5px; color: var(--muted); transition: .14s;
}
.kid-chip b { font-weight: 700; color: var(--text); }
.kid-chip small { font-size: 11.5px; }
.kid-chip:not(.on):hover { border-color: var(--primary); color: var(--primary); }
.kid-chip.on { background: var(--primary); border-color: var(--primary); box-shadow: 0 4px 10px -4px rgba(58, 91, 246, .6); }
.kid-chip.on b, .kid-chip.on small { color: #fff; }
/* 别的账号的孩子（点一下免密切号登录）：浅蓝底做区分 */
.kid-chip.kid-x { border-style: dashed; border-color: #b9c6f5; background: #f6f8ff; }

/* ---------- 「学生与账号」手机端分组缩略按钮 ---------- */
.roster-chips { display: none; }
@media (max-width: 620px) {
  /* v24.4：四个功能按钮正好一行（等宽四格），不再横向溢出一点 */
  .roster-chips {
    display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 6px; padding: 2px 0 8px;
  }
  .roster-chips::-webkit-scrollbar { display: none; }
  .roster-chips button {
    min-width: 0; padding: 7px 2px; border-radius: 99px; border: 1.5px solid var(--line);
    background: #fff; font-family: inherit; font-size: 12px; font-weight: 600; color: var(--muted);
    white-space: nowrap; cursor: pointer; transition: .14s; text-align: center;
    overflow: hidden; text-overflow: ellipsis; letter-spacing: -.2px;
  }
  .roster-chips button.on { background: var(--primary); border-color: var(--primary); color: #fff; box-shadow: 0 4px 10px -4px rgba(58, 91, 246, .6); }
}

.conf-bar { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 6px; }
.cb-seg { flex: 1; min-width: 92px; text-align: center; padding: 9px 6px; border-radius: 11px; font-size: 13px; font-weight: 700; }
.cb-seg.ok { background: var(--success-soft); color: var(--success); }
.cb-seg.wait { background: var(--warn-soft); color: var(--warn); }
.cb-seg.no { background: #f1f3f7; color: var(--muted); }

.pill .x { border: none; background: transparent; color: var(--muted); cursor: pointer; font-size: 12px; margin-left: 4px; padding: 0 2px; font-family: inherit; }
.pill .x:hover { color: var(--danger); }
.hidden-inp { margin-top: 6px; }

/* ---------- PWA 安装弹窗 ---------- */
.modal-mask {
  position: fixed; inset: 0; z-index: 90;
  background: rgba(20, 26, 38, .45);
  -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px);
  display: flex; align-items: center; justify-content: center; padding: 20px;
  animation: fadeIn .18s ease;
}
.modal { width: 100%; max-width: 430px; padding: 24px; animation: cardIn .2s ease; }
.modal h3 { margin-bottom: 4px; }
.guide-steps { margin: 14px 0 6px; padding-left: 20px; font-size: 14px; line-height: 2.05; }
.guide-steps b { color: var(--primary); }
@keyframes fadeIn { from { opacity: 0; } }

/* ---------- 登录后的校徽 → 班徽翻转动画 ---------- */
.badge-intro {
  position: fixed; inset: 0; z-index: 200;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  background: radial-gradient(circle at 50% 42%, #fff 0%, #eef1fb 45%, #e2e8fa 100%);
  animation: fadeIn .25s ease;
  transition: opacity .4s ease;
}
.badge-intro.out { opacity: 0; }
/* v23.1：彩色光圈底已取消（家长反馈不要色块），开场只保留班徽上的闪光扫过（.bi-shine） */
.bi-stage { position: relative; width: 310px; height: 310px; perspective: 1400px; }
.bi-card {
  position: relative; width: 100%; height: 100%;
  transform-style: preserve-3d;
  animation: biIn .8s cubic-bezier(.2,.9,.25,1.1) both;
  transition: transform .95s cubic-bezier(.55,.06,.35,1);
}
/* 两段翻转（v13 改向左转）：spin1 = 转一整圈还是校徽；spin2 = 再翻半圈翻出班徽 */
.badge-intro.spin1 .bi-card { animation: none; transform: rotateY(-360deg); }
.badge-intro.spin2 .bi-card { animation: none; transform: rotateY(-540deg); }
@keyframes biIn {
  from { transform: rotateY(-180deg) scale(.4); opacity: 0; }
  to { transform: rotateY(0deg) scale(1); opacity: 1; }
}
.bi-face {
  position: absolute; inset: 0; backface-visibility: hidden; -webkit-backface-visibility: hidden;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 12px;
}
.bi-back { transform: rotateY(180deg); }
/* 图片保持原样（透明底直接透出背景），大小由超管端设置控制（inline style） */
.bi-img { width: 80%; height: 80%; object-fit: contain; filter: drop-shadow(0 12px 26px rgba(40, 60, 140, .22)); }
.bi-fallback {
  width: 80%; height: 80%; border-radius: 50%;
  background: linear-gradient(150deg, #3a5bf6, #7b6ef6);
  color: #fff; display: flex; flex-direction: column; align-items: center; justify-content: center;
  box-shadow: 0 12px 26px rgba(58,91,246,.28);
}
.bi-fallback b { font-size: 40px; line-height: 1; }
.bi-fallback span { font-size: 17px; opacity: .9; margin-top: 5px; }
/* v24.2：班徽图本体容器 —— 闪光/光圈只覆盖这块，下面的班名文字不再参与发光（否则圆心被文字带偏、看着歪） */
.bi-figure { position: relative; flex: 0 0 auto; display: flex; align-items: center; justify-content: center; --shine: 100%; }
.bi-figure > .bi-img, .bi-figure > .bi-fallback { width: 100%; height: 100%; }
/* 班徽上的光泽划过（v13 更闪：更宽的光带 + 二次回闪 + 中心爆闪）
   v24.3：大小由 --shine 控制（默认按图案实际大小，班徽设置里可调 0=自动）；边缘用径向遮罩羽化，不再是一圈硬边白 */
.bi-shine {
  position: absolute; left: 50%; top: 50%; width: var(--shine); height: var(--shine);
  transform: translate(-50%, -50%);
  pointer-events: none; overflow: hidden; border-radius: 50%;
  -webkit-mask-image: radial-gradient(circle, #000 52%, rgba(0,0,0,.5) 78%, rgba(0,0,0,0) 100%);
  mask-image: radial-gradient(circle, #000 52%, rgba(0,0,0,.5) 78%, rgba(0,0,0,0) 100%);
}
.bi-shine::before {
  content: ''; position: absolute; top: -20%; bottom: -20%; left: -100%; width: 60%;
  background: linear-gradient(105deg, rgba(255,255,255,0) 0%, rgba(255,255,255,.55) 45%, rgba(255,255,255,.78) 50%, rgba(255,255,255,.55) 55%, rgba(255,255,255,0) 100%);
  filter: drop-shadow(0 0 7px rgba(255,255,255,.45));
  transform: skewX(-18deg);
}
/* 中心爆闪：一枚白星光在班徽中央绽开（v24.3 收敛了一圈，别太扎眼） */
.bi-shine::after {
  content: ''; position: absolute; left: 50%; top: 50%; width: 22%; height: 22%; margin: 0;
  transform: translate(-50%, -50%) scale(.2);
  background: radial-gradient(circle, rgba(255,255,255,.95) 0%, rgba(255,255,255,.6) 30%, rgba(255,255,255,0) 70%);
  opacity: 0;
}
.badge-intro.shine .bi-shine::before { animation: biShine .95s cubic-bezier(.3,.1,.3,1) .05s both, biShine2 .8s ease-in .95s both; }
.badge-intro.shine .bi-shine::after { animation: biSpark .7s ease-out .55s both; }
@keyframes biShine {
  from { left: -100%; opacity: 0; }
  12% { opacity: 1; }
  to { left: 140%; opacity: 0; }
}
@keyframes biShine2 {
  from { left: -100%; opacity: 0; }
  15% { opacity: .9; }
  to { left: 140%; opacity: 0; }
}
@keyframes biSpark {
  0% { opacity: 0; transform: translate(-50%, -50%) scale(.2) rotate(0deg); }
  35% { opacity: 1; transform: translate(-50%, -50%) scale(1.6) rotate(40deg); }
  100% { opacity: 0; transform: translate(-50%, -50%) scale(3.2) rotate(90deg); }
}
.bi-cap {
  flex: 0 0 auto; font-size: 15px; font-weight: 700; color: var(--primary); letter-spacing: 1px;
  /* v23.1：去掉白色椭圆底，直接就是文字 */
}
.bi-skip {
  position: absolute; right: 18px; top: 18px; font-size: 13px; color: var(--muted);
  background: #fff; border: 1px solid var(--line); border-radius: 18px; padding: 5px 14px; cursor: pointer;
}
.bi-skip:hover { color: var(--primary); }

/* ---------- 标注分级颜色（v13 提亮）：班级橙 / 年级紫 / 全校红，都是显眼色 ---------- */
/* 三种范围要一眼分得开：班级=橙、年级=紫、全校=蓝（原来全校是红，跟班级的橙太像） */
:root { --pin-class: #1971c2; --pin-grade: #ae3ec9; --pin-school: #e03131; }
.pin-class { color: var(--pin-class); }
.pin-grade { color: var(--pin-grade); }
.pin-school { color: var(--pin-school); }
.cell-pin.pin-class { background: var(--pin-class); }
.cell-pin.pin-grade { background: var(--pin-grade); }
.cell-pin.pin-school { background: var(--pin-school); }
/* 图钉统一用 📌 这个真图钉图标：全校红 / 年级紫 / 班级蓝（v25.21 十三指定：全校红、班级蓝） */
.pin-ic { display: inline-block; font-style: normal; font-size: 13px; line-height: 1; margin: 0 3px 0 1px; vertical-align: -2px; }
.pin-ic::before { content: "📌"; }
.pin-ic.pin-grade { filter: hue-rotate(258deg) saturate(1.15); }
.pin-ic.pin-class { filter: hue-rotate(210deg) saturate(1.5) brightness(.95); }
.pin-ic.pin-school { filter: saturate(1.35); }
/* 日历上的图钉：直接就是 📌，斜着按在日期右上角 */
.cal-pin {
  position: absolute; top: 1px; right: 3px; font-style: normal;
  font-size: 13px; line-height: 1;
  filter: drop-shadow(0 1px 1px rgba(20, 30, 60, .28));
}
.cal-pin.pin-grade { filter: drop-shadow(0 1px 1px rgba(20, 30, 60, .28)) hue-rotate(258deg) saturate(1.15); }
.cal-pin.pin-class { filter: drop-shadow(0 1px 1px rgba(20, 30, 60, .28)) hue-rotate(210deg) saturate(1.5) brightness(.95); }
.cal-pin.pin-school { filter: drop-shadow(0 1px 1px rgba(20, 30, 60, .28)) saturate(1.35); }
.cal-pin + .cal-pin { right: 17px; }
.cal-pin + .cal-pin + .cal-pin { right: 31px; }
.pin-pill { background: rgba(25, 113, 194, .11); }
.pin-pill.pin-class { background: rgba(25, 113, 194, .11); }
.pin-pill.pin-grade { background: rgba(174, 62, 201, .11); }
.pin-pill.pin-school { background: rgba(224, 49, 49, .1); }
.tag.note-tag.pin-class { background: var(--pin-class); }
.tag.note-tag.pin-grade { background: var(--pin-grade); }
.tag.note-tag.pin-school { background: var(--pin-school); }
.ds-ev { display: flex; align-items: flex-start; gap: 10px; border-left: 5px solid var(--pin-school); background: rgba(224,49,49,.07); border-radius: 12px; padding: 14px 15px; margin-bottom: 10px; }
.ds-ev.pin-class { border-color: var(--pin-class); background: rgba(25,113,195,.07); }
.ds-ev.pin-grade { border-color: var(--pin-grade); background: rgba(112,72,232,.07); }
.ds-ev-scope { flex: 0 0 auto; font-size: 13px; font-weight: 700; color: #fff; background: var(--pin-school); border-radius: 7px; padding: 4px 10px; margin-top: 2px; }
.ds-ev.pin-class .ds-ev-scope { background: var(--pin-class); }
.ds-ev.pin-grade .ds-ev-scope { background: var(--pin-grade); }
.ds-ev-body { flex: 1; font-size: 18px; line-height: 1.5; }
.ds-ev-body b { font-weight: 700; }
.ds-ev-body .has-more { float: right; color: var(--primary); font-style: normal; font-size: 14px; font-weight: 700; }
.ev-modal h3 { margin: 6px 0 2px; }
.ev-detail { background: var(--bg-soft, #f7f8fc); border-radius: 10px; padding: 12px 14px; font-size: 14px; line-height: 1.8; margin-top: 8px; }
.ev-img { width: 100%; border-radius: 10px; margin-top: 10px; }
.ev-video { width: 100%; border-radius: 10px; margin-top: 10px; background: #000; }
.ev-link { margin-top: 10px; font-size: 14px; }
.ng-row { margin-bottom: 10px; }
.ng-row:last-child { margin-bottom: 0; }
.ng-t { display: block; font-size: 13px; margin-bottom: 6px; }
.note-item .has-more { float: right; color: var(--primary); font-style: normal; font-weight: 700; }

/* ---------- 管理端小组件：收款码按钮网格 / 日志身份筛选 / 花名册年级折叠 ---------- */
.btn-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
.btn-grid select { grid-column: 1 / -1; width: 100%; }
.btn-grid .btn { width: 100%; margin: 0; justify-content: center; }
@media (min-width: 641px) { .btn-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
/* v25.34 教职工列表「发通知」开关列 */
.tbl .c-notify { white-space: nowrap; }
.tbl .c-notify .btn { padding: 4px 10px; font-size: 12px; }

/* v25.33 操作日志 / 家长活跃度分析 两个主页签（默认停在操作日志） */
.log-main-tabs { display: flex; gap: 8px; flex-wrap: wrap; margin: 2px 0 14px; }
.log-main-tabs .lmt { border: 1px solid var(--line); background: #fff; border-radius: 12px; padding: 10px 18px; font-size: 15px; font-weight: 700; cursor: pointer; color: var(--fg, #222); }
.log-main-tabs .lmt .lmt-n { display: inline-block; margin-left: 4px; padding: 1px 7px; border-radius: 999px; background: var(--bg-soft, #f0f2f7); font-size: 12px; font-weight: 600; }
.log-main-tabs .lmt.on { background: var(--primary); border-color: var(--primary); color: #fff; }
.log-main-tabs .lmt.on .lmt-n { background: rgba(255, 255, 255, .25); }
.log-tabs { display: flex; gap: 6px; flex-wrap: wrap; margin: 4px 0 12px; }
.log-tabs .lt-chip { border: 1px solid var(--line); background: #fff; border-radius: 999px; padding: 5px 14px; font-size: 13px; cursor: pointer; }
.log-tabs .lt-chip.on { background: var(--primary); border-color: var(--primary); color: #fff; }
.log-sec { margin-bottom: 14px; }
.log-sec-t { font-weight: 600; font-size: 14px; margin-bottom: 6px; }
details.ro-sec { border: 1px solid var(--line); border-radius: 12px; margin-bottom: 10px; background: #fff; overflow: hidden; }
details.ro-sec > summary { list-style: none; cursor: pointer; display: flex; align-items: center; gap: 10px; padding: 11px 14px; font-size: 15px; background: var(--bg-soft, #f7f8fc); }
details.ro-sec > summary::-webkit-details-marker { display: none; }
details.ro-sec > summary .ro-arrow { margin-left: auto; font-style: normal; transition: transform .15s; }
details.ro-sec[open] > summary .ro-arrow { transform: rotate(90deg); }
details.ro-sec > summary .muted { font-weight: 400; font-size: 13px; }
details.ro-sec > *:not(summary) { padding: 0 6px; }

/* ---------- 确认单折叠 ---------- */
.confirm-card .conf-head { cursor: default; display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.confirm-card .conf-head[data-toggle] { cursor: pointer; }
.conf-arrow { margin-left: auto; color: var(--muted); font-size: 15px; transition: transform .2s ease; }
.confirm-card.folded .conf-arrow { transform: rotate(-90deg); }
.confirm-card.folded { padding-bottom: 12px; }

/* ---------- 超管：动画大小实时预览 ---------- */
.bp-live { display: flex; gap: 18px; flex-wrap: wrap; margin-bottom: 10px; }
.bp-cell { display: flex; flex-direction: column; align-items: center; gap: 6px; }
.bp-stage {
  position: relative;
  width: 150px; height: 150px; border-radius: 18px; overflow: visible; z-index: 1;
  background: radial-gradient(circle at 50% 42%, #fff 0%, #eef1fb 60%, #e2e8fa 100%);
  display: flex; align-items: center; justify-content: center;
}
.bp-stage img { width: 80%; height: 80%; object-fit: contain; filter: drop-shadow(0 8px 18px rgba(40,60,140,.2)); }
/* v24.3：发光大小预览圈（虚线圆＝闪光扫过的范围） */
.bp-ring {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
  border: 2px dashed var(--primary); border-radius: 50%; opacity: .75; pointer-events: none;
  width: 100%; height: 100%;
}
.bp-cell input[type="range"] { width: 140px; }
.bp-cell label { font-size: 13px; color: var(--text); }

/* 新版本更新条（手机上装着的旧版拉新） */
.upd-bar {
  position: fixed; left: 12px; right: 12px; bottom: 12px; z-index: 300;
  display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap;
  background: #fff; border: 1px solid var(--primary); border-radius: 14px; padding: 10px 14px;
  box-shadow: 0 10px 26px -10px rgba(58, 91, 246, .5); font-size: 13.5px;
}

/* ---------- 老师端身份切换 ---------- */
.view-switch { margin-bottom: 10px; align-items: center; }

/* ---------- 登录页：重名选择 ---------- */
.pick-box { border: 1px solid var(--line); border-radius: 14px; padding: 14px; background: var(--bg-soft, #f7f8fc); }
.pick-title { font-size: 14px; font-weight: 700; margin-bottom: 10px; color: var(--text); }
.pick-list { display: grid; gap: 8px; margin-bottom: 10px; }
.pick-item {
  display: flex; flex-direction: column; align-items: flex-start; gap: 2px;
  border: 1px solid var(--line); background: #fff; border-radius: 12px; padding: 10px 14px;
  cursor: pointer; font-family: inherit; font-size: 15px; color: var(--text);
  transition: all .15s ease;
}
.pick-item:hover { border-color: var(--primary); box-shadow: 0 4px 14px rgba(58,91,246,.15); transform: translateY(-1px); }
.pick-item small { color: var(--muted); font-size: 12px; }

@media (max-width: 620px) {
  .bi-stage { width: 252px; height: 252px; }
  #app { padding: 10px 11px 56px; }
  .stat-grid, .stat-grid.three, .stat-grid.four-m2 { grid-template-columns: repeat(2, 1fr); }
  .confirm-rows { grid-template-columns: 1fr; }
  .card { padding: 15px; }
  .auth-wrap { margin-top: 24px; }
  .cal-cell { font-size: 14px; border-radius: 11px; }
  /* 手机端表头：第一行标题居中，第二行姓名/身份/按钮整条居中（不再挤在右边、左边留空） */
  .topbar { padding: 10px 12px; border-radius: 15px; grid-template-columns: 1fr; justify-items: center; row-gap: 9px; }
  .topbar .brand { grid-column: 1; }
  .userchip {
    grid-column: 1; justify-self: center; justify-content: center; width: fit-content; flex-wrap: nowrap;
    background: #f4f6fc; border: 1px solid #e6eaf5; border-radius: 99px; padding: 4px 10px;
    gap: 6px; white-space: nowrap;
  }
  .userchip .btn { padding: 5px 9px; font-size: 12px; flex: none; }
  .userchip .uname, .userchip .role-badge { flex: none; }
  .brand-txt b { font-size: 18px; }
  .kid-chip { padding: 5px 12px; font-size: 13px; }
}

/* ===== v7：备注提示 / 单日设置弹窗 / 教职工账号 / 单价卡 ===== */
.note-tag { background: var(--warn-soft); color: var(--warn); font-size: 11px; }
.note-card { border-left: 4px solid var(--warn); }
.note-list { display: flex; flex-direction: column; gap: 8px; margin-top: 8px; }
.note-item { display: flex; align-items: center; gap: 10px; background: var(--warn-soft, #fff5e5); border-radius: 10px; padding: 10px 13px; font-size: 15px; line-height: 1.6; }
.note-item b { color: var(--warn); white-space: nowrap; }
.seg-row { display: flex; gap: 10px; margin: 12px 0 4px; }
.seg { flex: 1; padding: 12px; border-radius: 12px; border: 1.5px solid var(--line); background: #fff; font-size: 14.5px; font-weight: 600; color: var(--muted); cursor: pointer; transition: .15s; }
.seg.on { border-color: var(--primary); background: var(--primary-soft, #eef1ff); color: var(--primary); }
.price-card { background: linear-gradient(135deg, #f6f8ff, #fdfbff); }
.price-row { display: flex; justify-content: space-between; align-items: center; gap: 12px; flex-wrap: wrap; }
.staff-form .form-grid.three { grid-template-columns: repeat(3, 1fr); }
@media (max-width: 620px) {
  .staff-form .form-grid.three { grid-template-columns: 1fr; }
  .price-row { flex-direction: column; align-items: stretch; }
}

/* ===== v8：紧凑统计 / 日历重做 / 当日详情 / 班徽设置 / 必填说明 ===== */
[hidden] { display: none !important; }

/* 登录页特性标签：始终一行，不折行 */
.auth-feats { flex-wrap: nowrap !important; gap: 6px; }
.auth-feats span { white-space: nowrap; padding: 5px 10px; font-size: 11.5px; }
@media (max-width: 420px) {
  .auth-feats { gap: 5px; }
  .auth-feats span { font-size: 10.5px; padding: 4px 8px; }
}

/* ---- 家长端紧凑统计条（让日历尽量落在首屏） ---- */
.stat-grid.mini { grid-template-columns: repeat(4, 1fr) !important; gap: 8px; }
.mini-stat {
  background: var(--card); border: 1px solid var(--line); border-radius: 13px;
  box-shadow: var(--shadow-sm); padding: 9px 6px 8px; text-align: center;
  display: flex; flex-direction: column; align-items: center; gap: 1px;
}
.mini-stat .ic {
  width: 22px; height: 22px; border-radius: 7px; font-size: 12px; line-height: 22px;
  background: var(--primary-soft); margin-bottom: 1px;
}
.mini-stat b { font-size: 19px; font-weight: 800; letter-spacing: -.5px; color: var(--primary); line-height: 1.15; }
.mini-stat small { font-size: 11px; color: var(--muted); }
.mini-stat.d .ic { background: var(--danger-soft); } .mini-stat.d b { color: var(--danger); }
.mini-stat.s .ic { background: var(--success-soft); } .mini-stat.s b { color: var(--success); }
.mini-stat.w .ic { background: var(--warn-soft); } .mini-stat.w b { color: var(--warn); }
.mini-stat.w b.money { font-size: 16px; }
@media (max-width: 420px) { .mini-stat b { font-size: 17px; } .mini-stat.w b.money { font-size: 14.5px; } }

/* ---- 日历重做 ---- */
.cal-card { padding-top: 12px; }
.cal-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 12px; }
.cal-head .m-title { font-size: 16px; font-weight: 800; display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.cal-head .m-title .sub { font-size: 12px; font-weight: 500; color: var(--muted); }
.cal-nav { display: flex; gap: 6px; }
.cal-nav button {
  width: 32px; height: 32px; border-radius: 10px; border: 1.5px solid var(--line);
  background: #fff; color: var(--text); font-size: 17px; line-height: 1; cursor: pointer; transition: .15s;
}
.cal-nav button:hover { border-color: var(--primary); color: var(--primary); }
.cal-nav button:active { transform: scale(.93); }

.cal-grid { gap: 6px; }
.cal-dow {
  font-size: 11.5px; color: var(--muted); text-align: center; padding-bottom: 2px; font-weight: 600;
}
.cal-blank { border-radius: 11px; }

.cal-cell {
  aspect-ratio: 1 / .92; min-height: 46px; border-radius: 12px;
  display: flex; align-items: center; justify-content: center;
  font-size: 18px; font-weight: 600; position: relative; user-select: none;
  background: linear-gradient(180deg, #ffffff 0%, #f7f9ff 100%);
  border: 1.5px solid #e4e8f3; color: var(--text);
  cursor: pointer; transition: transform .13s, box-shadow .13s, border-color .13s;
  box-shadow: 0 1px 2px rgba(24, 40, 90, .04);
}
.cal-cell .d { position: relative; z-index: 1; }
.cal-cell:hover { transform: translateY(-2px); border-color: var(--primary); box-shadow: 0 6px 14px -6px rgba(58, 91, 246, .45); }
.cal-cell:active { transform: scale(.94); }

/* ---------- v24.6 请假看板：格子上的人数角标 ---------- */
.lv-badge {
  position: absolute; top: 3px; right: 3px; min-width: 16px; height: 16px; padding: 0 4px;
  border-radius: 99px; background: var(--warn); color: #fff; font-size: 10px; font-weight: 800;
  line-height: 16px; text-align: center; box-shadow: 0 1px 4px rgba(120, 60, 10, .3); z-index: 2;
}
.legend .lv-dot {
  width: 16px; height: 16px; border-radius: 99px; background: var(--warn); color: #fff;
  font-size: 10px; font-weight: 800; line-height: 16px; text-align: center; font-style: normal;
}
/* 某天操作入口卡（上学/休息 · 发提示 · 看请假） */
.hub-stat {
  display: flex; align-items: center; gap: 12px; padding: 12px 14px; border-radius: 14px;
  background: #f6f8ff; border: 1.5px solid var(--line);
}
.hub-stat.on { background: #fff6f0; border-color: #ffd9bf; }
.hub-num {
  flex: none; width: 46px; height: 46px; border-radius: 50%; display: flex; align-items: center;
  justify-content: center; font-size: 22px; font-weight: 800; background: #fff; color: var(--muted);
  border: 2px solid var(--line);
}
.hub-stat.on .hub-num { background: var(--warn); color: #fff; border-color: var(--warn); }
.hub-lbl { font-size: 13px; color: var(--muted); line-height: 1.45; }
.hub-list { display: flex; flex-direction: column; gap: 9px; margin-top: 12px; }
.hub-item {
  display: flex; align-items: center; gap: 12px; width: 100%; padding: 12px 14px; border-radius: 14px;
  border: 1.5px solid var(--line); background: #fff; cursor: pointer; text-align: left;
  font-family: inherit; transition: .15s;
}
.hub-item:hover { border-color: var(--primary); background: #f7faff; }
.hub-item i { font-size: 22px; font-style: normal; }
.hub-item > span { flex: 1; display: block; min-width: 0; }
.hub-item > span b { display: block; font-size: 15px; }
.hub-item > span small { display: block; color: var(--muted); font-size: 12px; margin-top: 2px; }
.hub-item em { color: var(--muted); font-style: normal; font-size: 18px; }
.hub-item.warn > span b { color: var(--warn); }
/* 请假名单逐级下钻 */
.lv-groups, .lv-names { display: flex; flex-direction: column; gap: 8px; margin-top: 10px; }
.lv-group, .lv-name {
  display: flex; align-items: center; gap: 10px; padding: 11px 13px; border-radius: 12px;
  border: 1.5px solid var(--line); background: #fff;
}
.lv-group { cursor: pointer; transition: .15s; }
.lv-group:hover { border-color: var(--primary); background: #f7faff; }
.lv-group > span { flex: 1; font-weight: 600; }
.lv-group b { color: var(--warn); }
.lv-group em { color: var(--muted); font-style: normal; }
.lv-name { flex-wrap: wrap; }
.lv-name b { font-size: 15px; min-width: 60px; }
.lv-name > span { color: var(--muted); font-size: 12px; }
.lv-tel { color: var(--primary); text-decoration: none; font-weight: 700; font-size: 13px; }

/* 休息日：淡红底 + 深红字（v16 去掉左上角小圆点，颜色整体调柔和） */
.cal-cell.off {
  background: #fff1f0;
  color: #c0392b; border-color: #ffd5d2; box-shadow: none; font-weight: 600;
}
.cal-cell.off:hover { transform: translateY(-1px); border-color: #ffb3ae; }
/* 调休上班日（周末被改成上学日）：淡蓝底 + 蓝字 */
.cal-cell.adj {
  background: #eaf2ff; color: #1c4fb8; border-color: #bcd6ff;
}
.cal-cell.adj:hover { border-color: #7aacff; }

/* 已请假 */
.cal-cell.leave {
  background: linear-gradient(150deg, #ff6b6f 0%, #e5383b 100%);
  color: #fff; border-color: transparent;
  box-shadow: 0 8px 16px -8px rgba(229, 56, 59, .75);
}
.cal-cell.leave .cell-badge { background: rgba(255, 255, 255, .22); color: #fff; }

/* 今天 */
.cal-cell.today { border-color: var(--warn); box-shadow: 0 0 0 2px rgba(245, 166, 35, .35); }
.cal-cell.today.leave { box-shadow: 0 0 0 2px #fff inset, 0 8px 16px -8px rgba(229, 56, 59, .75); border-color: #fff; }

/* 已过去的日期：稍微淡一点，但仍可点开补请假 */
.cal-cell.past { opacity: .78; }
.cal-cell.past.off { opacity: .6; }

.cell-badge {
  position: absolute; bottom: 3px; left: 50%; transform: translateX(-50%);
  font-size: 9px; font-weight: 700; line-height: 1.4; padding: 0 5px;
  border-radius: 6px; background: #eef1f8; color: var(--muted); white-space: nowrap;
}
/* 「休」字块跟休息日同色系（红），「课/补」跟调休上课同色系（蓝），不再红底蓝字打架 */
.cell-badge.off { background: #ffdcd8; color: #b03030; }
.cell-badge.alt { background: #d5e5ff; color: #1c4fb8; }
/* 管理员 / 老师端日历里的「休 / 课」小字同样按底色走 */
.cal-cell.off .tag { color: #b03030; font-weight: 700; }
.cal-cell.adj .tag { color: #1c4fb8; font-weight: 700; }
.cell-pin { position: absolute; top: 3px; right: 4px; font-size: 11px; line-height: 1; filter: saturate(1.2); }

.legend .lg-school { background: linear-gradient(180deg, #fff, #f7f9ff); border: 1.5px solid #e4e8f3; }
.legend .lg-leave { background: linear-gradient(150deg, #ff6b6f, #e5383b); }
.legend .lg-off { background: #fff1f0; border: 1.5px solid #ffd5d2; }
.legend .lg-adj { background: #eaf2ff; border: 1.5px solid #bcd6ff; }
/* v15：表头图标预览 */
.br-prev img { width: 36px; height: 36px; border-radius: 10px; object-fit: cover; box-shadow: 0 2px 6px rgba(24,40,90,.15); }
.legend span { display: inline-flex; align-items: center; }

/* ---- 当日详情卡 ---- */
.day-sheet { max-width: 400px; }
.ds-head { display: flex; align-items: center; gap: 14px; padding: 4px 0 12px; border-bottom: 1px dashed var(--line); }
.ds-date {
  width: 62px; height: 62px; flex: 0 0 62px; border-radius: 18px;
  background: linear-gradient(150deg, var(--primary), #7b6ef6); color: #fff;
  display: flex; align-items: center; justify-content: center;
  font-size: 28px; font-weight: 800; box-shadow: 0 10px 20px -10px rgba(58, 91, 246, .8);
}
.ds-meta { display: flex; flex-direction: column; gap: 5px; }
.ds-meta b { font-size: 15px; }
.ds-kind {
  align-self: flex-start; font-size: 12px; font-weight: 700; color: var(--success);
  background: var(--success-soft); border-radius: 8px; padding: 3px 9px;
}
.ds-kind.off { color: var(--muted); background: #f1f3f7; }
.ds-note {
  display: flex; gap: 10px; align-items: flex-start; margin-top: 12px;
  background: var(--warn-soft); border-left: 4px solid var(--warn); border-radius: 10px; padding: 10px 12px;
}
.ds-note .pin { font-size: 15px; line-height: 1.3; }
.ds-note b { display: block; font-size: 12px; color: var(--warn); margin-bottom: 2px; }
.ds-note p { margin: 0; font-size: 14px; line-height: 1.5; }
.ds-state {
  margin-top: 11px; font-size: 14px; text-align: center; padding: 9px;
  border-radius: 10px; background: #f5f7fc; color: var(--muted);
}
.ds-state.on { background: var(--danger-soft); color: var(--danger); font-weight: 600; }
.ds-btns { margin-top: 14px; display: flex; flex-direction: column; gap: 9px; }
.ds-btns .btn { margin: 0; }

/* ---- 首次登录必填说明 ---- */
.fp-why {
  background: #f6f8ff; border: 1px solid #dde3f7; border-radius: 12px;
  padding: 12px 14px; margin-bottom: 16px; font-size: 13px; line-height: 1.65; color: #454f6b;
}
.fp-why > b { display: block; font-size: 14px; color: var(--primary); margin-bottom: 6px; }
.fp-why ul { margin: 0 0 8px; padding-left: 18px; }
.fp-why li { margin-bottom: 3px; }
.fp-why p { margin: 0; font-size: 12.5px; color: var(--warn); font-weight: 600; }

/* ---- 班徽设置 ---- */
.badge-modal { max-width: 440px; }
.badge-pick { margin: 6px 0 14px; }
.bp-preview {
  width: 100%; height: 190px; border: 2px dashed var(--line); border-radius: 16px;
  background: #fbfcfe; display: flex; align-items: center; justify-content: center;
  cursor: pointer; overflow: hidden; transition: .15s;
}
.bp-preview:hover { border-color: var(--primary); background: #f6f8ff; }
.bp-preview img { max-width: 82%; max-height: 82%; object-fit: contain; }
.bp-preview.big { height: 300px; border-style: solid; cursor: default; }
.bp-empty { text-align: center; font-size: 13px; color: var(--muted); line-height: 1.7; }
.bp-empty small { font-size: 11.5px; opacity: .8; }
.bp-tip { font-size: 12px; color: var(--muted); margin-top: 8px; }

@media (max-width: 480px) {
  .cal-cell { min-height: 42px; font-size: 14px; border-radius: 10px; }
  .cal-grid { gap: 4px; }
  .ds-date { width: 54px; height: 54px; flex-basis: 54px; font-size: 24px; }
  .bp-preview { height: 160px; }
}

/* ===== v11/v12：总览统计卡可点下钻 / 分级明细弹窗（重新设计） ===== */
.stat.tap { cursor: pointer; transition: transform .13s, box-shadow .13s; }
.stat.tap:hover { transform: translateY(-2px); box-shadow: 0 10px 20px -10px rgba(58, 91, 246, .35); }
.stat.tap:active { transform: scale(.96); }

.drill-modal {
  max-width: 600px; width: 94vw; max-height: 86vh; overflow: hidden;
  background: #fff; border-radius: 18px; box-shadow: 0 24px 60px -18px rgba(20, 35, 80, .45);
  display: flex; flex-direction: column;
}
.drill-head {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 14px 18px 12px;
  background: linear-gradient(135deg, #f2f6ff 0%, #fdfbff 70%);
  border-bottom: 1px solid #e9edf8; border-radius: 18px 18px 0 0;
}
.dh-l { display: flex; align-items: center; gap: 11px; min-width: 0; }
.dh-ico {
  flex: 0 0 auto; width: 38px; height: 38px; border-radius: 12px; font-size: 19px;
  display: flex; align-items: center; justify-content: center;
  background: linear-gradient(135deg, var(--primary, #3a5bf6) 0%, #6d8bff 100%);
  box-shadow: 0 6px 14px -6px rgba(58, 91, 246, .6);
}
.dh-t h3 { margin: 0; font-size: 16px; line-height: 1.25; }
.drill-crumb { display: flex; align-items: center; gap: 5px; margin-top: 3px; flex-wrap: wrap; }
.crumb-chip {
  font-size: 11.5px; font-weight: 700; color: var(--primary, #3a5bf6);
  background: rgba(58, 91, 246, .09); border: 1px solid rgba(58, 91, 246, .18);
  border-radius: 999px; padding: 1px 9px; white-space: nowrap;
}
.crumb-sep { color: #b6c2e2; font-size: 11px; }
.drill-x {
  flex: 0 0 auto; width: 30px; height: 30px; border-radius: 10px; border: 1.5px solid var(--line, #e4e8f3);
  background: #fff; color: var(--muted, #8a93a8); font-size: 13px; cursor: pointer; transition: .13s;
}
.drill-x:hover { color: var(--primary, #3a5bf6); border-color: var(--primary, #3a5bf6); }
.drill-body { padding: 12px 16px 4px; overflow-y: auto; flex: 1 1 auto; min-height: 0; -webkit-overflow-scrolling: touch; }
.drill-foot { padding: 10px 16px 14px; display: flex; gap: 8px; flex-wrap: wrap; }
.drill-foot:empty { display: none; }
.drill-modal .tbl-wrap { max-height: 54vh; overflow: auto; border: 1px solid #edf0f8; border-radius: 12px; }
.drill-row { cursor: pointer; transition: background .12s; }
.drill-row:hover { background: #f5f8ff; }
.drill-row .lnk { color: var(--primary); font-weight: 600; font-size: 13px; white-space: nowrap; }
/* 家长账号下钻：年级大块瓷砖 */
.drill-stats { display: grid; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: 10px; padding: 2px 0 8px; }
.drill-tile {
  border: 1.5px solid #e7ebf7; background: linear-gradient(180deg, #fff, #f6f8ff);
  border-radius: 14px; padding: 13px 10px 11px; cursor: pointer; text-align: center; transition: .14s;
}
.drill-tile:hover { transform: translateY(-2px); border-color: var(--primary, #3a5bf6); box-shadow: 0 10px 20px -10px rgba(58, 91, 246, .4); }
.drill-tile b { display: block; font-size: 24px; color: var(--primary, #3a5bf6); line-height: 1.2; }
.drill-tile span { font-size: 12.5px; color: var(--muted, #8a93a8); font-weight: 600; }
.drill-tile::after { content: '›'; display: block; color: #c2cbe4; font-weight: 700; margin-top: 2px; }
/* 名单操作列：三个按钮不换行挤在一起 */
.tbl td.op-cell { white-space: nowrap; }
.tbl td.op-cell .btn { margin: 1px 0; }
/* 宽表紧凑模式：列多的表格（学生名单/教职工）压缩内边距和字号，电脑一屏放得下 */
.tbl-compact th { padding: 8px 7px; font-size: 12px; }
.tbl-compact td { padding: 7px 7px; font-size: 13px; }
.tbl-compact .btn.small { padding: 4px 8px; font-size: 12px; }
.tbl-compact code.inline { font-size: 11.5px; }
.tbl-compact .pill { font-size: 11px; padding: 1px 7px; }
@media (max-width: 900px) {
  .tbl-compact th { padding: 8px 5px; font-size: 11.5px; }
  .tbl-compact td { padding: 6px 5px; font-size: 12.5px; }
}

/* 教职工列表头部：标题 + 新建按钮同行 */
.staff-top-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; margin-bottom: 8px; }

/* ===== v13：手机端弹窗 / 下钻适配（弹窗铺满可视区，表格不再被裁） ===== */
@media (max-width: 620px) {
  .modal-mask { padding: 8px; }
  .modal { padding: 18px 15px; max-width: 100%; }
  .drill-modal { width: 98vw; max-width: 98vw; max-height: 92vh; border-radius: 16px; }
  .drill-head { padding: 10px 12px 9px; border-radius: 16px 16px 0 0; }
  .dh-ico { width: 32px; height: 32px; font-size: 16px; border-radius: 10px; }
  .dh-t h3 { font-size: 14.5px; }
  .crumb-chip { font-size: 10.5px; padding: 1px 7px; }
  .drill-body { padding: 10px 10px 4px; }
  .drill-foot { padding: 8px 10px 12px; }
  /* v25.14：原来这里把内层滚动整个关掉，导致列多时右边被弹窗裁掉看不见（如「未生成」那一列）。
     改成保留横向滚动 + 限制高度，既能左右滑也能上下滑。 */
  .drill-modal .tbl-wrap { max-height: 48vh; overflow: auto; margin: 0; padding: 0; border: none; border-radius: 10px; }
  .drill-modal table.tbl { min-width: 0; width: 100%; }
  .drill-modal .tbl th { padding: 7px 5px; font-size: 11.5px; }
  .drill-modal .tbl td { padding: 6px 5px; font-size: 12px; }
  .drill-modal .drill-row .lnk { font-size: 11px; white-space: nowrap; }
  .drill-stats { grid-template-columns: repeat(2, 1fr); }
  .drill-tile b { font-size: 20px; }
  .tbl-wrap { -webkit-overflow-scrolling: touch; }
}

/* ===== v21：手机端大表只留关键列，不再被屏幕裁掉右边 ===== */
/* only-pc / only-m：同一功能渲染两套按钮（桌面完整文字 / 手机图标），CSS 控制显隐 */
.only-m { display: none; }
@media (max-width: 620px) {
  .only-pc { display: none !important; }
  .only-m { display: inline-block; }
  /* 次要列整列隐藏：序号 / 年级 / 邮箱 / 请假日期 / 请假次数 / 就餐次数 / 编号 / 勾选框 */
  .c-idx, .c-grade, .c-email, .c-dates, .c-leave, .c-lunch, .c-code, .c-chk, .c-last, .c-acc2 { display: none; }
  /* 解除桌面的 640px 最小宽度，列数少了之后表格要能缩进屏幕 */
  table.tbl { min-width: 0; }
  /* 列内边距与状态徽标收紧，一屏塞下关键列 */
  .tbl th, .tbl td { padding: 7px 4px; }
  .tbl .pill { font-size: 10.5px; padding: 2px 6px; }
  /* 名单表：开号状态在手机上缩成学生名下的小徽标（桌面仍是独立一列） */
  .tbl td .acc-mini { display: block; font-style: normal; font-size: 10px; font-weight: 700; color: var(--success); margin-top: 1px; white-space: nowrap; }
  .tbl td .acc-mini.warn { color: var(--warn); }
  /* v24.4：教职工表手机端，账号缩到姓名下面一行 */
  .tbl td .acc-mini.mono { color: var(--muted); font-weight: 600; font-size: 9.5px; letter-spacing: -.2px; }
  /* 合计行在手机上改为表格下方的一行文字（.m-total），避免 colspan 错位 */
  tr.total.only-pc { display: none; }
  .m-total { font-size: 12.5px; color: var(--muted); background: #f7f9fc; border: 1px solid #eef1f8; border-radius: 10px; padding: 8px 10px; margin-top: 8px; line-height: 1.7; }
  .m-total b { color: var(--text); }
  /* 宽列压缩：手机号 10.5px、操作按钮更紧凑、按钮间空隙清零 */
  .c-phone { font-size: 10.5px; letter-spacing: -.2px; }
  .tbl-compact td.op-cell { font-size: 0; }
  .tbl-compact .btn.small.only-m { padding: 3px 5px; font-size: 12px; }
  /* v24.4：教职工表一行塞得下 —— 身份下拉、手机号、操作图标都要再收一点 */
  .tbl-compact select { max-width: 76px; font-size: 11px; padding: 3px 2px; }
  .tbl-compact .c-phone code.inline { font-size: 10px; letter-spacing: -.3px; }
  .tbl-compact td.op-cell .btn.small.only-m { padding: 3px 4px; }
  .tbl th { white-space: nowrap; }
}

/* 消息提醒卡（开启推送 / 安装到桌面） */
.push-card { border-left: 4px solid var(--primary); }
.push-card h3 { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.push-card h3 .pill { margin-left: auto; }
.push-card .hint { line-height: 1.75; }
.push-card .btn-row { margin-top: 4px; }


/* ===== v25.3：我的资料默认折叠（v25.4：标题强制单行，不再折成两行） ===== */
.profile-card { padding: 0; }
.profile-card summary {
  display: flex; align-items: center; gap: 8px;
  padding: 14px 16px; cursor: pointer; list-style: none; user-select: none;
  white-space: nowrap;
}
.profile-card summary::-webkit-details-marker { display: none; }
.profile-card .pc-t { font-weight: 700; font-size: 16px; flex: 0 0 auto; }
.profile-card summary .sub { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.profile-card .pc-arrow { margin-left: auto; flex: 0 0 auto; color: var(--muted, #98a2b3); transition: transform .15s; }
.profile-card[open] .pc-arrow { transform: rotate(90deg); }
.profile-card .pc-body { padding: 0 16px 14px; border-top: 1px dashed var(--line, #e8ecf4); padding-top: 12px; }
@media (max-width: 360px) { .profile-card summary .sub { display: none; } }

/* ===== v25.14：长期不在校就餐卡也默认折叠（说明文字太长） ===== */
details.card > summary.nm-sum { display: flex; align-items: center; gap: 8px; padding: 14px 16px; cursor: pointer; list-style: none; user-select: none; }
details.card > summary.nm-sum::-webkit-details-marker { display: none; }
details.card > summary.nm-sum .sub { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
details.card > summary.nm-sum .pc-arrow { margin-left: auto; flex: 0 0 auto; color: var(--muted, #98a2b3); transition: transform .15s; }
details.card[open] > summary.nm-sum .pc-arrow { transform: rotate(90deg); }
details.card > p.hint { padding: 0 16px 14px; border-top: 1px dashed var(--line, #e8ecf4); padding-top: 12px; }

/* ===== v25.4：家长端「我的孩子」管理（手动拆出被误合在一起的孩子） ===== */
.kid-mgr { margin-top: 12px; border-top: 1px dashed var(--line, #e8ecf4); padding-top: 10px; }
.kid-mgr .km-title { font-weight: 700; font-size: 14px; margin-bottom: 8px; }
.kid-mgr .km-title .sub { font-weight: 400; font-size: 12px; margin-left: 6px; }
.kid-mgr .km-t2 { margin-top: 10px; }
.kid-mgr .km-row { display: flex; flex-wrap: wrap; gap: 8px; }
.kid-mgr .km-chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 10px; border: 1px solid var(--line, #e8ecf4); border-radius: 999px;
  background: #fff; font-size: 13px;
}
.kid-mgr .km-chip b { font-weight: 700; }
.kid-mgr .km-chip small { color: var(--muted, #98a2b3); font-size: 11px; }
.kid-mgr .km-other { border-color: #ffd9a8; background: #fff8ee; }
.kid-mgr .km-out { opacity: .7; border-style: dashed; }
.kid-mgr .km-x {
  border: none; background: transparent; color: var(--muted, #98a2b3);
  font-size: 12px; cursor: pointer; padding: 2px 4px; border-radius: 6px;
}
.kid-mgr .km-x:hover { background: #f1f4fb; color: var(--primary, #3a5bf6); }
.kid-mgr .km-r:hover { color: var(--success, #22a06b); }

.fld.chk { display: flex; align-items: center; gap: 8px; flex-direction: row; font-weight: 400; cursor: pointer; }
.fld.chk input[type=checkbox] { width: 18px; height: 18px; flex: none; }

/* ===== v25.4：上传付款截图（label 包真实 file input，原生唤起选择框） ===== */
.pay-upload-lbl { display: inline-flex; align-items: center; justify-content: center; cursor: pointer; }
.pay-upload-lbl.busy { opacity: .65; pointer-events: none; }

/* ===== v24.8：防伪水印（一张图，Ctrl+Shift+M 切换右下角显隐） ===== */
.watermark {
  position: fixed; right: 16px; bottom: 16px; z-index: 320;
  pointer-events: none; opacity: .55; display: none;
}
.watermark img { display: block; max-width: 130px; max-height: 110px; object-fit: contain; }
@media (max-width: 480px) {
  .watermark { right: 10px; bottom: 10px; opacity: .5; }
  .watermark img { max-width: 96px; max-height: 84px; }
}


/* ===== v25.8：年级组长 6 卡 / 各班下钻 / 日历临时来吃标记 / 上传按钮 ===== */
/* 六个数值卡：桌面 3 列两行 */
.stat-grid.six { grid-template-columns: repeat(3, 1fr); }
/* 当前用来排序的那张卡描个边，点过之后看得出按什么排的 */
.stat.on { box-shadow: 0 0 0 2px var(--primary) inset; }
@media (max-width: 620px) {
  .stat-grid.six { grid-template-columns: repeat(2, 1fr); }
  /* 各班汇总表：手机上只留 班级 / 就餐 / 已确认 / 截图 / 操作，一屏放得下不再横向拖 */
  .c-n2, .c-amt2 { display: none; }
}
/* 日历「临时来吃」：绿色「餐」小标 + 格子描边 */
.cell-badge.eat { background: #dff5e4; color: #137a3c; }
.cal-cell.extra-eat { border-color: rgba(19, 122, 60, .5); }
.lg-eat { display: inline-block; width: 9px; height: 9px; border-radius: 3px; background: #dff5e4; border: 1px solid #137a3c; margin-right: 3px; vertical-align: middle; }
/* 上传按钮里的真实 file input：不能用 hidden/display:none（微信 iOS 里点了不弹选择框），
   改成挪到屏幕外 + 透明，点 label 照样能原生唤起 */
.file-hidden { position: absolute; width: 1px; height: 1px; opacity: 0; left: -9999px; top: 0; }
/* v25.9：上传按钮改成「透明 file input 铺满整个按钮」——点击直接落在 input 本身上（真实点击），
   微信内置浏览器 / iOS Safari 都会正常弹出「拍照 / 相册」。原来那种「挪到屏幕外 + 程序触发」在微信里不弹。 */
.pay-upload-lbl { position: relative; overflow: hidden; }
.pay-upload-lbl > input[type="file"].file-hidden {
  position: absolute; left: 0; top: 0; width: 100%; height: 100%;
  opacity: 0; cursor: pointer; z-index: 3; border: 0; padding: 0; margin: 0;
  -webkit-appearance: none; appearance: none; font-size: 0;
}
/* 付款截图两个主按钮：一行等宽 */
.pay-2btn { display: flex; gap: 10px; margin-top: 12px; }
.pay-2btn > * { flex: 1 1 0; min-width: 0; }
.pay-done.tap { cursor: pointer; }
/* 兜底用的「看得见」的选图按钮：某些浏览器不弹框时靠它 */
.pay-file-fallback {
  display: block; width: 100%; margin-top: 6px; padding: 9px 10px;
  font-size: 13px; color: var(--text); background: #fff;
  border: 1px dashed var(--primary); border-radius: 10px;
}
.pay-upload-lbl.busy { opacity: .62; }
/* 各班汇总：整行可点进班 */
.cls-row { cursor: pointer; }
.cls-row:hover td { background: #f6f8ff; }

/* v25.9 年级组长点数值卡 → 各班排行条 */
.lv-group.rank { display: flex; align-items: center; gap: 10px; }
.lv-group.rank > span { flex: 0 0 66px; }
.lv-group.rank > .rank-bar { flex: 1 1 auto; display: block; height: 8px; background: #eef1f6; border-radius: 99px; overflow: hidden; }
.lv-group.rank > .rank-bar > b { display: block; height: 100%; background: var(--primary); border-radius: 99px; }
.lv-group.rank > b { flex: 0 0 auto; min-width: 54px; text-align: right; }
.lv-group.rank > em { flex: 0 0 auto; }


/* ================= v25.10 ================= */
/* 上传付款截图：file input 真实可见（opacity:1），上面只盖一层 pointer-events:none 的装饰文字。
   之前用 opacity:0 铺满按钮，微信内置浏览器 / iOS Safari 就是不弹选择框。 */
/* 一行两按钮：按钮默认的左右 padding 会撑出 40px 宽度下限，导致两边不等宽 —— 去掉横向内边距才是真等宽 */
.pay-2btn > .btn { padding-left: 0; padding-right: 0; }
.up-slot { position: relative; display: block; height: 44px; border-radius: 11px; overflow: hidden; background: var(--success); }
/* v25.12（小米 / 微信 X5）：控件必须**真实可见**。X5 对 opacity:0 / appearance:none 的
   file input 不唤起选图，所以这里用 ::-webkit-file-upload-button + ::file-selector-button
   把原生按钮美化成绿色整块；在不支持伪元素的浏览器上退化为系统默认按钮 —— 但始终可见可点。 */
.up-real {
  position: absolute; left: 0; top: 0; width: 100%; height: 100%;
  z-index: 2; cursor: pointer; border: 0; padding: 0; margin: 0;
  background: transparent; color: transparent; font-size: 14px; line-height: 44px;
  overflow: hidden;
}
.up-real::-webkit-file-upload-button,
.up-real::file-selector-button {
  -webkit-appearance: none; appearance: none;
  display: block; width: 100%; height: 44px; border: 0; border-radius: 11px;
  background: var(--success); color: transparent; text-indent: -9999px;
  font-size: 15px; font-weight: 600; cursor: pointer;
}
/* 原生「选择文件」四个字隐掉（color:transparent + text-indent 挪出），文案由 .up-cover 统一显示；
   控件本身仍是真实可见的绿色块 —— 不影响 X5 内核唤起选图 */
.up-slot.busy { opacity: .62; }
.up-warn { display: block; padding: 8px 10px; background: var(--warn-soft); border-radius: 10px; color: var(--warn); font-size: 12px; line-height: 1.6; }
.up-warn .btn { margin-top: 6px; }
/* 只读查看标记（年级组长点进某个班时） */
.ro-tip { display: inline-flex; align-items: center; padding: 0 10px; font-size: 12px; color: var(--warn); background: var(--warn-soft); border-radius: 99px; height: 32px; }
/* 发布确认单 / 导出：班级勾选列表 */
.cls-pick { display: flex; flex-direction: column; gap: 8px; margin: 10px 0; max-height: 44vh; overflow: auto; }
.cp-row { display: flex; align-items: center; gap: 8px; padding: 9px 10px; border: 1px solid var(--line); border-radius: 10px; background: #fff; cursor: pointer; }
.cp-row.on { border-color: var(--primary); background: var(--primary-soft); }
.cp-row > b { flex: 0 0 auto; }
.cp-row > span { flex: 1 1 auto; font-size: 12px; min-width: 0; }
.cp-row > i { flex: 0 0 auto; font-style: normal; }
.exp-list { display: flex; flex-direction: column; gap: 8px; margin-top: 12px; }


/* ================= v25.11 ================= */
/* 弹窗里看某班人员：只读标记 + 紧凑表格 */
.modal .stat-grid { margin-top: 12px; }
.modal .tbl-wrap { max-height: 46vh; overflow: auto; }
.modal .ro-tip { flex: 0 0 auto; }

/* 备用通道 + 步骤面板（v25.12） */
.up-alt { margin-top: 10px; }
.up-native { display: block; width: 100%; font-size: 14px; }
.up-alt-t { margin: 0 0 6px; font-size: 12px; color: var(--muted); line-height: 1.5; }
.up-steps { margin-top: 10px; }
.up-step {
  padding: 7px 10px; margin-bottom: 5px; border-radius: 9px;
  background: #f4f6fa; font-size: 13px; line-height: 1.55; color: var(--text);
}
.up-step > b { display: inline-block; width: 18px; height: 18px; line-height: 18px; text-align: center;
  margin-right: 6px; border-radius: 50%; background: var(--line); color: #fff; font-size: 11px; }

/* ================= v25.13（小米浏览器不弹选图专项） =================
   诊断结论：控件已真实可见、点击也落在控件上，浏览器就是不弹选图 —— 属浏览器层拦截
  （最常见：小米浏览器没拿到「照片/文件」系统权限）。应对：①给按钮加 pointer-events:none
  的文字覆盖层（不挡点击）②加「拍照上传」通道（走相机权限，绕开文件权限）
  ③页面内直接给出权限修复步骤卡。 */
.up-cover {
  position: absolute; left: 0; top: 0; right: 0; bottom: 0; z-index: 3;
  display: flex; align-items: center; justify-content: center;
  pointer-events: none; color: #fff; font-size: 14px; font-weight: 600;
  font-style: normal; letter-spacing: .3px;
}
.up-slot-cam { margin-top: 8px; }
.up-slot-cam .up-real::-webkit-file-upload-button,
.up-slot-cam .up-real::file-selector-button { background: #e8890c; }
.up-fix {
  margin-top: 10px; padding: 10px 12px; background: #f4f6fa;
  border: 1px dashed var(--line); border-radius: 10px;
  font-size: 12px; line-height: 1.7; color: var(--muted);
}
.up-fix b { display: block; color: var(--text); font-size: 13px; margin-bottom: 4px; }
.up-fix p { margin: 2px 0; }
.up-step.ok { background: var(--success-soft); }
.up-step.ok > b { background: var(--success); }
.up-step.bad { background: var(--warn-soft); color: var(--warn); }
.up-step.bad > b { background: var(--warn); }
.up-warn { display: block; padding: 8px 10px; background: var(--warn-soft); border-radius: 10px; color: var(--warn); font-size: 12px; line-height: 1.6; }

/* v25.38 老师端「手机 / 电脑企微发通知」指引弹窗 */
.gd-box { margin: 10px 0; padding: 10px 12px; background: var(--bg-soft, #f5f7fa); border-radius: 10px; }
.gd-box h4 { margin: 0 0 6px; font-size: 14px; color: var(--text, #16202e); }
.gd-steps { margin: 0; padding-left: 20px; font-size: 13px; line-height: 1.75; color: var(--text-2, #41506a); }
.gd-steps li { margin: 3px 0; }
