/* 设计系统：一套令牌 + 一组组件，所有页面共用 —— 不再各页自写样式 */
:root {
  /* ---- 色彩（沿用现有站点配色，本次只调版式，色值一律未动）---- */
  --brand: #e8792b;
  --brand-dark: #c4600f;
  --brand-soft: #fdf0e2;
  --bg: #faf7f3;
  --surface: #ffffff;
  --border: #ece3d8;
  --text: #2b2318;
  --text-muted: #7c7268;
  --ok: #2f7d5b; --ok-soft: #e7f4ed;
  --warn: #b0751c; --warn-soft: #fdf3e2;
  --danger: #bc3b3b; --danger-soft: #fbeaea;
  --info: #2b6cb0; --info-soft: #e8f0fa;

  /* ---- 版式令牌（2026-10-10 版式升级）---- */
  --radius: 14px;              /* 卡片圆角：10 → 14 */
  --radius-md: 11px;
  --radius-sm: 8px;
  --gap: 18px;
  --side-w: 252px;             /* 侧边栏：232 → 252 */
  --top-h: 64px;               /* 顶栏：自适应 → 64 */
  --line-soft: #f4ede4;        /* 更淡的分隔线，用于表格内线 */
  --shadow-1: 0 1px 2px rgba(43, 35, 24, .05);
  --shadow-2: 0 2px 10px rgba(43, 35, 24, .055), 0 1px 2px rgba(43, 35, 24, .04);
  --shadow-3: 0 10px 28px rgba(43, 35, 24, .09), 0 2px 6px rgba(43, 35, 24, .04);
  --shadow-brand: 0 8px 22px rgba(232, 121, 43, .26);
  --shadow: var(--shadow-2);
  --font: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", system-ui, sans-serif;
}
* { box-sizing: border-box; }
body {
  margin: 0; background: var(--bg); color: var(--text);
  font-family: var(--font); font-size: 15px; line-height: 1.6;
}
a { color: var(--brand-dark); text-decoration: none; }
a:hover { text-decoration: underline; }

