:root{
  --bg:#f6f8fa; --panel:#fff; --line:#d0d7de; --text:#1f2328; --sub:#57606a;
  --blue:#0969da; --green:#1a7f37; --orange:#bc4c00; --red:#cf222e; --shadow:0 1px 3px rgba(31,35,40,.08);
  /* 安全区：刘海屏/挖孔屏的系统栏与手势条会盖住内容，把实际内边距取出来用。
     【必须带0px 兜底】不支持 env() 的老浏览器会把整条声明判为非法而丢弃，
     0px 兜底保证「拿不到就当没有」，布局与改动前完全一致。 */
  --sat:env(safe-area-inset-top,0px);
  --sar:env(safe-area-inset-right,0px);
  --sab:env(safe-area-inset-bottom,0px);
  --sal:env(safe-area-inset-left,0px);
}
*{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{margin:0;background:var(--bg);color:var(--text);
  font-family:-apple-system,BlinkMacSystemFont,"PingFang SC","Microsoft YaHei",Segoe UI,sans-serif;font-size:14px;line-height:1.6;
  /* 底部手势条留白；左右留白应对横屏时的刘海 */
  padding-bottom:var(--sab);padding-left:var(--sal);padding-right:var(--sar)}
a{color:var(--blue);text-decoration:none}
.wrap{max-width:1080px;margin:0 auto;padding:0 20px}
.mono{font-family:ui-monospace,Consolas,monospace;font-size:12.5px}

/* ===== 顶部导航（v5.4 重做：胶囊按钮组）===== */
.topbar{background:rgba(255,255,255,.92);backdrop-filter:saturate(180%) blur(12px);
  -webkit-backdrop-filter:saturate(180%) blur(12px);
  border-bottom:1px solid var(--line);position:sticky;top:0;z-index:10;
  box-shadow:0 1px 3px rgba(31,35,40,.05);
  /* 【关键】状态栏是「盖在网页之上」的，顶栏背景要一路铺到屏幕最顶端，
     但真正的按钮/文字必须躲开刘海与状态栏，否则第一行点不到也看不清。
     做法：背景铺满（不加 margin），内容用内边距下压。 */
  padding-top:var(--sat)}
/* 顶栏比正文宽：.wrap 上限 1080px 时，管理员的 8 个按钮（总宽约 795px）
   加上品牌区/用户区/退出按钮会被挤到放不下，只能靠滚动 + 居中留白兜着。
   顶栏是全宽条形，放宽到 1320px 后宽屏上就能一次排开所有按钮、不用滚。 */
.bar{max-width:1320px;display:flex;align-items:center;gap:14px;height:60px}

/* 品牌：图标底板 + 文字，去掉了原来的 emoji 直出 */
.brand{display:flex;align-items:center;gap:9px;color:var(--text);flex:0 0 auto}
.brand:hover{color:var(--text)}
.brand .logo{width:30px;height:30px;border-radius:9px;display:inline-flex;
  align-items:center;justify-content:center;font-size:16px;
  background:linear-gradient(135deg,#0969da,#218bff);box-shadow:0 2px 6px rgba(9,105,218,.28)}
.brand .bname{font-weight:700;font-size:16px;letter-spacing:.2px;white-space:nowrap}
@media (max-width:900px){.brand .bname{display:none}}

/* 导航：横向胶囊按钮组，当前页为实心蓝。
   overflow-x:auto 让按钮放不下时可横向滚动。
   flex:0 1 auto —— 允许收缩（flex-shrink:1）。空间够时占满，放不下时收缩到
   剩余宽度并开始滚动。不能写成 0 0 auto，否则会把 .bar 撑出横向溢出。
   JS 判断「是否真的放不下」时不能用 nav.clientWidth（它是收缩后的值），
   要用父容器剩余空间，见 base.html 的 fitsInBar()。
   .spacer 是 JS 动态插入的居中留白（不可见、不可点），让首尾按钮也能被滚到正中。 */
.bar nav{display:flex;align-items:center;gap:4px;margin-left:auto;flex:0 1 auto;
  overflow-x:auto;
  /* 故意不写 scroll-behavior:smooth。
    规范里 scrollBy 的 behavior:'auto' 表示「听CSS 的」，
     写成 smooth 后连「立即就位」也会变成动画 ——
     每次点按钮跳页后新 DOM 的 scrollLeft 归零，
     按钮行就会从第一个按钮滑过来，看着像每次都从头开始移动。
     要动画就在 JS 里显式传 behavior:'smooth'。 */
  -webkit-overflow-scrolling:touch;scrollbar-width:none;
  padding:3px 2px}
.bar nav::-webkit-scrollbar{display:none}
.bar nav .spacer{flex:0 0 auto;width:0;pointer-events:none}
.bar nav .nb{display:inline-flex;align-items:center;gap:5px;flex:0 0 auto;
  color:var(--sub);font-size:13.5px;padding:7px 12px;border-radius:9px;
  border:1px solid transparent;white-space:nowrap;
  transition:background .15s,color .15s,box-shadow .15s}
.bar nav .nb i{font-style:normal;font-size:13.5px;line-height:1;opacity:.85}
.bar nav .nb:hover{background:#eef2f6;color:var(--text)}
/* 当前页：实心蓝 + 白字。
   注意：这里必须同时覆盖 adminonly，否则 3 个 class 的 .nb.adminonly 会盖掉选中态颜色 */
.bar nav .nb.on,.bar nav .nb.on.adminonly{
  background:var(--blue);color:#fff;font-weight:600;
  box-shadow:0 2px 8px rgba(9,105,218,.3)}
.bar nav .nb.on i,.bar nav .nb.on.adminonly i{opacity:1}
/* 管理员专属按钮：仅靠字重微调区分，且选中后不能再改颜色（见上一条） */
.bar nav .nb.adminonly:not(.on){color:var(--sub)}
.bar nav .nb.adminonly:not(.on) i{opacity:.85}
/* 键盘可达性：Tab 聚焦到被滚动裁掉的按钮时，浏览器默认会把它滚进视野 */
.bar nav .nb:focus-visible{outline:2px solid var(--blue);outline-offset:2px}

/* 邮件状态胶囊（已按需去掉图标，仅保留纯文字提示时仍可用） */
.status{font-size:12px;padding:3px 10px;border-radius:20px;border:1px solid;white-space:nowrap}
.status.ok{color:var(--green);border-color:#a7d7b6;background:#eaf6ee}
.status.warn{color:var(--orange);border-color:#f0d3ab;background:#fff8ec}

main{padding:24px 20px 40px}
/* ===== 提示区 ======
   .flash 本身仍保留横幅样式，作为「脚本不可用」时的降级形态（见模板里的
   noscript）。正常情况下 #flashbox 是隐藏的，消息由 flash.js 转成
   弹窗（错误）/ 浮条（成功）。 */
.flashbox{margin-bottom:16px}
.flashbox[hidden]{display:none}
.flash{padding:10px 14px;border-radius:8px;margin-bottom:8px;border:1px solid}
.flash.ok{color:var(--green);background:#eaf6ee;border-color:#a7d7b6}
.flash.err{color:var(--red);background:#ffebe9;border-color:#ffcecb}

/* ---- 成功提示：自动消失的浮条 ---- */
.ftoast{position:fixed;left:50%;top:50%;transform:translate(-50%,-50%);
  z-index:1001;max-width:78vw;padding:11px 18px;border-radius:10px;
  background:rgba(31,35,40,.92);color:#fff;font-size:14.5px;line-height:1.5;
  text-align:center;white-space:pre-wrap;word-break:break-word;
  box-shadow:0 10px 28px rgba(0,0,0,.26);pointer-events:none;
  animation:ftoast-in .16s ease-out}
.ftoast.ftoast-out{animation:ftoast-out .2s ease-in forwards}
@keyframes ftoast-in{from{opacity:0;transform:translate(-50%,-50%) scale(.94)}
  to{opacity:1;transform:translate(-50%,-50%) scale(1)}}
@keyframes ftoast-out{to{opacity:0;transform:translate(-50%,-50%) scale(.97)}}

/* ---- 错误提示：需点「确定」的弹窗 ---- */
.fdlg-mask{position:fixed;inset:0;z-index:1002;display:none;
  align-items:center;justify-content:center;padding:24px;
  background:rgba(31,35,40,.45)}
.fdlg-mask.on{display:flex;animation:fd-in .12s ease-out}
@keyframes fd-in{from{opacity:0}to{opacity:1}}
.fdlg{width:100%;max-width:340px;background:var(--panel);border-radius:12px;
  box-shadow:0 14px 36px rgba(31,35,40,.28);overflow:hidden;
  animation:fd-pop .16s ease-out}
@keyframes fd-pop{from{opacity:0;transform:translateY(8px) scale(.97)}
  to{opacity:1;transform:none}}
.fdlg-body{display:flex;gap:12px;align-items:flex-start;padding:18px 18px 4px}
/* 图标用纯 CSS 画，避免多引一个字体图标文件 */
.fdlg-ic{flex:0 0 auto;width:20px;height:20px;border-radius:50%;margin-top:1px;
  background:var(--red);color:#fff;font-size:14px;font-weight:700;
  text-align:center;line-height:20px}
.fdlg-msg{flex:1;min-width:0;font-size:15px;line-height:1.55;color:var(--text);
  /* 异常信息常含换行（如「发送失败：{exc}」），必须保留换行否则会挤成一行 */
  white-space:pre-wrap;word-break:break-word}
.fdlg-foot{padding:8px 18px 16px;text-align:right}
.fdlg-ok{min-width:76px;text-align:center}

@media (prefers-reduced-motion:reduce){
  .ftoast,.ftoast.ftoast-out,.fdlg-mask.on,.fdlg{animation:none}
}

.cards{display:grid;grid-template-columns:repeat(4,1fr);gap:14px;margin-bottom:18px}
.card{background:var(--panel);border:1px solid var(--line);border-radius:10px;padding:14px 16px;box-shadow:var(--shadow)}
.card .num{font-size:26px;font-weight:700;line-height:1.2}
.card .num.ok{color:var(--green)} .card .num.hot{color:var(--red)}
.card .lab{color:var(--sub);font-size:12.5px}

.panel{background:var(--panel);border:1px solid var(--line);border-radius:10px;padding:18px 20px;margin-bottom:18px;box-shadow:var(--shadow)}
.panel.narrow{max-width:640px}
.panel-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:14px}
.panel-head h2{margin:0;font-size:16px}
.empty{color:var(--sub);padding:8px 0}

.tbl{width:100%;border-collapse:collapse}
.tbl th{text-align:left;font-size:12.5px;color:var(--sub);font-weight:600;padding:8px 10px;border-bottom:1px solid var(--line)}
.tbl td{padding:11px 10px;border-bottom:1px solid #eaeef2;vertical-align:middle}
.tbl tr:last-child td{border-bottom:none}
.tbl tr.off{opacity:.5}
.tbl .t{font-weight:600}
.tbl .sub{color:var(--sub);font-size:12.5px}
.right{text-align:right}
.ops{white-space:nowrap}

.tag{display:inline-block;font-size:12px;padding:2px 8px;border-radius:20px;margin-right:6px}
.tag.lunar{color:#8250df;background:#fbefff}
.pill{display:inline-block;font-size:12.5px;padding:3px 10px;border-radius:20px;font-weight:600}
.pill.d0{color:#fff;background:var(--red)}
.pill.d1{color:#fff;background:var(--orange)}
.pill.d2{color:var(--text);background:#fff3c4}
.pill.d3{color:var(--sub);background:#eaeef2}

.btn{display:inline-block;padding:7px 14px;border:1px solid var(--line);border-radius:8px;background:#f6f8fa;color:var(--text);cursor:pointer;font-size:13.5px}
.btn:hover{background:#eef1f4}
.btn.primary{background:var(--blue);border-color:var(--blue);color:#fff}
.btn.primary:hover{background:#0860ca}
.lnk{background:none;border:none;color:var(--blue);cursor:pointer;font-size:13px;padding:2px 6px}
.lnk.danger{color:var(--red)}
.inline{display:inline}

/* 字段通用（登录/注册页没有 .form 包裹，因此不限定作用域） */
.fld{display:block;margin-bottom:14px;text-align:left}
.fld > span{display:block;font-size:13px;color:var(--sub);margin-bottom:6px}
.req{color:var(--red)}
.form input,.form select,.form textarea,
.fld input,.fld select,.fld textarea{
  width:100%;padding:8px 10px;border:1px solid var(--line);border-radius:8px;font-size:14px;
  font-family:inherit;background:#fff;color:var(--text)}
.form input:focus,.form select:focus,.form textarea:focus,
.fld input:focus,.fld select:focus,.fld textarea:focus{
  outline:none;border-color:var(--blue);box-shadow:0 0 0 3px rgba(9,105,218,.12)}
.form small{display:block;color:var(--sub);font-size:12px;margin-top:5px}
.row2{display:grid;grid-template-columns:1fr 1fr;gap:14px}
.chk{display:flex;align-items:flex-start;gap:8px;margin:10px 0 16px;font-size:13.5px;color:var(--sub)}
.chk input{margin-top:4px}
/* checkbox 不是文本框，必须排除掉上面 .form input 的 width:100%/padding，
   否则勾选框会被撑成整行宽、把文字挤到边上甚至换行出去。
   （`.form input` 的选择器权重与 .chk input 相同，靠顺序覆盖不可靠，
     这里用更高权重的 .form .chk input 明确排除。） */
.form input[type=checkbox],
.form input[type=radio]{
  width:auto;padding:0;flex:0 0 auto;margin-top:4px;
  border:none;background:none;border-radius:0;box-shadow:none}
.form input[type=checkbox]:focus,
.form input[type=radio]:focus{outline:none;box-shadow:none}
.hr{border:none;border-top:1px solid var(--line);margin:18px 0}
.actions{display:flex;gap:10px;margin-top:6px}

.notice{background:#fff8ec;border:1px solid #f0d3ab;color:#7a4d00;padding:10px 14px;border-radius:8px;margin-bottom:16px;font-size:13px}
.err{color:var(--red);font-size:13px}
.tip{font-size:13.5px;color:var(--sub)}
.tip ul{margin:8px 0 0;padding-left:20px}
.tip code{background:#f0f3f6;padding:1px 6px;border-radius:4px;font-size:12.5px}
.foot{color:var(--sub);font-size:12.5px;padding:6px 20px 28px}

.warnbar{background:#fff8ec;border:1px solid #f0d3ab;color:#7a4d00;
  padding:10px 14px;border-radius:8px;font-size:13px}
.warnbar a{color:#7a4d00;text-decoration:underline}
.warnbar code{background:#fff;padding:1px 6px;border-radius:4px;font-weight:600}

/* 100vh 是「视口高」，但 body 已经带了下方的安全区内边距（避开手势条），
   直接用 100vh 会让页面比视口高出那截，多出一小段无意义的可滚动空白。
   dvh 会随地址栏收起而变化，更贴近真实可视高度；老浏览器不认就退回 100vh。 */
.loginwrap{min-height:100vh;min-height:calc(100dvh - var(--sab));
  display:flex;align-items:center;justify-content:center;padding:24px}
.logincard{background:#fff;border:1px solid var(--line);border-radius:12px;box-shadow:var(--shadow);
  padding:32px 30px;width:100%;max-width:340px;text-align:center}
.logincard .logo{font-size:38px;line-height:1}
.logincard h1{font-size:19px;margin:8px 0 2px}
.logincard .sub{color:var(--sub);font-size:13px;margin:0 0 18px}
.logincard .fld{text-align:left}
.btn.wide{width:100%;padding:10px;margin-top:6px;font-size:15px}
.tiptext{margin-top:14px;font-size:12.5px;line-height:1.6;color:var(--orange)}
.tiptext code{background:#fff3e3;padding:1px 5px;border-radius:4px}

/* ---- 表格横向滚动容器（窄屏必须） ---- */
.tblwrap{overflow-x:auto;-webkit-overflow-scrolling:touch}

@media (max-width:720px){
  /* 统计卡 2 列；表单两栏并一栏 */
  .cards{grid-template-columns:repeat(2,1fr)}
  .row2{grid-template-columns:1fr}

  /* 顶栏：两行布局。第一行 品牌+身份+退出，第二行 导航横向滑动 */
  .bar{height:auto;flex-wrap:wrap;gap:6px 10px;padding:9px 0 0;row-gap:6px}
  .brand{white-space:nowrap;flex:0 0 auto;min-width:0}
  .bar nav{order:10;flex:0 0 100%;margin-left:0;gap:6px;
    padding:3px 2px 9px}
  .bar nav .nb{padding:7px 12px;font-size:13px}
  .me{margin-left:auto;flex:0 0 auto}
  .me .who{max-width:88px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .btn.logout{flex:0 0 auto}

  /* 面板头：标题和按钮允许换行 */
  .panel-head{flex-wrap:wrap;gap:10px}
  .panel-head .btn{white-space:nowrap}
  .panel{padding:14px 14px}

  /* 表格：禁止逐字换行，交给 .tblwrap 横向滚动 */
  .tbl th,.tbl td{white-space:nowrap}
  .tbl th:first-child,.tbl td:first-child{padding-left:2px}
  .tbl .t{max-width:180px;white-space:normal}   /* 标题列允许两行，其余列不换行 */

  /* 统计卡 2 列（原已设置），数字缩小一点 */
  .card .num{font-size:22px}

  main{padding:16px 14px 32px}
  .wrap{padding:0 14px}
  .foot{padding:6px 14px 24px}
  .form input,.form select,.form textarea,
  .fld input,.fld select,.fld textarea{font-size:16px}  /* 防 iOS 聚焦自动放大 */
  .btn{padding:8px 13px}
  details.more > summary{padding:4px 6px}   /* 手机点按热区大一点 */
  /* 滚动容器会裁剪绝对定位的下拉，手机端改为原位展开。
     【但这条规则有例外，见下面 .tblwrap 那条】
     注意这里**不再写 min-width** —— 原来写死 210px 会让窄屏下浮层
     右侧空一大块（实测内容最宽 81px，空 115px）。
     宽度交给主规则的 width:max-content 决定。

     【v6.7】这条规则改成只在 **JS 没接管** 时才生效（html:not(.has-drop)）。
     原因：它是"点开瞬间"被画出来的那一帧 —— <details> 展开是同步的，
     而 toggle 事件异步，浏览器会先按这条规则画出「浮层在文档流里」的状态
     （实测卡片被撑高 180px→289px），下一帧 JS 改成 fixed 又缩回去
     = 用户看到的「点一下管理，整条数据闪一下」。
     moredrop.js 加载后会给 <html> 加 .has-drop，这条规则就让位给 JS。
     JS 没跑时（.has-drop 不存在）依然原位展开，兜底能力不变。 */
  html:not(.has-drop) details.more[open] .morebox{position:static;margin-top:8px}
  /* .tblwrap 是横向滚动容器（overflow-x:auto），绝对定位的浮层会被它裁掉：
     实测按钮命中测试返回 null —— 看得到、点不动。
     所以表格里的下拉**只能**原位展开。
     而原位展开会把所在行撑高、把下面的行推走（实测撑高 93px），
     这就是"点管理按钮时下面内容会移动"的根因。
     真正的解法是 static/moredrop.js —— 用 position:fixed 按视口坐标定位，
     既不撑开文档流，也不会被滚动容器裁掉。
     这条 CSS 只是 JS 没跑起来时的兜底。 */
  html:not(.has-drop) .tblwrap details.more[open] .morebox{position:static}
  .ops{white-space:normal}                  /* 操作列允许换行，避免整表被撑得过宽 */
}

/* ---- 多用户：顶部身份、角色徽章、用户管理 ---- */
.me{display:flex;align-items:center;gap:7px;margin-left:4px;flex:0 0 auto;
  padding:4px 10px 4px 4px;border-radius:20px;background:#f2f5f8;border:1px solid var(--line)}
.me .avatar{width:24px;height:24px;border-radius:50%;flex:0 0 auto;
  display:inline-flex;align-items:center;justify-content:center;
  font-size:12px;font-weight:700;color:#fff;letter-spacing:.5px;
  background:linear-gradient(135deg,#57606a,#8b949e)}
.me .who{font-size:13px;color:var(--text);font-weight:600;max-width:110px;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.role{display:inline-block;font-size:11px;padding:1px 7px;border-radius:10px;
  background:#eaeef2;color:var(--sub);border:1px solid var(--line)}
.role.admin{background:#ddf4ff;color:var(--blue);border-color:#b6e3ff}
/* 管理员专属内容的统一标记。
   顶部导航里的 adminonly 已由 .bar nav .nb.adminonly 单独接管字重，
   这里只兜其他位置（如页面内提示块），避免覆盖导航的选中态样式。 */
.adminonly:not(.nb){font-weight:600}
.headright{display:flex;align-items:center;gap:8px}
.btn.sm{padding:5px 10px;font-size:12.5px}
.btn.danger{color:var(--red);border-color:#f0c0c0}
.btn.danger:hover{background:#ffeef0}
/* 顶部退出按钮：低调描边，不与导航抢视线 */
.btn.logout{flex:0 0 auto;background:#fff;color:var(--sub);border-color:var(--line);
  padding:6px 12px;font-size:13px}
.btn.logout:hover{background:#f0f3f6;color:var(--red);border-color:#f0c0c0}

details.more{position:relative;display:inline-block}
details.more > summary{list-style:none;cursor:pointer;color:var(--blue);font-size:13px;
  padding:4px 9px;border-radius:999px;border:1px solid transparent;transition:background .12s,border-color .12s}
details.more > summary::-webkit-details-marker{display:none}
details.more > summary:hover{background:#eef4fb;border-color:#d5e3f3}
details.more[open] > summary{font-weight:600;background:#e6effa;border-color:#c9dcf2}

/* 浮层宽度：按内容自适应，不再硬撑
   【为什么不能写死 min-width】实测（窄屏 420 / 宽屏 1280）：
   盒子里最宽的文字是「录入人：管理员」81px，但 min-width:230px 把内容区撑到
   188~208px → 右侧空 107~127px，视觉上就是"空了一大块"。
   改成 min-width:0 + width:max-content，让盒子贴着内容。
   【为什么保留一个很小下限】太窄的浮层在手机上点不准，
   112px 是"三个汉字 + 两边内边距"的量，正好不空但也不虚胖。
   用户管理页的浮层里有并排的输入框，内容本身就宽，max-content 会自然展开。 */
.morebox{position:absolute;right:0;top:26px;z-index:20;
  min-width:112px;width:max-content;max-width:min(280px,calc(100vw - 24px));
  background:#fff;border:1px solid var(--line);border-radius:10px;padding:6px;
  box-shadow:0 6px 20px rgba(31,35,40,.12)}
.morebox form{display:flex;gap:6px;margin-bottom:4px;align-items:center}
.morebox form:last-child{margin-bottom:0}
.morebox input{flex:1;min-width:0;padding:5px 8px;border:1px solid var(--line);
  border-radius:6px;font-size:12.5px;font-family:inherit;background:#fff;color:var(--text)}

/* 浮层里的操作项：做成"整行可点的小按钮"
   【为什么不用原来那种裸文字 .lnk】裸文字点不准（手机上热区太小），
   而且三个操作项平铺在盒子里没有一个共同的视觉块，看起来像散着的文字。
   改成铺满整行 + 淡底 + 圆角：点击热区变大，三行也各自成块、层次清楚。
   —— 注意是**左对齐**：铺满整行的元素若居中，文字会与同排的其他项错开。 */
.morebox .moreact{margin-bottom:4px}
.morebox .lnk{display:block;width:100%;text-align:left;
  padding:7px 10px;line-height:1.4;
  border:1px solid transparent;border-radius:7px;
  background:#f4f7fa;color:var(--text);font-size:13px;
  transition:background .12s,border-color .12s}
.morebox .lnk:hover{background:#eaf1f9;border-color:#d3e2f2}
/* 危险项（删除）用淡红底，区别于普通操作，避免误点 */
.morebox .lnk.danger{background:#fdf0f0;color:var(--red)}
.morebox .lnk.danger:hover{background:#fbe3e3;border-color:#f0c5c5}
/* 录入人那行只是信息，不做成按钮 */
.morebox .gby{color:var(--sub);font-size:11.5px;margin-top:6px;
  padding:2px 10px 4px;white-space:nowrap}
.tbl tr.off td{opacity:.55}

/* 二级页返回按钮（礼簿详情 / 新增礼簿 / 新增收礼） */
.backlink{display:inline-flex;align-items:center;gap:4px;margin:0 0 12px;padding:7px 14px;
  border:1px solid var(--line);border-radius:999px;background:#fff;color:var(--sub);
  text-decoration:none;font-size:14px}
.backlink:hover{border-color:var(--blue);color:var(--blue)}

/* 勾选框旁的灰色小提示（如「勾选即生效」） */
.chkhint{display:block;color:var(--sub);font-size:12px;opacity:.75;margin-top:2px}

/* ===== 农历换算助手（回答「闰六月该不该勾」）=====
   放在「按农历」勾选之后、「闰月」勾选之前：先让用户拿到结论，再决定勾不勾。 */
.lunarcard{border:1px solid #d8e2f0;background:#f4f8fd;border-radius:10px;
  padding:14px 16px;margin:4px 0 16px}
.lunarcard-h{font-size:14px;font-weight:600;color:var(--text);margin-bottom:6px}
.lunarcard-p{font-size:12.5px;color:var(--sub);margin:0 0 12px;line-height:1.7}
.lunarmode{display:flex;gap:8px;margin-bottom:12px;flex-wrap:wrap}
.lnbtn{flex:1;min-width:140px;padding:8px 10px;border:1px solid var(--line);
  border-radius:8px;background:#fff;color:var(--sub);font-size:13px;
  font-family:inherit;cursor:pointer}
.lnbtn:hover{border-color:var(--blue);color:var(--blue)}
.lnbtn.on{border-color:var(--blue);background:var(--blue);color:#fff;font-weight:600}
.lnrow{display:flex;gap:8px;align-items:center}
.lnrow input,.lnrow select{flex:1;min-width:0;padding:8px 10px;border:1px solid var(--line);
  border-radius:8px;font-size:14px;font-family:inherit;background:#fff;color:var(--text)}
.lnrow .btn{flex:0 0 auto;white-space:nowrap}
.lnpane small{color:var(--sub);font-size:12px}

.lnout{margin-top:12px;padding:12px 14px;border-radius:8px;background:#fff;
  border:1px solid var(--line);font-size:13px}
.lnout.warn{border-color:#d4a72c;background:#fffbe9}
.lnout.ok{border-color:#4ac26b;background:#f2fbf4}
.lnout.err{border-color:var(--red);background:#fff5f5}
.lnres-t{font-weight:600;font-size:15px;margin-bottom:4px}
.lnres-p{color:var(--sub);margin:0 0 8px;font-size:12.5px;line-height:1.7}
.lnres-sub{font-size:12.5px;font-weight:600;margin:10px 0 4px}
.lnres-list{display:flex;flex-wrap:wrap;gap:6px}
.lnres-list span{background:#f0f3f6;border:1px solid var(--line);border-radius:6px;
  padding:3px 8px;font-size:12px;font-family:ui-monospace,Consolas,monospace;color:var(--sub)}
.lnres-list.leap span{background:#fff4e5;border-color:#e0b070;color:#8a5300}
.lnres-tip{margin-top:10px;padding:8px 10px;background:#fff8e6;border-left:3px solid #d4a72c;
  border-radius:4px;font-size:12.5px;color:#7a5300;line-height:1.7}
.lnres-tip.ok{background:#f2fbf4;border-left-color:#4ac26b;color:#1a5c34}
/* 「下一次会在哪天」是用户最终要的那个答案，单独用等宽底色区分出来 */
.lnres-hint{margin-top:10px;padding:9px 11px;background:#eef3fb;border:1px solid #d8e2f0;
  border-radius:6px;font-size:12.5px;color:#26456e;line-height:1.7;
  font-family:ui-monospace,Consolas,monospace}
.lnout .btn{margin-top:10px}
/* 「99% 不需要勾」这句要够醒目，否则用户还是会凭印象勾上 */
.leapwarn{color:var(--orange)}
/* 被环境变量锁定时置灰不可点 */
.chk input:disabled{opacity:.5;cursor:not-allowed}
