/* ==========================================================================
   视觉增强层（v1.18）—— 不改动 style.css 的功能样式，只叠加观感
   --------------------------------------------------------------------------
   【为什么单独一个文件，而不是直接改 style.css】
   style.css 里混着大量**功能性与安全性**的样式，改错会直接影响行为：
     · checkbox/radio 的排除规则（写成高权重是为了覆盖 .form input）
     · .tblwrap 的横向滚动（窄屏表格能不能用全靠它）
     · 移动端 font-size:16px（防 iOS 聚焦自动放大，改小页面会跳）
     · 导航 scroll-behavior 刻意不写 smooth（有专门的断言守着）
   视觉调整若与这些规则写在同一个文件里，一次手滑就可能把功能改坏，
   而且很难在 review 时看出来 —— 因为两件事长得不像。
   分成独立文件后：**功能样式不动**，视觉层可以放心迭代。

   【加载顺序】
   必须在 style.css **之后**加载，这样同一特异度下靠后者生效，
   不需要到处写 !important。

   【设计基调】
   浅色 + 克制的蓝，层次靠三样东西建立，而不是靠颜色堆砌：
     ① 阴影分级 —— 卡片微浮起、面板再高一档、浮层最高
     ② 留白节奏 —— 同类元素间距统一，避免"有的挤有的散"
     ③ 圆角收敛 —— 小元素 8px、卡片 12px、面板 16px，成体系而非随意
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. 设计令牌
   --------------------------------------------------------------------------
   只新增不覆盖：--line / --text 等原有变量继续由 style.css 定义，
   这里只补「阴影、圆角、缓动」这三类原先散落各处的值。
   集中成令牌是为了让整站的观感能一次调平，而不是逐页微调。
   -------------------------------------------------------------------------- */
:root{
  /* 阴影三档：越"浮起来"越深。原先全站只有 0 1px 3px 一个值，
     导致卡片和面板看起来是同一层，页面没有纵深感。 */
  --sh-1:0 1px 2px rgba(31,35,40,.06);          /* 卡片：刚好离开背景 */
  --sh-2:0 2px 8px rgba(31,35,40,.08);          /* 面板：明显的块 */
  --sh-3:0 8px 24px rgba(31,35,40,.12);         /* 浮层/下拉 */
  /* 品牌蓝的两档：主蓝用于实心，次蓝用于浅底上的文字（保证对比度） */
  --blue-soft:#ddf4ff;
  --blue-line:#b6e3ff;
  /* 圆角梯度 */
  --r-sm:8px; --r-md:12px; --r-lg:16px;
  /* 过渡：统一时长与曲线，避免各元素"快慢不一"显得毛躁 */
  --ease:cubic-bezier(.2,.7,.3,1);
}

/* --------------------------------------------------------------------------
   2. 页面底色：极淡的竖向渐变
   --------------------------------------------------------------------------
   为什么不用纯色 #f6f8fa：内容区很长（一屏拉到底），
   纯色背景下长页面容易"发平"，视觉上找不到内容从哪里开始。
   渐变幅度极小（#f8fafc → #eef2f6），只为了让顶部的"空气感"出来。
   注意：必须短（900px 内结束），长渐变在滚动时会一直变色，反而更乱。
   -------------------------------------------------------------------------- */
