/* ============================================================================
 * source/css/site-inject.css —— 站点注入样式合集
 * ----------------------------------------------------------------------------
 * 本文件由 _config.fomalhaut.yml 的 inject.head 段抽出（2026-10-03 屎山重构）。
 * 抽出来的原因：在 YAML 里写 CSS 没有语法高亮、没有补全、缩进错一位就会被静默吞掉；
 * 在一个两千行的配置文件里翻样式更是折磨。现在样式集中在这个文件里，配置里只留一行 <link>。
 *
 * 【层叠顺序 = 本文件从上到下的顺序，与抽取前完全一致，不要随意重排】
 *   配置里那条 <link> 的位置，就是原先第一个 <style> 块的位置，所以它相对于
 *   主题样式表 / 其它注入块的优先级没有变。
 *
 * 【唯一的位置变化（已评估，无影响）】
 *   原 scroll-gap-css（锚点 scroll-padding-top:70px）在 YAML 里排在 aside-show /
 *   aside-pos 两个「运行时空槽」之前，现在排到了它们之后。两者管的属性完全不搭界
 *   （滚动容器锚点定位 vs 侧栏显隐/左右位置），不会互相覆盖。
 *
 * 【注意】配置里那些空标签 <style id="themeColor"></style>、#rightSide、#transPercent、
 *   #bgFilterParam、#defineBg、#menu_shadow、#nav-display、#aside-show、#aside-pos
 *   是「运行时空槽」：由右下角美化面板的 JS 在运行时写入内容，不能删、不能挪。
 *
 * 【本文件目录】共 16 块（后面的优先级更高）
 *    1. scroll-gap-css     ← 原 _config.fomalhaut.yml:1209-1212
 *    2. annoV2             ← 原 _config.fomalhaut.yml:1216-1295
 *    3. pcLightTheme       ← 原 _config.fomalhaut.yml:1306-1344
 *    4. asideWider         ← 原 _config.fomalhaut.yml:1364-1379
 *    5. listPagination     ← 原 _config.fomalhaut.yml:1437-1437
 *    6. pageWidthLimit     ← 原 _config.fomalhaut.yml:1438-1438
 *    7. rightMenuState     ← 原 _config.fomalhaut.yml:1444-1452
 *    8. webinfoCard        ← 原 _config.fomalhaut.yml:1492-1518
 *    9. ft-hide-self       ← 原 _config.fomalhaut.yml:1522-1526
 *   10. aplayerVolumeFix   ← 原 _config.fomalhaut.yml:1538-1542
 *   11. readModeIconGuard  ← 2026-10-04 新增（阅读模式标题风车兜底）
 *   13. cardAnimPerf       ← 2026-10-04 新增（首页卡片箭头 / 置顶角标流光改走 transform）
 *   14. loadingIdle        ← 2026-10-04 新增（加载动画在遮罩隐藏后停掉）
 *   15. cardGlassOff       ← 2026-10-04 新增（关闭卡片毛玻璃特效）
 *   16. searchPanelUX      ← 2026-10-11 新增（搜索加载提示位置修正 + 搜索历史）
 *   17. darkModeSpeed      ← 2026-10-11 新增（昼夜切换动画时长调整：覆盖天空/星球/日月互换时长，整屏遮挡 ~1.5s）
 * ========================================================================== */

/* ── 1/12  #scroll-gap-css  ← 原 _config.fomalhaut.yml:1209-1212 ── */
/* 锚点跳转兜底：给常驻顶栏留出高度。scroll-padding-top 作用于滚动容器的锚点定位， */
/* 使得「JS 完全没跑 / pjax 换页后点击处理丢失」时，原生锚点跳转也不会把标题顶到常驻顶栏底下。 */
/* 实测注意：不要再给目标元素加 scroll-margin-top，两者会叠加（70+70=140px）造成偏移过大。 */
/* JS 版补偿见 inject.bottom 的 scroll-gap-fix（实测落点 70px）。 */
html { scroll-padding-top: 70px !important; }

/* ── 2/12  #annoV2  ← 原 _config.fomalhaut.yml:1216-1295 ── */
/* 公告栏 · 信息板改版样式（配合 card_announcement.content 的新结构，纯 CSS + 变量） */
/* 公告栏 · 信息板改版（配合 _config.fomalhaut.yml 的 card_announcement.content）
 * 只作用于侧栏 .card-announcement 这一张卡；配色跟着 --theme-color 走，
 * 由它派生三档，每个变量第一行是「不支持 color-mix() 的老浏览器」回退值：
 *   --anno-accent  主题色原色
 *   --anno-strong  原色压深(浅色)/提亮(深色)一档 → 当文字用的胶囊、下载按钮、欢迎信息里的高亮
 *   --anno-chip-* / --anno-soft-*  胶囊与软底的底色/描边
 * 深色适配只覆盖变量，规则本体一套。
 */