/* 布局 */
.shell { display: flex; min-height: 100vh; }
.sidebar {
  width: var(--side-w); flex: none;
  /* 深褐底加一层同色系纵向渐变，顶部略亮（色相未变，只是层次） */
  background: linear-gradient(180deg, #33261a 0%, #241a11 100%);
  color: #f0e9e1;
  padding: 20px 12px 14px; position: sticky; top: 0; height: 100vh; overflow-y: auto;
  display: flex; flex-direction: column;
}
/* 品牌区：反白 logo（原稿是深棕+金色透明图，落在深褐侧边栏上几乎看不见） */
.sidebar .brand {
  display: block; flex: none;
  padding: 2px 8px 16px; margin-bottom: 6px;
  border-bottom: 1px solid rgba(255, 255, 255, .10);
}
.sidebar .brand-logo {
  display: block; width: 100%; max-width: 212px; height: auto;
  filter: brightness(0) invert(1) drop-shadow(0 2px 8px rgba(0, 0, 0, .32));
}
.sidebar .brand small {
  display: block; font-weight: 400; font-size: 11px; color: #c2b6a8;
  margin-top: 8px; letter-spacing: .8px;
}
.nav-group { margin-bottom: 12px; }
.nav-group a {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 11px; margin: 1px 0; border-radius: var(--radius-sm);
  color: #e6e0da; font-size: 14px; position: relative;
  transition: background .16s ease, color .16s ease;
}
.nav-group a:hover { background: rgba(255, 255, 255, .08); color: #fff; text-decoration: none; }
.nav-group a.active {
  background: rgba(232, 121, 43, .20); color: #fff; font-weight: 600;
  box-shadow: inset 0 0 0 1px rgba(232, 121, 43, .32);
}
.nav-group a.active::before {
  content: ""; position: absolute; left: -12px; top: 50%; transform: translateY(-50%);
  width: 3px; height: 20px; border-radius: 0 3px 3px 0;
  background: linear-gradient(180deg, #f2a25a, var(--brand));
}
.nav-group a .ico { width: 17px; height: 17px; flex: none; opacity: .82; }
.nav-group a:hover .ico, .nav-group a.active .ico { opacity: 1; }
/* 一级菜单改按钮：可折叠（2026-09-18）。收起时只留标题，展开状态记在浏览器里 */
.nav-group .label {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  width: 100%; background: none; border: 0; cursor: pointer; text-align: left;
  font-family: inherit; font-size: 11px; letter-spacing: 1.4px; color: #948b83;
  padding: 8px 8px 7px;
}
.nav-group .label > span:first-child { display: flex; align-items: center; gap: 9px; flex: 1; min-width: 0; }
.nav-group .label > span:first-child::after {
  content: ""; flex: 1; height: 1px; min-width: 10px; background: rgba(255, 255, 255, .10);
}
.nav-group .label:hover { color: #ded4c9; }
.nav-group .label:hover > span:first-child::after { background: rgba(255, 255, 255, .18); }
.nav-group .label .chev { font-size: 10px; transition: transform .15s ease; }
.nav-group.collapsed .label .chev { transform: rotate(-90deg); }
.nav-group.collapsed .links { display: none; }
main .content.loading { opacity: .55; transition: opacity .12s ease; }
.main { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.topbar {
  min-height: var(--top-h);
  background: rgba(255, 255, 255, .9);
  backdrop-filter: saturate(180%) blur(12px);
  -webkit-backdrop-filter: saturate(180%) blur(12px);
  border-bottom: 1px solid var(--border);
  padding: 10px 24px; display: flex; align-items: center; gap: 14px;
  position: sticky; top: 0; z-index: 30;
}
.topbar h1 { font-size: 18px; margin: 0; font-weight: 700; letter-spacing: -.2px; }
.topbar .spacer { flex: 1; }
/* 顶部统计卡上滑后在标题右侧常驻的「小卡片」形态（2026-10-12 院方要求：
   仍然保持卡片样式、不用胶囊；同时主页面原来的整排卡片同步渐变消失）
   绝对定位：显示/隐藏不会推挤顶栏其它元素（否则会出现"按钮突然左移"的跳动），
   并且始终有盒子，方便每帧测量目标位置。 */
.title-chips{position:absolute;top:50%;left:0;transform:translateY(-50%);
  display:flex;align-items:center;gap:6px;overflow:hidden;
  max-width:min(780px,56vw);opacity:0;pointer-events:none;
  transition:opacity .12s ease;z-index:1}
.title-chips[hidden]{display:none !important}
/* 绝对定位的小卡片不能压住顶栏右侧按钮（宽屏才有空间放它） */
.topbar .topbar-actions, .topbar .userbox{position:relative;z-index:2}
@media (max-width:1100px){
  .title-chips{display:none !important}   /* 平板/窄屏顶栏是两行，放不下就不显示，避免叠字 */
}
.title-card{position:relative;display:flex;flex-direction:column;justify-content:center;
  background:var(--surface);border:1px solid var(--border);border-radius:9px;
  padding:3px 10px 4px 12px;min-width:0;box-shadow:var(--shadow-1)}
.title-card::before{content:"";position:absolute;left:0;top:0;bottom:0;width:3px;border-radius:9px 0 0 9px;
  background:linear-gradient(180deg,#f2a25a,var(--brand))}
.title-card .k{font-size:10.5px;color:var(--text-muted);line-height:1.2;white-space:nowrap;
  overflow:hidden;text-overflow:ellipsis;max-width:150px}
.title-card .v{font-size:14.5px;font-weight:700;line-height:1.2;letter-spacing:-.2px;
  font-variant-numeric:tabular-nums}
/* 飞行期间：主页面那排卡片当场让位（不是淡出），飞行交给下面的幽灵卡；留占位不跳页 */
.grid.stat-hidden{opacity:0;pointer-events:none}
/* 幽灵卡：大卡片本体的克隆，从原位置/尺寸一路缩放到标题旁小卡片的位置/尺寸 */
.stat-ghost{background:var(--surface);border-radius:var(--radius);overflow:hidden;
  box-shadow:0 18px 40px rgba(43,35,24,.22);will-change:transform,opacity;
  /* 关键：统计卡自带 transition: transform .16s（悬停抬起用），幽灵卡继承它就会"追着"滚动跑、
    永远滞后一截（看起来就是卡顿/抖动）。幽灵卡必须关掉过渡，逐帧跟手。 */
  transition:none !important}
/* 收尾用的"小卡片文字层"（院方 2026-10-15）：
   飞行到最后不再让小卡片另起一张淡入（那样会出现两张卡叠在一起），
   而是让大卡本体一路缩到标题旁，只把里面的文字渐变成小卡片的文字。
   静态值是"大卡那套"（起点）：每帧的字号/留白由 JS 按当前缩放渲染级插值，
   起点正好接上大卡、终点正好等于标题旁小卡片，中途不会跳字号、也不会被拉伸。 */
.stat-ghost .ghost-chip{position:absolute;inset:0;display:flex;flex-direction:column;justify-content:flex-start;
  padding:13px 15px 0 17px;opacity:0;pointer-events:none}
.stat-ghost .ghost-chip .k{font-size:12.5px;color:var(--text-muted);font-weight:500;line-height:1.2;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.stat-ghost .ghost-chip .v{font-size:23px;font-weight:700;line-height:1.15;margin-top:4px;letter-spacing:-.5px;
  white-space:nowrap;font-variant-numeric:tabular-nums}
/* 到位时把外观切到小卡片那套（圆角/投影/左侧橙条），尺寸按缩放比例反算，渲染出来与真小卡片一致 */
.stat-ghost.late{box-shadow:var(--shadow-1)}
.stat-ghost.late::before{content:"";position:absolute;left:0;top:0;bottom:0;width:var(--gbar,3px);
  border-radius:9px 0 0 9px;background:linear-gradient(180deg,#f2a25a,var(--brand))}

/* 左右分栏页（左列表 + 右详情）：两栏各自独立滚动、左栏纵向铺满（2026-10-12 院方要求） */
.pane-layout{
  display:grid;gap:14px;align-items:stretch;
  height:calc(100vh - var(--topbar-h, 60px) - var(--footer-h, 60px) - 32px);min-height:360px;
}
.pane-layout > *{min-height:0;overflow:auto}
body.pane-page .content{padding-bottom:16px}   /* 与顶部一致，不再贴着页脚 */
.userbox { display: flex; align-items: center; gap: 10px; padding-left: 14px; border-left: 1px solid var(--border); }
.userbox .who { font-size: 13px; color: var(--text-muted); display: flex; align-items: center; gap: 9px; }
.user-avatar {
  width: 32px; height: 32px; border-radius: 50%; flex: none;
  display: grid; place-items: center; font-size: 13px; font-weight: 600; color: #fff;
  background: linear-gradient(135deg, #f2a25a, var(--brand-dark));
  box-shadow: 0 2px 6px rgba(232, 121, 43, .3);
}
.user-meta { display: flex; flex-direction: column; line-height: 1.25; }
.user-meta .n { font-size: 13px; font-weight: 600; color: var(--text); }
.user-meta .r { font-size: 11px; color: var(--text-muted); }
.userbox .logout-form { display: flex; margin: 0; }
/* 内容区上下留白一致（2026-10-12 院方要求：原来上 22 / 下 40，分栏页更是上 22 / 下 0，
   看着"上面空一大截、下面贴着底"） */
.content { padding: 16px 24px; flex: 1; }

/* 手机端专用控件（☰ 开抽屉、× 收抽屉、遮罩）：桌面端一律不显示，导航仍是左侧常驻栏。
   选择器带父级是为了压过后面的 .btn { display: inline-block }（同权重时后者会赢）。 */
.topbar .nav-toggle, .sidebar .nav-close, .nav-mask { display: none; }
.nav-close {
  position: absolute; top: 12px; right: 10px; z-index: 2; width: 34px; height: 34px;
  align-items: center; justify-content: center; border-radius: 8px; cursor: pointer;
  border: 1px solid rgba(255, 255, 255, .22); background: rgba(255, 255, 255, .08);
  color: #f0e9e1; font-size: 18px; line-height: 1;
}

/* 卡片与网格 */
.card {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 18px 20px; box-shadow: var(--shadow-2);
  overflow: hidden;
}
.card + .card { margin-top: var(--gap); }
/* 卡片标题升级为"卡片头"：用负边距撑满整宽，加下分隔线（不用改各页模板） */
.card > h2:first-child {
  margin: -18px -20px 16px; padding: 15px 20px 13px;
  border-bottom: 1px solid var(--border);
  background: linear-gradient(180deg, #fffefd, #fdfaf6);
}
/* 卡片头想放右侧按钮时用这个包一层（直接放 h2 的话没法跟按钮同行） */
.card > .card-head:first-child {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  margin: -18px -20px 16px; padding: 15px 20px 13px;
  border-bottom: 1px solid var(--border);
  background: linear-gradient(180deg, #fffefd, #fdfaf6);
}
.card > .card-head:first-child > h2 { margin: 0; }
.card-head .card-head-actions { margin-left: auto; display: flex; gap: 8px; align-items: center; }
.card h2 { font-size: 15px; margin: 0 0 12px; font-weight: 700; letter-spacing: .1px; }
.grid { display: grid; gap: var(--gap); }
/* 内容区里相邻两块之间统一 16px（2026-10-12 院方反馈：统计卡那排"上面 16px、下面 0"，
   反过来有些页是"上面 0、下面 16"）—— 卡片之间另有 .card + .card 的 18px，不冲突 */
.content > * + * { margin-top: 16px; }
.grid.cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grid.cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.grid.cols-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
/* 统计卡 / 待办卡按「一行 6–8 张」定尺寸（2026-10-12 院方要求）：
   卡片不再撑满整行，宽度约 160–200px，屏幕越宽一行放得越多；
   表单里的 cols-3/cols-4 不受影响（只挑直接子元素是卡片的那种网格）。 */
.grid.cols-3:has(> .stat), .grid.cols-4:has(> .stat),
.grid.cols-3:has(> a.todo), .grid.cols-4:has(> a.todo) {
  grid-template-columns: repeat(auto-fill, minmax(164px, 1fr));
}
.stat {
  position: relative; overflow: hidden;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 13px 15px 13px 17px;
  box-shadow: var(--shadow-2);
  transition: transform .16s ease, box-shadow .2s ease;
}
.stat::before {
  content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 3px;
  background: linear-gradient(180deg, #f2a25a, var(--brand));
}
/* 幽灵卡（飞行中的克隆）左侧橙条：宽度由 JS 按渲染级插值写进 --gbar，
   否则整卡缩放会把橙条一起缩细，收尾最后一帧跟真小卡片对不上。 */
.stat.stat-ghost::before { width: var(--gbar, 3px); border-radius: 9px 0 0 9px; }
.stat:hover { transform: translateY(-2px); box-shadow: var(--shadow-3); }
.stat .k { font-size: 12.5px; color: var(--text-muted); font-weight: 500; }
.stat .v { font-size: 23px; font-weight: 700; line-height: 1.15; margin-top: 4px; letter-spacing: -.5px; font-variant-numeric: tabular-nums; }
.stat .s { font-size: 11.5px; color: var(--text-muted); margin-top: 4px; line-height: 1.5; }

/* 缴费确认卡片：橙色=已确认，绿色=已打印；颜色和文字同时标识状态 */
.pay-tabs {
  display: inline-flex;
  gap: 5px;
  padding: 4px;
  margin-bottom: 12px;
  border: 1px solid var(--border);
  border-radius: 11px;
  background: #fbf7f1;
}
.pay-tab {
  display: inline-flex;
  min-height: 36px;
  align-items: center;
  gap: 7px;
  padding: 7px 12px;
  border: 0;
  border-radius: 8px;
  background: transparent;
  color: var(--text-muted);
  font: inherit;
  font-size: 13.5px;
  font-weight: 600;
  cursor: pointer;
}
.pay-tab::before {
  width: 7px;
  height: 7px;
  flex: none;
  border-radius: 50%;
  content: "";
}
.pay-tab[data-pay-tab="confirmed"]::before {
  background: var(--brand);
  box-shadow: 0 0 0 3px rgba(232, 121, 43, .12);
}
.pay-tab[data-pay-tab="printed"]::before {
  background: var(--ok);
  box-shadow: 0 0 0 3px rgba(47, 125, 91, .12);
}
.pay-tab[data-pay-tab="confirmed"][aria-selected="true"] {
  background: var(--brand-soft);
  color: var(--brand-dark);
}
.pay-tab[data-pay-tab="printed"][aria-selected="true"] {
  background: var(--ok-soft);
  color: var(--ok);
}
.pay-tab-count {
  display: inline-grid;
  min-width: 22px;
  height: 22px;
  padding: 0 6px;
  place-items: center;
  border-radius: 999px;
  background: #eee8df;
  color: var(--text-muted);
  font-size: 11.5px;
  font-variant-numeric: tabular-nums;
}
.pay-tab[data-pay-tab="confirmed"][aria-selected="true"] .pay-tab-count {
  background: rgba(232, 121, 43, .14);
  color: var(--brand-dark);
}
.pay-tab[data-pay-tab="printed"][aria-selected="true"] .pay-tab-count {
  background: rgba(47, 125, 91, .13);
  color: var(--ok);
}
.pay-card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
  gap: 10px;
}
.pay-card {
  position: relative;
  display: flex;
  min-width: 0;
  min-height: 164px;
  flex-direction: column;
  overflow: hidden;
  padding: 10px 11px;
  border: 1px solid #f0d3ba;
  border-radius: var(--radius-md);
  background: linear-gradient(180deg, #fffdfb 0%, #fff7ee 100%);
  box-shadow: var(--shadow-1);
  transition: transform .16s ease, box-shadow .16s ease, border-color .16s ease;
}
.pay-card::before {
  position: absolute;
  inset: 0 auto 0 0;
  width: 4px;
  background: linear-gradient(180deg, #f2a25a, var(--brand));
  content: "";
}
.pay-card.is-printed {
  border-color: #c5e4d2;
  background: linear-gradient(180deg, #fcfffd 0%, #eff9f3 100%);
}
.pay-card.is-printed::before {
  background: linear-gradient(180deg, #7dbb98, var(--ok));
}
.pay-card:hover {
  border-color: #e6c4a5;
  box-shadow: var(--shadow-2);
  transform: translateY(-2px);
}
.pay-card.is-printed:hover { border-color: #a9d7bc; }
.pay-card-top {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 6px;
}
.pay-person { flex: 1 1 auto; min-width: 0; }
.pay-name-row {
  display: flex;
  min-width: 0;
  align-items: center;
  flex-wrap: wrap;
  row-gap: 3px;
  gap: 5px;
}
.pay-avatar { display: none; }
.pay-card.is-printed .pay-avatar {
  background: var(--ok-soft);
  color: var(--ok);
}
.pay-name {
  flex: 1 1 auto;
  min-width: 3em;
  font-size: 14.5px;
  font-weight: 700;
  line-height: 1.3;
  overflow: visible;
  text-overflow: clip;
  white-space: normal;
  word-break: break-word;
}
.pay-bed {
  flex: none;
  padding: 1px 7px;
  border-radius: 999px;
  background: #f3eee7;
  color: var(--text-muted);
  font-size: 10.5px;
}
.pay-period {
  overflow: hidden;
  margin: 4px 0 0;
  color: var(--text-muted);
  font-size: 10.5px;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.pay-state { flex: none; }
.pay-state .tag { font-size: 10.5px; padding: 2px 7px; }
.pay-amount-row {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 12px;
  margin-top: 10px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--line-soft);
}
.pay-k { display: block; color: var(--text-muted); font-size: 10.5px; }
.pay-amount {
  display: block;
  margin-top: 2px;
  font-size: 20px;
  line-height: 1.1;
  letter-spacing: -.6px;
  font-variant-numeric: tabular-nums;
}
.pay-amount-note {
  color: var(--text-muted);
  font-size: 10.5px;
  line-height: 1.55;
  text-align: right;
}
.pay-meta {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 5px 8px;
  margin-top: 7px;
}
.pay-meta > div { min-width: 0; }
.pay-meta span {
  display: block;
  color: var(--text-muted);
  font-size: 10px;
}
.pay-meta b {
  display: block;
  overflow: hidden;
  margin-top: 2px;
  font-size: 11.5px;
  font-weight: 600;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.pay-card-foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 5px;
  margin-top: auto;
  padding-top: 8px;
}
.pay-card-foot .btn {
  min-width: 0;
  flex: 1 1 0;
  white-space: nowrap;
}
.pay-card-foot .btn.primary { flex: 1 1 0; }
.pay-print-by {
  margin-left: auto;
  color: var(--text-muted);
  font-size: 11px;
  white-space: nowrap;
}
.pay-ready {
  color: var(--ok);
  font-size: 11px;
  font-weight: 600;
  white-space: nowrap;
}
.pay-records-details {
  margin-top: 14px;
  padding-top: 12px;
  border-top: 1px solid var(--border);
}
.pay-records-details > summary {
  color: var(--text-muted);
  font-size: 12.5px;
  cursor: pointer;
}

/* 待办卡片（首页"今天要处理的"）：整块可点，左侧一条橙色标识 */
a.todo {
  display: block; background: var(--surface); border: 1px solid var(--border);
  border-left: 3px solid var(--brand); border-radius: var(--radius-md);
  padding: 11px 13px; color: inherit; box-shadow: var(--shadow-1);
  transition: transform .16s ease, box-shadow .2s ease, background .16s ease;
}
a.todo:hover {
  background: var(--brand-soft); text-decoration: none;
  box-shadow: var(--shadow-2); transform: translateY(-2px);
}
a.todo .k { font-size: 13px; color: var(--text-muted); }
a.todo .v { font-size: 21px; font-weight: 700; line-height: 1.2; color: var(--brand-dark); margin: 3px 0 2px; font-variant-numeric: tabular-nums; }
a.todo .s { font-size: 11.5px; color: var(--text-muted); }

/* 表格 */
.table-wrap { overflow: auto; max-height: 68vh; }
table.data { width: 100%; border-collapse: collapse; font-size: 14px; }
table.data th, table.data td { padding: 12px 12px; text-align: left; border-bottom: 1px solid var(--line-soft); white-space: nowrap; }
table.data th {
  color: var(--text-muted); font-weight: 600; font-size: 12.5px; letter-spacing: .3px; background: #fdf9f3;
  position: sticky; top: 0; z-index: 2; box-shadow: inset 0 -1px 0 var(--border);
}
/* 列之间加极淡的竖线：一行列多了以后，眼睛不容易串列 */
table.data th + th, table.data td + td { border-left: 1px solid var(--line-soft); }
/* 隔行浅底：长表格横向追踪更容易 */
table.data tbody tr:nth-child(even) { background: #fefcfa; }
table.data tbody tr:hover { background: #fdf6ee; }
table.data tbody tr:last-child td { border-bottom: none; }
/* 数字列：表头与数据都要右对齐，两侧一致才不会看错列（只对齐数据会错位） */
table.data td.num, table.data th.num { text-align: right; font-variant-numeric: tabular-nums; }
/* 数字列左边多留一点空隙，和前面的文字列拉开距离 */
table.data th.num, table.data td.num { padding-left: 18px; }
table.data td.wrap { white-space: normal; word-break: break-word; }
table.data tbody tr:last-child td { border-bottom: none; }
/* 记录下方整行展开：展开内容横跨整张表，不再挤在右边一格 */
tr.detail-row > td { background: #fdf9f3; padding: 14px 16px; white-space: normal; }
tr.detail-row { border-bottom: 1px solid var(--border); }

/* ---------- 用户与权限页：权限列 + 冻结列（2026-10-10） ---------- */
/* 业务权限列：一个账号可能挂着好几个权限标签，整行会被拉得很长。
   这里把标签缩小、允许换行；行高仍由 td 的内边距决定，不会因为多一行就明显变高。 */
table.data td.perm-cell {
  white-space: normal; max-width: 248px;
  /* 行高压到 1.1：标签是 inline-flex，父行高撑出来的 strut 会让每行多占 5～7px，
     两行就多出 10px 上下，整张表的行高就不齐了（2026-10-10 实测调参） */
  line-height: 1.1;
}
table.data td.perm-cell .tag {
  /* 上下不留 margin：两行标签时能省下 4px，行高才压得回 56px（原来 92px） */
  font-size: 11px; line-height: 1.3; padding: 0 6px; margin: 0 3px 0 0;
  vertical-align: middle;
}
table.data td.perm-cell .tag::before { width: 4px; height: 4px; }
/* 「+3」这种收起来的计数：和权限标签同款，但用灰色，一眼区分 */
table.data td.perm-cell .perm-more {
  background: #f0ede9; color: var(--text-muted); cursor: help;
}

/* 冻结表头 + 冻结前两列（用户名 / 显示名）：表格横向滚动时不会丢失"这是谁"。
   --col1-w 由页面脚本按实际列宽写进来，第 2 列的 left 跟着它走。 */
table.data.freeze-cols thead th:nth-child(-n+2) {
  position: sticky; z-index: 5; background: #fdf9f3;
}
table.data.freeze-cols tbody td:nth-child(1),
table.data.freeze-cols tbody td:nth-child(2) {
  position: sticky; z-index: 3;
}
table.data.freeze-cols th:nth-child(1),
table.data.freeze-cols td:nth-child(1) { left: 0; }
table.data.freeze-cols th:nth-child(2),
table.data.freeze-cols td:nth-child(2) {
  left: var(--col1-w, 108px);
  border-right: 1px solid var(--border);
  box-shadow: 7px 0 9px -7px rgba(43, 35, 24, .18);
}
/* 冻结列要自己带底色，否则下面的内容会透出来；隔行色与悬停色都要跟上 */
table.data.freeze-cols tbody tr:nth-child(odd) td:nth-child(-n+2) { background: #fff; }
table.data.freeze-cols tbody tr:nth-child(even) td:nth-child(-n+2) { background: #fefcfa; }
table.data.freeze-cols tbody tr:hover td:nth-child(-n+2) { background: #fdf6ee; }

/* 状态标签 */
.tag {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 3px 10px; border-radius: 999px;
  font-size: 12.5px; line-height: 1.6; white-space: nowrap; font-weight: 600;
}
.tag::before { content: ""; width: 5px; height: 5px; border-radius: 50%; background: currentColor; opacity: .8; flex: none; }
.tag.ok { background: var(--ok-soft); color: var(--ok); }
.tag.warn { background: var(--warn-soft); color: var(--warn); }
.tag.danger { background: var(--danger-soft); color: var(--danger); }
.tag.info { background: var(--info-soft); color: var(--info); }
.tag.muted { background: #f0ede9; color: var(--text-muted); }
.tag.brand { background: var(--brand-soft); color: var(--brand-dark); }

/* 表单与按钮 */
label.field { display: block; margin-bottom: 12px; font-size: 13px; color: var(--text-muted); }
/* 注意：这里要排除 checkbox / radio。以前不排除，权限勾选项的复选框被改成
   display:block + width:100%，结果「复选框」和它后面的文字被拆成了两行。 */
label.field input:not([type="checkbox"], [type="radio"]),
label.field select,
label.field textarea {
  display: block; width: 100%; margin-top: 4px; padding: 8px 10px;
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  font-size: 15px; color: var(--text); background: #fff;
}
/* ---------- 控件高度统一（2026-10-10） ----------
   Chrome 给 select 的 UA 行高比 input 大，同样的 padding 下 select 会高出 2px，
   并排时上下缘对不齐；date 有内置日历按钮会再高几像素；没被 label.field 包住的
   裸 input（如周食谱页的"用餐人数"）只有 21px。这里统一给一个明确高度，
   并让按钮与控件同高（都是 38px），工具栏一行看起来才是齐的。 */
/* 用 :not(选择器列表) 而不是串一串 :not()：后者会把权重堆到 0,7,1，
   连登录卡片自己的规则都压不过去（登录页要保持原稿的舒展高度）。 */
input:not([type="checkbox"], [type="radio"], [type="file"], [type="submit"],
          [type="button"], [type="range"], [type="color"]),
select {
  height: 38px;
}
/* 文件选择框：Chrome 的原生控件在不同页面高度从 21px 到 45px 不等，
   这里给它和其它控件一致的高度，并把「选择文件」按钮做成和站点一致的圆角样式 */
input[type="file"] {
  padding: 4px 8px; height: 38px;
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  background: #fff; color: var(--text-muted); font-size: 13px;
}
input[type="file"]::file-selector-button {
  margin-right: 10px; padding: 2px 12px;
  border: 1px solid var(--border); border-radius: 6px;
  background: #fff; color: var(--text);
  font-family: inherit; font-size: 13px; cursor: pointer;
  transition: background .16s ease, border-color .16s ease, color .16s ease;
}
input[type="file"]::file-selector-button:hover {
  background: var(--brand-soft); border-color: var(--brand); color: var(--brand-dark);
}
label.field input:not([type="checkbox"], [type="radio"]):focus,
label.field select:focus, label.field textarea:focus {
  outline: 2px solid var(--brand-soft); border-color: var(--brand);
}
/* 复选框 / 单选框保持 inline，和后面的文字待在同一行、垂直居中 */
label.field input[type="checkbox"],
label.field input[type="radio"] {
  display: inline-block; width: auto; height: auto;
  margin: 0; padding: 0; border: none; background: none;
  vertical-align: middle; accent-color: var(--brand); cursor: pointer;
}
/* 权限勾选组：一堆「复选框 + 文字」，每项内部同一行，整体自动换行 */
.perm-checks {
  display: flex; flex-wrap: wrap; gap: 7px 16px;
  padding-top: 5px; max-width: 940px;
}
.perm-checks > label {
  display: inline-flex; align-items: center; gap: 5px; flex: none;
  font-size: 13px; font-weight: 400; line-height: 1.45;
  white-space: nowrap; cursor: pointer; color: var(--text);
}
.perm-checks > label input[type="checkbox"] { margin: 0; flex: none; }
.perm-checks > label:hover { color: var(--brand-dark); }
/* 字段名 + 必填胶囊同一行（用户与权限页的表单用，
   代替会自动浮到上一行的 ::before） */
.field-label { display: inline-flex; align-items: center; gap: 6px; }
.field-label .req {
  font-style: normal; font-size: 11px; line-height: 1.7; padding: 0 6px;
  border-radius: 999px; color: var(--danger); background: var(--danger-soft);
}
.users-form label.field:has(input[required])::before { display: none; }
/* 必填项自动打标：只要控件带 required，标签右侧就显示"必填" */
label.field:has(input[required])::before,
label.field:has(select[required])::before,
label.field:has(textarea[required])::before {
  content: "必填"; float: right; font-size: 11px; line-height: 1.7;
  color: var(--danger); background: var(--danger-soft);
  padding: 0 6px; border-radius: 999px;
}
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  padding: 8px 15px; border-radius: var(--radius-sm);
  border: 1px solid var(--border); background: #fff; color: var(--text);
  font-size: 14px; font-weight: 500; cursor: pointer; box-shadow: var(--shadow-1);
  /* 固定行高：<a class="btn"> 会继承 body 的 1.6，比 <button class="btn"> 高出 2px，
     同一行里两种按钮一高一矮，这里把两者的盒模型拉平（都等于控件高度 38px） */
  line-height: 1.4;
  transition: background .16s ease, border-color .16s ease, box-shadow .18s ease, transform .12s ease;
}
.btn:hover { background: #fdf9f4; border-color: #e3d7c7; text-decoration: none; box-shadow: var(--shadow-2); }
.btn.primary { background: var(--brand); border-color: var(--brand); color: #fff; box-shadow: 0 1px 2px rgba(232, 121, 43, .22); }
.btn.primary:hover {
  background: var(--brand-dark); border-color: var(--brand-dark);
  box-shadow: var(--shadow-brand); transform: translateY(-1px);
}
.btn.small { padding: 4px 10px; font-size: 13px; }
.btn:active { transform: translateY(1px); }
.btn:disabled, .btn[disabled] { opacity: .55; cursor: not-allowed; transform: none; }
.btn:focus-visible, a:focus-visible, input:focus-visible, select:focus-visible {
  outline: 2px solid var(--brand); outline-offset: 1px;
}
.btn.ghost { background: transparent; color: var(--text-muted); }
.btn.ghost:hover { background: #f6f1ea; color: var(--text); }
input:disabled, select:disabled, textarea:disabled {
  background: #f7f4f0; color: var(--text-muted); cursor: not-allowed;
}
code { background: #f4efe8; padding: 1px 5px; border-radius: 4px; font-size: 12.5px; }
summary { cursor: pointer; }
details[open] > summary { background: var(--brand-soft); border-color: var(--brand); color: var(--brand-dark); }
details > *:not(summary) { animation: fade-in .12s ease-out; }
@keyframes fade-in { from { opacity: 0; transform: translateY(-2px); } to { opacity: 1; transform: none; } }
.toolbar { display: flex; flex-wrap: wrap; gap: 10px; align-items: flex-end; margin-bottom: 12px; }
.toolbar .spacer { flex: 1; }
/* 工具栏里的每个「标签 + 控件」统一纵向排布：
   原来 input / select 在行内的落点差 2px（浏览器对两种控件的行盒算法不同），
   并排时下缘参差；改成 flex 列之后两者位置完全一致，
   再配合 align-items: flex-end，右边按钮与控件的下缘也在同一条线上。 */
.toolbar label.field {
  margin: 0; display: flex; flex-direction: column; gap: 4px; justify-content: flex-end;
}
.toolbar label.field > .hint { line-height: 1.35; }
.toolbar input[type="text"], .toolbar input[type="month"], .toolbar input[type="date"],
.toolbar input[type="number"], .toolbar select { margin-top: 0; }

/* 需求填报：同一个长者可以一次录多条，一行一组（名称 / 剩余量 / 预计可用 / 删除） */
.item-row {
  display: grid; grid-template-columns: minmax(0, 1.6fr) minmax(0, .8fr) minmax(0, 1fr) minmax(0, 1fr) auto;
  gap: 10px; align-items: end; padding: 10px 12px; margin-bottom: 10px;
  border: 1px solid var(--border); border-radius: var(--radius-sm); background: #fffdfa;
}
.item-row .field { margin: 0; }
@media (max-width: 760px) { .item-row { grid-template-columns: 1fr; } }

/* 打印：只留内容，去掉导航、按钮和侧栏，便于打印二维码、台账、合同清单 */
@media print {
  .sidebar, .topbar .userbox, .topbar .btn, .toolbar, .btn, details > summary { display: none !important; }
  .shell { display: block; }
  .content { padding: 0; }
  .card { box-shadow: none; border-color: #ddd; }
  .table-wrap { max-height: none; overflow: visible; }
  table.data th { position: static; }
  .print-only { display: block !important; }
}
.print-only { display: none; }

/* 空状态与提示 */
.empty { padding: 34px 16px; text-align: center; color: var(--text-muted); font-size: 14px; }
.hint { font-size: 13px; color: var(--text-muted); }

/* 缴费确认的姓名联想：输入框下面浮一层候选，支持中文/全拼/首字母过滤。
   2026-09-17 加：预收表一百多人，下拉翻页太慢，收款同事习惯打首字母（qns → 曲乃生）。 */
.combo-list {
  position: absolute; top: 100%; left: 0; z-index: 40;
  min-width: 260px; max-height: 280px; overflow-y: auto;
  margin-top: 4px; padding: 4px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: 10px; box-shadow: 0 12px 28px rgba(15, 23, 42, .16);
}
.combo-item {
  display: flex; align-items: baseline; gap: 10px;
  padding: 7px 10px; border-radius: 7px; cursor: pointer;
}
.combo-item:hover, .combo-item.active { background: var(--brand-soft, #fff4e6); }
.combo-name { font-weight: 600; }
.combo-meta { font-size: 12px; color: var(--text-muted); }
.combo-empty { padding: 8px 10px; font-size: 13px; color: var(--text-muted); }

/* 提交前的核对框（缴费确认）。hidden 属性会被 display:flex 盖掉，所以显式写一条。 */
.modal-mask {
  position: fixed; inset: 0; z-index: 80;
  display: flex; align-items: center; justify-content: center;
  padding: 20px; background: rgba(15, 23, 42, .45);
}
.modal-mask[hidden] { display: none; }
.modal-card {
  width: 100%; max-width: 400px;
  padding: 18px 20px 16px;
  background: var(--surface); border-radius: 14px;
  box-shadow: 0 24px 60px rgba(15, 23, 42, .3);
}
.modal-card h3 { margin: 0 0 14px; font-size: 15px; }
.modal-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 16px; }
/* 岗位预设弹窗：内容比「核对缴费」多，放宽一点，超高时自己滚 */
.modal-card.wide { max-width: 900px; max-height: 86vh; overflow-y: auto; }
.modal-head { display: flex; align-items: center; gap: 12px; margin-bottom: 14px; }
.modal-head h3 { margin: 0; font-size: 16px; }
.modal-close {
  margin-left: auto; width: 32px; height: 32px; flex: none;
  display: grid; place-items: center; cursor: pointer;
  border: 1px solid var(--border); border-radius: 8px;
  background: #fff; color: var(--text-muted); font-size: 18px; line-height: 1;
}
.modal-close:hover { background: #f6f1ea; color: var(--text); }
.small { font-size: 12.5px; }
.notice { padding: 10px 12px; border-radius: var(--radius-sm); font-size: 14px; margin-bottom: 12px; }
.notice.info { background: var(--info-soft); color: var(--info); }
.notice.warn { background: var(--warn-soft); color: var(--warn); }
.notice.danger { background: var(--danger-soft); color: var(--danger); }

/* 两栏详情 */
.split { display: grid; grid-template-columns: minmax(0, 2fr) minmax(260px, 1fr); gap: var(--gap); }
.kv { display: grid; grid-template-columns: 92px 1fr; gap: 6px 12px; font-size: 14px; }
.kv .k { color: var(--text-muted); }

@media (max-width: 980px) {
  .grid.cols-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .grid.cols-3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .split { grid-template-columns: 1fr; }
}
@media (max-width: 720px) {
  /* 导航已经改成抽屉（见下面 760 断点），这里不再把它铺到内容上方 */
  /* 卡片紧凑化（2026-10-10 用户要求）：统计/待办卡片手机上两列并排，不再一卡一行；
     只有真正的两栏详情（cols-2）才铺成单列 */
  .grid.cols-2 { grid-template-columns: 1fr; }
  .grid.cols-3, .grid.cols-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .content { padding: 14px; }
}

/* 页脚备案信息：与门牌页同一口径（鲁ICP备2026048979号-1 / 鲁公网安备37070502000773号） */
.site-footer {
  border-top: 1px solid var(--border);
  padding: 14px 22px 22px;
  color: var(--text-muted); font-size: 12px; line-height: 1.8;
  display: flex; flex-wrap: wrap; gap: 4px 12px; align-items: center;
}
.site-footer .footer-brand { font-weight: 600; color: var(--text); }
.site-footer .sep { color: #d8ccbd; }
.site-footer a { color: var(--text-muted); }
.site-footer a:hover { color: var(--brand-dark); }

@media (max-width: 720px) {
  .site-footer { padding: 12px 14px 18px; gap: 2px 10px; }
}

/* 家属填报/提交成功等独立页面的页脚（与主站页脚同一口径） */
.entry-footer {
  margin: 26px auto 0; padding: 14px 16px 28px;
  border-top: 1px solid var(--border);
  color: var(--text-muted); font-size: 12px; line-height: 1.9; text-align: center;
}
.entry-footer .sep { color: #d8ccbd; }
.entry-footer a { color: var(--text-muted); }
.entry-footer a:hover { color: var(--brand-dark); }

/* 登录页：左侧品牌区 + 右侧登录卡片；窄屏自动上下堆叠（断点 860px） */
.login-body { background: var(--bg); }
.login-shell {
  min-height: 100vh; display: grid;
  grid-template-columns: minmax(340px, 46fr) minmax(360px, 54fr);
}
.login-brand {
  position: relative; overflow: hidden;
  /* 暖米色底 + 两层橙色光晕；新 logo 是深棕+金色透明图，浅底才保得住原色 */
  background:
    radial-gradient(circle at 88% 90%, rgba(232, 121, 43, .20), rgba(232, 121, 43, 0) 60%),
    radial-gradient(circle at 2% 2%, rgba(232, 121, 43, .10), rgba(232, 121, 43, 0) 55%),
    linear-gradient(158deg, #fffbf6 0%, #fdf2e5 50%, #f7e4cd 100%);
  color: var(--text); padding: 54px 56px 54px 60px;
  display: flex; flex-direction: column; justify-content: center; gap: 16px;
  border-right: 1px solid var(--border);
}
/* 点阵纹理：薄薄铺一层，避免大块纯色发“空”（向右下渐隐） */
.login-brand::before {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background-image: radial-gradient(rgba(198, 122, 63, .16) 1px, transparent 1px);
  background-size: 22px 22px;
  -webkit-mask-image: linear-gradient(155deg, #000 0%, rgba(0, 0, 0, .35) 42%, transparent 68%);
  mask-image: linear-gradient(155deg, #000 0%, rgba(0, 0, 0, .35) 42%, transparent 68%);
}
/* 左缘品牌色带：给整块加一条竖向暖色锚 */
.login-brand::after {
  content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 5px;
  background: linear-gradient(180deg, var(--brand) 0%, #f0a35b 52%, rgba(232, 121, 43, .12) 100%);
}
.login-logo { position: relative; width: 100%; max-width: 400px; height: auto; align-self: flex-start; }
.login-kicker {
  position: relative; margin: 6px 0 0; font-size: 15px; font-weight: 600;
  letter-spacing: 6px; color: var(--brand-dark);
}
/* 按用户要求：logo 下方不再放整句说明（品牌信息由 logo 自身承担，版面更干净） */
.login-lead { display: none; }
.login-points { position: relative; list-style: none; margin: 10px 0 0; padding: 0; display: grid; gap: 9px; font-size: 13px; color: var(--text-muted); }
.login-points li { display: flex; align-items: center; gap: 9px; }
.login-points li::before {
  content: ""; flex: none; width: 6px; height: 6px; border-radius: 50%;
  background: var(--brand); box-shadow: 0 0 0 3px rgba(232, 121, 43, .16);
}
/* 品牌区底部一行说明，用虚线压边，收住下半部分的空白 */
.login-brand-foot {
  position: relative; margin: 16px 0 0; padding-top: 14px;
  border-top: 1px dashed rgba(232, 121, 43, .38);
  font-size: 12px; letter-spacing: .5px; color: var(--text-muted);
}
.login-panel {
  /* 右侧橙色渐变底：白卡片浮在上面，橙色集中在表单侧 */
  position: relative; overflow: hidden;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 20px; padding: 44px 24px;
  background: linear-gradient(155deg, #f4a35c 0%, var(--brand) 50%, #bf5c0d 100%);
}
.login-panel::before {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background-image: radial-gradient(rgba(255, 255, 255, .18) 1px, transparent 1px);
  background-size: 22px 22px;
  -webkit-mask-image: linear-gradient(155deg, #000, rgba(0, 0, 0, .32) 45%, transparent 70%);
  mask-image: linear-gradient(155deg, #000, rgba(0, 0, 0, .32) 45%, transparent 70%);
}
.login-panel::after {
  content: ""; position: absolute; left: -120px; bottom: -150px;
  width: 360px; height: 360px; border-radius: 50%;
  background: rgba(255, 255, 255, .12);
}
/* 橙色面板上的装饰：右上角大圆环 + 一枚错位小环，给大面积橙色加层次 */
.panel-deco {
  position: absolute; right: -74px; top: -78px; width: 252px; height: 252px;
  border-radius: 50%; border: 28px solid rgba(255, 255, 255, .13);
  pointer-events: none;
}
.panel-deco::after {
  content: ""; position: absolute; left: 28px; top: 182px;
  width: 104px; height: 104px; border-radius: 50%;
  border: 12px solid rgba(255, 255, 255, .10);
}
.login-card {
  position: relative; overflow: hidden;
  width: 100%; max-width: 384px; background: var(--surface);
  border-radius: 18px; padding: 32px 28px 26px;
  box-shadow: 0 2px 4px rgba(80, 35, 4, .12), 0 26px 60px rgba(80, 35, 4, .32);
}
/* 卡片顶部渐变条：与品牌区色带呼应 */
.login-card::before {
  content: ""; position: absolute; left: 0; right: 0; top: 0; height: 4px;
  background: linear-gradient(90deg, var(--brand) 0%, #f2a25a 55%, #f8c98f 100%);
}
.login-card h2 { margin: 0; font-size: 20px; letter-spacing: .5px; }
.login-sub { margin: 6px 0 18px; }
/* 输入框：比通用样式更舒展；聚焦时橙色描边 + 柔和外发光 */
.login-card label.field input {
  padding: 11px 13px; border-radius: 10px;
  border: 1px solid var(--border); background: #fffdfb;
  transition: border-color .15s ease, box-shadow .15s ease, background .15s ease;
}
.login-card label.field input:focus {
  outline: none; border-color: var(--brand); background: #fff;
  box-shadow: 0 0 0 3px rgba(232, 121, 43, .16);
}
/* 登录按钮：橙色渐变 + 阴影，悬停微抬、按下回沉（覆盖 .btn.primary 的平面样式） */
.login-card .login-submit {
  width: 100%; padding: 12px 16px; font-size: 15px; letter-spacing: 4px; margin-top: 10px;
  border: none; border-radius: 10px; color: #fff;
  background: linear-gradient(135deg, #ef8a3c 0%, var(--brand) 46%, var(--brand-dark) 100%);
  box-shadow: 0 10px 22px rgba(232, 121, 43, .28);
  transition: transform .12s ease, box-shadow .15s ease, filter .15s ease;
}
.login-card .login-submit:hover { filter: brightness(1.04); transform: translateY(-1px); box-shadow: 0 13px 26px rgba(232, 121, 43, .34); }
.login-card .login-submit:active { transform: translateY(1px); box-shadow: 0 6px 14px rgba(232, 121, 43, .24); }
.login-card .login-submit:disabled { filter: none; transform: none; box-shadow: none; opacity: .72; }
.login-help { margin: 14px 0 0; text-align: center; }
/* 备案件落在橙色底上：改浅色文字 + 轻投影保证可读 */
.login-beian {
  position: relative; margin: 0; font-size: 12px; line-height: 1.9; text-align: center;
  color: rgba(255, 246, 238, .94); text-shadow: 0 1px 2px rgba(90, 40, 5, .25);
}
.login-beian .sep { color: rgba(255, 246, 238, .55); }
.login-beian a { color: rgba(255, 246, 238, .96); text-decoration: none; }
.login-beian a:hover { color: #fff; text-decoration: underline; }

@media (max-width: 860px) {
  /* 手机端：橙色整页 + 一张白色卡片；卡片内 logo→标题→表单一条视觉线 */
  .login-shell {
    position: relative;
    grid-template-columns: 1fr;
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: 0; padding: 26px 16px 22px;   /* 卡片上下两半必须严丝合缝 */
    background-image:
      radial-gradient(rgba(255, 255, 255, .15) 1px, transparent 1px),
      linear-gradient(155deg, #f4a35c 0%, var(--brand) 48%, #bf5c0d 100%);
    background-size: 24px 24px, auto;
  }
  /* 底色装饰：右上圆环 + 左下柔光，垫在卡片下层 */
  .login-shell::before {
    content: ""; position: absolute; right: -58px; top: -34px; z-index: 0;
    width: 186px; height: 186px; border-radius: 50%;
    border: 20px solid rgba(255, 255, 255, .13); pointer-events: none;
  }
  .login-shell::after {
    content: ""; position: absolute; left: -76px; bottom: -64px; z-index: 0;
    width: 230px; height: 230px; border-radius: 50%; pointer-events: none;
    background: radial-gradient(circle, rgba(255, 255, 255, .20), rgba(255, 255, 255, 0) 70%);
  }
  .login-brand, .login-panel { position: relative; z-index: 1; }
  .panel-deco { display: none; }     /* 面板在手机上透明，桌面那组装饰收起 */
  /* 卡片上半：品牌信息居中 */
  .login-brand {
    width: 100%; max-width: 380px;
    background: var(--surface);
    border-radius: 22px 22px 0 0; border-right: none;
    padding: 30px 26px 0; gap: 10px;
    align-items: center; text-align: center;
  }
  .login-brand::before {            /* 卡片顶部橙色彩条（桌面端此处是点阵） */
    content: ""; position: absolute; left: 0; right: 0; top: 0; height: 4px;
    border-radius: 22px 22px 0 0; display: block;
    background: linear-gradient(90deg, var(--brand), #f4a35c 55%, #f9d3a6);
  }
  .login-brand::after { display: none; }     /* 竖向色带在小屏收起 */
  .login-logo { max-width: 250px; margin: 0 auto; }
  .login-kicker { font-size: 13px; font-weight: 500; letter-spacing: 4px; margin: 2px 0 0; color: var(--muted); }
  .login-points, .login-brand-foot { display: none; }
  /* 卡片下半：纯表单，与上半共拼一张卡（去掉第二个标题，避免与品牌名重复） */
  .login-panel {
    width: 100%; max-width: 380px;
    background: transparent; padding: 0; gap: 16px;
    align-items: stretch; justify-content: flex-start;
  }
  .login-panel::before, .login-panel::after { display: none; }
  .login-card {
    max-width: none; padding: 0 26px 26px; border-radius: 0 0 22px 22px;
    background: var(--surface);
    box-shadow: none; overflow: visible;
  }
  .login-card::before { display: none; }     /* 彩条已在整张卡片顶部 */
  .login-card h2 { display: none; }          /* 隐藏「欢迎回来」，只留一行引导语 */
  .login-sub { margin: 0 0 20px; text-align: center; }
  .login-beian { margin-top: 0; }            /* 落在橙色底上，沿用浅色文字 */
}
/* 全局控件高度统一（38px）是为后台工具栏对齐用的；
   登录卡片保持原有的舒展高度，不被压扁 */
.login-card label.field input,
.login-card label.field select { height: auto; }
/* ---------- 大字模式（2026-09-21 用户要求：厨房/餐饮同事核对用） ---------- */
html[data-font="large"] body { zoom: 1.16; }
html[data-font="large"] table.data td,
html[data-font="large"] table.data th { font-size: 15px; padding: 9px 12px; }
html[data-font="large"] .btn.small { padding: 8px 14px; font-size: 15px; }
html[data-font="large"] .card h2 { font-size: 18px; }
html[data-font="large"] .stat .v { font-size: 23px; }
html[data-font="large"] #font-toggle { background: var(--brand); border-color: var(--brand); color: #fff; }

/* ---------- 手机端（食材核对要在手机上能用） ----------
   2026-09-29 用户选 B 方案：导航从「内容上方一整块（占 38% 屏高、自己还要滚）」改成
   「顶栏 ☰ → 左侧抽屉」，内容区不再被挤下去；桌面端（>760px）完全不变。 */
@media (max-width: 760px) {
  body { overflow-x: hidden; }
  .shell { display: block; }
  .main { width: 100%; min-width: 0; }
  .content { padding: 12px 10px 60px; }
  .grid.cols-2 { grid-template-columns: 1fr; }
  .grid.cols-3, .grid.cols-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
  .pay-tabs { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); width: 100%; }
  .pay-tab { justify-content: center; padding-inline: 8px; }
  .pay-card-grid { grid-template-columns: 1fr; }
  .pay-card { min-height: 0; padding: 12px; }
  .card-head:has(#pay-card-search) .card-head-actions { width: 100%; }
  #pay-card-search { width: 100% !important; }
  .pay-card-foot .btn { flex: 1 1 0; }
  .table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
  table.data { min-width: 520px; }
  .toolbar { flex-wrap: wrap; gap: 6px; }
  .btn { padding: 8px 14px; }
  input, select, textarea { font-size: 16px; }   /* iOS 聚焦时不自动放大 */

  /* 顶栏常驻一行：☰ + 当前页名 + 大字/退出（标题过长省略，不再换行挤掉内容） */
  .topbar { position: sticky; top: 0; z-index: 40; flex-wrap: nowrap; gap: 8px; padding: 8px 12px; }
  .topbar h1 { font-size: 16px; width: auto; flex: 1 1 auto; min-width: 0;
               white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .topbar .userbox { border-left: 0; padding-left: 0; gap: 6px; }
  .userbox .who { display: none; }
  /* ☰ 是手机上最主要的入口：做成品牌色实心块（42×42 好按），一眼能找到 */
  .topbar .nav-toggle {
    display: inline-flex; align-items: center; justify-content: center;
    width: 42px; height: 42px; padding: 0; border-radius: 10px;
    background: var(--brand); border-color: var(--brand); color: #fff;
    font-size: 20px; line-height: 1; box-shadow: 0 2px 6px rgba(232, 121, 43, .35);
  }
  .topbar .nav-toggle:hover { background: var(--brand-dark); border-color: var(--brand-dark); }
  html[data-font="large"] .topbar .nav-toggle { width: 46px; height: 46px; padding: 0; font-size: 22px; }

  /* 导航 = 左侧抽屉，平时收在屏幕外；打开时铺满屏高、自己可滚 */
  .sidebar {
    position: fixed; top: 0; bottom: 0; left: 0; width: min(86%, 330px); height: auto; max-height: none;
    z-index: 60; overflow-y: auto;
    padding: calc(16px + env(safe-area-inset-top)) 12px calc(18px + env(safe-area-inset-bottom));
    transform: translateX(-104%); transition: transform .22s ease;
  }
  html.nav-open .sidebar { transform: translateX(0); box-shadow: 6px 0 26px rgba(28, 24, 20, .3); }
  body.nav-open { overflow: hidden; }
  .sidebar .nav-close { display: inline-flex; top: calc(12px + env(safe-area-inset-top)); }
  .nav-mask { display: block; position: fixed; inset: 0; z-index: 55; background: rgba(28, 24, 20, .42);
              opacity: 0; pointer-events: none; transition: opacity .18s ease; }
  .nav-mask[hidden] { display: none; }
  html.nav-open .nav-mask { opacity: 1; pointer-events: auto; }
  /* 手指点得着：抽屉里的条目加高 */
  .nav-group a { padding: 11px 10px; font-size: 15px; }
  .nav-group .label { padding: 8px 8px 4px; }
}

/* ---------- 新入住进度（2026-09-29 第三版）----------
   五步摊开成带名字的标签：绿=已完成、橙=当前卡点、灰=还没到，
   一眼能读出"哪几步做完了、卡在哪一步"。时间点进悬停提示，多了就点「详情」看时间轴。
   （前两版：① 每步连时间全铺开太挤；② 只留圆点又看不出步骤名。） */
table.data td.progress-cell { white-space: normal; min-width: 400px; }
.steps { display: flex; flex-wrap: wrap; gap: 5px; }
.steps .s { font-size: 12px; padding: 1px 9px; border-radius: 999px; white-space: nowrap;
            border: 1px solid var(--border); background: #fff; color: var(--text-muted); }
.steps .s.done { background: var(--ok-soft); border-color: #bfe0cf; color: var(--ok); }
.steps .s.now { background: var(--brand); border-color: var(--brand); color: #fff; font-weight: 600; }
.steps .wait { font-size: 12px; color: var(--warn); background: var(--warn-soft);
               border-radius: 999px; padding: 1px 8px; align-self: center; }
.timeline { display: grid; gap: 6px; padding: 6px 0 2px; }
.timeline .row { display: flex; align-items: center; gap: 10px; font-size: 13px; }
.timeline .mark { width: 20px; height: 20px; border-radius: 50%; flex: none;
                  display: inline-flex; align-items: center; justify-content: center;
                  font-size: 11px; border: 1px solid var(--border);
                  background: #fff; color: var(--text-muted); }
.timeline .row.done .mark { background: var(--ok-soft); border-color: var(--ok); color: var(--ok); }
.timeline .row.now .mark { background: var(--brand); border-color: var(--brand); color: #fff; }
.timeline .row .at { min-width: 100px; color: var(--text-muted); font-variant-numeric: tabular-nums; }
.timeline .row .label { min-width: 90px; }
.timeline .row.now .label { color: var(--brand-dark); font-weight: 600; }
.timeline .row .note { font-size: 12px; color: var(--text-muted); }

/* 首次入住填报：每个上传框选完就给一张缩略图（6 张都能看出传的是哪张） */
.idbox .pick-preview { display: none; max-width: 150px; max-height: 120px;
                       margin-top: 6px; border: 1px solid var(--border); border-radius: 6px; }

/* 合同编号：前缀固定显示在框里，只让填后面三位序号（2026-10-10） */
.no-input { display: flex; align-items: center; gap: 2px; margin-top: 4px;
            border: 1px solid var(--border); border-radius: var(--radius-sm);
            background: #fff; padding: 0 10px; }
.no-input:focus-within { outline: 2px solid var(--brand-soft); border-color: var(--brand); }
.no-input .no-prefix { font-size: 14px; color: var(--text-muted); white-space: nowrap; }
.no-input input { border: 0; margin: 0; padding: 8px 0; width: 4.2em; background: transparent; }
.no-input input:focus { outline: none; }

/* ---------- 移动端优化（2026-10-10 全量巡检后的整改）----------
   巡检结论（tools/mobile_audit.py，390×844 视口）：
   ① 顶栏把「页面操作按钮」和标题、大字、退出挤在同一行 —— 标题被省略号截到只剩几个字
      （合同到期提醒只剩 4px 宽），按钮被挤成 2～5 行（最高 114px）；
   ② 各页「新增/修改」表单用的是内联 grid（4 列 ×150px），手机上直接横向溢出；
   ③ 手机端按钮高度只有 28～30px，低于 40px 的触控建议值；
   ④ 表格比屏幕宽但右缘没有任何"可以横滑"的提示。
   下面按这四条整改，桌面端（>760px）行为完全不变。 */

/* 表单栅格：替代各页内联的 `grid-template-columns:repeat(4, minmax(150px,1fr))` */
.form-grid { display: grid; gap: 8px; align-items: end; }
.form-grid.cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.form-grid.cols-4 { grid-template-columns: repeat(4, minmax(140px, 1fr)); }
.form-grid .field { margin: 0; }
.form-grid .span-2 { grid-column: span 2; }
.form-grid .span-all { grid-column: 1 / -1; }

/* 抽屉底部的账号/退出：桌面端不显示（顶栏里已有），只在手机上出现 */
.sidebar-foot { display: none; }

/* 表格横滑提示条（手机端由 base.html 注入，滚过就撤掉） */
.scroll-hint {
  margin: 0 0 6px; padding: 4px 10px; border-radius: 999px;
  background: var(--brand-soft); color: var(--brand-dark);
  font-size: 12px; display: inline-block;
}
.table-wrap.is-scrollable {
  box-shadow: inset -14px 0 14px -14px rgba(43, 35, 24, .28),
              inset 14px 0 14px -14px rgba(43, 35, 24, .10);
}

/* 页面没放操作按钮时（大多数页），这层不占位 */
.topbar-actions { display: flex; align-items: center; gap: 8px; }
.topbar-actions:empty { display: none; }
/* 操作按钮超出屏幕（手机上按钮多）时，右缘渐隐提示"还能往左滑" */
.topbar-actions.is-scrollable { box-shadow: inset -16px 0 14px -14px rgba(43, 35, 24, .22); }

@media (max-width: 760px) {
  /* ① 顶栏两行：第一行 ☰ + 标题 + 大字；第二行页面自己的操作按钮（可横滑） */
  .topbar { flex-wrap: wrap; row-gap: 6px; padding: 8px 12px 6px; }
  .topbar .spacer { display: none; }
  .topbar h1 { flex: 1 1 auto; min-width: 0; font-size: 15px; }
  .topbar.chips-on h1 { flex: 0 1 auto; max-width: 36vw; }
  .topbar.chips-on .userbox { display: none; }

  /* ①-b 顶部统计卡 / 待办卡：手机上按两列换行，所有卡片不滑动即可看全。 */
  .grid:has(> .stat), .grid:has(> a.todo) {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 10px;
    overflow: visible;
    padding-bottom: 0;
  }
  .grid:has(> .stat) > *, .grid:has(> a.todo) > * { width: auto; min-width: 0; }
  /* 滚动后的小卡片回到标题行右侧；标题限宽，其余空间留给小卡片横滑查看。 */
  .title-chips {
    display: flex !important;              /* 压掉 ≤1100/≤720 两处的 display:none */
    right: 12px; top: 8px; bottom: auto;
    height: 38px; transform: none;
    max-width: none; align-items: center;
    justify-content: flex-start; gap: 5px; padding: 0 12px 0 0;
    overflow: hidden;
    scroll-padding-right: 12px;
    pointer-events: none;
  }
  .title-chips::-webkit-scrollbar { display: none; }
  .title-card { padding: 2px 8px 3px 10px; border-radius: 8px; flex: 0 0 auto;
    min-width: 72px; max-width: 128px;
    box-shadow:0 3px 10px rgba(43,35,24,.12) }
  .title-card.title-more { min-width:38px; max-width:48px; justify-content:center;
    padding-left:8px; color:var(--brand-dark); font-weight:700 }
  /* 标签不截断（放不下就横滑看，别把「≤ 3 天（尽快联系）」切成半句） */
  .title-card .k { font-size: 12px; max-width: none; overflow: visible; }
  .title-card .v { font-size: 13px; }
  .topbar-actions {
    order: 9; flex: 1 0 100%;
    display: flex; align-items: center; gap: 8px;
    overflow-x: auto; overflow-y: hidden;
    margin: 0 -12px; padding: 2px 12px 4px;
    scrollbar-width: none; -webkit-overflow-scrolling: touch;
  }
  .topbar-actions::-webkit-scrollbar { display: none; }
  .topbar-actions:empty { display: none; }
  .topbar-actions .btn { flex: none; white-space: nowrap; }
  /* 退出收进抽屉（见 base.html 的 .sidebar-foot）：顶栏留出宽度给标题 */
  .topbar .userbox .logout-form { display: none; }
  .topbar .userbox { border-left: 0; padding-left: 0; }

  /* 抽屉底部账号区 */
  .sidebar-foot {
    display: flex; align-items: center; justify-content: space-between; gap: 10px;
    margin-top: auto; padding: 12px 8px calc(10px + env(safe-area-inset-bottom, 0px));
    border-top: 1px solid rgba(255, 255, 255, .14);
    /* 菜单很长时也要能随时看到当前账号与退出：固定在抽屉底部 */
    position: sticky; bottom: 0; z-index: 2;
    background: linear-gradient(180deg, rgba(36, 26, 17, .94), #241a11 42%);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
  }
  .sidebar-foot .who { font-size: 13px; color: #c2b6a8; min-width: 0;
                       overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .sidebar-foot .logout-form { display: flex; margin: 0; flex: none; }
  .sidebar-foot .btn {
    background: rgba(255, 255, 255, .10); border-color: rgba(255, 255, 255, .22); color: #f0e9e1;
  }
  .sidebar-foot .btn:hover { background: rgba(255, 255, 255, .18); }

  /* ③ 触控尺寸：手指点得着（原来 .btn.small 只有 28px 高） */
  .btn { min-height: 40px; display: inline-flex; align-items: center; justify-content: center;
         padding: 9px 14px; }
  .btn.small { min-height: 36px; padding: 7px 12px; }
  .topbar .btn.small { min-height: 38px; }
  table.data .btn.small { min-height: 34px; padding: 6px 10px; }
  .toolbar { gap: 8px; }

  /* ② 手机上的表单栅格一律单列（内联 grid 的页面已改用 .form-grid） */
  .form-grid.cols-2, .form-grid.cols-4 { grid-template-columns: 1fr; }
  .form-grid .span-2, .form-grid .span-all { grid-column: auto; }

  /* 卡片与内容留白收紧一点，屏幕窄时把空间还给内容 */
  .card { padding: 14px 14px; }
  .card h2 { margin-bottom: 10px; }

  /* 工具栏里的输入框：原来写死了 80～200px，手机上铺满整行更好按 */
  .toolbar .field { flex: 1 1 100%; }
  /* 排除 checkbox / radio：它们也匹配 input，被拉成 100% 宽之后
     复选框会占满整行、后面的文字全被挤到行外（2026-10-10 移动端实测） */
  .toolbar .field input:not([type="checkbox"], [type="radio"]),
  .toolbar .field select { width: 100% !important; }
  .toolbar > .btn { flex: 1 1 auto; }

  /* 表格不再做"框内纵向滚动"：手机上双层滚动很容易滑错，直接把页面拉长；
     横向滚动照旧（上面有 .scroll-hint 提示），表头也不再吸顶（避免和吸顶的顶栏打架） */
  .table-wrap { max-height: none; }
  table.data th { position: static; }

  /* 折叠开关与页脚链接：文字链接也要有能点中的高度 */
  summary.hint { display: inline-block; padding: 8px 0; }
  .site-footer a { display: inline-block; padding: 4px 0; }
  .entry-footer a { display: inline-block; padding: 4px 0; }

  /* 卡片紧凑化（2026-10-10 用户要求）：两列后每格约 170px，
     数值与说明按窄卡口径收紧，长金额也不会顶破卡片 */
  .stat { padding: 12px 12px; }
  .stat .v { font-size: 20px; }
  /* 说明文字不低于 12px：10-12 卡片瘦身时桌面缩到 11.5px，手机上读不清
     （2026-10-12 手机端全量巡检：工作台待办卡 / 系统用户页必填胶囊也一并提上来） */
  .stat .s { line-height: 1.45; font-size: 12px; }
  a.todo .s, .field-label .req { font-size: 12px; }
  a.todo { padding: 11px 12px; }
  a.todo .v { font-size: 20px; }
  /* 大字模式整页放大 1.16 倍，两列会挤，退回单列 */
  html[data-font="large"] .grid.cols-3,
  html[data-font="large"] .grid.cols-4 { grid-template-columns: 1fr; }
}

/* ---------- 护理员工作台（2026-10-13） ----------
   只有入口卡片的极简页：手机端、只有现场录入权限的账号（护理员）登录后落在这里。
   设计定稿见 outputs/护理员导航页-设计稿-20261013（A2 暖色实心卡：卡片高 88、
   间距 30、字 24、图标块 53）。卡片上只有图标 + 名称，整组在屏幕上纵向居中；
   桌面端不会自动进这个页（管理员手工打开也能看）。入口表：app/web/hub.py 的 HUB_ITEMS。 */
/* 手机端 .content 下内边距是 60px（给普通页留的），这里收回来，否则整块内容偏上；
   手机端 .shell 是块级流（侧栏变抽屉），撑不满，只能按实测高度算（见下面的 min-height） */
.hub-page .content { padding-bottom: 12px; }
.hub-wrap {
  width: 100%; max-width: 460px; margin: 0 auto;
  display: flex; flex-direction: column; justify-content: center; gap: 30px;
  /* 172px = 顶栏 64 + 页脚 84 + 上下内边距 24（390×844 实测；
     卡片组中心与屏幕中心相差 ≤ 10px，且一屏放得下、不出现滚动条） */
  min-height: calc(100vh - 172px);
  min-height: calc(100dvh - 172px);
}
.hub-card {
  position: relative; overflow: hidden; color: #fff;
  display: flex; align-items: center; justify-content: center; gap: 15px;
  min-height: 88px; border-radius: 18px;
  transition: transform .14s ease;
}
.hub-card:hover { text-decoration: none; }
.hub-card:active { transform: scale(.985); }
/* 右侧大图标只当纹理：出血裁切 + 低透明度，不抢文字 */
.hub-card .hub-mark {
  position: absolute; right: -30px; top: 50%; transform: translateY(-50%);
  width: 152px; height: 152px; opacity: .13; pointer-events: none;
}
.hub-card .hub-ico {
  width: 53px; height: 53px; flex: none; border-radius: 15px;
  background: rgba(255, 255, 255, .26);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.55), 0 2px 6px rgba(0,0,0,.05);
  display: grid; place-items: center;
}
.hub-card .hub-ico svg { width: 29px; height: 29px; }
.hub-card .hub-title { font-size: 24px; font-weight: 700; letter-spacing: .06em; }
.hub-card.tone-vitals {
  background:
    radial-gradient(120% 150% at 10% 0%, rgba(255,255,255,.26) 0%, rgba(255,255,255,0) 46%),
    linear-gradient(135deg, #f2a869 0%, #e57f2d 48%, #c85c11 100%);
  box-shadow: 0 18px 32px -8px rgba(226,110,26,.42), 0 3px 10px rgba(226,110,26,.14),
              inset 0 1px 0 rgba(255,255,255,.38);
}
.hub-card.tone-glucose {
  background:
    radial-gradient(120% 150% at 10% 0%, rgba(255,255,255,.24) 0%, rgba(255,255,255,0) 46%),
    linear-gradient(135deg, #f18a86 0%, #dd5c62 48%, #b8485a 100%);
  box-shadow: 0 18px 32px -8px rgba(200,70,85,.40), 0 3px 10px rgba(200,70,85,.13),
              inset 0 1px 0 rgba(255,255,255,.34);
}
/* 大字模式：卡片用 min-height 撑开、字再放大一档，24px 的字不会被挤出去 */
html[data-font="large"] .hub-card { min-height: 100px; }
html[data-font="large"] .hub-card .hub-title { font-size: 26px; }