body{
  background:linear-gradient(180deg,#f8fafc 0,#f2f5f8 480px,#eef2f6 900px) fixed;
  background-color:var(--bg);
}
/* 背景固定，避免长页面滚动时底色跟着动（iOS 上 fixed 渐变会露白，改用色兜底） */
@supports not (background-attachment:fixed){
  body{background:var(--bg)}
}

/* --------------------------------------------------------------------------
   3. 顶栏：从"一条线"变成"一条浮起来的板"
   -------------------------------------------------------------------------- */
.topbar{
  background:rgba(255,255,255,.86);
  backdrop-filter:saturate(180%) blur(16px);
  -webkit-backdrop-filter:saturate(180%) blur(16px);
  border-bottom:1px solid rgba(208,215,222,.7);
  box-shadow:0 1px 0 rgba(31,35,40,.03),var(--sh-1);
}
/* 品牌图标：加一圈浅色描边，与顶栏底色分离 */
.brand .logo{box-shadow:0 2px 8px rgba(9,105,218,.3),0 0 0 1px rgba(255,255,255,.7) inset}
/* 导航胶囊：默认态给一点底，hover 才加深 —— 原先默认完全透明，
   在渐变顶栏上会显得"按钮浮在半空"。 */
.bar nav .nb{
  background:rgba(240,243,246,.7);
  border-color:rgba(208,215,222,.55);
  transition:background .16s var(--ease),color .16s var(--ease),
             box-shadow .16s var(--ease),border-color .16s var(--ease);
}
.bar nav .nb:hover{background:#e4e9ef;border-color:rgba(208,215,222,.9)}
/* 当前页：实心蓝 + 更明确的高度感 */
.bar nav .nb.on,.bar nav .nb.on.adminonly{
  background:linear-gradient(180deg,#218bff,var(--blue));
  border-color:transparent;
  box-shadow:0 2px 10px rgba(9,105,218,.34),0 1px 2px rgba(9,105,218,.2) inset;
}

/* --------------------------------------------------------------------------
   4. 统计卡：这是全站最该"有设计"的地方
   --------------------------------------------------------------------------
   原来四张卡长得完全一样 —— 读者只能靠读文字区分"总数/启用/24小时/7天"，
   而数字是这页最重要的信息，视觉上却没有任何侧重。
   改法：给"需要特别注意的数字"（24 小时内、有待还的）单独配色，
   并在卡片顶部加一条细色带做锚点。**不改任何数据与逻辑**。
   -------------------------------------------------------------------------- */
/* --------------------------------------------------------------------------
   3.5 页面标题区
   --------------------------------------------------------------------------
   原来所有页面一进来就是内容，用户不知道自己在哪一页。
   标题区解决三件事：说清「这是哪页」、说清「当前状态」、给出主操作。
   -------------------------------------------------------------------------- */
.pagehead{
  display:flex;align-items:flex-end;justify-content:space-between;
  gap:16px;flex-wrap:wrap;margin-bottom:20px;
}
.pagehead h1{
  margin:0;font-size:21px;font-weight:650;letter-spacing:-.2px;
  display:flex;align-items:center;gap:9px;
}
/* 标题前的色块：比面板标题的竖条更粗，作为「页」级别的锚点 */
.pagehead h1::before{
  content://;width:4px;height:20px;border-radius:3px;
  background:linear-gradient(180deg,#218bff,var(--blue));
  flex:0 0 auto;
}
.pagehead .ph-sub{
  margin:5px 0 0;color:var(--sub);font-size:13px;
  padding-left:13px;   /* 与标题的色块左对齐 */
}
.pagehead > .btn{flex:0 0 auto}

/* 【v6.10】v6.9 曾经加过一个 .ph-acts 容器（标题区放两个按钮时用），
   现在**整条规则删掉了** —— v6.10 把礼簿/纪念日页的次级「+ 新增提醒」
   撤掉后，所有页面的标题区都只剩**一个**按钮，直接挂在 .pagehead 下，
   由上面那条 `.pagehead > .btn{flex:0 0 auto}` 兜住。
   留着一条没人用的 CSS 就是死代码 —— 将来谁看到 .ph-acts 会以为
   "标题区该这么写"，改模板时又会被坑一次。 */

.cards{gap:16px;margin-bottom:22px}
/* 卡片图标：右上角的小色块，给四张完全一样的卡一个视觉区分点。
   用字符而非图片：项目零第三方依赖，且这些符号在任何系统字体里都有。 */
.card .card-ic{
  position:absolute;right:14px;top:14px;
  width:26px;height:26px;border-radius:8px;
  display:flex;align-items:center;justify-content:center;
  font-size:14px;font-weight:700;line-height:1;
}
.card .card-ic.blue{color:#0969da;background:#ddf4ff}
.card .card-ic.green{color:#1a7f37;background:#eaf6ee}
.card .card-ic.red{color:#cf222e;background:#ffebe9}
.card .card-ic.slate{color:#57606a;background:#eef1f4}
.card{
  position:relative;
  border-radius:var(--r-md);
  box-shadow:var(--sh-1);
  padding:16px 18px;
  overflow:hidden;
  transition:box-shadow .18s var(--ease),transform .18s var(--ease);
}
.card .num{
  font-size:28px;font-weight:700;letter-spacing:-.5px;
  font-variant-numeric:tabular-nums;   /* 数字等宽对齐，跳动时不抖 */
  padding-right:34px;                   /* 数字与图标不重叠 */
}
.card .lab{font-size:12.5px;margin-top:2px}
/* 悬停轻微抬升：给"这是一块可交互的信息"暗示。
   幅度刻意极小（2px）—— 幅度大了会像按钮，而这些卡其实不可点。 */
.card:hover{box-shadow:var(--sh-2);transform:translateY(-2px)}
/* 顶部色带：默认用中性蓝灰，.ok/.hot 的卡自动换成对应色 */
.card::before{
  content:"";position:absolute;left:0;right:0;top:0;height:3px;
  background:linear-gradient(90deg,#8b949e,#c9d1d9);
}
.card:has(.num.ok)::before{background:linear-gradient(90deg,#1a7f37,#4ac26b)}
.card:has(.num.hot)::before{background:linear-gradient(90deg,#cf222e,#ff7b72)}
/* 【为什么用 :has() 而不是给卡片加 class】
   模板里卡片是 <div class="card"><div class="num ok">…，
   分类信息在**内层**数字上。外层加 class 要改所有模板，
   而 :has() 直接按内层状态选中外层，模板一行都不用动 ——
   少改模板就少一处可能出错的地方。 */
/* 不支持 :has() 的老 WebView：色带退化为中性色，不影响可读性 */
@supports not selector(:has(*)){
  .card::before{background:linear-gradient(90deg,#8b949e,#c9d1d9)}
}

/* --------------------------------------------------------------------------
   5. 面板：圆角与阴影升级，加左侧色条做"分区锚"
   -------------------------------------------------------------------------- */
.panel{
  border-radius:var(--r-lg);
  box-shadow:var(--sh-2);
  padding:22px 24px;
  margin-bottom:22px;
  border-color:rgba(208,215,222,.8);
}
/* 面板标题：加粗 + 下方细线，让"这块叫什么"一眼可见 */
.panel-head{
  margin-bottom:18px;
  padding-bottom:12px;
  border-bottom:1px solid rgba(208,215,222,.6);
}
/* 面板标题下的一句说明：告诉用户"填完会发生什么"，
   省得用户对着一堆字段猜流程。 */
.panel-lead{
  margin:-8px 0 16px;color:var(--sub);font-size:13px;line-height:1.65;
  padding-left:11px;border-left:2px solid rgba(139,148,158,.35);
}

.panel-head h2{
  font-size:16.5px;font-weight:650;
  display:flex;align-items:center;gap:8px;
}
/* 标题前的短竖条：纯装饰，成本极低但能显著提升"分区感" */
.panel-head h2::before{
  content:"";width:3px;height:15px;border-radius:2px;
  background:linear-gradient(180deg,#218bff,var(--blue));
  flex:0 0 auto;
}
/* 说明/规则类面板：不该和操作面板长得一样，压低存在感 */
.panel.tip{
  background:linear-gradient(180deg,#fbfcfe,#f6f8fa);
  border-style:dashed;
  box-shadow:none;
  padding:18px 22px;
}
.panel.tip .panel-head h2::before{background:#8b949e}
/* .panel.tip 里没有 panel-head，用 :has() 判断有无标题条来画左侧线 */
.panel.tip:not(:has(.panel-head)){
  border-left:3px solid #c9d1d9;
}

/* --------------------------------------------------------------------------
   6. 按钮：立体感 + 明确的按压反馈
   --------------------------------------------------------------------------
   原先按钮只有背景色变化，点下去"像没点"。
   加 :active 的下压（transform:translateY）—— 这是最直接的物理反馈。
   -------------------------------------------------------------------------- */
.btn{
  border-radius:var(--r-sm);
  font-weight:500;
  transition:background .15s var(--ease),border-color .15s var(--ease),
             box-shadow .15s var(--ease),transform .08s var(--ease);
}
.btn:hover{box-shadow:var(--sh-1)}
.btn:active{transform:translateY(1px);box-shadow:none}
/* 主按钮：渐变 + 内高光，一眼认出"主要动作" */
.btn.primary{
  background:linear-gradient(180deg,#218bff,var(--blue));
  border-color:transparent;
  box-shadow:0 1px 3px rgba(9,105,218,.3);
}
.btn.primary:hover{background:linear-gradient(180deg,#2c95ff,#0a5ed0);box-shadow:0 2px 8px rgba(9,105,218,.36)}
.btn.primary:active{background:var(--blue)}
/* 危险操作：红色只用在描边上，不做实心 —— 实心红会让人下意识避开本该点的按钮 */
.btn.danger{color:var(--red);border-color:#f0c0c0;background:#fff}
.btn.danger:hover{background:#ffeef0;border-color:#e88a8a}

/* --------------------------------------------------------------------------
   7. 表单控件
   -------------------------------------------------------------------------- */
.fld > span,.panel label,.fld label{font-weight:500;color:var(--sub)}
.form input,.form select,.form textarea,
.fld input,.fld select,.fld textarea{
  border-radius:var(--r-sm);
  transition:border-color .15s var(--ease),box-shadow .15s var(--ease);
  /* 去掉移动端浏览器默认的 appearance，保持与桌面一致 */
  -webkit-appearance:none;appearance:none;
}
/* select 加自定义箭头：去掉原生箭头后必须补，否则用户不知道它能展开。
   用 background-image 画 SVG，不额外引入字体文件（项目零第三方依赖）。 */
.form select,.fld select{
  padding-right:34px;
  background-image:url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M2.5 4.5L6 8l3.5-3.5' fill='none' stroke='%2357606a' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat:no-repeat;
  background-position:right 11px center;
  background-size:12px 12px;
}
/* checkbox / radio 保留原生外观 —— 前面那条 appearance:none 绝不能套到它们身上，
   否则勾选框会变成一个什么都不画的空白框（v1.17 踩过同类坑）。 */
.form input[type=checkbox],.form input[type=radio],
.fld input[type=checkbox],.fld input[type=radio]{
  -webkit-appearance:auto;appearance:auto;
  width:auto;padding:0;margin:0;
  /* 放大点击热区，但不放大视觉尺寸 */
  width:18px;height:18px;margin-top:2px;cursor:pointer;
}
/* 分组：让"这几项是一组"看得出来 */
.row2{gap:16px}
.hr{border-top:1px dashed rgba(208,215,222,.9)}

/* --------------------------------------------------------------------------
   8. 表格：行分隔更轻，悬停有反馈
   -------------------------------------------------------------------------- */
/* 【v6.13】表头 sticky 的定位参照是「最近的滚动容器」，不是视口。
   .tblwrap 有 overflow-x:auto → 它就是滚动容器 →
   .tbl th 的 position:sticky;top:60px 会相对 **.tblwrap 自己**算，
   于是表格还没滚动，表头就被硬生生下压 60px，正好盖住第一行数据。
   （浏览器实测：表头底边 325 − 首行顶边 265 = 重叠 60px，
     用户管理/发送日志两页都是这个值；移动端因为
     @media(max-width:720px) 把 th 改成 static，所以没暴露。）

   修法：桌面端让 .tblwrap 不再是滚动容器
   （实测 414/720/721/800/1024/1440/1920 七档真实视口下，
     桌面档表格宽度 == 面板内宽，从不溢出，
     所以横向滚动在桌面端本来就没用上，交给窄屏的媒体查询即可）。
   这样 th 的 sticky 就回到「相对视口」的正常语义：
   页面滚动时表头吸附在 60px（顶栏下方），静止时不会错位。

   ⚠ 代价：overflow-x:auto 那道「表格再宽也不撑破页面」的兜底没了，
   所以必须补上断词 —— 见下面 .tbl 的 word-break。
   （实测注入 220 个不换行字符：改之前 tblW=2365 把页面撑到 2410px 宽，
     改之后加了 word-break 才回到 990px 不撑破。） */
@media (min-width:721px){
  .tblwrap{overflow-x:visible}
}
.tbl th{
  background:#f6f8fa;
  color:var(--sub);font-weight:600;
  font-size:12.5px;letter-spacing:.2px;
  border-bottom:1px solid var(--line);
  position:sticky;top:60px;z-index:1;   /* 顶栏是 sticky，表头跟随滚动时压住 */
}
.tbl th:first-child{border-top-left-radius:var(--r-sm)}
.tbl th:last-child{border-top-right-radius:var(--r-sm)}
.tbl td{border-bottom:1px solid #eef1f4}
/* 桌面端兜底：超长内容（提醒详情、错误信息、连续英文/URL）必须能断行，
   否则表格会把整个页面撑出横向滚动条。
   break-word 只在「本行放不下」时才断，正常文字不受影响。 */
@media (min-width:721px){
  .tbl td{overflow-wrap:break-word;word-break:break-word}
}
/* 悬停高亮：长表格里横向定位行很实用 */
.tbl tbody tr{transition:background .12s var(--ease)}
.tbl tbody tr:hover{background:#f6f9fd}
/* 末行不再画底线（原先用 :last-child，但被 .tblwrap 包着时不易命中） */
.tbl tbody tr:last-child td{border-bottom:none}

/* 【补 .act —— 模板里用了但 CSS 里没定义】
   users.html 的操作列表头/单元格都带 class="act"，
   但 style.css 从没定义过它 —— 结果是这一列既没右对齐、
   也没任何区分，看起来像"忘了排版"。
   表格里的操作列一律右对齐，是用户扫表格时的肌肉记忆。 */
.tbl .act{text-align:right;white-space:nowrap}
.tbl th.act{text-align:right}
/* 表头与首列对齐：首列（用户/标题）左对齐，操作列右对齐，中间列居中一点更好扫 */
.tbl td:first-child,.tbl th:first-child{padding-left:14px}
.tbl td:last-child,.tbl th:last-child{padding-right:14px}

/* --------------------------------------------------------------------------
   9. 徽章 / 药丸：原色块偏"平"，加描边与字重后更易扫读
   -------------------------------------------------------------------------- */
.pill{font-weight:600;letter-spacing:.2px;border:1px solid transparent}
/* 【补默认变体】模板里有多处只用 class="pill" 而不带任何变体
   （"本 IP 本小时注册 0/5"、"全站今日注册 0/20"、"否"、成员名...），
   而 style.css 只定义了 d0~d3 —— 不带变体的 .pill 落在这些规则之外，
   渲染出来就是**裸文字**，跟正文里的普通字没有任何区别，
   读者根本看不出这是一枚状态标签。
   补一个中性灰蓝的默认样式：既能被认出来是标签，
   又不与 ok/warn 的语义色冲突（那三种带变体的优先级更高）。 */
.pill{color:#42526b;background:#eef2f7;border-color:#d5dde8}
.pill.d0{background:#cf222e;border-color:#b62324;box-shadow:0 1px 2px rgba(206,34,46,.28)}
.pill.d1{background:#bc4c00;border-color:#9c4000}
.pill.d2{background:#fff3c4;border-color:#e5d38a;color:#6b5200}
.pill.d3{background:#eaeef2;border-color:#d8dee4}
/* 【补三个原本缺失的变体】
   模板里实际用到了 .pill.ok / .pill.warn / .pill.off，
   但 style.css 只定义了 d0~d3 —— 这三个类**完全没有样式**，
   渲染出来是「有 padding 有背景吗」取决于浏览器默认值，
   实际表现是"文字裸着飘"、看不出是状态标签。
   这是实打实的视觉 bug，不是审美偏好问题。
   （.pill.warn 曾在 book_detail.html 的内联 <style> 里定义过，
     所以那个页面看着正常，其他页面就是坏的。）
   一并补齐，顺带统一配色语言。 */
.pill.ok{color:#1a7f37;background:#eaf6ee;border-color:#a7d7b6}
.pill.warn{color:#9c4000;background:#fff8ec;border-color:#f0d3ab}
.pill.off{color:var(--sub);background:#f0f3f6;border-color:#d8dee4}
/* 状态标签统一一点尺寸，看起来像同一套体系 */
.pill.ok,.pill.warn,.pill.off{font-size:12px;padding:3px 10px}
.tag.lunar{background:#fbefff;border:1px solid #e6d4ff;font-weight:600}
/* 待还/未还这类"需要行动"的金额，单独提亮 */
.money{color:var(--green);font-size:14.5px;font-weight:700}

/* --------------------------------------------------------------------------
   10. 空状态：原来只有一行灰字，像是加载失败
   -------------------------------------------------------------------------- */
.empty{
  text-align:center;padding:36px 20px;color:var(--sub);
  background:repeating-linear-gradient(45deg,#fbfcfd,#fbfcfd 10px,#f7f9fb 10px,#f7f9fb 20px);
  border:1px dashed var(--line);border-radius:var(--r-md);
}
/* 空状态图标：用 CSS 画一个简单的"文档"轮廓，不引图片 */
.empty::before{
  content:"";display:block;width:34px;height:40px;margin:0 auto 12px;
  border:2px solid #c9d1d9;border-radius:4px;
  background:linear-gradient(180deg,transparent 12px,#c9d1d9 12px,#c9d1d9 14px,transparent 14px,
             transparent 22px,#c9d1d9 22px,#c9d1d9 24px,transparent 24px);
}

/* --------------------------------------------------------------------------
   11. 提示条 / 说明块
   -------------------------------------------------------------------------- */
.notice,.warnbar{border-radius:var(--r-sm);box-shadow:var(--sh-1)}
.notice{border-left:3px solid #d4a72c}
.warnbar{border-left:3px solid #d4a72c}
.flash{border-radius:var(--r-sm);box-shadow:var(--sh-1)}

/* --------------------------------------------------------------------------
   12. 二级页返回按钮：改成"面包屑"观感
   -------------------------------------------------------------------------- */
.backlink{
  background:#fff;border-radius:999px;
  box-shadow:var(--sh-1);
  font-weight:500;
  transition:border-color .15s var(--ease),color .15s var(--ease),
             box-shadow .15s var(--ease),transform .12s var(--ease);
}
.backlink:hover{box-shadow:var(--sh-2);transform:translateX(-2px)}
.backlink::before{content:"←";font-size:14px;line-height:1}

/* --------------------------------------------------------------------------
   13. 礼簿卡片：加左侧色带 + 悬停浮起
   -------------------------------------------------------------------------- */
.bookcard{
  border-radius:var(--r-md);
  box-shadow:var(--sh-1);
  padding:14px;
  transition:box-shadow .18s var(--ease),transform .18s var(--ease);
}
.bookcard:hover{box-shadow:var(--sh-2);transform:translateY(-2px)}
.bookcard .cover{border-radius:10px;box-shadow:0 2px 10px rgba(31,35,40,.16)}
.bookcard .btitle a{transition:color .15s var(--ease)}

/* --------------------------------------------------------------------------
   13.5 礼簿详情：收礼行的状态色条与金额配色
   --------------------------------------------------------------------------
   【为什么这两条从 book_detail.html 的内联 <style> 挪到这儿】
   原来它们和「已还/待还」的结构写在一起，但**颜色是视觉决策**：
   改色号要动模板、而模板里还混着布局。
   更实际的问题是：断言只能查一个文件 ——
   色条写在内联样式里，就没法在"视觉层是否完整"这条断言里一起验，
   容易漏改、也无从判断视觉层是否自洽。
   组件的**结构**样式（头像、列表、搜索行）继续留在模板里，
   这里只接管**观感**，与 ui.css 的分层一致。
   -------------------------------------------------------------------------- */
/* 左侧色条：一眼区分「还没还」和「已经还了」——
   这页的核心信息就是这笔人情还在不在，橙/绿比读文字快得多。
   用 inset box-shadow 而不是 border-left：border 会把内容整体推移 3px，
   开着关切换时整行文字会跳一下。 */
.grow.is-pending{box-shadow:inset 3px 0 0 #e3a008}
.grow.is-ok{box-shadow:inset 3px 0 0 #4ac26b}
/* 金额同步配色，让"在等还"这件事在扫数字时也能看出来 */
.gamt-pending{color:#b26a00}
.gamt-ok{color:var(--green)}

/* --------------------------------------------------------------------------
   14. 农历助手卡：这是唯一自带 <style> 的组件，给它统一视觉语言
   -------------------------------------------------------------------------- */
.lunarcard{
  border-radius:var(--r-md);
  box-shadow:var(--sh-1);
  background:linear-gradient(180deg,#f7fafe,#f0f6fc);
}
.lnbtn{border-radius:var(--r-sm);font-weight:500;transition:all .15s var(--ease)}
.lnbtn.on{
  background:linear-gradient(180deg,#218bff,var(--blue));
  border-color:transparent;
  box-shadow:0 1px 3px rgba(9,105,218,.3);
}
.lnout{border-radius:var(--r-sm);box-shadow:var(--sh-1)}
.lnres-hint{border-radius:var(--r-sm)}

/* --------------------------------------------------------------------------
   15. 下拉浮层：升到最高阴影档，与页面拉开距离
   -------------------------------------------------------------------------- */
.morebox{border-radius:var(--r-md);box-shadow:var(--sh-3)}
.me{border-radius:999px;background:#f2f5f8}
.me .avatar{box-shadow:0 1px 3px rgba(31,35,40,.18)}

/* --------------------------------------------------------------------------
   15.5 「管理」浮层的层级（v6.7）
   --------------------------------------------------------------------------
   【问题】用户截图：浮层上方还能看见**第二个**卡片的「管理」按钮。

   【根因】position:fixed 的 z-index 只在**自己所在的层叠上下文**里有效。
   浮层开在卡片内部，而卡片里有 position+z-index 的祖先：
     · 纪念日卡片：.aniv-head   （position:relative; z-index:3）
     · 提醒卡片：  .remcard-more （position:absolute; z-index:3）
   浮层的 z-index:20 只在这个上下文**内部**比较 —— 出了这个上下文，
   它对外的身份就是那个祖先的 z-index:3。
   两张卡片的祖先 z-index 相同（都是 3）→ 按 DOM 顺序决定谁在上面
   → 后一张卡片的「管理」按钮就压住了浮层。

   【正解】打开浮层时把承载它的祖先提上去（moredrop.js 加 .drop-lifted）。
   提到多少？
     · 必须 > 卡片内部的其它层（.aniv-main/.aniv-foot 是 1）→ 4 以上
     · 必须 < 顶栏（.topbar 是 10）→ 否则浮层会盖住吸顶导航
   取 6：既压得住相邻卡片，又盖不住顶栏。

   【为什么用 class 而不是直接写 style】
   收起时要还原；而且 z-index 的值集中写在 CSS 里好维护好审查。

   【为什么这里要写三条选择器（特异度陷阱）】
   承载层的 z-index 在别处已经定过了，而且**规则写在本文节后面**：
     · .aniv-head      （position:relative; z-index:3）—— 纪念日卡片
     · .remcard-more   （position:absolute;  z-index:3）—— 提醒卡片
   光写 .drop-lifted{z-index:6} 的特异度是 (0,1,0)，跟上面两条**一样**，
   而同特异度**靠后者胜** → 提层会被后面的 z-index:3 覆盖掉，
   实测 computed z-index 仍然是 3（提层形同虚设）。
   正解：把提层规则的特异度提上去 ——
     .aniv-head.drop-lifted     → (0,2,0) > .aniv-head      (0,1,0)
     details.more.drop-lifted   → (0,2,1) > .remcard-more   (0,1,0)
   （.drop-lifted 保留一条兜底，给既不是 .aniv-head 也不是 details.more 的承载层。）
   -------------------------------------------------------------------------- */
.drop-lifted,
.aniv-head.drop-lifted,
details.more.drop-lifted,
/* v6.12：提醒卡片的承载层规则提到了 `.remcard > details.remcard-more`（0,2,1），
   和上面 `details.more.drop-lifted`（0,2,1）**同特异度**，
   而它写在文件更靠后 → 提层会被基线的 z-index:3 压回去（v6.7 的老毛病复发）。
   正解：给提醒卡片单开一条更高特异度的提层规则（0,3,1）。
   （浏览器实测：改之前 computed z-index 是 3，不是 6。） */
.remcard > details.remcard-more.drop-lifted{z-index:6}

/* --------------------------------------------------------------------------
   16. 移动端：视觉增强必须让位给可用性
   -------------------------------------------------------------------------- */
/* 悬停抬升在触屏上没有意义（没有 hover 态），且会让点击目标"跳动"。
   触屏上把过渡整体关掉。 */
@media (hover:none){
  .card:hover,.bookcard:hover{transform:none;box-shadow:var(--sh-1)}
  .backlink:hover{transform:none}
}
@media (max-width:720px){
  /* 表头的 sticky 偏移量要跟着顶栏的两行高度变，否则会盖住内容 */
  .tbl th{top:0;position:static}
  .panel{padding:16px 15px;border-radius:var(--r-md)}
  .card .num{font-size:23px}
  .empty{padding:28px 16px}
  /* 触屏按压反馈加大：手指粗，桌面那 1px 的下压几乎看不出来。
     2px 是「明确按下去了」与「按钮在乱跳」之间的平衡点。 */
  .btn:active{transform:translateY(2px)}
}
/* --------------------------------------------------------------------------
   17. 纪念日（v6.5）
   --------------------------------------------------------------------------
   【一条必须守住的约束：卡片上不能出现 transform】
   「管理」浮层用 position:fixed 定位（moredrop.js），
   而 fixed 元素的包含块 = 最近的**带 transform 的祖先**。
   一旦 .anivcard 上出现 transform（哪怕是 hover 抬升、或入场动画），
   包含块就变成卡片本身 → 浮层会跑到完全错误的位置，
   而卡片又有 overflow:hidden → 浮层还会被裁掉（看得到、点不到）。
   所以：卡片的 hover 只改阴影不改位移；入场动画只做 opacity，
   位移/缩放效果放在**子元素**上（子元素不是浮层的祖先，不影响包含块）。
   -------------------------------------------------------------------------- */

/* 单位切换器 */
.unitbar{display:flex;align-items:center;gap:8px;margin:0 0 18px;flex-wrap:wrap}
.unitbar .ulab{font-size:12.5px;color:var(--sub);margin-right:2px}
.unitbtn{
  display:inline-flex;align-items:center;justify-content:center;
  min-width:46px;height:30px;padding:0 14px;border-radius:999px;
  border:1px solid rgba(208,215,222,.9);background:#fff;color:var(--sub);
  font-size:13px;font-weight:500;text-decoration:none;line-height:1;
  transition:background .16s var(--ease),color .16s var(--ease),
             border-color .16s var(--ease),box-shadow .16s var(--ease);
}
.unitbtn:hover{border-color:var(--blue-line);color:var(--blue);background:var(--blue-soft)}
.unitbtn.on{
  background:linear-gradient(180deg,#218bff,var(--blue));
  border-color:transparent;color:#fff;
  box-shadow:0 1px 4px rgba(9,105,218,.3);
}
.unitbar .uhint{font-size:12px;color:var(--sub);margin-left:4px}

/* 分段标题 */
.anivsection{margin-bottom:26px}
.ashead{display:flex;align-items:center;gap:9px;margin:0 0 12px}
.ashead h2{margin:0;font-size:15px;font-weight:650;display:flex;align-items:center;gap:8px}
.ashead h2::before{content:"";width:3px;height:14px;border-radius:2px;
  background:linear-gradient(180deg,#218bff,var(--blue));flex:0 0 auto}
.ascount{font-size:12px;color:var(--sub);background:#eef2f7;border:1px solid #dde3ea;
  border-radius:999px;padding:2px 9px}

/* 卡片 */
.anivgrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(320px,1fr));gap:16px}
.anivcard{
  position:relative;overflow:hidden;
  border-radius:var(--r-lg);border:1px solid rgba(208,215,222,.8);
  background:#fff;padding:16px 18px 14px;
  box-shadow:var(--sh-1);
  /* 【只淡入，不位移】见本节开头的约束说明 */
  animation:anivIn .38s var(--ease) both;
  transition:box-shadow .18s var(--ease),border-color .18s var(--ease);
}
.anivcard:hover{box-shadow:var(--sh-2);border-color:rgba(180,192,204,.9)}
/* 顶部的类别色带 */
.anivcard::before{
  content:"";position:absolute;left:0;right:0;top:0;height:4px;
  background:linear-gradient(90deg,var(--ac1),var(--ac2));
}
/* 右上角缓慢呼吸的光晕 —— 让静态卡片有"活着"的感觉 */
.anivcard::after{
  content:"";position:absolute;right:-64px;top:-74px;width:190px;height:190px;
  border-radius:50%;pointer-events:none;
  background:radial-gradient(circle,var(--ac1),transparent 68%);
  opacity:.12;animation:anivGlow 7.5s ease-in-out infinite;
}
@keyframes anivIn{from{opacity:0}to{opacity:1}}
@keyframes anivGlow{
  0%,100%{transform:scale(1);opacity:.12}
  50%{transform:scale(1.18);opacity:.2}
}
/* 错开入场，让一屏卡片不是齐刷刷出现 */
.anivgrid .anivcard:nth-child(2){animation-delay:.05s}
.anivgrid .anivcard:nth-child(3){animation-delay:.1s}
.anivgrid .anivcard:nth-child(4){animation-delay:.15s}
.anivgrid .anivcard:nth-child(5){animation-delay:.2s}
.anivgrid .anivcard:nth-child(6){animation-delay:.25s}
.anivgrid .anivcard:nth-child(7){animation-delay:.3s}
.anivgrid .anivcard:nth-child(8){animation-delay:.35s}

/* 卡片头
   【z-index 必须是 3，不能是 1】
   浮层（.morebox）开在卡片**里面**，而浮层的 z-index:20 只在它自己所在的
   层叠上下文里有效 —— 那个上下文是 .aniv-head（position:relative + z-index）。
   .aniv-head / .aniv-main / .aniv-foot 三者若都是 z-index:1，就平级了，
   按 DOM 顺序 .aniv-main（在后）画在上面 → **盖住浮层的按钮**。
   症状是「看得到浮层，点不到按钮」（elementFromPoint 命中卡片内容）。
   这跟"overflow 裁剪"是两回事 —— 提 .aniv-head 的 z-index 就够了。
   实测过：把 .aniv-head 提到 9 → 命中立刻变回浮层里的链接。 */
.aniv-head{display:flex;align-items:center;gap:10px;margin-bottom:14px;
  position:relative;z-index:3}
.aniv-ic{
  width:34px;height:34px;flex:0 0 34px;border-radius:11px;
  display:flex;align-items:center;justify-content:center;
  font-size:15px;font-weight:700;color:#fff;line-height:1;
  background:linear-gradient(135deg,var(--ac1),var(--ac2));
  box-shadow:0 2px 8px rgba(31,35,40,.16);
}
.aniv-htxt{flex:1;min-width:0}
.aniv-htxt h3{margin:0;font-size:15px;font-weight:650;letter-spacing:-.1px;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.aniv-sub{font-size:12px;color:var(--sub);margin-top:2px;font-variant-numeric:tabular-nums}

/* 大数字区 */
.aniv-main{display:flex;align-items:flex-end;gap:14px;position:relative;z-index:1}
.aniv-num{display:flex;align-items:baseline;gap:5px;flex:0 0 auto;
  /* 数字"弹"出来 —— 放在子元素上，不影响浮层的包含块 */
  animation:anivPop .5s var(--ease) both;animation-delay:.06s}
@keyframes anivPop{from{opacity:0;transform:scale(.88)}to{opacity:1;transform:none}}
.aniv-big{
  font-size:42px;font-weight:750;line-height:1;letter-spacing:-1.6px;
  font-variant-numeric:tabular-nums;
  background:linear-gradient(135deg,var(--ac1),var(--ac2));
  -webkit-background-clip:text;background-clip:text;
  color:transparent;-webkit-text-fill-color:transparent;
}
.aniv-unit{font-size:13px;color:var(--sub);font-weight:500}
.aniv-meta{flex:1;min-width:0;padding-bottom:3px}
.aniv-bd{font-size:13.5px;font-weight:600;color:var(--text)}
.aniv-live{font-size:12px;color:var(--sub);margin-top:3px;font-variant-numeric:tabular-nums}

/* 环形进度：离下一个周年过去了多少 */
.aniv-ring{position:relative;width:56px;height:56px;flex:0 0 56px;margin-left:auto}
.aniv-ring svg{width:100%;height:100%;transform:rotate(-90deg);display:block}
.rk-trk{fill:none;stroke:#eaeef2;stroke-width:4}
.rk-bar{fill:none;stroke:var(--ac1);stroke-width:4;stroke-linecap:round;
  transition:stroke-dashoffset .6s var(--ease)}
.rk-txt{position:absolute;inset:0;display:flex;flex-direction:column;
  align-items:center;justify-content:center;line-height:1.2;pointer-events:none}
.rk-txt b{font-size:12.5px;font-weight:700;color:var(--ac2);font-variant-numeric:tabular-nums}
.rk-txt span{font-size:9.5px;color:var(--sub)}

/* 底部说明行 */
.aniv-foot{display:flex;flex-wrap:wrap;gap:6px 10px;margin-top:13px;padding-top:11px;
  border-top:1px dashed rgba(208,215,222,.9);position:relative;z-index:1}
.aniv-foot .af{font-size:12px;color:var(--sub)}
.aniv-foot .af.note{color:#6b5200;background:#fff8ec;border:1px solid #f0d3ab;
  border-radius:6px;padding:1px 7px}

/* 即将到来的卡片：给一点暖色，一眼分出"快到了" */
.anivcard.up{background:linear-gradient(180deg,#fffdf7,#fff 46%);border-color:#f0e2c4}

/* --------------------------------------------------------------------------
   17.5 纪念日自定义排序（v6.6）
   --------------------------------------------------------------------------
   【一条必须守住的约束：卡片上不能出现 transform】
   上面的说明已经讲过原因（fixed 浮层的包含块）。
   拖拽时需要"抬起"的效果 —— 只能改阴影/描边，**不能改 transform**，
   否则拖起来浮层会跑飞、还会被裁掉。
   -------------------------------------------------------------------------- */

/* 拖拽把手：贴在卡片左上角，像"抓住这里拖动"的提示 */
.aniv-grip{
  position:absolute;left:6px;top:50%;transform:translateY(-50%);
  z-index:4;font-size:15px;line-height:1;color:#b6c0cc;
  cursor:grab;padding:6px 4px;letter-spacing:-1px;user-select:none;
  -webkit-user-select:none;touch-action:none;
}
.aniv-grip:active{cursor:grabbing;color:var(--blue)}

/* 可排序的卡片：给个抓手位置，左边留白 */
.anivcard.sortable{padding-left:30px}
.anivcard.sortable.dragging{
  opacity:.55;
  box-shadow:0 8px 24px rgba(31,35,40,.18);
  border-color:var(--blue-line);
  /* 【不能用 transform】见本节开头的约束说明 */
}

/* 上移 / 下移按钮组 */
.aniv-moves{display:flex;flex-direction:column;gap:2px;flex:0 0 auto}
.aniv-move{
  width:24px;height:20px;padding:0;border:1px solid rgba(208,215,222,.95);
  background:#fff;color:var(--sub);border-radius:6px;font-size:12px;line-height:1;
  cursor:pointer;display:flex;align-items:center;justify-content:center;
  transition:background .16s var(--ease),color .16s var(--ease),border-color .16s var(--ease);
}
.aniv-move:hover{background:var(--blue-soft);color:var(--blue);border-color:var(--blue-line)}
.aniv-move:active{transform:translateY(1px)}

/* 排序栏：与单位栏同风格，多一个方向按钮 */
.sortbar .dirbtn{min-width:auto;font-size:12.5px;padding:0 12px}
.sortbar .dirbtn.on{
  background:linear-gradient(180deg,#7048e8,#5f3dc4);
  box-shadow:0 1px 4px rgba(95,61,196,.3);
}

/* 自定义排序的单一列表：卡片按整行排，拖拽更顺手 */
.anivgrid-custom{grid-template-columns:repeat(auto-fill,minmax(340px,1fr))}

@media (max-width:720px){
  .anivcard.sortable{padding-left:26px}
  .aniv-grip{left:3px;font-size:14px}
  .aniv-move{width:26px;height:24px}   /* 触屏热区做大一点 */
  .anivgrid-custom{grid-template-columns:1fr}
}

/* --------------------------------------------------------------------------
   19. 提前提醒的档位选择（v6.6）
   --------------------------------------------------------------------------
   原来这里是裸文本框（塞着 "0" 或 "30,7,3,1,0"），用户完全看不懂。
   改成点选按钮后，最重要的两点：
     1) 按钮热区要够大 —— 手机上是手指点，40px 是最低线
     2) 选中态必须一眼可见 —— 深蓝填充 + 白字，和未选中的描边态拉开
   -------------------------------------------------------------------------- */
.advfield > span{display:flex;align-items:baseline;gap:8px;flex-wrap:wrap}
.advfield .advtip{font-size:12px;color:var(--sub);font-weight:400}
.advchips{display:flex;flex-wrap:wrap;gap:8px;margin:2px 0 8px}
.advchip{
  /* 【v6.8】未选中态的边框色提出来存成变量 ——
     第 21 节要在触屏下把 hover 复位成"未选中态"，
     硬编码一份值的话，以后改了这里忘了改那里，样式就漂了。 */
  --chip-rest-bd:rgba(208,215,222,.95);
  min-height:38px;padding:8px 14px;border-radius:999px;
  border:1px solid var(--chip-rest-bd);background:#fff;color:var(--text);
  font-size:13.5px;font-weight:500;line-height:1.2;cursor:pointer;
  transition:background .16s var(--ease),color .16s var(--ease),
             border-color .16s var(--ease),box-shadow .16s var(--ease);
}
/* 【v6.8 修】原来这里是 background:var(--blue-soft) —— 浅蓝底 + 蓝边 + 蓝字。
   问题：这个浅蓝跟选中态（深蓝渐变）**是同色系**，一旦"取消选择"之后
   元素还停在 hover 上（见下面第 21 节，触屏上 :hover 会粘滞），
   用户会以为"没取消掉"—— 底色看着还是"选中的淡色版"。
   改成**只描边、不动底色**，三态一眼分得开：
     静止 = 白底 + 灰边 + 深色字
     悬停 = 白底 + 蓝边 + 蓝字   ← 底色始终是白的
     选中 = 深蓝渐变 + 白字 + 阴影 */
.advchip:hover{border-color:var(--blue-line);color:var(--blue)}
.advchip.on{
  background:linear-gradient(180deg,#218bff,var(--blue));
  border-color:transparent;color:#fff;font-weight:600;
  box-shadow:0 1px 5px rgba(9,105,218,.28);
}
.advpreview{
  font-size:13px;color:var(--text);background:#f6f8fa;border:1px solid #e4e8ed;
  border-radius:10px;padding:10px 12px;line-height:1.7;
}
.advpreview ul{margin:4px 0 0;padding-left:18px}
.advpreview .advnote{
  margin-top:8px;padding-top:8px;border-top:1px dashed #d8dee4;
  font-size:12.5px;color:var(--sub);
}

@media (max-width:720px){
  .advchip{min-height:40px;padding:9px 15px;font-size:14px}
}

/* --------------------------------------------------------------------------
   20. 提醒列表的卡片（v6.6）
   --------------------------------------------------------------------------
   参考用户给的样式稿：左侧线性图标、中间标题+日期副标题、右侧大数字。
   【为什么用渐变底色】一眼区分"快到了"和"还早"：
     临近（≤7天）→ 暖色渐变，远处 → 冷色渐变。
   【不能用 transform】同 17 节的约束：卡片内要开 fixed 浮层，
   卡片上出现 transform 会让浮层定位跑到完全错误的地方。
   -------------------------------------------------------------------------- */
.remcards{display:grid;grid-template-columns:repeat(auto-fill,minmax(360px,1fr));gap:14px}
.remcard{
  position:relative;overflow:hidden;
  display:flex;align-items:center;gap:13px;
  padding:16px 16px 14px;border-radius:var(--r-lg);
  border:1px solid rgba(208,215,222,.8);
  background:linear-gradient(135deg,#eef4fd 0%,#f7faff 100%);
  box-shadow:var(--sh-1);
  transition:box-shadow .18s var(--ease),border-color .18s var(--ease);
}
.remcard:hover{box-shadow:var(--sh-2);border-color:rgba(180,192,204,.9)}
/* 临近的提醒：暖色渐变，一眼看出"快到了" */
.remcard.soon{
  background:linear-gradient(135deg,#fff3e6 0%,#ffe9ec 100%);
  border-color:#f3d3c4;
}
.remcard.off{
  background:linear-gradient(135deg,#f4f5f7 0%,#fafbfc 100%);
  border-color:#e2e6ea;
  opacity:.78;
}

/* 左侧线性图标 */
.remcard-ic{
  flex:0 0 46px;width:46px;height:46px;border-radius:14px;
  display:flex;align-items:center;justify-content:center;
  background:#fff;border:1px solid rgba(208,215,222,.9);
  color:var(--blue);
}
.remcard-ic svg{width:24px;height:24px;display:block}
.remcard.soon .remcard-ic{color:#e8590c;border-color:#f0cdb6}
.remcard.off .remcard-ic{color:#8b949e}

/* 中间：标题 + 副标题 */
.remcard-main{flex:1;min-width:0}
.remcard-title{
  font-size:16px;font-weight:650;letter-spacing:-.2px;color:var(--text);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.remcard-sub{
  display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-top:4px;
  font-size:12.5px;color:var(--sub);font-variant-numeric:tabular-nums;
  /* 【v6.19】子项之间不要有「换行空隙」——
     flex-wrap 的行间距用 row-gap 控制，这里给 0，
     免得文字被挤下去后两行之间留一大块空白。 */
  row-gap:2px;
}
/* 【v6.20】农历段与公历段各自完整、放不下就整段换行。
   之前是一整串「农历冬月十二 · 2026-12-20 星期7」，
   手机上放不下会：
     · v6.19 之前 → 在日期中间断行（「2027-08-」+ 换行的「29 星期7」）
     · v6.19 之后 → 被省略号截断（「2026-1...」）—— 用户要的是**完整换行**，不是缩略
   现在后端把内容拆成两段（.rs-a 农历 / .rs-b 公历+星期），
   两段各自 nowrap、各自不被压缩：
     · 段内永不断开（日期不会被劈成两半）
     · 放不下时整段换到下一行，**内容完整不截断**
   注意：这里**不能**加 text-overflow:ellipsis / overflow:hidden ——
   那样又会变回截断。宁可让 flex-wrap 把它换到下一行。 */
.remcard-sub .rs-a,
.remcard-sub .rs-b{
  white-space:nowrap;   /* 段内不断行 */
  flex:0 1 auto;        /* 允许压缩（配合下面 flex-wrap 换行） */
}
/* 后面的小标签（农历 / 每年 / 收件人）不参与换行 ——
   它们是「角标」性质，挤在一起也该在一行。
   写死 flex-wrap:nowrap 会让整行都挤不下，
   所以只给这几个角标加 white-space:nowrap（它们本来就短）。 */
.remcard-sub .tag.lunar,
.remcard-sub .remcard-rep,
.remcard-sub .remcard-owner{white-space:nowrap;flex:0 0 auto}
.remcard-sub .tag.lunar{
  background:#f3e8ff;color:#8250df;border-color:#e0d0f5;
  border-radius:5px;padding:1px 6px;font-size:11.5px;
}
.remcard-rep{color:var(--sub)}
.remcard-owner{color:var(--sub)}
.remcard-note{
  margin-top:5px;font-size:12px;color:var(--sub);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}

/* 右侧：大数字 + 单位 + 小标签 */
.remcard-right{
  flex:0 0 auto;text-align:right;line-height:1.1;
  display:flex;flex-direction:column;align-items:flex-end;
}
.remcard-num{
  font-size:32px;font-weight:750;
  /* 【v6.19】负字距原来给到 -1.2px，**太狠了**。
     letter-spacing 会在每个字符**后面**都加一次间距，
     所以最后一个字符的右边也会少掉 1.2px ——
     数字越宽，「6」这种带弧形收笔的字看着越像被削了一刀
     （用户反馈「306 的 6 右侧有点不圆润」）。

     实测三档对比（同一份数据、同样的卡片）：
       字距 -1.2px → 数字盒宽 48px（缺 1.2px）
       字距 -0.6px → 数字盒宽 50px（缺 0.6px，视觉上已完整）
       字距  0     → 数字盒宽 52px（完全完整，但数字之间略松）

     选 **-0.6px + margin-right 0.6px**：
       · 字符之间依然紧凑（不会松垮）；
       · 最后一个字右边缘的缺口缩到 0.6px（肉眼不可见）；
       · margin-right 把这 0.6px 补回盒子宽度，
         所以数字整体右边缘不会因为放宽字距而往右挪。 */
  letter-spacing:-0.6px;
  margin-right:0.6px;
  font-variant-numeric:tabular-nums;
  background:linear-gradient(135deg,#218bff,#7048e8);
  -webkit-background-clip:text;background-clip:text;
  color:transparent;-webkit-text-fill-color:transparent;
}
.remcard.soon .remcard-num{background:linear-gradient(135deg,#e8590c,#c2255c)}
.remcard-num.past{background:linear-gradient(135deg,#8b949e,#57606a)}
.remcard-num.muted{background:none;color:#adb5bd;-webkit-text-fill-color:#adb5bd}
.remcard-unit{font-size:12.5px;color:var(--sub);font-weight:600;margin-top:2px}
.remcard-tag{font-size:11.5px;color:var(--sub);opacity:.85;margin-top:1px}

/* 「管理」浮层入口：放在卡片右上角（v6.12 修：这条规则之前根本没生效）
   -----------------------------------------------------------------------
   【坑 1：position 被更高特异度的规则压掉了】
   style.css 里有 `details.more{position:relative;display:inline-block}`，
   特异度 (0,1,1)；本文件原来的 `.remcard-more{position:absolute}` 是 (0,1,0)。
   特异度低的赢不了 —— 「ui.css 在 style.css 之后加载」这条规矩在这里**不适用**
   （只有同特异度才看加载顺序）。
   结果：按钮压根没去右上角，而是留在流内当普通 flex 项，
   只剩 right:10px / top:8px 两条声明还在生效 —— 而 relative 模式下
   这两条是**相对位移**：按钮被硬生生左移 10px、下移 8px，
   正好压到右边的大数字上（实测与数字只剩 1px，视觉上就是"数字被挡住"）。

   【坑 2：所以必须显式写 position:relative 并把 right/top 归零】
   不归零的话，残留的相对位移还会继续把按钮往数字上推。

   【为什么不用 absolute】
   大数字是右对齐 + 垂直居中的。绝对定位到右上角，在**矮卡片**上一定压住数字
   （实测矮卡片的数字顶边只比卡片顶边低 15px，而按钮高 31px）。
   保持在流内 + align-self:flex-start：
     · 依然落在卡片右上角（流内最后一个 flex 项，align-self 顶对齐）；
     · 但由 flex 布局保证**永远不可能和数字重叠**（两者是并排的两列）。
   -------------------------------------------------------------------------- */
.remcard > details.remcard-more{
  position:relative;right:auto;top:auto;z-index:3;
  /* margin-top:6px —— 卡片圆角是 16px(r-lg)，按钮贴着内容区顶边(14px)会压在
     圆角弧上，看起来像"挂在卡片外面"。往下挪 6px 就完全落在卡片里面。 */
  align-self:flex-start;margin-left:10px;margin-top:6px;
}
.remcard > details.remcard-more > summary{
  font-size:12px;padding:3px 8px;color:var(--sub);
  border-radius:6px;list-style:none;
}
.remcard > details.remcard-more > summary::-webkit-details-marker{display:none}
.remcard > details.remcard-more > summary:hover{background:#eaf1f9;color:var(--blue)}
.remcard > details.remcard-more[open] > summary{background:#e6effa;color:var(--blue);font-weight:600}

@media (max-width:720px){
  .remcards{grid-template-columns:1fr;gap:12px}
  .remcard{padding:14px 14px 12px;gap:11px}
  .remcard-ic{flex:0 0 40px;width:40px;height:40px;border-radius:12px}
  .remcard-ic svg{width:21px;height:21px}
  .remcard-title{font-size:15px}
  .remcard-num{font-size:28px}
}

/* --------------------------------------------------------------------------
   21. 日期滚轮选择器（v6.6）
   --------------------------------------------------------------------------
   【为什么要自己做，不直接用 input[type=date]】
   原生控件在安卓 WebView 里唤起的是系统日期选择器，
   跨年份要一格一格点 —— 选 1985 年的生日得点到崩溃。
   自己做一个滚轮，滑到哪停在哪。

   【关键约束：原生 input 不能用 display:none 藏掉】
   藏掉之后浏览器做 required 校验会报 "not focusable"，
   表单**静默提交不了**（连报错提示都看不到）——
   必须用 opacity:0 + pointer-events:none（仍然可聚焦、可校验）。
   -------------------------------------------------------------------------- */
.dw-wrap{position:relative;display:block}
.dw-native{
  /* 透明但仍可聚焦、可校验 */
  opacity:0;
  pointer-events:none;
  position:absolute;left:0;top:0;width:100%;height:100%;
  z-index:1;
}
.dw-face{
  width:100%;min-height:40px;padding:9px 12px;text-align:left;
  border:1px solid var(--line);border-radius:10px;background:#fff;
  color:var(--text);font-size:14px;font-family:inherit;line-height:1.4;
  cursor:pointer;
  transition:border-color .16s var(--ease),background .16s var(--ease);
}
.dw-face:hover{border-color:var(--blue-line);background:var(--blue-soft)}
.dw-face.has{font-weight:500;font-variant-numeric:tabular-nums}
.dw-face:not(.has){color:var(--sub)}

/* 面板 */
.dw-sheet{position:fixed;inset:0;z-index:1200}
.dw-sheet[hidden]{display:none}
.dw-mask{position:absolute;inset:0;background:rgba(31,35,40,.45)}
.dw-panel{
  position:absolute;left:0;right:0;bottom:0;
  background:#fff;border-radius:16px 16px 0 0;
  box-shadow:0 -6px 24px rgba(31,35,40,.18);
  padding:0 0 max(14px,env(safe-area-inset-bottom));
  max-height:88vh;display:flex;flex-direction:column;
  animation:dwUp .26s var(--ease);
}
@keyframes dwUp{from{transform:translateY(100%)}to{transform:translateY(0)}}

.dw-head{
  display:flex;align-items:center;justify-content:space-between;
  padding:12px 14px;border-bottom:1px solid #eaeef2;flex:0 0 auto;
}
.dw-title{font-size:15px;font-weight:650;color:var(--text);text-align:center;flex:1}
.dw-btn{
  border:none;background:none;font-family:inherit;font-size:14.5px;
  padding:6px 10px;border-radius:8px;cursor:pointer;min-width:56px;
}
.dw-cancel{color:var(--sub);text-align:left}
.dw-cancel:hover{background:#f2f5f8}
.dw-ok{color:var(--blue);font-weight:600;text-align:right}
.dw-ok:hover{background:var(--blue-soft)}

/* 三列滚轮 —— scroll-snap 负责"滑到哪停在哪" */
.dw-wheels{
  display:flex;gap:6px;padding:8px 10px 0;
  flex:1;min-height:0;
}
.dw-col{
  flex:1;height:200px;               /* VISIBLE(5) × ITEM_H(40) */
  overflow-y:auto;scroll-snap-type:y mandatory;
  -webkit-overflow-scrolling:touch;
  border-radius:10px;background:#f7f9fb;
  position:relative;
}
.dw-items{padding:80px 0}            /* PAD = (5-1)/2 × 40 = 80 */
.dw-item{
  height:40px;line-height:40px;text-align:center;
  scroll-snap-align:center;
  font-size:15px;color:var(--sub);
  font-variant-numeric:tabular-nums;
  transition:color .12s var(--ease);
}
.dw-item.on{color:var(--text);font-weight:650;font-size:17px}

/* 底部快捷区 */
.dw-foot{
  flex:0 0 auto;padding:10px 12px 4px;
  display:flex;align-items:center;gap:10px;flex-wrap:wrap;
  border-top:1px solid #eaeef2;
}
.dw-decades{display:flex;gap:6px;flex-wrap:wrap;flex:1;min-width:0}
.dw-dec,.dw-today{
  border:1px solid rgba(208,215,222,.95);background:#fff;color:var(--sub);
  border-radius:999px;padding:5px 10px;font-size:12px;cursor:pointer;
  font-family:inherit;min-height:30px;
}
.dw-dec:hover,.dw-today:hover{border-color:var(--blue-line);color:var(--blue);background:var(--blue-soft)}
.dw-today{font-weight:600;color:var(--blue);flex:0 0 auto}

body.dw-open{overflow:hidden}

@media (max-width:720px){
  .dw-col{height:190px}
  .dw-item{height:38px;line-height:38px}
  .dw-items{padding:76px 0}
  .dw-face{min-height:42px;font-size:15px}
}

/* --------------------------------------------------------------------------
   18. 移动端：视觉增强必须让位给可用性
   -------------------------------------------------------------------------- */
@media (max-width:720px){
  .anivgrid{grid-template-columns:1fr;gap:13px}
  .anivcard{padding:14px 15px 13px}
  .aniv-big{font-size:36px}
  .aniv-ring{width:48px;height:48px;flex:0 0 48px}
  .unitbtn{min-width:42px;height:32px;padding:0 12px;font-size:13px}
  .unitbar .uhint{display:none}      /* 窄屏放不下，底部说明面板里有同样的解释 */
}

/* 减少动效偏好：一律关掉过渡与位移动画 */
@media (prefers-reduced-motion:reduce){
  .card,.bookcard,.btn,.backlink,.tbl tbody tr,.bar nav .nb{
    transition:none !important;
  }
  .card:hover,.bookcard:hover,.backlink:hover{transform:none !important}
  /* 纪念日：入场淡入与呼吸光晕一并关掉 */
  .anivcard,.anivcard::after,.aniv-num{animation:none !important}
  .anivcard::after{opacity:.14}
  .aniv-num{opacity:1}
  .rk-bar{transition:none !important}
}

/* --------------------------------------------------------------------------
   21. 触屏上不许留 hover 残留（v6.8）
   --------------------------------------------------------------------------
   【用户反馈】"取消选择后样式未恢复到选中之前"——
   提前提醒的档位按钮，点掉之后停在浅蓝色，看着像还没取消。

   【实测根因】**状态逻辑是对的**，不是 JS 的锅：
     class      : 'advchip on' → 'advchip'   ✅ 已移除
     adv.value  : '30分钟,0' → '0'          ✅ 已回退
     computed bg: 深蓝渐变 → rgb(221,244,255) ← **这个是 .advchip:hover 的颜色**
   把鼠标移开 → 立刻恢复白底 rgb(255,255,255)。
   ⇒ 是**视觉状态**停在 hover 上，不是数据没清。

   【为什么会粘住】触屏上没有真正的鼠标指针，但浏览器会给"最后被点的那个
   元素"保持 :hover 状态，**直到用户点了别处才消失**（业界叫 sticky hover）。
   于是「点一下选中 → 再点一下取消」之后，按钮就一直停在悬停态。

   【为什么用媒体查询，而不是 JS 去记状态】
   触屏本来就没有"悬停"这个概念，把 hover 反馈在触屏上关掉才是对的；
   按下反馈交给 :active（手指按住的那一瞬间才亮，点完就消失）。

   【两个必须踩准的坑】
   ① **媒体查询不改变特异度**！
      写在文件前面的 @media (hover:none) 里的 .advchip:hover，
      会被**后面**同特异度的 .advchip:hover 覆盖掉（同特异度靠后者胜）。
      所以这段必须放在文件**靠后**的位置，且特异度要提上去。
   ② 复位规则**必须排除选中态**（:not(.on)）——
      不加的话它特异度比 .advchip.on 高，会把**选中态也复位成未选中**。
   -------------------------------------------------------------------------- */
@media (hover:none){
  /* 未选中的按钮：触屏上悬停不改变任何样式 = 取消后立刻回到点击前 */
  .advchips .advchip:not(.on):hover{
    border-color:var(--chip-rest-bd);
    color:var(--text);
  }
  /* 按下瞬间给个反馈（浅蓝底），点完就消失 —— 取代悬停反馈 */
  .advchips .advchip:not(.on):active{
    border-color:var(--blue-line);
    color:var(--blue);
    background:var(--blue-soft);
  }
}

/* --------------------------------------------------------------------------
   18. 底部「今日面板」（v6.14）
   --------------------------------------------------------------------------
   【为什么换掉原来的 footer】
   原来写的是「服务时间 · 常驻于飞牛 OS · 后台自动巡检 · 版本号（功能清单）」——
   静态的运维信息，对使用者没价值，还占掉手机屏幕底部最贵的一行。
   换成每天都会变的内容：实时时钟 / 农历 / 下一个重要日 / 每日一言。

   【布局】
   手机（≤720px）：一行紧凑排布，时钟最大，其余依次缩小；
   桌面（>720px）：分四栏并排，中间对齐。

   【为什么不用 position:sticky】
   v6.13 刚踩过这个坑：sticky 的定位参照是**最近的滚动容器**，不是视口。
   这里刻意不依赖 sticky —— 面板就在文档流末尾，滚到底自然出现，
   不需要它「吸附」，也就不会踩到那条规则。 */
.todaypanel{
  display:flex;flex-wrap:wrap;align-items:center;gap:6px 14px;
  color:var(--sub);font-size:12.5px;padding:10px 20px 30px;
  /* 顶边一条极淡的渐变分隔线，和上面的卡片区分开 */
  border-top:1px solid transparent;
  background:linear-gradient(180deg,rgba(255,255,255,0),rgba(255,255,255,.7));
}
@media (min-width:721px){
  .todaypanel{justify-content:center;gap:10px 30px;padding:14px 20px 34px}
}

/* ---- 时钟：面板里最醒目的一块 ---- */
.tp-clock{display:inline-flex;align-items:baseline;gap:6px}
/* 秒数单独一个 span（JS 每秒只改它，不重排整块） */
.tp-time{
  font-size:19px;font-weight:700;letter-spacing:.5px;
  color:var(--text);font-variant-numeric:tabular-nums;
  /* 等宽数字：不然秒数从 8 跳到 9 时整块会左右抖 */
  font-feature-settings:"tnum" 1;
}
.tp-week{font-size:12.5px;color:var(--sub)}

/* 秒数的呼吸效果：每秒钟轻微亮一下 */
.tp-time .tp-sec{color:var(--blue);transition:color .3s ease}
.tp-time.tick .tp-sec{color:var(--blue);opacity:.45}

/* ---- 农历 ---- */
.tp-lunar{
  font-size:12.5px;color:var(--sub);
  padding:1px 9px;border-radius:20px;background:#eef2f6;
}

/* ---- 下一个重要日 ---- */
.tp-next{display:inline-flex;align-items:baseline;gap:6px;flex-wrap:wrap}
.tp-next-label{font-size:12px;color:var(--sub)}
.tp-next-title{font-size:13px;font-weight:600;color:var(--text)}
.tp-next-days{
  font-size:12.5px;font-weight:700;color:var(--blue);
  padding:1px 8px;border-radius:20px;background:#eaf2fd;
}
/* 「就是今天 / 明天」用暖色，一眼就能和「N 天后」区分 */
.tp-next-days.is-near{color:#fff;background:var(--orange)}
/* 目标日期：更淡，属于补充信息 */
.tp-next-date{font-size:11.5px;color:var(--sub);opacity:.75}

/* ---- 每日一言：整块最淡，让它像句悄悄话 ---- */
/* 【这条规则的三个版本必须放在一起，不能分散在文件各处】
   v6.12 踩过「同特异度看位置」的坑：这里原本在文件**后面**还有一条
   @media(min-width:721px){.tp-word{flex-basis:auto}}，
   和上面的 flex-basis:100% 特异度相同 (0,1,0) → 后者胜 →
   桌面端「独占一行居中」被悄悄压掉，页面看着没报错但布局不对。
   所以：同一元素的所有规则**集中成一块**，改的时候只动这一块。 */
.tp-word{
  flex-basis:100%;          /* 独占一行（手机和桌面都一样） */
  font-size:12.5px;color:var(--sub);font-style:italic;
  padding-left:12px;position:relative;
}
/* 前面一个小引号 */
.tp-word::before{
  content:"\201C";position:absolute;left:0;top:-1px;
  font-size:17px;color:var(--blue);opacity:.45;font-style:normal;
}
/* 桌面上居中：独占一行后居中才有仪式感 */
@media (min-width:721px){
  .tp-word{text-align:center;padding-left:0;margin-top:2px}
  .tp-word::before{position:static;margin-right:2px;display:inline-block}
}
/* 打字机效果的光标：JS 加 .typing 类时显示 */
.tp-word.typing::after{
  content:"";display:inline-block;width:1.5px;height:1em;
  margin-left:2px;vertical-align:-2px;background:var(--blue);
  animation:tpblink .9s steps(1) infinite;
}
@keyframes tpblink{0%,49%{opacity:1}50%,100%{opacity:0}}

/* ---- 版本号：缩到最小，固定在右上角 ---- */
/* 【为什么不用 margin-left:auto】
   flex-wrap 换行时，margin-left:auto 会把版本号推到**新行**并居中，
   看起来像多了一行没对齐的东西。改用绝对定位钉在右上角，
   不参与 flex 布局，永远不换行。 */
.todaypanel{position:relative}
.tp-ver{
  position:absolute;top:10px;right:20px;
  font-size:11px;color:var(--sub);
  opacity:.45;font-variant-numeric:tabular-nums;
}
@media (min-width:721px){
  .tp-ver{top:14px;right:20px}
}

/* ---- 减少动效：关掉呼吸/闪烁 ---- */
@media (prefers-reduced-motion:reduce){
  .tp-word.typing::after{animation:none}
  .tp-time .tp-sec{transition:none}
}