.card-announcement {
  --anno-accent: var(--theme-color, #FF1493);

  --anno-strong: #25706b;
  --anno-strong: color-mix(in srgb, var(--anno-accent) 62%, #000);

  --anno-muted: rgba(60, 60, 67, .55);
  --anno-muted: color-mix(in srgb, var(--font-color, #1f2937) 55%, transparent);

  --anno-chip-bg: rgba(255, 20, 147, .075);
  --anno-chip-bg: color-mix(in srgb, var(--anno-accent) 7.5%, transparent);
  --anno-chip-bd: rgba(255, 20, 147, .22);
  --anno-chip-bd: color-mix(in srgb, var(--anno-accent) 22%, transparent);

  --anno-soft-bg: rgba(255, 20, 147, .06);
  --anno-soft-bg: color-mix(in srgb, var(--anno-accent) 6%, transparent);
  --anno-soft-bd: rgba(255, 20, 147, .16);
  --anno-soft-bd: color-mix(in srgb, var(--anno-accent) 16%, transparent);
}
[data-theme="dark"] .card-announcement {
  --anno-strong: #7fe3da;
  --anno-strong: color-mix(in srgb, var(--anno-accent) 78%, #fff);
  --anno-chip-bg: rgba(255, 20, 147, .14);
  --anno-chip-bg: color-mix(in srgb, var(--anno-accent) 14%, transparent);
  --anno-chip-bd: rgba(255, 20, 147, .32);
  --anno-chip-bd: color-mix(in srgb, var(--anno-accent) 32%, transparent);
  --anno-soft-bg: rgba(255, 20, 147, .12);
  --anno-soft-bg: color-mix(in srgb, var(--anno-accent) 12%, transparent);
  --anno-soft-bd: rgba(255, 20, 147, .26);
  --anno-soft-bd: color-mix(in srgb, var(--anno-accent) 26%, transparent);
}
.card-announcement .anno2 { font-size: 13.5px; line-height: 1.75; text-align: left; }
.card-announcement .anno2 a { text-decoration: none; }
.card-announcement .a-row { display: flex; align-items: center; gap: 6px; padding: 7px 0; flex-wrap: nowrap;}
.card-announcement .a-row + .a-row { border-top: 1px dashed rgba(127, 127, 127, .18); flex-wrap: nowrap;}
.card-announcement .a-row.a-sub { border-top: 0; padding-top: 0; }
.card-announcement .a-row.a-flat { border-top: 0; padding: 0; }
.card-announcement .a-lb { flex: 0 0 56px; font-size: 12px; letter-spacing: .4px; color: var(--anno-muted); font-weight: 700; white-space: nowrap; }
.card-announcement .a-chip { display: inline-flex; align-items: center; gap: 6px; font-weight: 700; font-size: 13px;
  color: var(--anno-strong); background: var(--anno-chip-bg); border: 1px solid var(--anno-chip-bd);
  border-radius: 999px; padding: 4px 9px; line-height: 1.7; transition: .25s; flex: 0 0 auto;}
.card-announcement .a-chip:hover { background: var(--anno-accent); border-color: var(--anno-accent); color: var(--on-theme); }
.card-announcement .a-chip .a-dot { width: 5px; height: 5px; border-radius: 50%; background: currentColor; opacity: .75; }
.card-announcement .a-note { font-size: 12.5px; color: var(--anno-muted); font-weight: 500; margin-left: auto;
  white-space: nowrap; flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis;}
/* 排版规则（2026-10-04 修正）：.a-row 一律 flex-wrap:nowrap —— 一行装不下时只允许两种结果：
   ① .a-note 自己省略成「Cloudfl…」（flex:0 1 auto + min-width:0 + text-overflow:ellipsis）；
   ② 容器查询按宽度逐档收起注记/徽标。绝不把注记挤到第二行把行撑高（用户实测反馈过）。
   胶囊与徽标是 flex:0 0 auto，不会被压缩，保证域名与延时完整可读。 */
/* ── 线路延时徽标（2026-10-04 新增）────────────────────────────────────────
   由 source/js/inject/ping-route.js 在每条线路胶囊后面插入 <span class="a-ms">，
   显示「本机 → 该线路」的一次网络往返（如 82ms）。等宽数字 + 最小宽度锁死，
   状态：wait/load → ok（主题色）/ slow ≥400ms（琥珀）/ bad ≥1s（红）/ fail（—，删除线）。
   从 — → ··· → 82ms 的长度变化都不会引起布局位移（min-width 锁住）；ok 的配色由主题色派生。
   位置说明：徽标在 DOM 里紧跟胶囊，靠 .a-note 的 margin-left:auto 被推到右侧、与「Vercel」
   这类注记相邻（用户圈的是「线路名后面那块空位」）。宽 42px 是内测值：narrow 断点下
   「胶囊 + 82ms」仍能排在同一行，超时最长显示「999ms」也不会撑宽。 */
.card-announcement .a-ms { flex: 0 0 auto; min-width: 42px; text-align: center;
  font-size: 11.5px; font-weight: 700; font-variant-numeric: tabular-nums; letter-spacing: .2px;
  color: var(--anno-muted); background: transparent; border: 1px solid transparent;
  border-radius: 999px; padding: 2px 6px; line-height: 1.6; cursor: pointer;
  transition: color .25s, background .25s, border-color .25s; user-select: none; }
.card-announcement .a-ms:hover { border-color: var(--anno-chip-bd); }
.card-announcement .a-ms[data-state="load"] { color: var(--anno-muted); opacity: .7; }
.card-announcement .a-ms[data-state="ok"] { color: var(--anno-strong);
  background: var(--anno-chip-bg); border-color: var(--anno-chip-bd); }
.card-announcement .a-ms[data-state="slow"] { color: #e8a33d; border-color: rgba(232, 163, 61, .34);
  background: rgba(232, 163, 61, .10); }
/* ≥1s：红色（很慢）。浅色卡片用深一点的红，深色卡片覆盖成亮红 —— 与 slow 同一种写法 */
.card-announcement .a-ms[data-state="bad"] { color: #d23b3b; border-color: rgba(210, 59, 59, .34);
  background: rgba(210, 59, 59, .10); }
[data-theme="dark"] .card-announcement .a-ms[data-state="bad"] { color: #ff7a7a; border-color: rgba(255, 122, 122, .38);
  background: rgba(255, 122, 122, .12); }
.card-announcement .a-ms[data-state="fail"] { color: var(--anno-muted); text-decoration: line-through;
  text-decoration-thickness: 1px; opacity: .6; }
/* 卡片更窄时（窗口变小 / 侧栏收窄）用容器查询自动降一档，保证「Cloudflare」这类注记永远排在同一行。 */
/* 降档只收「行间距 + 标签列 + 胶囊内边距 + 胶囊内圆点间距」这四种尺寸，字号一律不动 —— */
/* 用户两次要求过胶囊/线路注记的字要更大（13px / 12px 就是这个结论），这里绝不能再缩回去。 */
.card-announcement .anno2 { container-type: inline-size; }
@container (max-width: 320px) {
  .card-announcement .a-row { gap: 3px; }
  /* 标签列改成「按内容、最小 44px」并禁止换行：「手机 App」在 48px 定宽里会折成两行（用户反馈）。
     主线路/备用线路内容约 38px，被 min-width 抬到 44px，三行胶囊仍对齐。 */
  .card-announcement .a-lb { flex: 0 0 auto; min-width: 44px; font-size: 12px; }
  .card-announcement .a-chip { padding: 3px 6px; gap: 4px; font-size: 13px; }
  .card-announcement .a-ms { min-width: 34px; padding: 2px 4px; font-size: 11.5px; }
}
/* 320 这一档同时收四处（行间距 6→3、标签列 56→48、胶囊内边距 9→6、徽标 min-width 42→32），
   字号一律不动。阈值必须是 320 而不是 285：线上桌面卡片内容宽正好 272px，
   而「备用线路 + github.example.com + 999ms + Github」在原尺寸下要 279px —— 286-320 这段
   如果不收，注记就会掉到第二行。收完之后最宽的一行 ≈269px，272px 下仍有 3px 余量。 */
/* 卡片再窄时先让出「线路注记」，保住延时徽标（用户要的是能看见延时）。
   268 是实测值：最宽的「netlify.example.com + 999ms + Netlify + 标签」在容器 269px 时刚好 266px。 */
@container (max-width: 268px) { .card-announcement .a-note { display: none; } }
/* 最窄一档：放不下徽标，连同它一起收起，绝不换行。
   230 是实测值：容器 231px 时「标签 48 + 最长胶囊 120 + 徽标 44 + 间距」= 223px 刚好排下。 */
@container (max-width: 230px) { .card-announcement .a-ms { display: none; } }
/* 再窄（手机抽屉等）：注记与徽标都已收起，只剩「标签 + 胶囊」，此时恢复换行兜底，避免横向裁切。 */
@container (max-width: 230px) { .card-announcement .a-row { flex-wrap: wrap; } }
.card-announcement .a-sect { margin-top: 11px; padding-bottom: 18px; }
.card-announcement .a-approw { display: flex; align-items: center; gap: 8px; margin-top: 7px; }
.card-announcement .a-btn { display: inline-flex; align-items: center; justify-content: center; gap: 6px; font-weight: 700;
  font-size: 13.5px; color: var(--on-theme);
/* 渐变方向改成「往远离前景色的方向」（浅色预设 → 提亮、深色预设 → 压暗）。
   原来是从主题色渐到 --anno-strong（= 主题色 62% + 黑），深色那头配深字只有 2.2~3.4:1，
   就是「字被渐变吃掉」的原因；现在两端都 ≥5.6:1。第一行是不支持 color-mix 时的回退。 */
background: linear-gradient(135deg, var(--anno-accent), var(--anno-strong));
background: linear-gradient(135deg, color-mix(in srgb, var(--anno-accent) 88%, var(--on-theme-away, #ffffff)), color-mix(in srgb, var(--anno-accent) 66%, var(--on-theme-away, #ffffff)));
  border-radius: 10px; padding: 8px 16px; line-height: 1.6; transition: .25s;
  box-shadow: 0 3px 10px rgba(255, 20, 147, .35);
  box-shadow: 0 3px 10px color-mix(in srgb, var(--anno-accent) 35%, transparent); flex: 0 0 auto;}
.card-announcement .a-btn:hover { color: var(--on-theme); filter: brightness(1.06); transform: translateY(-1px);
  box-shadow: 0 6px 16px color-mix(in srgb, var(--anno-accent) 45%, transparent); }
.card-announcement .a-btn svg { width: 13px; height: 13px; fill: currentColor; }
/* 原「欢迎信息」块的配色（#welcome-info）已于 2026-10-28 随卡片一起删除，
   卡片位置换成了「每日一言」+ 悬停音乐播放器，样式单独放在 source/css/daily-say.css。 */

/* ── 3/12  #pcLightTheme  ← 原 _config.fomalhaut.yml:1306-1344 ── */
/* 版权卡片 · 白天配色（2026-10-05）：原文那套粉-青-米渐变是主题作者写死的固定值，跟主题色无关； */
/* 更要紧的是两处彩色小字白天几乎看不见：文章链接 #99a9bf 只有 1.89:1、值行用主题色原色只有 1.71:1 */
/* （实测自用户截图，WCAG AA 小字要 4.5:1）。注意 #FF1493 放在纯白上也只有 2.13:1 —— 所以光换底色没用， */
/* 必须把文字按同色系压深一档，才有现在这套： */
/*   值行/许可协议  color-mix(主题色 50%, #0d1f22) → 5.1~5.5:1（13 种主题色全验过，最差的黄色 4.69:1） */
/*   文章链接        保留它那支灰蓝压深 → ≈6:1 */
/*   卡片底色        主题色 14% / 3% / 18% 混白的三档渐变，跟着右下角主题色选择器联动 */
/* 只作用于 html[data-theme="light"]；暗色模式的 #07080a + flashlight 观感完全不动。 */
/* 每处 color-mix() 的上一行是不支持它的老浏览器回退值（沿用上方 annoV2 的写法）。 */
/* 主题源码 post.styl 里的原渐变仍在，这里按「优先改配置」的约定从配置层覆盖。 */
/* 版权卡片 · 白天配色（主题色系淡渐变 + 同色系深墨字） */
html[data-theme="light"] #post .post-copyright {
  background: linear-gradient(45deg, #e3f7f5, #f9fdfd, #d1eeef) !important;
  background: linear-gradient(45deg,
      color-mix(in srgb, var(--theme-color, #FF1493) 14%, #fff),
      color-mix(in srgb, var(--theme-color, #FF1493) 3%, #fff),
      color-mix(in srgb, var(--theme-color, #FF1493) 18%, #f2f7fa)) !important;
  border-color: #c9e7e8 !important;
  border-color: color-mix(in srgb, var(--theme-color, #FF1493) 18%, #e9eef2) !important;
  /* 原 box-shadow 是 currentColor（深灰实心偏移影），浅底上会显得脏，压到 10% 黑 */
  box-shadow: 2px 2px 5px rgba(0, 0, 0, .1) !important;
}
/* 值行（作者 / 发表日期 / 更新日期 / 许可协议）：主题色压深一档当墨色用 */
html[data-theme="light"] #post .post-copyright .post-copyright-cc-info,
html[data-theme="light"] #post .post-copyright .post-copyright-cc-info a {
  color: #23726f !important;
  color: color-mix(in srgb, var(--theme-color, #FF1493) 50%, #0d1f22) !important;
}
/* 文章链接：保留它自己那支灰蓝，只压深（1.89:1 → ≈6:1） */
html[data-theme="light"] #post .post-copyright__type .post-copyright-info a {
  color: #586575 !important;
  color: color-mix(in srgb, #99a9bf 50%, #16202b) !important;
}
/* 白天别再用主题色原色当悬停色（浅底上同样看不清）：改成压深 + 下划线 */
html[data-theme="light"] #post .post-copyright-info a:hover,
html[data-theme="light"] #post .post-copyright-cc-info a:hover {
  color: #23726f !important;
  color: color-mix(in srgb, var(--theme-color, #FF1493) 50%, #0d1f22) !important;
  text-decoration: underline !important;
  text-underline-offset: 3px;
}
/* 右下角那枚 CC 水印：由原来的灰改成跟着主题色染一点（仍由 opacity 保持很淡） */
html[data-theme="light"] #post .post-copyright:before {
  color: #61a0a4;
  color: color-mix(in srgb, var(--theme-color, #FF1493) 40%, #7b8794);
}

/* ── 4/12  #asideWider  ← 原 _config.fomalhaut.yml:1364-1379 ── */
/* 侧栏宽度（第三轮，2026-10-04）：第二轮把侧栏顶到 .layout 最右边，结果撞上了右侧悬浮工具条， */
/* 所以这一轮同时处理「宽度」和「右边留够工具条的位置」两件事。 */
/* 两个必须知道的上游事实： */
/*  1) 站点自定义 CSS `.aside-content { max-width: 318px; min-width: 300px }`（类选择器）会把侧栏锁死在 318px； */
/*     元素本身是 #aside-content.aside-content（themes/fomalhaut/layout/includes/widget/index.pug:1）， */
/*     所以要用 ID+类 的选择器才压得住它。站点还有 `.layout { max-width: 1400px }`（覆盖主题的 1200px）。 */
/*  2) 右侧悬浮工具条 #rightside 是 position: fixed（themes/fomalhaut/source/css/_layout/rightside.styl:1-4 */
/*     是 right: -48px，custom.css:2284-2288 再 translateX(-58px)，按钮宽 38px，见 custom.css:1087-1096）—— */
/*     换算下来按钮左边缘大约在「窗口右边 −48px」处，所以布局内容必须在它左边收住，不能贴到窗口最右。 */
/* 第三轮做法：① 压缩整个布局宽度（max-width 取 min(1400px, 100vw - 140px)）；② 侧栏固定 380px， */
/* 主列 flex-grow 吃满剩余。结果：卡片确实离开按钮了，但左右两侧被压出两条空隙，看着没铺满 —— 已废弃。 */
/* 第四轮做法（当前，2026-10-04）：**不压缩布局宽度**，只把 .layout 的右侧内边距加大到 78px， */
/* 让右列内容在工具条左边收住、左列仍然贴到窗口左边（左右都铺满）；窗口比 1400px 布局上限更宽时， */
/* 布局居中本身就会离右边越来越远，所以右侧内边距按 (100vw - 1400px)/2 逐步回收，最少 15px。 */
/* 宽度上限测算（窗口 1440 CSS、扣 15px 滚动条）：布局 1400、右内边距 58 → 内容区 ≈ [27.5, 1354.5]， */
/* 卡片右边缘 1349.5，工具条按钮左边缘 1377 → 留约 27px 间隙。 */
/* 只在小屏以上生效：901px 以下主题自己的 +maxWidth900() 会把两者都设成 100%，不能被覆盖（见 aside.styl:10-11）。 */
/* 用 :not(.hide-aside) 避开「收纳侧栏」时主题的 `.layout.hide-aside > div { width: 100% !important }`。 */
/* 样式自 2026-10-03 起集中在 source/css/site-inject.css（配置里只留一行 <link>），不动主题源码； */
/* 本块的上一版备份 bak/announcement-20261004-v8-fill/before/，本次备份 bak/announcement-20261004-v9-narrow340/before/。 */
/* 左右都铺满：不动布局宽度，只把右侧内边距加大，让内容在悬浮工具条左边收住 */
@media screen and (min-width: 901px) and (max-width: 1400px) {
  .layout:not(.hide-aside) { padding-right: 78px; }
}
/* 窗口比布局上限 1400px 更宽时，布局居中已自带右侧余量，内边距按差额逐步收回（最少 15px） */
@media screen and (min-width: 1401px) {
  .layout:not(.hide-aside) { padding-right: max(15px, calc(78px - (100vw - 1400px) / 2)); }
}
/* 第五轮（2026-10-04 晚）：侧栏 360 → 340px —— 用户原话「侧栏又有点太宽了，稍微弄窄一点点」。 */
/* 340px 时卡片内容宽 = 340 − 20（#aside-content padding 0 5px 0 15px）− 48（.card-widget padding 20px 24px）= 272px； */
/* 最紧的是「cloudflare.example.com + Cloudflare」那行（衬底值约 265px），靠上面 @container ≤285px 的降档刚好排得下。 */
/* 再往下窄（≤335px 左右）这行就要换行，那时必须继续降档或改行结构。 */
@media screen and (min-width: 1200px) {
  #aside-content.aside-content { width: 340px; max-width: 340px; flex: 0 0 auto; }
  .layout:not(.hide-aside) > div:first-child { flex: 1 1 auto; width: auto; min-width: 0; }
}

/* ── 5/12  #listPagination  ← 原 _config.fomalhaut.yml:1437-1437 ── */
/* 归档 / 标签 / 分类等列表页的翻页按钮：样式对齐首页（卡片圆角 + 悬浮反馈 + 统一尺寸） */
.layout > div:not(.recent-posts) #pagination .pagination > *{display:inline-block;margin:0 6px;width:2.5em;height:2.5em;line-height:2.5em;text-align:center}.layout > div:not(.recent-posts) #pagination .pagination > *:not(.space){border-radius:8px;background:var(--card-bg);box-shadow:var(--card-box-shadow);transition:all .3s}.layout > div:not(.recent-posts) #pagination .pagination > *:not(.space):hover{background:var(--btn-hover-color);color:var(--btn-color);box-shadow:var(--card-hover-box-shadow)}

/* ── 6/12  #pageWidthLimit  ← 原 _config.fomalhaut.yml:1438-1438 ── */
.layout:has(#page),.layout:has(#archive),.layout:has(#tag),.layout:has(#category){max-width:1200px}

/* ── 7/12  #rightMenuState  ← 原 _config.fomalhaut.yml:1444-1452 ── */
/*  */
/* 侧边栏「右键模式」按钮：显示"站点自定义右键"当前是开还是关 */
/*   开 = 跟随主题色（主题默认外观，不动）；关 = 灰色 + 图标上一道斜杠 */
/*   状态源与 source/js/fomal.js 的 mouseMode 完全一致（localStorage 键 "mouse"，缺省视为开） */
/*   纯 HTML/CSS/JS 注入实现，不改主题源码（rightside.pug 的 button 原样保留） */
html[data-rm="off"] #rightside button:has(> i.fa-mouse){position:relative;background-color:#909090 !important;color:#fff !important;}
html[data-rm="off"] #rightside button:has(> i.fa-mouse):hover{background-color:#a8a8a8 !important;}
html[data-theme="dark"][data-rm="off"] #rightside button:has(> i.fa-mouse){background-color:#787878 !important;}
html[data-theme="dark"][data-rm="off"] #rightside button:has(> i.fa-mouse):hover{background-color:#8d8d8d !important;}
html[data-rm="off"] #rightside button:has(> i.fa-mouse) > i{opacity:.4;}
html[data-rm="off"] #rightside button:has(> i.fa-mouse)::after{content:"";position:absolute;left:50%;top:50%;width:20px;height:2px;border-radius:2px;background:#fff;opacity:.95;transform:translate(-50%,-50%) rotate(-45deg);}

/* ── 8/12  #webinfoCard  ← 原 _config.fomalhaut.yml:1492-1518 ── */
/* （2026-10-03）不蒜子已弃用，统计源改为 Vercount（见 additional-js.pug）。 */
/* 原先这两段（bsz-guard 拦截器 / bsz-lazy 延迟兜底）是专为 busuanzi.ibruce.info 写的； */
/* 其中 bsz-lazy 的 6 秒超时会把 Vercount 已经写好的数字覆盖成「—」，故整段删除。 */
/* 原文与备份见 bak/20261003-webinfo/。 */
/* 小站资讯卡（2026-10-03 改版）样式 */
/* 小站资讯卡 2026-10-03 改版 */
.card-webinfo .wi{margin-top:2px;container-type:inline-size}
.card-webinfo .wi-kpi{display:grid;grid-template-columns:repeat(3,1fr);gap:8px;margin:10px 0 12px}
.card-webinfo .wi-kpi-item{display:block;text-align:center;border-radius:10px;padding:10px 2px 8px;color:inherit;text-decoration:none;background:rgba(128,128,128,.09);background:color-mix(in srgb,var(--theme-color) 9%,transparent);transition:background .3s,transform .3s}
.card-webinfo a.wi-kpi-item:hover{transform:translateY(-2px);background:rgba(128,128,128,.16);background:color-mix(in srgb,var(--theme-color) 16%,transparent)}
.card-webinfo .wi-kpi-num{font-size:22px;line-height:1.1;font-weight:700;color:var(--theme-color);font-variant-numeric:tabular-nums}
.card-webinfo .wi-kpi-label{font-size:11px;opacity:.6;margin-top:4px;letter-spacing:.3px}
.card-webinfo .wi-time{display:flex;align-items:center;justify-content:center;gap:5px;flex-wrap:wrap;font-size:12px;padding:8px 0 2px;border-top:1px solid rgba(128,128,128,.2)}
.card-webinfo .wi-time-item{display:inline-flex;align-items:baseline;gap:3px}
.card-webinfo .wi-time-k{opacity:.55}
.card-webinfo .wi-time-v{font-weight:600;color:var(--theme-color);font-variant-numeric:tabular-nums}
.card-webinfo .wi-time-sep{opacity:.3}
/* 「更新」= 站点最后更新时间（最近一次部署）。构建时先渲染 MM-DD 兜底，
   页面加载后由 source/js/inject/webinfo-card.js 换成「N 分钟前 / N 小时前 / N 天前」。 */
.card-webinfo .wi-deploy{cursor:default}
/* 三项一行（已运行 / 距上次发文 / 更新）。实测（2026-10-04，无头 Chrome）：
   · 侧栏 340px → 卡片内容宽 288px，12px 字号下三项 + 4 个 5px 间距 ≈ 280px，刚好一行；
   · 901~1199px 侧栏只有 300px → 内容宽 248px（两栏布局下的地板值，再窄就没有了，
     <901px 时侧栏变整列反而更宽），12px 会挤成两行，故 ≤284px 时降字号一档。
   284 这个界值是算出来的：12px 档最少要 280px 才不换行，界值必须大于它、又要小于 288。 */
@container (max-width: 284px) {
  .card-webinfo .wi-time{font-size:10.5px;gap:4px}
  .card-webinfo .wi-time-item{gap:2px}
}
.card-webinfo .wi-chart{margin-top:10px;border-top:1px solid rgba(128,128,128,.2);padding-top:9px}
.card-webinfo .wi-chart-head{display:flex;justify-content:space-between;align-items:baseline;font-size:11px;opacity:.6;margin-bottom:6px}
.card-webinfo .wi-bars{display:flex;align-items:flex-end;gap:6px;height:50px}
.card-webinfo .wi-bar{flex:1 1 0;min-width:0;height:100%;display:flex;flex-direction:column;justify-content:flex-end;align-items:center}
.card-webinfo .wi-bar-n{font-size:10px;opacity:.5;line-height:1.2;margin-bottom:2px;font-variant-numeric:tabular-nums}
.card-webinfo .wi-bar-fill{width:100%;max-width:22px;border-radius:4px 4px 2px 2px;background:var(--theme-color);background:linear-gradient(180deg,var(--theme-color),color-mix(in srgb,var(--theme-color) 30%,transparent))}
.card-webinfo .wi-years{display:flex;gap:6px;margin-top:4px}
.card-webinfo .wi-year{flex:1 1 0;min-width:0;text-align:center;font-size:10px;opacity:.45}
.card-webinfo .wi-visit{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-top:10px;border-top:1px solid rgba(128,128,128,.2);padding-top:9px}
.card-webinfo .wi-visit-item{text-align:center}
.card-webinfo .wi-visit-num{font-size:16px;font-weight:600;line-height:1.3;font-variant-numeric:tabular-nums}
.card-webinfo .wi-visit-label{font-size:11px;opacity:.55;margin-top:2px}

/* ── 9/12  #ft-hide-self  ← 原 _config.fomalhaut.yml:1522-1526 ── */
/* 页脚「推荐友链⌛」隐藏本站自己那一项（2026-10-03） */
/* 该列表硬编码在 themes/fomalhaut/layout/includes/footer.pug:33-58，没有任何配置项可管； */
/* 按 href 精准隐藏（:has() 现代 Chrome 生效，老浏览器不支持时优雅降级为仍显示）。 */
/* 页脚推荐友链：去掉指向本站（example.com）的那一项 */
.ft-img-group .img-group-item:has(> a[href*="example.com"]) { display: none !important; }

/* ── 10/12  #aplayerVolumeFix  ← 原 _config.fomalhaut.yml:1538-1542 ── */
/* 八音盒 APlayer 音量条「点了看不出变化」修复（2026-10-03） */
/* 根因：APlayer 渲染出的 .aplayer-volume 自带内联 style="background:<data-theme 的颜色>"， */
/*   内联样式优先级高于样式表，于是 themes/fomalhaut/source/css/_custom/custom.css:1492 那句 */
/*   不带 !important 的 background: var(--theme-color) 从来没生效过——填充色一直是 */
/*   source/music/index.md 里 data-theme="#e3f2f5" 的浅灰蓝； */
/*   而槽色（custom.css:1488）是 color-mix(--theme-color 18%, #fff)，也是接近白的浅色， */
/*   两段肉眼几乎同色 → 拖动/点击音量条、点喇叭静音时只有声音变，看不出任何变化。 */
/* 修法照主题对 .aplayer-played / .aplayer-thumb 的既有做法（custom.css 里那两句都带 !important）， */
/*   这里补 !important 把填充色拉回主题色；再补夜间模式的槽色（custom.css 只给 */
/*   .aplayer-bar / .aplayer-loaded 写了夜间色，漏了音量条）。 */
/* 回滚：删掉下面这一整段即可（纯样式，不碰播放逻辑）。 */
#article-container .aplayer .aplayer-volume { background: var(--theme-color) !important; }
[data-theme="dark"] #article-container .aplayer .aplayer-volume-bar { background: color-mix(in srgb, var(--theme-color) 25%, #242424); }

/* ── 11/12  #readModeIconGuard  ← 2026-10-04 新增（站点级兜底） ── */
/* 阅读模式下的标题小风车兜底。
 * 主题在阅读模式里会把标题内边距整个清空（编译产物 public/css/index.css 里）：
 *   .read-mode #article-container h1 ~ h6 { padding: 0 }   —— 还有一份 :hover 版
 * 但标题前风车图标的负 margin 依然生效（themes/fomalhaut/source/css/_custom/custom.css:925-960，
 *   h1~h6 依次是 -1.55 / -1.35 / -1.22 / -1.05 / -0.9 / -0.9rem），
 * 于是图标被顶到标题盒左侧：桌面端卡片左右各有 40px 内边距还能兜住，
 * 窄屏卡片只剩 14px（.layout > div:first-child:not(.recent-posts) { padding: 36px 14px }），
 * 图标就会顶出卡片、在手机视口边缘被裁掉 —— 和友人帐 / 网址导航那两页是同一个毛病。
 * 这里只在窄屏补回左内边距（= 该级负 margin + 约 0.25rem 间隙），图标就稳定落在标题盒内；
 * 桌面端阅读模式保持原样，不改观感。
 * 特异性：#content-inner.layout #article-container h2 = (2,0,1) ＞ 主题的 .read-mode #article-container h2 = (1,1,1)，
 *   所以不需要 !important 也能压过（本文件在 /css/index.css 之后加载，顺序上也占优）。
 * 回滚：删掉下面这一整段即可（纯样式，不涉及任何 JS / 模板 / 主题源码）。 */
@media screen and (max-width: 768px) {
  .read-mode #content-inner.layout #article-container h1 { padding-left: 1.8rem; }
  .read-mode #content-inner.layout #article-container h2 { padding-left: 1.6rem; }
  .read-mode #content-inner.layout #article-container h3 { padding-left: 1.5rem; }
  .read-mode #content-inner.layout #article-container h4 { padding-left: 1.3rem; }
  .read-mode #content-inner.layout #article-container h5,
  .read-mode #content-inner.layout #article-container h6 { padding-left: 1.15rem; }
}

/* ── 13/13  cardAnimPerf  ← 2026-10-04 新增（首页卡片动画改走合成层）────────────
 * 背景：首页每张卡片里的小箭头 .recent-post-arrow 用 @keyframes ddd 动 top，
 *   置顶角标的流光 .post-sticky-shine 动 left。top / left 都是「非合成属性」，
 *   浏览器每帧要重算布局 + 重绘：首页 9 个箭头 + 3 个角标 = 每帧 12 次布局失效，
 *   页面静止不动也一直在跑 —— 属于「静置帧率不高 / 机身发热」的直接来源。
 * 做法：同名重声明 @keyframes（后声明者胜，主题 /css/index.css 在本文件之前），
 *   把动画属性换成 transform（合成层动画，不触发布局）；箭头原来的 top 静态值
 *   补上（动画在跑时 top 恒为 20~30px，见 custom.css 的 ddd 关键帧），位移交给
 *   translateY，观感与原来逐帧一致。
 * 注意：.recent-post-arrow 是 position: absolute + top: auto，必须显式补 top，
 *   否则动画一撤它会掉回 static 位置。主题里没有任何规则给这个元素设过 top
 *   （只有 @keyframes ddd 设过），因此补 top 不会跟别的规则打架。
 * 回滚：删掉本块即可（备份 bak/20261004-perf-idle-frame/before/source/css/site-inject.css）。
 * ──────────────────────────────────────────────────────────────────────────── */
.recent-post-arrow {
  top: 20px;
}

@keyframes ddd {
  0%   { transform: translateY(10px); }
  10%  { transform: translateY(0); }
  20%  { transform: translateY(10px); }
  30%  { transform: translateY(0); }
  60%  { transform: translateY(2px); }
  90%  { transform: translateY(0); }
  100% { transform: translateY(0); }
}

/* 置顶角标流光：left -60% → 118% 换成 translateX。
   元素自身宽度是角标宽度的 45%，所以 178% 的角标宽度 = 178/45 ≈ 395% 的元素宽度；
   角标是 overflow: hidden，多出来的部分本来也看不见。 */
@keyframes post-sticky-shine {
  0%,
  62% {
    transform: skewX(-18deg) translateX(0);
  }
  86%,
  100% {
    transform: skewX(-18deg) translateX(395%);
  }
}

/* ── 14/14  loadingIdle  ← 2026-10-04 新增（加载遮罩隐藏后停掉内部动画）────────
 * 背景：#loading-box（heo 版加载遮罩）加载完只是被加上 .loaded，让 .loading-bg
 *   变成 opacity: 0 / z-index: -1000 —— 元素并没有离开渲染树。里面的 .loading-img
 *   还挂着 animation: loadingAction 0.3s infinite（动的是 opacity），于是首页
 *   永远有一条「看不见但在跑」的动画，浏览器也就永远有活干。
 * 做法：只在 .loaded 状态下停掉内部动画。遮罩真正显示时（加载中 / pjax 换页，
 *   preloader 会移除 .loaded）规则不生效，动画照常。隐藏后的 0.3s 淡出是父层
 *   opacity 过渡，与本条无关，观感零变化。
 * 回滚：删掉本块即可（备份 bak/20261004-perf-idle-frame/before/source/css/site-inject.css）。
 * ──────────────────────────────────────────────────────────────────────────── */
#loading-box.loaded .loading-img {
  animation: none;
}

/* ── 15/15  cardGlassOff  ← 2026-10-04 新增（作者卡去掉实时背景模糊）─────────────
 * 背景：themes/fomalhaut/source/css/_custom/custom.css:3787-3793 在 ≥1200px 给作者卡
 *   的 ::before 加了 backdrop-filter: blur(11px) saturate(1.45)。卡片本身是随页面滚动的，
 *   而它背后的 #web_bg 是 position: fixed 不动的 —— 于是浏览器每一帧都要对「卡片此刻
 *   盖住的那块背景」重做一次高斯模糊。这是侧栏滚动时最贵的一项，弱 GPU 上直接掉帧。
 * 做法：用同样特异性的选择器（本文件在 /css/index.css 之后加载，后声明者胜）把
 *   backdrop-filter 置 none。渐变一个字没动 → 卡片的白色罩层、顶部渐隐、整体明度
 *   完全不变；唯一差别是卡片上半部分背后的背景图不再是磨砂的，而是清晰原图。
 * 如果觉得清晰背景图太花、压不住文字：把下面「备用」那段注释取消即可
 *   （整体比原渐变白 8% 左右，只影响 ≥1200px 的桌面端），一行就能调。
 * 想恢复玻璃拟态：删掉本块即可。
 * 回滚备份：bak/20261004-perf-idle-frame/before/source/css/site-inject.css
 * ──────────────────────────────────────────────────────────────────────────── */
#aside-content > .card-widget.card-info::before,
[data-theme="dark"] #aside-content > .card-widget.card-info::before {
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}

/* 备用：觉得背景图太抢时启用（取消这行的注释符号即可）
@media (min-width: 1200px) {
  #aside-content > .card-widget.card-info::before {
    background: linear-gradient(180deg, rgba(255,255,255,.14) 0%, rgba(255,255,255,.56) 30%, rgba(255,255,255,.82) 64%, rgba(255,255,255,.92) 100%);
  }
  [data-theme="dark"] #aside-content > .card-widget.card-info::before {
    background: linear-gradient(180deg, rgba(6,22,30,.14) 0%, rgba(6,22,30,.56) 30%, rgba(6,22,30,.82) 64%, rgba(6,22,30,.92) 100%);
  }
}
*/

/* 背景滤镜：仅面板内生效，原生滑条本身有 44px 触摸区域。 */
.settings .bf-panel { margin:18px 10px 24px; max-width:600px; padding:20px; border:1px solid rgba(128,128,128,.25); border-radius:16px; }
.settings .bf-heading,.settings .bf-value-row { display:flex; align-items:center; justify-content:space-between; gap:12px; }
.settings .bf-heading { font-weight:700; }
.settings .bf-heading input { margin:0; flex-shrink:0; }
.settings .bf-hint { margin:8px 0 18px; font-size:.8em; opacity:.8; line-height:1.6; }
.settings .bf-control { margin:18px 0; }
.settings .bf-value-row>label { font-weight:600; }
.settings .bf-number { display:flex; align-items:center; gap:8px; }
/* 卡片不透明度与背景滤镜共用数字框样式；覆盖主题滤镜输入框的 max-width:50px，避免三位数裁切与 flex 压缩。 */
.settings .bf-panel .bf-number input:is(#transNumber, #blurRad, #saturation, #contrast) { box-sizing:border-box; flex:0 0 76px; width:76px; min-width:76px; max-width:none; height:44px; margin:0; padding:6px 8px; border:1px solid rgba(128,128,128,.45); border-radius:8px; background:rgba(128,128,128,.08); color:inherit; font:inherit; font-size:16px; text-align:center; }
.settings .bf-panel input:focus-visible,.settings .bf-panel button:focus-visible { outline:2px solid var(--theme-color); outline-offset:3px; }
.settings .bf-panel .bf-slider { --bf-fill:0%; box-sizing:border-box; display:block; width:100%; height:44px; margin:2px 0 0; padding:0; border:0; border-radius:0; background:linear-gradient(to right,var(--theme-color) var(--bf-fill),rgba(128,128,128,.35) var(--bf-fill)) center / 100% 5px no-repeat; touch-action:pan-y; cursor:pointer; }
.settings .bf-slider::-webkit-slider-thumb { width:22px; height:22px; border:3px solid var(--theme-color); background:var(--theme-color); border-radius:50%; }
.settings .bf-slider::-moz-range-thumb { width:18px; height:18px; border:2px solid var(--theme-color); background:var(--theme-color); border-radius:50%; }
.settings .bf-slider::-moz-range-track { background:transparent; border:0; }
.settings .bf-limits { display:flex; justify-content:space-between; gap:8px; font-size:.72em; line-height:1.5; opacity:.75; }
.settings .bf-limits span:nth-child(2) { text-align:center; }
.settings .bf-footer { display:flex; justify-content:flex-end; margin-top:20px; }
.settings .bf-footer button { min-height:44px; padding:8px 12px; border:1px solid rgba(128,128,128,.45); border-radius:8px; color:inherit; background:transparent; font:inherit; font-size:.85em; cursor:pointer; }
.settings .bf-panel input:disabled,.settings .bf-panel button:disabled { opacity:.4; cursor:not-allowed; }
@media(max-width:480px) { .settings .bf-panel { margin:16px 0; padding:14px 12px; } }

/* ── 左下角胶囊组共用配色（#ds-mini + #fps，2026-10-28 两版）────────────────────
   左下角是**两个**控件竖着叠成一组：上面 #ds-mini（daily-say.css，172 高）、
   下面 #fps（本文件，52 高）。既然是同一组，底色/描边/文字必须是同一套值，
   所以配色抽到这里，daily-say.css 的 #ds-mini 直接引用（本文件先于它加载）。

   ⚠⚠ 第一版（掺主题色）已被作者否掉：粉主题下整块变成「红红的」玻璃，压在有纹理的
   壁纸上又糊成一团。作者给的参照是**侧栏卡片**（日历 / 倒计时 / 公告栏），
   所以现在不再自己调色，直接抄卡片那三件套（themes/fomalhaut/source/css/_custom/custom.css:446-465）：
     background: var(--trans-light) / var(--trans-dark)   ← 和卡片同一个变量、同一个滑条
     border:     var(--border-style)                      ← 1px 实线，深色主题也不另调
     box-shadow: 卡片那道投影的缩小版
   而且卡片**没有 backdrop-filter** —— 这一条很关键：胶囊原来写了 blur(18px)，
   压在照片上就是「糊的一块」；去掉之后才和卡片一样是「透下去的干净一层」。
   颜色只留在两个地方：图标 / 播放键实底（--glass-accent = 主题色）、帧率数值的状态色。
   这也是卡片自己的做法（公告栏的胶囊、日历里那个粉色 28 号），比整块染色干净得多。

   透明度仍然只有一个来源：--trans-*（美化面板的「卡片不透明度」）。
   ⚠ 不要再往 --glass-bg 里掺主题色，也不要给胶囊加 backdrop-filter —— 那正是被否掉的第一版。 */
html {
  --glass-base: var(--trans-light, rgba(250, 250, 250, .97));
  --glass-bg: var(--glass-base);                    /* 与卡片完全同款，不掺色 */
  --glass-bd: var(--border-style, 1px solid rgba(169, 169, 169, .7));
  --glass-chip: rgba(0, 0, 0, .08);
  --glass-chip: color-mix(in srgb, var(--theme-color, #FF1493) 12%, transparent);

  --glass-accent: var(--theme-color, #FF1493);      /* 实底（播放键）、图标：主题色原色 */
  --glass-ink: var(--font-color, #1f2937);          /* 正文：直接跟主题正文色，别自己压色相 */
  --glass-dim: color-mix(in srgb, var(--glass-ink) 62%, transparent);
  /* 中性薄片：小块「面」的底色（首页分类磁贴用）。掺 ink 不掺主题色，
     10% 压在不透明的卡上约等于 #e4e4e4，和原来写死的 #e9e9e9 视觉一致；
     卡片一透明它就跟着透 —— 这是「跟不跟滑块」的关键，不能写死颜色。 */
  --glass-veil: color-mix(in srgb, var(--glass-ink) 10%, transparent);

  --glass-shadow: 0 2px 10px rgba(7, 17, 27, .07);  /* 卡片 --card-box-shadow 的缩小版 */
}
html[data-theme="dark"] {
  --glass-base: var(--trans-dark, rgba(28, 28, 28, .97));
  --glass-bg: var(--glass-base);
  --glass-chip: rgba(255, 255, 255, .1);
  --glass-chip: color-mix(in srgb, var(--theme-color, #FF1493) 20%, transparent);
  --glass-shadow: 0 2px 12px rgba(0, 0, 0, .4);
}

/* FPS 轻量状态条：不阻挡点击，不加模糊或动画；预留数值与状态宽度，避免刷新抖动。
   配色按观感优先（2026-10-15 作者确认）：小字对比度有意不按 4.5:1 收紧，
   浅底压在深色壁纸上约 3.2–4.3:1；曾按对比度压深过一版，观感变闷、状态色也难区分，
   已回退 —— 不要再"优化"回去。背景滤镜那套数字框的对比度结论不适用于这里。
   状态色由 data-state（good/warn/low）交给 CSS 定义，不反查内联 style。
   状态色间距（2026-10-15）：原来 amber(#94600d) 与 red(#b13b42) 的 L* 与彩度几乎相同、
   色相只差 48°，12px 下很难一眼分开 —— 现在把 amber 推向金黄、red 推向纯红，
   Lab ΔE 从 43 提到 64（深色 44 → 60）。*/
html #fps, html[data-theme] #fps {
  /* 配色全部接到上面的 --glass-*：和上面的 #ds-mini 是同一块玻璃，同色同透明度。
     good（正常）跟着主题色的 ink 走，warn/low 保留琥珀/红 —— 那是语义色，
     换成主题色就分不出「顺畅还是卡顿」了，只按深浅主题调亮度。 */
  --fps-bg: var(--glass-bg);
  --fps-fg: var(--glass-ink);
  --fps-muted: var(--glass-dim);
  --fps-border: var(--glass-bd);        /* 现在是一整条 border 简写（= 卡片那条 --border-style） */
  /* good（正常）用主题色压深/提亮到能读；warn 琥珀 / low 红保留 —— 那是语义色，
     换成主题色就分不出「顺畅还是卡顿」了，只按深浅主题调亮度。 */
  --fps-good: #267d72;
  --fps-good: color-mix(in srgb, var(--theme-color, #FF1493) 72%, #101820);
  --fps-warn: #a0740d;
  --fps-low: #df2039;
  /* 定位：左下角竖向胶囊组的**下半格**（10-28 起改成 52×52 小胶囊，贴底 12）。
     上方是 #ds-mini（bottom 72、宽 52），两者同宽、同圆角、同玻璃底，竖着叠成一组。
     52 是卡出来的安全宽度：10 + 52 = 62，贴着正文左边界（约 60–160，随窗口宽度变化）
     也只擦到卡片内边距，不会压住字。
     竖排两行：上行是数值（状态色），下行是 FPS 小字 —— 横排那个「· 流畅 / 轻微掉帧」
     在 52px 里放不下，改成用数值颜色表达状态（:has(data-state) 见下）。
     注意这里**不能用 flex**：settings.js / beauty-boot.js 会用 inline style 把 #fps 写成
     display:block / none（帧率开关），inline 优先级高于任何选择器，flex 会被打回 block。
     所以改成两个 block 的 span 自己堆叠，靠 padding 让内容垂直居中。 */
  box-sizing:border-box; position:fixed; left:10px; bottom:12px;
  left:calc(10px + env(safe-area-inset-left,0px)); bottom:calc(12px + env(safe-area-inset-bottom,0px));
  z-index:1000; width:52px; height:52px; padding:0; text-align:center;
  border:var(--fps-border); border-radius:999px; background:var(--fps-bg); color:var(--fps-fg);
  font-size:13px; line-height:1; font-weight:500; white-space:nowrap;
  box-shadow:var(--glass-shadow); pointer-events:none; user-select:none;
}
/* 竖排重排：数值在上做主角、FPS 做副标题、状态文字整个藏掉（信息量转给数值颜色）。
   内容总高 16 + 2 + 8.5 = 26.5，胶囊内高 50，所以 padding-top 取 12 让它视觉居中。 */
html #fps .fps-value { display:block; width:auto; margin:0; padding-top:12px; font-size:16px; line-height:1; text-align:center; }
html #fps .fps-label { display:block; margin-top:2px; font-size:8.5px; line-height:1; letter-spacing:1px; text-align:center; }
html #fps .fps-state { display:none; }
/* 数值跟着 data-state 变色；保留 .fps-state 节点是因为 cursor.js 在监听它的属性变化 */
html #fps:has(.fps-state[data-state="good"]) .fps-value { color:var(--fps-good); }
html #fps:has(.fps-state[data-state="warn"]) .fps-value { color:var(--fps-warn); }
html #fps:has(.fps-state[data-state="low"])  .fps-value { color:var(--fps-low); }
/* 深色只翻三个「语义色」和 good 的提亮方向；底色/描边/文字已经在 --glass-* 里跟主题走过了，
   这里再写一遍会盖掉共享 token（以前就是在这里写死 rgba(18,29,35,.88) 的）。 */
html[data-theme="dark"] #fps {
  --fps-good: color-mix(in srgb, var(--theme-color, #FF1493) 58%, #eef4f7);
  --fps-warn:#f0cb68; --fps-low:#ff8a95;
}
#fps:empty { visibility:hidden; }
#fps > span { display:inline-block; vertical-align:middle; line-height:18px; flex:0 0 auto; }
#fps .fps-label { font-size:10px; letter-spacing:.6px; color:var(--fps-muted); }
#fps .fps-value { width:3ch; margin:0 6px; font-family:ui-monospace,SFMono-Regular,Consolas,monospace; font-variant-numeric:tabular-nums; font-weight:600; text-align:right; }
#fps .fps-state { min-width:3.5em; font-size:12px; }
#fps .fps-state::before { content:"·"; margin-right:5px; color:var(--fps-muted); }
#fps .fps-state[data-state="good"] { color:var(--fps-good); }
#fps .fps-state[data-state="warn"] { color:var(--fps-warn); }
#fps .fps-state[data-state="low"] { color:var(--fps-low); }
}
@media(max-width:600px) {
  /* 手机：48×48，组间距 12 + 48 + 6 = 66（#ds-mini 的 bottom 同步在 daily-say.css 里改） */
  html #fps, html[data-theme] #fps { width:48px; height:48px; }
  html #fps .fps-value { padding-top:10px; font-size:15px; }
}

/* 互动挂件与功能分区：沿用 bf-panel 的边框、留白与圆角，不改主题源码。 */
.beauty-neko-off .neko,
.beauty-neko-off #myscoll { display:none !important; }
.settings { container-type:inline-size; }
.settings .feature-grid { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:8px 22px; }
.settings .feature-opt { display:flex; align-items:center; justify-content:space-between; gap:12px; min-width:0; min-height:64px; padding:8px 0; cursor:pointer; }
.settings .feature-opt > span { min-width:0; font-weight:600; line-height:1.5; }
.settings .feature-opt small { display:block; margin-top:3px; font-size:.72em; font-weight:400; opacity:.75; line-height:1.5; }
.settings .feature-opt input[type="checkbox"] { flex-shrink:0; margin:0; }
@container (max-width:560px) { .settings .feature-grid { grid-template-columns:minmax(0,1fr); gap:4px; } }
@media(max-width:600px) { .settings .feature-grid { grid-template-columns:minmax(0,1fr); gap:4px; } }

/* 点击涟漪（第 4 个互动挂件，默认关闭 · 和猫咪/听话鼠标同一区）
   层是 0×0 且 pointer-events:none，不参与命中测试：链接、按钮、文字选择照常先拿到点击，
   所以不需要"只在空白处画"那种每次点击跑一遍命中测试的写法；关掉开关时连监听都不挂。
   z-index:9998 —— 高于正文/侧栏/美化面板（winbox 的 z-index 是个位数），
   低于光标圆点 #cursor-position(10086)、猫咪 .neko(99990)、右键菜单(19198)，也低于昼夜过场 .dm-stage。
   颜色全部从 --theme-color 派生，换主题色或自定义取色时自动跟随。 */
.ripple-layer { position:fixed; left:0; top:0; width:0; height:0; pointer-events:none; z-index:9998; }
.ripple-burst { position:absolute; left:0; top:0; width:0; height:0; }
.ripple-ring { box-sizing:border-box; position:absolute; left:0; top:0; width:46px; height:46px; margin:-23px 0 0 -23px; border-radius:50%; border:1.5px solid color-mix(in srgb, var(--theme-color, #FF1493) 55%, transparent); opacity:0; animation:ripple-out .52s cubic-bezier(.22,.61,.36,1) forwards; }
/* 第二环错开 60ms、更细更淡：两圈同心速度略不同，一眼是水波不是单圈涟漪。 */
.ripple-ring.is-late { border-width:1px; border-color:color-mix(in srgb, var(--theme-color, #FF1493) 30%, transparent); animation-delay:.06s; animation-duration:.56s; }
@keyframes ripple-out { from { transform:scale(.16); opacity:.9; } to { transform:scale(2.6); opacity:0; } }

/* 十色预设色板：站点注入覆盖主题变量，不改主题源码。
   深粉红色、珊瑚红、紫罗兰、樱花粉保持原色；与 boot/cursor 的 RGB 完全对应。 */
:root {
  --color-orange: rgb(215, 146, 77); /* 暖杏橙 #D7924D */
  --color-yellow: rgb(196, 166, 74); /* 蜂蜜金 #C4A64A */
  --color-puregreen: rgb(77, 175, 135); /* 玉石绿 #4DAF87 */
  --color-blue: rgb(74, 156, 199); /* 晴空蓝 #4A9CC7 */
  --color-heoblue: rgb(97, 106, 209); /* 柔靛蓝 #616AD1 */
  --color-darkblue: rgb(113, 133, 156); /* 雾蓝灰 #71859C */
  --color-matcha: rgb(102, 179, 77); /* 抹茶绿 #66B34D（2026-10-14 新增：补 80°–150° 的黄绿区） */
}

/* 主题色「实底上的前景色」--on-theme（2026-10-14 新增）
   由来：主题的按钮/标签/分页/右栏图标/气泡/选中底色全是白字压在 --theme-color 上，
   而 10 个预设里只有紫罗兰的白字过 WCAG AA（默认深粉红色只有 2.13:1，蜂蜜金 2.36:1）。
   前景色由站点脚本按主题色亮度算：
     · source/js/inject/beauty-boot.js —— 首帧前写（浅色预设不会先闪一下白字）
     · source/js/modules/settings.js 的 setColor() —— 换色时写
   亮度高的预设给近黑 #141a1c（实测最低 4.8:1），亮度低的给纯白（最低 4.4:1）。
   下面这段只做三件事：① 脚本没跑时的兜底；② 把主题里 var(--btn-color)=#fff 接到同一条链；
   ③ 把主题 CSS 里带 !important、没法靠变量覆盖的两处（TOC 当前项、作者卡按钮 hover）抄一遍。 */
:root { --on-theme: #ffffff; }
/* ── 实底图标块：右侧工具条那排 38×38（2026-10-15 第三版）────────────────────────
   这三轮试下来的结论：颜色越压深越"稳"，但越没活泼感；站点主人要的是亮。
   所以最终取「主题色原色 + 白图标 + 一层极轻的暗投影」：
     · 填充回到主题色原色（深粉红色 rgb(57,197,187)），不再压深 —— 这是最亮、最接近原设计的状态；
     · 白图标在原色底上名义对比只有 2.13:1（WCAG 不把投影算进对比度），
       但 0 1px 1px 的深色投影把字形边缘压出来，实际观感不糊（和改之前的样子基本一致，只是更清晰）。
   如果要回到"压深一档"的版本（白图标 3.45:1 但偏暗）：把下面两行的 background-color 换成
   color-mix(in srgb, var(--theme-color) 75%, #0b1416) 即可（备份见 bak/theme-ink-20261014/before/）。
   hover 仍是主题自带的 --btn-hover-color（浅橙 #FF7242），保持不变。 */
#rightside > div > a,
#rightside > div > button {
  background-color: var(--theme-color);
  color: #fff;
  text-shadow: 0 1px 1px rgba(6, 32, 34, .45);
}
#rightside > div > a svg,
#rightside > div > button svg { filter: drop-shadow(0 1px 1px rgba(6, 32, 34, .45)); }
/* 主题 var.styl:70 的 $button-color = #fff，所有 var(--btn-bg)（=主题色）面上的字与图标 */
:root { --btn-color: var(--on-theme) !important; }
/* 选中文字：Chrome 侧主题只设了底色，Firefox 侧写死白字（custom.css:274 / 2106） */
*::selection { color: var(--on-theme); }
::-moz-selection { color: var(--on-theme); }
/* TOC 当前项（custom.css:2109-2114） */
#aside-content #card-toc .toc-content .toc-link.active,
#aside-content #card-toc .toc-content .toc-link.active:hover { color: var(--on-theme) !important; }
/* 主题 CSS 里写死 white、但底色就是主题色/渐变主题色的几处（custom.css:1473 作者卡按钮、
   3812 设置面板保存按钮、3813 切换背景按钮、4013 恢复默认按钮）：统一接到 --on-theme。
   标签外挂按钮（_tags/button.styl:11 的 $btn-color=#fff）hover 时底色换成 --btn-hover-color，也要跟着走。 */
/* ⚠ 作者卡「微信 - Wechat」按钮**不在**上面那类里 —— 它的常态底色是白/半透明白
   （custom.css:3806 `rgba(255,255,255,.82)`），不是主题色。原来这里错写成
   `color: var(--on-theme)`，而 --on-theme 是「压在主题色实底上的字色」：
   主题色选黑 / 深蓝 / 深绿时它算出 #fff，于是白字压白底 → 整行字消失（作者 10-28 报的 bug）。
   常态文字只能跟正文色（--glass-ink）走，只有 hover 之后底色才是主题色、才轮到 --on-theme。 */
#aside-content > .card-widget.card-info > #card-info-btn {
  /* 底色 = 卡片同一块玻璃（--glass-bg 就是 --trans-light / --trans-dark），**不掺主题色**。
     踩过一次坑：这里曾用 --glass-chip（= 主题色 12% / 深色 20% 薄片），
     于是主题色选粉就是一片粉底、选黑就是一片灰底（黑 12% 压白卡 = 灰），
     作者 10-28 直接否掉。主题色只留给 hover 的实底，常态必须是中性玻璃。
     描边用 --glass-bd（= 卡片那条 --border-style），文字用 --glass-ink（= --font-color）。 */
  background-color: var(--glass-bg) !important;
  color: var(--glass-ink) !important;
  border: var(--glass-bd);
  box-shadow: var(--glass-shadow);
}
/* 深色必须单写一条：custom.css:3872 的 `[data-theme="dark"] …　#card-info-btn` 特异性是 (2,3,0)，
   比上面那条 (2,2,0) 高，不写就会被它的 #eaf7f7 / rgba(255,255,255,.14) 盖回去。 */
[data-theme="dark"] #aside-content > .card-widget.card-info > #card-info-btn {
  background-color: var(--glass-bg) !important;
  color: var(--glass-ink) !important;
  border: var(--glass-bd);
  box-shadow: var(--glass-shadow);
}

/* ── 首页分类磁贴（#catalog_magnet，由 hexo-magnet-fomal 注入）──────────────────
   插件把配色**写死**在它自己注入的 <style> 里，值取自 _config.yml 的
   magnet.color_setting：`.magnet_item{background:#e9e9e9}`、`.magnet_link{color:black}`。
   后果就是作者 10-28 报的「调整透明度的时候这个标签没反应」：
   外面那张卡片跟着 --trans-light 变透明了，里面这块磁贴永远是一坨实心灰（rgb(233,233,233)，
   实测滑块从 97% 拉到 28% 它一个字节都不变）；顺带 `.magnet_link` 的黑色字在深色主题下直接看不见。
   修法：改用中性薄片 --glass-veil（ink 10% 透明）—— 卡片不透明时≈#e4e4e4，和原来观感一致，
   卡片一透明它就跟着透；文字接 --glass-ink / --glass-dim。
   这里靠 **id + class (1,1,0)** 压过插件注入的 class 选择器 (0,1,0)，
   既不用 !important，也不用去改插件和 _config.yml 里那串写死的颜色。 */
#catalog_magnet .magnet_item { background: var(--glass-veil); }
/* hover 必须自己再写一条：上面那条是 (1,1,0)，插件给的 `.magnet_item:hover` 只有 (0,2,0)，
   id 压过 class + 伪类，不写的话 hover 反而被常态底盖掉、整块失去反馈。
   底色用**实底** --theme-color 而不是插件原来的 --text-bg-hover（= 主题色 70%）：
   70% 的黑压在半透明白卡上合成出来是**深灰**，看着像没生效；实底才和作者卡按钮的 hover 一致。 */
#catalog_magnet .magnet_item:hover { background: var(--theme-color, #FF1493); }
#catalog_magnet .magnet_link { color: var(--glass-ink); }
/* hover 底色是主题色实底 → 字必须用 --on-theme（黑/白按亮度自动算）。
   插件原来写死 white，浅色主题色（白/黄）下就是白压白。 */
#catalog_magnet .magnet_link:hover { color: var(--on-theme); }
#catalog_magnet .magnet_link_more { color: var(--glass-dim); }
.settings .bgp-save, .settings .picbtn, #reset_btn { color: var(--on-theme); }
#article-container .btn-beautify:hover { color: var(--on-theme); }
/* tag-hide 的折叠按钮：底色是 $tag-hide-bg、字是 var(--white)，hover 换成 --btn-hover-color */
#article-container .hide-button:hover { color: var(--on-theme); }
/* 音乐卡标签 + 作者卡按钮 hover（custom.css:1705 / 3889 / 3950，主题里带 !important） */
#aside-content > .card-widget.card-info > #card-info-btn:hover,
[data-theme="dark"] #aside-content > .card-widget.card-info > #card-info-btn:hover { color: var(--on-theme) !important; }
/* 新增档位的圆点样式：主题 CSS 里没有 #matcha 这条规则（它是站点新增的档位），
   所以边框/选中态在这里补齐，配色引用上面同一份色板变量。 */
#matcha { border: 3px solid var(--color-matcha); }
#matcha:checked { box-shadow: 0 0 0 2px #fff inset; border-radius: 50%; border: 3px solid var(--color-matcha); background-color: var(--color-matcha); }
/* 主题色：24px 可见圆环 / 44px 热区；按面板宽度换行，不依赖屏幕宽度。 */
.settings .content.colorRow { display:flex; flex-wrap:wrap; justify-content:flex-start; align-items:center; gap:4px 2px; padding:4px 0 0 8px; margin:0; }
.settings .colorRow .theme-choice { position:relative; display:inline-flex; align-items:center; justify-content:center; flex:0 0 44px; width:44px; height:44px; border-radius:50%; cursor:pointer; }
.settings .colorRow .theme-choice input[name="colors"] { box-sizing:border-box; flex:none; min-width:24px; width:24px; height:24px; margin:0; padding:0; border-width:3px; cursor:pointer; transition:transform .18s ease; }
.settings .colorRow .theme-choice:hover input[name="colors"],.settings .theme-custom:hover .theme-rainbow { transform:scale(1.08); }
.settings .colorRow .theme-choice input:focus-visible { outline:2px solid currentColor; outline-offset:5px; }
.settings .colorRow .theme-custom { margin-left:6px; }
.settings .theme-rainbow { display:block; position:relative; width:24px; height:24px; flex:none; border-radius:50%; background:conic-gradient(var(--color-red),var(--color-orange),var(--color-yellow),var(--color-matcha),var(--color-puregreen),var(--color-green),var(--color-blue),var(--color-darkblue),var(--color-heoblue),var(--color-purepurple),var(--color-pink),var(--color-red)); transition:transform .18s ease; }
.settings .theme-rainbow::before { content:""; position:absolute; inset:3px; border-radius:50%; background:#f5f5f5; }
[data-theme="dark"] .settings .theme-rainbow::before { background:#333; }
.settings .theme-rainbow::after { content:""; position:absolute; inset:7px; border-radius:50%; background:var(--custom-theme-color,#c74bd0); opacity:0; }
.settings .theme-custom.is-selected .theme-rainbow::after { opacity:1; }
.settings .colorRow .theme-custom input[type="color"] { position:absolute; inset:0; box-sizing:border-box; width:44px; height:44px; margin:0; padding:0; border:0; opacity:0; cursor:pointer; }
.settings .colorRow .theme-custom:has(input:focus-visible) { outline:2px solid currentColor; outline-offset:0; }
.settings .theme-color-hint { margin:8px 12px 22px; font-size:.75em; line-height:1.7; opacity:.8; }
@media(prefers-reduced-motion:reduce) { .settings .theme-rainbow,.settings .colorRow .theme-choice input[name="colors"] { transition:none; } }

/* 字体/背景预览：站点模块专用，保持首屏字体和壁纸默认策略。 */
.settings .ap-panel { --ap-border:rgba(40,55,65,.16); --ap-surface:rgba(255,255,255,.52); --ap-soft:rgba(255,255,255,.32); margin:12px 0 24px; padding:20px; border:1px solid var(--ap-border); border-radius:16px; min-width:0; }
[data-theme="dark"] .settings .ap-panel { --ap-border:rgba(255,255,255,.16); --ap-surface:rgba(255,255,255,.055); --ap-soft:rgba(255,255,255,.025); }
.settings .ap-section-head { display:flex; justify-content:space-between; align-items:flex-start; gap:16px; margin-bottom:16px; }
.settings .ap-eyebrow { font-weight:700; margin:0 0 4px!important; font-size:1.05em; }
.settings .ap-hint,.settings .ap-bg-meta { margin:4px 0 12px!important; opacity:.78; font-size:.85em; line-height:1.7; overflow-wrap:anywhere; }
.settings #article-container .ap-subtitle { margin:18px 0 10px; padding:0; font-size:1.05em; font-weight:600; }
.settings #article-container .ap-subtitle::before { display:none; }
.settings .ap-btn,.settings .ap-font-option,.settings .ap-bg-option { font:inherit; color:inherit; background:var(--ap-surface); border:1px solid var(--ap-border); border-radius:10px; box-shadow:none; cursor:pointer; transition:border-color .16s,background-color .16s; }
.settings .ap-btn { min-height:44px; padding:8px 14px; line-height:1.5; flex-shrink:0; }
.settings .ap-btn:hover,.settings .ap-font-option:hover,.settings .ap-bg-option:hover { border-color:var(--theme-color); }
.settings .ap-btn:focus-visible,.settings .ap-font-option:focus-visible,.settings .ap-bg-option:focus-visible,.settings .ap-details>summary:focus-visible,.settings .ap-bg-advanced>summary:focus-visible,.settings #pic-link:focus-visible { outline:2px solid var(--theme-color); outline-offset:3px; }
.settings .ap-btn:disabled { opacity:.45; cursor:not-allowed; }
.settings #swfs,.settings #swfs_code,.settings .ap-font-grid { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:10px; }
.settings .ap-font-option { position:relative; min-height:72px; padding:12px 32px 12px 14px; text-align:left; min-width:0; }
.settings .ap-font-name { display:block; font-weight:600; line-height:1.5; overflow-wrap:anywhere; }
.settings .ap-font-option small { display:block; margin-top:4px; opacity:.78; font-size:.78em; line-height:1.6; }
.settings .ap-check { position:absolute; right:12px; top:12px; color:var(--theme-color); display:none; }
.settings .ap-font-option[aria-pressed="true"],.settings .ap-bg-option[aria-pressed="true"],.settings .ap-tabs .ap-btn[aria-pressed="true"] { border-color:var(--theme-color); background:color-mix(in srgb,var(--theme-color) 12%,var(--ap-surface)); box-shadow:inset 0 0 0 1px var(--theme-color); }
.settings .ap-font-option[aria-pressed="true"] .ap-check { display:block; }
.settings .ap-preview { margin-top:16px; padding:16px 18px; border:1px solid var(--ap-border); border-radius:12px; background:var(--ap-soft); min-width:0; }
.settings .ap-current { margin:0 0 10px!important; font-size:.8em; opacity:.78; font-family:system-ui,sans-serif; }
.settings .ap-text-sample { font-size:18px; line-height:1.85; margin:0!important; overflow-wrap:anywhere; }
.settings #article-container .ap-code-sample { margin:0; padding:0; background:transparent; color:inherit; font-size:14px; line-height:1.8; white-space:pre-wrap; overflow-wrap:anywhere; border-radius:0; }
.settings .ap-status { min-height:1.7em; margin:10px 0 0!important; font-size:.8em; line-height:1.7; opacity:.82; overflow-wrap:anywhere; }
.settings .ap-status[data-state="error"] { opacity:1; font-weight:600; }
.settings .ap-details,.settings .ap-bg-advanced { margin:14px 0; border-top:1px solid var(--ap-border); }
.settings .ap-details>summary,.settings .ap-bg-advanced>summary { min-height:44px; line-height:1.6; padding:12px 0; cursor:pointer; font-size:.88em; }
.settings .ap-license { margin-bottom:0; }
.settings .ap-bg-current { display:grid; grid-template-columns:150px minmax(0,1fr); align-items:center; gap:12px 18px; margin-bottom:10px; }
.settings .ap-bg-current>.ap-btn { grid-column:2; justify-self:start; }
.settings .ap-bg-thumb { margin:0!important; display:block; width:100%; aspect-ratio:16/9; object-fit:cover; border-radius:8px; background:var(--ap-soft); }
.settings .ap-bg-current>.ap-bg-thumb { grid-row:span 2; position:relative; overflow:hidden; }
.settings .ap-bg-current>.ap-bg-thumb img { width:100%; height:100%; object-fit:cover; }
.settings .ap-bg-placeholder { border:1px dashed var(--ap-border); }
.settings .ap-bg-name { display:block; line-height:1.55; font-size:.9em; overflow-wrap:anywhere; }
.settings .ap-tabs,.settings .ap-bg-actions { display:flex; flex-wrap:wrap; gap:8px; margin:14px 0; }
.settings .ap-tabs .ap-btn { flex:0 1 auto; }
.settings .ap-bg-grid { display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:12px; margin:14px 0; }
.settings .ap-panel [hidden] { display:none!important; }
.settings .ap-bg-option { position:relative; overflow:hidden; min-width:0; padding:6px; text-align:left; }
.settings .ap-bg-option .ap-bg-name { padding:6px 3px 2px; }
.settings .ap-bg-option .ap-bg-meta { padding:0 3px; margin:0 0 3px!important; font-size:.72em; }
.settings #ap-bg-category-mobile .ap-bg-thumb { aspect-ratio:3/4; }
.settings .ap-bg-check { position:absolute; top:12px; right:12px; display:grid; place-items:center; width:24px; height:24px; background:var(--theme-color); color:var(--on-theme); border-radius:50%; box-shadow:0 1px 5px rgba(0,0,0,.2); }
.settings .ap-bg-swatch { min-height:54px; }
.settings #define_colors { box-sizing:border-box; width:72px; height:44px; margin:0 0 8px; vertical-align:middle; border:1px solid var(--ap-border); border-radius:8px; cursor:pointer; }
.settings #pic-link { box-sizing:border-box; width:100%; min-height:44px; padding:10px 12px; margin:8px 0 0; border:1px solid var(--ap-border); border-radius:10px; background:var(--ap-surface); color:inherit; font:inherit; font-size:.85em; }
.settings #ap-bg-custom-preview { width:100%; max-height:230px; position:relative; overflow:hidden; margin-top:12px; }
.settings #ap-bg-custom-preview img { width:100%; height:100%; max-height:230px; object-fit:contain; }
@container(max-width:560px) { .settings .ap-panel { padding:14px; } .settings #swfs,.settings #swfs_code,.settings .ap-font-grid { grid-template-columns:minmax(0,1fr); } .settings .ap-bg-grid { grid-template-columns:repeat(2,minmax(0,1fr)); } .settings .ap-section-head { flex-direction:column; gap:8px; } .settings .ap-bg-current { grid-template-columns:100px minmax(0,1fr); } .settings .ap-bg-current>.ap-btn { grid-column:1 / -1; } }
@media(max-width:600px) { .settings .ap-panel { padding:14px; } .settings #swfs,.settings #swfs_code,.settings .ap-font-grid { grid-template-columns:minmax(0,1fr); } .settings .ap-bg-grid { grid-template-columns:repeat(2,minmax(0,1fr)); } .settings .ap-section-head { flex-direction:column; gap:8px; } .settings .ap-bg-current { grid-template-columns:100px minmax(0,1fr); } .settings .ap-bg-current>.ap-btn { grid-column:1 / -1; } }
@media(prefers-reduced-motion:reduce) { .settings .ap-btn,.settings .ap-font-option,.settings .ap-bg-option { transition:none; } }

/* 萤火虫微光：只在下方背景层漂浮，位于正文/弹窗之后，不拦截点击。 */
#fireflies-stage {
  position:fixed; left:0; right:0; bottom:0;
  height:44vh; min-height:180px; max-height:440px;
  z-index:-1; overflow:hidden; pointer-events:none; user-select:none;
  contain:layout paint; margin:0; padding:0;
}
#fireflies-stage[hidden] { display:none!important; }
#fireflies-stage .ff-mote {
  position:absolute; display:block; width:34px; height:34px;
  margin:0; padding:0; pointer-events:none;
  animation:ff-drift var(--ff-drift-time) ease-in-out var(--ff-delay) infinite alternate;
}
#fireflies-stage .ff-glow {
  position:relative; display:block; width:100%; height:100%; border-radius:50%;
  background:radial-gradient(circle,rgba(var(--ff-color),.5) 0,rgba(var(--ff-color),.16) 20%,rgba(var(--ff-color),0) 70%);
  animation:ff-breathe var(--ff-breathe-time) ease-in-out var(--ff-delay) infinite;
}
#fireflies-stage .ff-glow::after {
  content:''; position:absolute; left:50%; top:50%; transform:translate(-50%,-50%);
  width:var(--ff-size); height:var(--ff-size); border-radius:50%;
  background:rgb(var(--ff-color)); box-shadow:0 0 6px 1px rgba(var(--ff-color),.65);
}
#fireflies-stage[data-paused="true"] .ff-mote,
#fireflies-stage[data-paused="true"] .ff-glow { animation-play-state:paused!important; }
@keyframes ff-drift {
  0% { transform:translate(-12px,10px); }
  45% { transform:translate(8px,-14px); }
  100% { transform:translate(22px,-32px); }
}
@keyframes ff-breathe {
  0%,100% { opacity:.18; }
  45% { opacity:.95; }
  70% { opacity:.5; }
}
@media(prefers-reduced-motion:reduce) {
  #fireflies-stage { display:none!important; }
  #fireflies-stage .ff-mote,#fireflies-stage .ff-glow { animation:none!important; }
  #snow { display:none!important; }
}

/* ── 16/16  #searchPanelUX  ← 2026-10-11 新增（搜索加载提示位置修正 + 搜索历史） ── */
/* 配套 JS：source/js/inject/search-lazy.js（inject.bottom 里带 ?v=20261011）。
   加载提示 .search-lazy-tip 由 JS 插在 #algolia-search-results 的首位（即 #algolia-hits 的前一个兄弟）：
   这样 hits 组件整块替换自己容器的内容时不会连带删掉它，也避开了 #algolia-hits > div 的滚动条样式。 */
#algolia-search-results > .search-lazy-tip { padding: 22px 0 26px; text-align: center; font-size: 14px; opacity: .6; }
#algolia-search-results > .search-lazy-tip i { margin-right: 6px; }

/* 搜索历史：插在 #algolia-search-input 之后（.search-wrap 内），随面板一起显隐。
   显隐由 JS 控制 hidden 属性（没有记录 / 已发起搜索 / 输入框里有内容时收起）。 */
.search-history { margin: 0 0 4px; }
.search-history[hidden] { display: none !important; }
.search-history-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 6px; font-size: 13px; opacity: .72; }
.search-history-title i { margin-right: 5px; }
.search-history-clear { padding: 2px 6px; border: 0; border-radius: 6px; background: none; color: inherit; font-size: 12px; line-height: 1.4; cursor: pointer; transition: opacity .2s, background .2s; }
.search-history-clear:hover { background: rgba(0,0,0,.06); opacity: 1; }
.search-history-list { display: flex; flex-wrap: wrap; gap: 6px; max-height: 56px; overflow-y: auto; }
.search-history-item { display: inline-flex; align-items: center; gap: 4px; max-width: 100%; padding: 3px 8px; border-radius: 999px; background: rgba(0,0,0,.05); font-size: 12px; line-height: 1.5; cursor: pointer; transition: background .2s; }
.search-history-item:hover { background: rgba(0,0,0,.09); }
.search-history-text { max-width: 180px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.search-history-del { font-size: 11px; opacity: .45; transition: opacity .2s, color .2s; }
.search-history-del:hover { opacity: 1; color: #f56c6c; }

[data-theme="dark"] .search-history-item { background: rgba(255,255,255,.08); }
[data-theme="dark"] .search-history-item:hover { background: rgba(255,255,255,.14); }
[data-theme="dark"] .search-history-clear:hover { background: rgba(255,255,255,.1); }

/* 桌面端面板是「内容撑高 + top:10%」，而 #algolia-hits > div 的 max-height 按 80vh-240px 算，
   历史条最多再占约 90px。这里在历史可见时把结果区收窄 100px，避免面板顶出视口底部；
   @supports 兜底：不认识 :has() 的浏览器直接忽略这条，退回原样（不会比现在更差）。 */
@supports selector(:has(*)) {
  #algolia-search .search-wrap:has(.search-history:not([hidden])) #algolia-hits > div { max-height: calc(80vh - 340px); }
}

/* ── 17/17  #darkModeSpeed  ← 2026-10-11 新增（昼夜切换动画提速：整屏遮挡 ~3s → ~1.5s） ── */
/* 主题 _layout/sun_moon.styl 里天空交叉淡化 2s、星球转一圈 2s，太阳月亮互换是硬切；这里覆盖掉这些时长。
   数字与 source/js/modules/shell.js 的 NIGHT_SKY_FADE_MS / NIGHT_PLANET_MS / NIGHT_ICON_MS 对齐，改一边记得改另一边。
   本文件在 /css/index.css 之后加载，同特异性后加载者胜；这里仍加 !important，是为了以后主题换选择器或
   给元素加内联样式时不至于失效（这块就是专门用来盖主题值的）。 */
.Cuteen_DarkSky:before { transition: .75s ease all !important; }
.Cuteen_DarkPlanet { animation-duration: 1s !important; -webkit-animation-duration: 1s !important; }
.Cuteen_DarkSky #sun, .Cuteen_DarkSky #moon { transition: opacity .4s ease !important; }

/* 系统开了「减少动态效果」时不要动画（JS 侧已经不会插遮罩了，这里是兜底） */
@media (prefers-reduced-motion: reduce) {
  .Cuteen_DarkSky:before { transition: none !important; }
  .Cuteen_DarkPlanet { animation: none !important; }
  .Cuteen_DarkSky #sun, .Cuteen_DarkSky #moon { transition: none !important; }
}
/* ── 18/18  #darkModeStage  ← 2026-10-11 新增（昼夜切换「黄昏落幕」：三拍剧本 + 圆形揭幕；「轻」档仍走第 17 块的老转盘）──
   与 source/js/modules/shell.js 的 DM_* 常量一一对应，两边要一起改：
     DM_BEAT1_MS 450（日落/日出） → DM_BEAT2_MS 450（暮色 + 第一批星） → DM_BEAT3_MS 600（星夜 + 揭幕，合计 1500）
     DM_REVEAL_AT_MS 1150 起揭幕  DM_REVEAL_MS 350 揭完  转昼整体 ×0.8（--dm-k: .8 → 1200ms）
   视线层次（DOM 顺序，从下到上）：夜空 → 夜色层 → 暮色 → 星星 → 太阳 → 月亮 → 云 → 远山 → 山脚辉光 → 流星
   只动 opacity / transform / mask；没有 canvas、没有 rAF；手机 ≤600px 由 shell.js 把星星减半、这里把云关掉 */
@property --dm-r { syntax: '<length>'; inherits: false; initial-value: 0px; }

.dm-stage { position: fixed; inset: 0; z-index: 88888890; overflow: hidden; pointer-events: none;
  --dm-x: 50%; --dm-y: 42%; --dm-r: 0px; --dm-k: 1;
  -webkit-mask-image: radial-gradient(circle var(--dm-r) at var(--dm-x) var(--dm-y), transparent 99%, #000 100%);
          mask-image: radial-gradient(circle var(--dm-r) at var(--dm-x) var(--dm-y), transparent 99%, #000 100%);
  transition: --dm-r 350ms cubic-bezier(.22,.61,.36,1), opacity 140ms linear 210ms; }
.dm-stage[data-to="light"] { --dm-k: .8; }
.dm-stage.is-reveal { --dm-r: 160vmax; opacity: 0; }

/* ① 天空：底子（暖橙→紫） + 夜色层（慢慢吃掉） + 暮色层（中间站，先亮后灭） */
.dm-stage .dm-sky, .dm-stage .dm-dusk, .dm-stage .dm-stars { position: absolute; inset: 0; }
.dm-stage .dm-sky { background: linear-gradient(to top, #ffb26b 0%, #ef7d67 26%, #6d4b90 62%, #241f45 100%); }
.dm-stage .dm-sky::after { content: ''; position: absolute; inset: 0; opacity: 0;
  background: linear-gradient(to top, #0b1030 0%, #16244f 34%, #2b3a6b 62%, #4a3567 100%);
  animation: dm-night-fall calc(1100ms * var(--dm-k)) ease-in forwards; }
.dm-stage .dm-dusk { opacity: 0;
  background: linear-gradient(to top, #ffb26b 0%, #d4588f 42%, #4b2a6b 78%, #1a1638 100%);
  animation: dm-dusk-glow calc(900ms * var(--dm-k)) ease-out forwards; }
@keyframes dm-night-fall { 0% { opacity: 0 } 45% { opacity: .45 } 100% { opacity: 1 } }
@keyframes dm-dusk-glow { 0% { opacity: 0 } 32% { opacity: .9 } 100% { opacity: 0 } }

/* ② 太阳 / 月亮：同一条弧线，一个下去另一个上来；月亮带环形山 */
.dm-stage .dm-sun, .dm-stage .dm-moon { position: absolute; left: 50%; top: 34%; width: 92px; height: 92px; margin: -46px 0 0 -46px; border-radius: 50%; }
.dm-stage .dm-sun { background: radial-gradient(circle at 38% 34%, #fff7cf 0 16%, #ffe07a 44%, #ffb43d 76%, #f08a1e 100%);
  box-shadow: 0 0 60px 18px rgba(255,190,90,.45), 0 0 150px 44px rgba(255,150,60,.16);
  animation: dm-sun-set calc(950ms * var(--dm-k)) cubic-bezier(.4,.1,.3,1) forwards; }
@keyframes dm-sun-set { 0% { opacity: 1; transform: translate3d(0,-14px,0) scale(1) } 55% { opacity: .92; transform: translate3d(-18px,52px,0) scale(.96) } 100% { opacity: 0; transform: translate3d(-34px,168px,0) scale(.8) } }
.dm-stage .dm-moon { opacity: 0; background: radial-gradient(circle at 34% 30%, #fff 0 30%, #e9eefc 62%, #c3ccdf 100%);
  box-shadow: 0 0 44px 10px rgba(206,224,255,.35), inset -14px -10px 26px rgba(150,163,190,.35);
  animation: dm-moon-rise calc(950ms * var(--dm-k)) cubic-bezier(.4,.1,.3,1) forwards; }
@keyframes dm-moon-rise { 0% { opacity: 0; transform: translate3d(64px,150px,0) scale(.78) } 42% { opacity: .9 } 100% { opacity: 1; transform: translate3d(0,0,0) scale(1) } }
/* 转昼时反过来：月亮沉下去、太阳升上来（两端的帧与上面互为倒放，接得上） */
.dm-stage[data-to="light"] .dm-sun { opacity: 0; animation-name: dm-sun-rise; }
.dm-stage[data-to="light"] .dm-moon { opacity: 1; animation-name: dm-moon-set; }
@keyframes dm-sun-rise { 0% { opacity: 0; transform: translate3d(-34px,168px,0) scale(.8) } 45% { opacity: .9 } 100% { opacity: 1; transform: translate3d(0,-14px,0) scale(1) } }
@keyframes dm-moon-set { 0% { opacity: 1; transform: translate3d(0,0,0) scale(1) } 55% { opacity: .85 } 100% { opacity: 0; transform: translate3d(64px,150px,0) scale(.78) } }
.dm-stage .dm-moon::after { content: ''; position: absolute; inset: 0; border-radius: 50%;
  background: radial-gradient(circle at 66% 34%, rgba(148,161,188,.5) 0 11%, transparent 12%),
              radial-gradient(circle at 40% 62%, rgba(148,161,188,.42) 0 8%, transparent 9%),
              radial-gradient(circle at 71% 69%, rgba(148,161,188,.36) 0 6%, transparent 7%); }

/* ③ 星星：两批亮（第一批在暮色里先冒头，剩下的在第三拍铺满），之后轻轻闪 */
.dm-stage .dm-star { position: absolute; left: var(--dm-sx,50%); top: var(--dm-sy,30%); width: var(--dm-ss,2px); height: var(--dm-ss,2px);
  border-radius: 50%; background: #fff; opacity: 0; box-shadow: 0 0 7px rgba(214,232,255,.92);
  animation: dm-star-in calc(900ms * var(--dm-k)) ease-out calc(var(--dm-sd,0ms) * var(--dm-k)) forwards,
             dm-star-flicker calc(1400ms * var(--dm-k)) ease-in-out calc((var(--dm-sd,0ms) + 700ms) * var(--dm-k)) infinite alternate; }
@keyframes dm-star-in { 0% { opacity: 0; transform: translate3d(0,5px,0) scale(.5) } 55% { opacity: 1; transform: translate3d(0,0,0) scale(1) } 100% { opacity: var(--dm-so,.95); transform: translate3d(0,0,0) scale(1) } }
@keyframes dm-star-flicker { 0% { opacity: var(--dm-so,.95) } 100% { opacity: .55 } }

/* ④ 云（只有华丽档）：掠过日月时短暂遮一下再让开 */
.dm-stage[data-tier="standard"] .dm-clouds { display: none; }
.dm-stage .dm-clouds { position: absolute; inset: 0; }
.dm-stage .dm-clouds i { position: absolute; display: block; border-radius: 50%; filter: blur(9px); opacity: 0; background: radial-gradient(58% 100% at 50% 62%, rgba(255,238,218,.9) 0 44%, rgba(248,222,208,.5) 64%, transparent 100%); box-shadow: 7vw 1.1vw 0 -1.7vw rgba(255,238,218,.55), -6.5vw 1.5vw 0 -2.1vw rgba(246,220,206,.45); }
  background: radial-gradient(60% 60% at 40% 45%, rgba(255,255,255,.55), rgba(215,225,255,.18) 70%, transparent 72%); }
.dm-stage .dm-clouds i:nth-child(1) { left: -14%; top: 44%; width: 34vw; height: 9vw; animation: dm-cloud-a calc(1500ms * var(--dm-k)) linear calc(120ms * var(--dm-k)) forwards; }
.dm-stage .dm-clouds i:nth-child(2) { right: -16%; top: 26%; width: 26vw; height: 7vw; animation: dm-cloud-b calc(1600ms * var(--dm-k)) linear calc(60ms * var(--dm-k)) forwards; }
@keyframes dm-cloud-a { 0% { opacity: 0; transform: translate3d(0,0,0) } 25% { opacity: .85 } 100% { opacity: 0; transform: translate3d(58vw,10px,0) } }
@keyframes dm-cloud-b { 0% { opacity: 0; transform: translate3d(0,0,0) } 30% { opacity: .7 } 100% { opacity: 0; transform: translate3d(-48vw,-6px,0) } }

/* ⑤ 远山剪影 + 山脚辉光：有了地平线，日月才有「落下去 / 升起来」的参照 */
.dm-stage .dm-horizon { position: absolute; left: 0; right: 0; bottom: 0; height: 34%; background-repeat: no-repeat; background-position: bottom center; background-size: 100% 100%;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1440 200' preserveAspectRatio='none'><path fill='%230d1226' d='M0 200V152l126-24 132 30 138-44 148 36 140-30 152 34 158-26 150 32 152-20 144 24V200Z'/></svg>"); }
.dm-stage .dm-horizon::after { content: ''; position: absolute; inset: 0; opacity: .62; background-repeat: no-repeat; background-position: bottom center; background-size: 100% 100%;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1440 200' preserveAspectRatio='none'><path fill='%23272c52' d='M0 200V116l150-34 132 44 156-62 138 48 152-66 152 56 160-38 142 46 158-28 100 22V200Z'/></svg>"); }
.dm-stage .dm-glow { position: absolute; left: 0; right: 0; bottom: 0; height: 46%; opacity: 0;
  background: radial-gradient(70% 100% at 50% 108%, rgba(255,176,94,.72) 0 22%, rgba(255,120,80,.26) 46%, transparent 72%);
  animation: dm-glow-pulse calc(1000ms * var(--dm-k)) ease-out calc(60ms * var(--dm-k)) forwards; }
@keyframes dm-glow-pulse { 0% { opacity: .12 } 34% { opacity: .95 } 100% { opacity: .1 } }

/* ⑥ 流星：标准档一颗；华丽档 ::after 再来一颗（转昼不放，免得「天亮还掉流星」） */
.dm-stage[data-to="light"] .dm-meteor { display: none; }
.dm-stage .dm-meteor { position: absolute; left: 66%; top: 14%; width: 190px; height: 2px; border-radius: 2px; opacity: 0; transform-origin: right center;
  background: linear-gradient(90deg, rgba(255,255,255,0) 0%, rgba(214,232,255,.25) 45%, #fff 100%);
  filter: drop-shadow(0 0 6px rgba(206,228,255,.9));
  animation: dm-meteor-run calc(720ms * var(--dm-k)) cubic-bezier(.35,.5,.5,1) calc(940ms * var(--dm-k)) forwards; }
@keyframes dm-meteor-run { 0% { opacity: 0; transform: rotate(-20deg) translate3d(0,0,0) scaleX(.25) } 14% { opacity: 1 } 62% { opacity: 1 } 100% { opacity: 0; transform: rotate(-20deg) translate3d(-340px,120px,0) scaleX(1) } }
.dm-stage[data-tier="flourish"] .dm-meteor::after { content: ''; position: absolute; left: -30%; top: 38%; width: 140px; height: 2px; border-radius: 2px; opacity: 0;
  background: linear-gradient(90deg, rgba(255,255,255,0) 0%, rgba(214,232,255,.25) 45%, #fff 100%);
  animation: dm-meteor-run calc(720ms * var(--dm-k)) cubic-bezier(.35,.5,.5,1) calc(1180ms * var(--dm-k)) forwards; }

/* ⑦ 设置面板里的档位下拉：跟 feature-opt 的排版对齐 */
/* ⑦′ 昼夜档位：四个胶囊按钮 + 一句跟着变的说明（原来用下拉，选项文字会被截断、也看不出能点） */
.settings .feature-opt.dm-wide { grid-column: 1 / -1; flex-wrap: wrap; align-items: flex-start; padding: 10px 0; }
.settings .dm-seg { display: flex; flex-shrink: 0; gap: 6px; padding: 4px; border: 1px solid rgba(128,128,128,.22); border-radius: 999px; background: rgba(128,128,128,.12); }
.settings .dm-seg button { min-height: 34px; padding: 5px 14px; border: 1px solid transparent; border-radius: 999px; background: transparent; color: inherit; font: inherit; font-size: .84em; font-weight: 600; line-height: 1; cursor: pointer; transition: background .18s, color .18s, border-color .18s, box-shadow .18s; }
.settings .dm-seg button:hover { background: rgba(128,128,128,.18); }
.settings .dm-seg button.is-on { background: var(--theme-color); border-color: var(--theme-color); color: var(--on-theme); box-shadow: 0 2px 10px rgba(0,0,0,.14); }
.settings .dm-seg button:focus-visible { outline: 2px solid var(--theme-color); outline-offset: 3px; }
.settings .feature-opt .dm-seg-note { flex: 1 0 100%; margin: 6px 0 0; font-size: .76em; font-weight: 400; line-height: 1.6; opacity: .82; }
@media (max-width: 600px) { .settings .feature-opt.dm-wide { flex-direction: column; align-items: stretch; } .settings .dm-seg { width: 100%; } .settings .dm-seg button { flex: 1 1 0; padding: 5px 6px; } .settings .feature-opt .dm-seg-note { flex: 0 0 auto; width: 100%; } }

/* ⑧ 兜底：手机缩小日月、关掉云；系统要求减少动态就不放这块幕布 */
@media (max-width: 600px) {
  .dm-stage .dm-sun, .dm-stage .dm-moon { width: 74px; height: 74px; margin: -37px 0 0 -37px; }
  .dm-stage .dm-clouds { display: none; }
  .dm-stage .dm-horizon { height: 17%; background-position: bottom left; background-size: 150% 100%; }
  .dm-stage .dm-horizon::after { background-position: bottom left; background-size: 150% 100%; }
  .dm-stage .dm-glow { height: 22%; }
}
@media (prefers-reduced-motion: reduce) { .dm-stage { display: none !important; } }

/* ---------- 美化设置面板：标题栏三个按钮跟随自定义鼠标 ----------
 * WinBox 自带样式里写了 `.wb-control * {cursor:pointer}`，还有 `.wb-drag{cursor:move}`，
 * 优先级 (0,1,0) 比 cursor.js 注入的 `*{cursor:url(圆点)}` 高，所以面板右上角
 * 最小化/最大化/关闭会露出系统手型。这里用 (0,3,0) + !important 把标题栏和面板内容
 * 整块交还给圆点；四周的缩放边缘(.wb-n/.wb-e/…)故意不动，保留 resize 提示。
 * 鼠标特效关掉（html 上没有 beauty-cursor-on）时本段不生效。 */
html.beauty-cursor-on .winbox .wb-header,
html.beauty-cursor-on .winbox .wb-header *,
html.beauty-cursor-on .winbox .wb-body,
html.beauty-cursor-on .winbox .wb-body * { cursor: inherit !important; }

/* ---------- 去掉加密文章的「Encrypt again」按钮 ----------
 * 文章 front-matter 里有 password 时，hexo-blog-encrypt 的 /lib/hbe.js 会在解锁成功后
 * 往 #hexo-blog-encrypt 里追加一个 <button class="hbe-button">Encrypt again</button>
 * （点它会把密码从 localStorage 删掉再刷新，重新上锁）。站点不需要这个入口，直接隐藏。
 * 注意：改的是 node_modules 里插件生成的脚本，所以只能从样式层隐藏；
 * 升级插件、hexo clean 之后这条依然生效（它挂在站点样式表里，不依赖插件版本）。 */
.hbe-button { display: none !important; }

/* ---------- 表格容器别永远画滚动条 ----------
 * 主题 `_global/index.styl` 里写的是 `.table-wrap { overflow-x: scroll }`，
 * `scroll` 是「不管溢不溢出都留出滚动条」：Windows 上的 Chromium 会把 thumb 填满整条轨道，
 * 在文章正文里表现成表格底部多出一条 8px 的浅灰横线（加密文章解密后主题重复包了一层的话
 * 就是两条）。这里改成 auto —— 内容真超出宽度时照样能横向滚动，不超出就干干净净。
 * 特异性 (1,1,0) 高于主题的 (0,1,0)，且本文件在主题样式之后加载。 */
#article-container .table-wrap { overflow-x: auto; }

/* ==========================================================================
   代码块字体：把面板那 4 个选项接到本机字体上（2026-10-29 加）
   --------------------------------------------------------------------------
   现象：美化面板「代码字体」四个按钮（Monaco / Consolas / Maple Mono / Hack）点了没反应，
   代码块反而变成正文字体。原因不是按钮坏了，是这 4 个 family 名（Monaco_1 / Consolas_1 /
   MapleMono_1 / Hack_1）**全站没有任何 @font-face** —— 名字带 _1 后缀是为了和系统族名区分，
   但没有本地 face 就等于「指向一个不存在的字体」，浏览器顺着栈往后找，直接掉到 var(--global-font)。
   做法：用 local() 指到本机同名系统字体。装了就用，没装这一条自动跳过（表现与改动前一致，不会更差）。
   这些是系统字体，不占流量，所以不需要 unicode-range 分片。
   ========================================================================== */
@font-face { font-family: Monaco_1;     src: local("Monaco"), local("Menlo"); font-display: swap; }
@font-face { font-family: Consolas_1;   src: local("Consolas"); font-display: swap; }
@font-face { font-family: MapleMono_1;  src: local("Maple Mono"), local("Maple Mono NF"), local("MapleMono"); font-display: swap; }
@font-face { font-family: Hack_1;       src: local("Hack"), local("Hack Nerd Font"); font-display: swap; }

/* ==========================================================================
   美化设置面板：从右上角齿轮「弹出来 / 弹回去」（2026-10-29 加）
   --------------------------------------------------------------------------
   需求：面板原来是一帧硬切出来的（display:none → block），打开/关闭都没过程，很突兀。
   做法：整块窗口只做 transform / opacity / filter 三段过渡，起点是**齿轮按钮的中心**。
         transform-origin 由 settings.js 的 winboxSetTransformOrigin() 按「齿轮中心相对面板左上角」
         算成一对像素值写进 style（齿轮在面板右上方时值是负的，属正常），
         这样 scale(.14) 时窗口正好缩在齿轮上，看起来就是从按钮里长出来。
   类名约定（与 settings.js 一一对应，改名字两边都要改）：
     .wb-pop      刚打开时的「收起态」，transition:none，让初始状态一帧到位；
     .wb-pop-out  收起动画态，过渡更短更干脆；
     两个都不在 = 正常显示态。
   注意：Winbox 自身只用 left/top 定位，不写 transform，所以这里动 transform 不冲突。
   ========================================================================== */
#meihuaBox {
  transform-origin: 100% 0; /* JS 算不出齿轮位置时的兜底：右上角 */
  /* 起手别太快：曲线前段压平一点，前 100ms 还看得出「从齿轮里往外长」，
     末尾 y2=1.03 留一点点过冲，就是「弹」的那一下 */
  transition: transform 0.5s cubic-bezier(0.34, 0.06, 0.22, 1.03),
    opacity 0.3s ease-out, filter 0.3s ease-out;
}
#meihuaBox.wb-pop {
  transform: scale(0.14);
  opacity: 0;
  filter: blur(7px);
  transition: none !important;
}
#meihuaBox.wb-pop-out {
  transform: scale(0.1);
  opacity: 0;
  filter: blur(7px);
  transition: transform 0.3s cubic-bezier(0.4, 0.05, 0.6, 0.5), opacity 0.24s ease-in,
    filter 0.24s ease-in;
}
/* will-change 只在这两帧期间挂：常驻会让整块面板常驻合成层，正文容易失去次像素抗锯齿、发虚 */
#meihuaBox.wb-pop,
#meihuaBox.wb-pop-out {
  will-change: transform, opacity;
}
/* --------------------------------------------------------------------------
   最小化标题条（.winbox.min，2026-10-29）
   需求：点「—」不要把面板扔到左下角，要收到右上角齿轮按钮的正下方。
   位置（left/top/width/height）由 settings.js 的 dockWinboxMin() 按齿轮实测矩形写内联，
   这里只管观感和过渡：
     · 过渡写在这条 .min 规则上 —— Winbox 内部是先改尺寸再 addClass("min")，同一帧内完成，
       但过渡归属看「变更后的样式」，所以依旧会从面板原位置滑到齿轮下方；
     · 标题条里只留标题文字，✕ / 最大化键藏掉（点标题条本体就是还原，别再给两个会打架的按钮）；
     · 手型光标 + 顶部圆角，看着像一张「收起来的卡片」。
   -------------------------------------------------------------------------- */
#meihuaBox.min {
  transition: left 0.36s cubic-bezier(0.3, 1, 0.28, 1), top 0.36s cubic-bezier(0.3, 1, 0.28, 1),
    width 0.36s cubic-bezier(0.3, 1, 0.28, 1), height 0.36s cubic-bezier(0.3, 1, 0.28, 1);
  opacity: 1;
  filter: none;
  transform: none;
  cursor: pointer;
  overflow: hidden;
}
#meihuaBox.min .wb-close,
#meihuaBox.min .wb-max,
#meihuaBox.min .wb-full {
  display: none !important;
}
/* 缩成标题条的过程中把面板内容藏掉。
   这里不能用 display:none：设置页根节点带内联 display:block，Winbox 自带的
   .winbox.min .wb-body>*{display:none} 根本盖不住它；而且 display:none 会让 .wb-body
   的 scrollHeight 归零、滚动位置被夹到 0，还原后又会跳回顶部。
   用 visibility:hidden 恰好：不画内容、布局还在、滚动位置原样保留。 */
#meihuaBox.min .wb-body > * {
  visibility: hidden !important;
}
/* 缩的过程中别露出那块灰白底板，只留一条和标题栏同色的条在飞，视觉上更像「收起来了」 */
#meihuaBox.min .wb-body {
  background: transparent !important;
}
#meihuaBox.min .wb-header,
#meihuaBox.min .wb-drag {
  cursor: pointer;
}
#meihuaBox.min .wb-drag {
  padding-left: 0;
  padding-right: 0;
  text-align: center;
}
#meihuaBox.min .wb-header .wb-title {
  font-size: 13.5px;
  letter-spacing: 0.5px;
}
/* 尊重系统「减少动态效果」：只留一个淡入淡出 */
@media (prefers-reduced-motion: reduce) {
  #meihuaBox,
  #meihuaBox.wb-pop,
  #meihuaBox.wb-pop-out {
    transition: opacity 0.2s ease !important;
    transform: none !important;
    filter: none !important;
  }
}

/* 音乐馆页头站名的静态辉光（10-30，纯装饰，不依赖音频数据） */
#page-site-info #site-title {
  text-shadow: 0 2px 20px color-mix(in srgb, var(--theme-color, #ff1493) 45%, transparent);
}

/* ============================================================================
   全站宽度改造（10-30，第十九版）
   作者要求：
     ①「把全站的页面都改的像这么大（音乐馆这么宽）」
     ②「左边可以以文章的最左边来确定距离，但是右边不可以以文章页面定距离了，
        要以目录的最右边来定距离」—— 两条红线间距 20px，目录尺寸不动
     ③ 音乐馆页：左右留白相等（右边到菜单按钮的距离保持，左边改成一样），整体改小一点

   已知上游事实（量过，别猜）：
     · 主题 `.layout`（_page/common.styl）：display:flex; max-width:1200px; padding:40px 15px
       → 站点自定义 CSS 又把它改成 max-width:1400px（_custom/custom.css:1033）
     · 主题 `.layout > div:first-child`（文章列）：width:74%
       → 站点 ≥1200px 时改成 flex:1 1 auto; width:auto（site-inject 第 4/12 块）
     · `#aside-content`（右侧目录）：width:26%，站点 ≥1200px 时固定 340px
     · 右侧悬浮工具条 #rightside：position:fixed，按钮 38px，右边缘 ≈ 窗口右 −48px
       → 内容必须在它左边收住（site-inject 第 4/12 块已经把 .layout 右内边距加大到 78px）
     · 音乐馆页（.mp-page）此前是 body:has() 单独把 .layout 撑到 max-width:none，
       左右内边距 124px / 96px —— 这一版按作者要求改成两边相等并整体收窄。

   这里的做法：
     · 全站 .layout 上限 1400 → 1560px（窗口不够宽时自然回落到 100%）
     · 文章页：文章列吃掉剩余空间，右边缘 = 目录左边缘；
       目录右边缘到窗口右边留 20px（作者的两条红线间距）
     · 音乐馆页：左右内边距统一 96px，并给一个比全站略小的上限（作者说"改小一点"）
   ========================================================================== */

/* ── 全站统一（10-30 第二十一版，取代第十九版的固定 20/68 方案）────────────
   作者原话：「现在把全站的全部页面都按照这个距离来修改 主页给我恢复以前的样子
             其他全站的页面全部照这个音乐馆的页面修改
             现在的窗口比如说是1600 那么两边都是165
             其他的页面全部按照这个百分比来定」
   即：除首页外，所有页面的左右留白都用音乐馆那套比例公式：
       padding-left  = calc(10.3125vw + 21px)
       padding-right = calc(10.3125vw + 7px)
   （10.3125vw = 165px / 1600 视口；两个固定补偿来自胶囊 left:10/宽52 与
     工具条 right:48，推导见下方音乐馆块。）
   首页 #body-wrap.home 单独恢复成老样子（见再下面一块）。 */
@media screen and (min-width: 861px) {
  #body-wrap:not(.home) .layout {
    max-width: none;
    margin-left: 0;
    margin-right: 0;
    padding-left: calc(10.3125vw + 21px);
    padding-right: calc(10.3125vw + 7px);
  }
}

/* ── 首页恢复以前的样子（10-30 第二十一版）────────────────────────────
   「以前」= 站点自定义 CSS 的设定：.layout 上限 1400px 居中（custom.css:1033），
   内边距按主题默认 40px 15px，右侧再按第 4/12 块的侧栏规则给悬浮工具条留位：
     901~1400px 视口 → padding-right 78px
     1401px 以上     → padding-right 随居中余量动态回收（最少 15px）
   首页布局是 recent-posts 卡片流，跟内容页（文章/归档/音乐馆）不是一套排版，
   所以单独恢复，不跟全站统一。 */
@media screen and (min-width: 861px) {
  #body-wrap.home .layout {
    max-width: 1400px;
    margin-left: auto;
    margin-right: auto;
    padding-left: 15px;
  }
}
@media screen and (min-width: 901px) and (max-width: 1400px) {
  #body-wrap.home .layout { padding-right: 78px; }
}
@media screen and (min-width: 1401px) {
  #body-wrap.home .layout { padding-right: max(15px, calc(78px - (100vw - 1400px) / 2)); }
}

/* --- 音乐馆页：左右留白相等，整体比全站略窄 ---
   作者原话：「右边的距离菜单按钮距离就刚刚好 我告诉你该到多大…
   比如说右边的距离菜单按钮距离是10px 那么现在就改为20px
   左边距离音乐胶囊也改为20px 两边相等 20px 我只是举例子
   实际是多少还要看你当时给我改的是多少」

   实测依据（1600 视口，tools/mpwidth.mjs 量出来的）：
     · 左：音乐胶囊 #ds-mini 固定在 left:10px、宽 52px → 右边缘 62px
       （#fps 帧率徽章也在左边，见 daily-say.css:393-396）
     · 右：悬浮工具条 #rightside 固定在 窗口右 −48px → 左边缘 1544
   「右边刚刚好」= 卡片右边缘到工具条左边缘 = 165px（改之前的实测值）。
   左边要做到一样 → 卡片左边缘 = 62（胶囊右边缘）+ 165 = 227px。

   但 .layout 是居中的（margin:0 auto），左右内边距一改，两侧留白会跟着变，
   而且「卡片左边缘到胶囊」还隔着 .layout 自身的居中余量 —— 直接写死像素会在
   窗口变宽时错位。所以这里改用「左右内边距相等 + 限制布局宽度」的做法：
   胶囊占位 62px + 工具条占位 48px = 110px 的固定悬浮物，
   两侧各留 96px 内容留白（左右完全相等），布局整体不铺满（max-width 1440px，
   比全站的 1620px 窄 —— 这就是作者说的「有点太大了，再改小一点」）。 */
@media screen and (min-width: 861px) {
  body:has(#article-container .mp-page) .layout {
    /* 改成按视口比例换算（作者 10-30 第二十版）：
       「按照现在的窗口大小和整体的页面尺寸换算成百分比来控制，
         不管窗口多大，布局的整体比例是不会变的」
       基准：1600 视口时「卡片右 → 工具条左」= 165px → 165/1600 = 10.3125vw。
       两段固定补偿来自两个**不随窗口缩放**的固定定位元素：
         左：胶囊 #ds-mini 固定 left:10px、宽 52px → 右边缘恒为 62px
         右：工具条 #rightside 固定 right:48px → 左边缘 = 视口宽 − 56px
       于是：
         距离左 = (PL + 41) − 62 = PL − 21
         距离右 = (V−56) − (V−8−PR−41) = PR − 7
       要两边相等且都 = 10.3125vw：
         PL = 10.3125vw + 21px
         PR = 10.3125vw + 7px
       实测：1000/1200/1280/1440/1600/1920 六档视口，两侧距离逐档相等。 */
    /* 音乐馆页左右留白相等，且距离不随窗口宽度漂移：
       做法是**布局铺满（不居中）** + 左右内边距直接给两个固定悬浮物的位置：
         左：胶囊 #ds-mini 固定 left:10px、宽 52px → 右边缘 62px
         右：工具条 #rightside 固定在 窗口右 −48px → 左边缘 = 100vw − 56px
       padding-left = 62 + 165 = 227px（165 = 卡片到悬浮物的距离，两边一样）
       padding-right = 56 + 165 = 221px
       「有点太大了，再改小一点」→ 加 max-width:1360px，让内容区不至于铺得太开。 */
    /* 关键：布局必须**不居中**（margin:0），否则内边距会被居中余量抵消，
       左右距离就不等于「到悬浮物的距离」了。 */
    max-width: none;
    margin-left: 0;
    margin-right: 0;
    /* 实测校准（1600 视口）：
       卡片左边缘 = padding-left + 41（#article-container 到 .mp-deck-card 卡片边还有 41px）
       卡片右边缘 = 视口宽 − padding-right − 41
       要「卡片到胶囊(右边缘 62)」= 165 → 卡片左 227 → padding-left = 227−41 = 186
       要「卡片到工具条(左边缘 1544)」= 165 → 卡片右 1379 → padding-right = 1592−41−1379 = 172 */
    padding-left: calc(10.3125vw + 21px);
    padding-right: calc(10.3125vw + 7px);
  }
}

/* ── 备选方案 B：距离绝对恒定 165px（不随窗口缩放）─────────────────────
   如果作者要的是「不管窗口多大，卡片到工具条始终差 165px」，
   把下面这段的注释去掉、同时把上面那条 padding 注释掉即可。
   公式（胶囊右恒 62、工具条左 = V−56）：
     距离左 = PL − 21 = 165  → PL = 186px
     距离右 = PR − 7  = 165  → PR = 172px
   注意：这样卡片宽度会随窗口线性变化（1000 屏 676px、1920 屏 1406px）。 */
/*
body:has(#article-container .mp-page) .layout {
  padding-left: 186px;
  padding-right: 172px;
}
*/

/* ── 天文馆页（box/astronomy）──────────────────────────────────────────
   作者 10-31 明确要求：不要动整页布局尺寸（.layout 留白/侧栏保持全站默认），
   只放大「红框那张深色卡片」本身（voyager.html 的 .wrap / iframe 画布）。
   因此这里不再 override .layout，留白/侧栏交给全站规则。
   卡片尺寸的调整写在 index.md 的 iframe 与 voyager.html 的 .wrap 上。 */

/* ── 页脚「站点运行 X 年 Y 天」（2026-10-31 新增）────────────────────────
   位置：themes/fomalhaut/layout/includes/footer.pug 的 .copyright 里，
        紧跟「©2023-2026 By chengicli」之后的 #ftRun。
   文字由 source/js/modules/footer-time.js 每秒写入（值没变就不写 DOM），规则与
   「已经和女朋友 X 天啦💞」一致：
     · 不满 1 年只显示天数：50 天 → 「50 天」，不出现「0 年」
     · 满整年省略「0 天」：正好 365 天 → 「1 年」，不是「1 年 0 天」
   数字加粗 + 主题色，和 #ftLove 的视觉语言保持一致。 */
#footer-wrap .copyright #ftRun {
  margin-left: 10px;
  font-size: 14px;
  font-variant-numeric: tabular-nums;
}
#footer-wrap .copyright #ftRun b {
  margin: 0 2px;
  color: var(--theme-color);
  font-weight: 700;
}
@media screen and (max-width: 768px) {
  #footer-wrap .copyright #ftRun {
    display: block;
    margin: 4px 0 0;
  }
}

/* ---------------------------------------------------------------------------
 * 全站禁止选中文字（避免拖拽/双击误选）。只放开：文章详情页正文、代码框、输入框、每日一言句子。
 * 判定依据：文章页有 #post，Page 类型页面（螺纹速查 / 留言板 / 友链等）是 #page，两者互斥。
 * 每日一言标题「每日一言·······悬停音乐」保持禁选，只放开 .ds-quote / .ds-from。
 * ------------------------------------------------------------------------- */
body { -webkit-user-select: none; user-select: none; }
#post #article-container,
pre,
code,
figure.highlight,
input,
textarea,
[contenteditable="true"] { -webkit-user-select: text; user-select: text; }
#daily-say .ds-quote,
#daily-say .ds-from { -webkit-user-select: text; user-select: text; }

/* Page 页面默认禁选；front-matter 写 selectable: true 时整页放开（模板 page.pug 会加 .is-selectable） */
#page.is-selectable,
#page.is-selectable * { -webkit-user-select: text; user-select: text; }
