/* 网址详情页（独立 HTML）样式 —— 第一百五十七轮
 *
 * 两段来源，刻意不手抄：
 *   ① 用户在桌面给的「网址详情页-demo.html」的 <style> —— 原样搬来，保证视觉与 demo 一致；
 *   ② renderer/styles.css 里的 .kb-md-* 段（mdLite 渲染输出所用的类）—— 详情页正文由渲染层的
 *      mdLite 渲染（含 XSS 白名单净化），而独立 HTML 拿不到全局 styles.css ⇒ 必须内联这一段，
 *      否则正文会退化成浏览器默认样式（标题没了边距、表格没了边框）。
 *
 * ⚠️ demo 的 :root 只定义了它自己用到的变量；kb-md 段还引用 --app-fs-k（应用内字号系数），
 *    独立页里不存在 ⇒ 下面补一个默认值 1（等价于 100% 字号）。
 */
:root{
  --bg:#14100c; --bg-soft:#1b1611; --panel:#211b14; --panel-hover:#2b231a;
  --border:#352c21; --text:#efe8e1; --text-dim:#ae9b86;
  --accent:#f0a63c; --accent-soft:rgba(240,166,60,.15); --accent-btn:#c8761c;
  --link:#8ab4f8; --radius:12px; --shadow:0 6px 24px rgba(0,0,0,.5);
  --mono:'Consolas','Microsoft YaHei',monospace;
}
html[data-theme="light"]{
  --bg:#fdf8ef; --bg-soft:#f7efe2; --panel:#fffdf8; --panel-hover:#faf6ef;
  --border:#ecdfc9; --text:#2e2820; --text-dim:#93826a;
  --accent:#c8761c; --accent-soft:rgba(200,118,28,.12); --accent-btn:#b8731a;
  --link:#1d4ed8; --shadow:0 6px 24px rgba(120,85,45,.13);
}
*{margin:0;padding:0;box-sizing:border-box}
body{
  background:var(--bg); color:var(--text); min-height:100vh;
  font-family:'Segoe UI','Microsoft YaHei',system-ui,-apple-system,sans-serif;
  font-size:14px; line-height:1.7;
  -webkit-font-smoothing:antialiased;
}
a{color:var(--link);text-decoration:none}
a:hover{text-decoration:underline}
.wrap{max-width:1180px;margin:0 auto;padding:0 24px}

/* 阅读进度条（第一百九十六轮改落点）
   原先贴 top:0 —— 那时本页自带一个吸顶 <header>，进度条压在它顶边。
   现在那个 <header> 已整个删除（顶栏由壳的 SiteTopNav 承担，见 renderer/src/export/ExportPageShell.vue），
   所以进度条改挂到壳顶栏的**下沿**。
   ⚠️ 不能留在 top:0：壳顶栏是半透明毛玻璃，一条亮橙线压在它的字上很难看。
   ⚠️ 不需要「吸顶时上移」这类滚动联动：.sh-topnav 未吸顶时也在 hero 的第一行、高度同为
      var(--sh-topnav-h)（styles.css 的 :root 定义，本页引了同一个样式表 ⇒ 变量可用），
      两种状态下「下沿」是同一个 y ⇒ 固定 top 就恒正确，也就不会出现滚动抖动。 */
#progress{position:fixed;top:var(--sh-topnav-h,60px);left:0;height:2px;background:var(--accent);width:0;z-index:60;transition:width .08s linear}

/* 面包屑（第一百九十六轮从吸顶 <header> 迁进正文 hero）
   原先它与「返回导航 + 主题钮」一起待在吸顶栏里，而吸顶栏整个删了。那两者都有替代者 ——
   返回/回首页由壳顶栏的品牌区与导航项承担、主题钮由壳的浮钮（SiteFloatActions）承担 ——
   但面包屑**没有替代者**：它既是访客在本页里的位置感，也是喂给爬虫的内链结构（首页 › 分类 › 本条）。
   所以只搬位置、不动语义。
   ⚠️ 刻意保持 a / b / .sep 三个子元素结构不变：详情页与分类页共用这一段样式。
   ⚠️ 这里只做「正文里的一行导航」，不再有 flex:1 / 吸顶背景那套（那是顶栏语境下的需求）。 */
.crumb{display:flex;align-items:center;gap:8px;font-size:13px;color:var(--text-dim);
  min-width:0;white-space:nowrap;overflow:hidden;margin-bottom:12px}
.crumb a{color:var(--text-dim)}
.crumb a:hover{color:var(--accent);text-decoration:none}
.crumb b{color:var(--text);font-weight:500;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.crumb .sep{opacity:.5}

/* Hero */
.hero{padding:38px 0 30px;border-bottom:1px solid var(--border)}
.hmain{display:flex;gap:36px;align-items:flex-start}
.hlogo{
  width:76px;height:76px;flex:none;border-radius:16px;background:var(--panel);
  border:1px solid var(--border);display:grid;place-items:center;overflow:hidden;
}
.hlogo img{width:52px;height:52px;object-fit:contain;display:block}
.hinfo{flex:1;min-width:0}
h1{font-size:27px;font-weight:500;letter-spacing:.2px;line-height:1.3}
.hmeta{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin-top:9px;font-size:13px;color:var(--text-dim)}
.hmeta .dot{opacity:.4}
.tag{
  display:inline-block;padding:2px 9px;border-radius:999px;font-size:12px;
  background:var(--accent-soft);color:var(--accent);border:1px solid transparent;
}
.lead{margin-top:14px;font-size:14.5px;line-height:1.85;color:var(--text);max-width:860px}
.acts{display:flex;flex-wrap:wrap;gap:10px;margin-top:20px}
.btn{
  display:inline-flex;align-items:center;gap:7px;height:38px;padding:0 18px;border-radius:10px;
  font-size:13.5px;cursor:pointer;transition:.15s;border:1px solid var(--border);
  background:var(--panel);color:var(--text);text-decoration:none;
}
.btn:hover{border-color:var(--accent);color:var(--accent);text-decoration:none}
.btn.primary{background:var(--accent-btn);border-color:var(--accent-btn);color:#fff}
.btn.primary:hover{filter:brightness(1.1);color:#fff}
.btn svg{width:15px;height:15px}
.btn.ghost{background:transparent}

/* 网站预览图（自动抓取） */
.hleft{display:flex;gap:22px;align-items:flex-start;flex:1;min-width:0}
.hprev{
  flex:0 0 366px;margin:0;position:relative;border-radius:var(--radius);overflow:hidden;
  border:1px solid var(--border);background:var(--panel);box-shadow:var(--shadow);
  transition:border-color .2s,transform .2s;
}
.hprev:hover{border-color:var(--accent);transform:translateY(-2px)}
.hprev-bar{
  display:flex;align-items:center;gap:5px;height:30px;padding:0 11px;
  background:var(--bg-soft);border-bottom:1px solid var(--border);
}
.hprev-bar i{width:8px;height:8px;border-radius:50%;background:#5a4a38;flex:none}
.hprev-bar i:nth-child(1){background:#e0705f}
.hprev-bar i:nth-child(2){background:#e0b64f}
.hprev-bar i:nth-child(3){background:#7fbf6a}
.hprev-url{
  margin-left:6px;font-size:11.5px;color:var(--text-dim);overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap;font-family:var(--mono);
}
.hprev-tag{
  margin-left:auto;flex:none;font-size:10px;letter-spacing:.4px;color:var(--accent);
  background:var(--accent-soft);padding:1px 6px;border-radius:5px;text-transform:lowercase;
}
/* 第一百七十八轮：角标如实反映图片来源 —— local = 本地物化图，remote = 第三方实时图。
   remote 刻意**不抢主色**（改用中性灰）：它不是「本站的能力」，让站长一眼能看出
   「这张是别人家的服务给的」—— 隐私与可用性都靠这一眼自证。两种主题下都成立（全走变量）。 */
.hprev-tag[data-src="remote"]{
  color:var(--text-dim);background:var(--bg-soft);border:1px solid var(--border);
}
.hprev-shot{position:relative;aspect-ratio:16/10;background:var(--bg-soft);overflow:hidden}
.hprev-shot img{
  width:100%;height:100%;object-fit:cover;object-position:top center;display:block;
  /* 默认就可见：图的可见性不依赖 JS 状态。骨架在最上层盖着，成功后 skeleton display:none 自然露出。
     早先写法是 opacity:0 由 [data-state=ok] 置 1 —— 状态没置上或过渡不推进，图就永久空白。 */
  cursor:zoom-in;transition:transform .35s ease;
}
/* 刻意不做淡入动画：骨架消失本身就是视觉切换。用 animation 起始帧做半透明，
   一旦动画不推进（渲染层不出帧）图就永久停在半透明 —— 可见性不该赌在动画上。 */
.hprev[data-state="ok"]:hover .hprev-shot img{transform:scale(1.035)}
.hprev-skel{
  position:absolute;inset:0;z-index:1;background:var(--bg-soft);
  display:grid;place-content:center;justify-items:center;gap:7px;
  padding:16px;text-align:center;color:var(--text-dim);
}
.hprev[data-state="ok"] .hprev-skel{display:none}
/* 第一百七十八轮删掉了原先这里的一条 `.hprev[data-state="fail"] .hprev-skel-s{display:none}`。
   它来自 demo：那时 fail 态的副标题只是一句凑数的占位话，藏起来更干净。
   但空态现在承载的是**唯一一条**告诉站长「怎么才能有预览图」的指引
   （书签卡片右键「抓取预览图」／分组头「批量抓图」），把它藏起来等于让用户
   看着一块空白卡片去猜 —— 实测（.workbuddy/r178-prev.cjs A7）改前 computed display=none，
   即那句文案在 DOM 里但用户一个字都看不到。失败回退（PAGE_JS#shotFailed）补的下一步同理。 */
.hprev-spin{
  width:24px;height:24px;border-radius:50%;border:2.5px solid var(--border);
  border-top-color:var(--accent);animation:hspin .8s linear infinite;
}
@keyframes hspin{to{transform:rotate(360deg)}}
.hprev-skel-t{font-size:12.5px;color:var(--text)}
.hprev-skel-s{font-size:11px;opacity:.72;line-height:1.5}
.hprev-re{
  position:absolute;z-index:2;right:9px;bottom:9px;width:30px;height:30px;border-radius:9px;
  display:grid;place-items:center;cursor:pointer;padding:0;color:#efe8e1;
  background:rgba(18,14,10,.74);border:1px solid rgba(255,255,255,.18);
  backdrop-filter:blur(6px);opacity:0;transition:opacity .18s,border-color .18s;
}
.hprev:hover .hprev-re{opacity:1}
.hprev[data-state="fail"] .hprev-re{opacity:1;transition:none}
.hprev-re:hover{border-color:var(--accent);color:var(--accent)}
.hprev-re svg{width:14px;height:14px}
.hprev-cv{position:absolute;z-index:3;left:0;bottom:0;right:0;height:2px;background:transparent}
.hprev[data-state="load"] .hprev-cv{background:var(--accent);animation:hbar 1.5s ease-in-out infinite;transform-origin:left}
@keyframes hbar{0%{transform:scaleX(.06)}50%{transform:scaleX(.72)}100%{transform:scaleX(.06)}}

/* 大图查看 */
.lightbox{
  position:fixed;inset:0;z-index:200;display:none;place-items:center;padding:40px;
  background:rgba(8,6,4,.86);backdrop-filter:blur(4px);cursor:zoom-out;
}
.lightbox.on{display:grid}
.lightbox img{
  max-width:min(1360px,92vw);max-height:88vh;border-radius:10px;
  border:1px solid var(--border);box-shadow:0 24px 70px rgba(0,0,0,.6);
}
.lightbox-cap{margin-top:14px;font-size:12.5px;color:#c9c1b7;text-align:center}

/* 两栏 */
.cols{display:grid;grid-template-columns:minmax(0,1fr) 302px;gap:34px;padding:34px 0 10px;align-items:start}
article{min-width:0}

/* 正文排版 */
.sec{padding:0 0 34px;scroll-margin-top:76px}
.sec h2{
  font-size:19px;font-weight:500;margin-bottom:14px;padding-left:12px;
  border-left:3px solid var(--accent);line-height:1.4;
}
.sec h3{font-size:15px;font-weight:500;margin:20px 0 8px;color:var(--text)}
.sec p{margin-bottom:12px;line-height:1.9}
.sec ul,.sec ol{margin:0 0 14px 20px}
.sec li{margin-bottom:7px;line-height:1.85}
.sec li::marker{color:var(--accent)}
code{
  font-family:var(--mono);font-size:12.5px;background:var(--bg-soft);
  padding:1.5px 6px;border-radius:5px;border:1px solid var(--border);color:var(--accent);
}
pre{
  background:var(--bg-soft);border:1px solid var(--border);border-radius:10px;
  padding:14px 16px;overflow-x:auto;margin:0 0 14px;
}
pre code{background:none;border:none;padding:0;font-size:12.5px;color:var(--text);line-height:1.8}
table{width:100%;border-collapse:collapse;margin:0 0 16px;font-size:13.5px}
th,td{border:1px solid var(--border);padding:9px 12px;text-align:left;vertical-align:top}
th{background:var(--bg-soft);font-weight:500;color:var(--text);white-space:nowrap}
td{color:var(--text)}
tbody tr:hover{background:var(--bg-soft)}
.note{
  background:var(--accent-soft);border-left:3px solid var(--accent);border-radius:0 8px 8px 0;
  padding:11px 14px;margin:0 0 14px;font-size:13.5px;line-height:1.8;
}
details{border:1px solid var(--border);border-radius:10px;margin-bottom:10px;background:var(--panel);overflow:hidden}
summary{
  padding:12px 16px;cursor:pointer;font-size:14px;font-weight:500;list-style:none;
  display:flex;align-items:center;justify-content:space-between;gap:10px;
}
summary::-webkit-details-marker{display:none}
summary::after{content:'+';color:var(--accent);font-size:17px;line-height:1;flex:none}
details[open] summary::after{content:'−'}
details[open] summary{border-bottom:1px solid var(--border)}
.faq-body{padding:13px 16px;font-size:13.5px;line-height:1.85;color:var(--text)}

/* Sidebar */
aside{position:sticky;top:74px;display:flex;flex-direction:column;gap:16px}
.card{background:var(--panel);border:1px solid var(--border);border-radius:var(--radius);padding:15px 16px}
.card h4{
  font-size:12px;font-weight:500;letter-spacing:.6px;color:var(--text-dim);
  text-transform:uppercase;margin-bottom:11px;
}
.toc a{
  display:block;padding:5px 0 5px 11px;font-size:13px;color:var(--text-dim);
  border-left:2px solid var(--border);transition:.15s;text-decoration:none;
}
.toc a:hover{color:var(--text);text-decoration:none}
.toc a.on{color:var(--accent);border-left-color:var(--accent);font-weight:500}
.kv{display:flex;justify-content:space-between;gap:12px;padding:6px 0;font-size:13px;border-bottom:1px dashed var(--border)}
.kv:last-child{border-bottom:none}
.kv span{color:var(--text-dim);flex:none}
.kv b{font-weight:400;color:var(--text);text-align:right;word-break:break-all}
.lks a{display:flex;align-items:center;gap:8px;padding:7px 0;font-size:13px;color:var(--text)}
.lks a:hover{color:var(--accent);text-decoration:none}
.lks .ic{width:15px;height:15px;flex:none;color:var(--text-dim)}
.lks small{display:block;color:var(--text-dim);font-size:11.5px;margin-left:23px;word-break:break-all}
.kws{display:flex;flex-wrap:wrap;gap:6px}
/* 第一百九十七轮：标签块里既有 <span>（没有页面的标签）也有 <a>（有页面的标签）
   ⇒ 两者必须**同形**，否则「有的能点有的不能」访客看不出来；再用 hover 把可点的那些点明。 */
.kws span,.kws a{
  padding:3px 9px;border-radius:6px;font-size:12px;background:var(--bg-soft);
  border:1px solid var(--border);color:var(--text-dim);
}
.kws a{text-decoration:none;transition:.15s}
.kws a:hover{color:var(--accent);border-color:var(--accent)}

/* 相关推荐 */
.recs{border-top:1px solid var(--border);padding:34px 0 10px;margin-top:12px}
.recs h2{font-size:17px;font-weight:500;margin-bottom:16px}
.rgrid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:14px}
.rc{
  display:flex;gap:12px;padding:14px;border-radius:var(--radius);background:var(--panel);
  border:1px solid var(--border);transition:.15s;text-decoration:none;color:inherit;
}
.rc:hover{border-color:var(--accent);transform:translateY(-1px);text-decoration:none}
.rlogo{
  width:36px;height:36px;flex:none;border-radius:9px;background:var(--bg-soft);
  border:1px solid var(--border);display:grid;place-items:center;overflow:hidden;
}
.rlogo img{width:22px;height:22px;object-fit:contain}
.rlogo i{font-style:normal;font-size:15px;color:var(--accent);font-weight:500}
.rt{font-size:13.5px;font-weight:500;margin-bottom:3px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.rd{font-size:12px;color:var(--text-dim);line-height:1.6;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.rinfo{min-width:0;flex:1}

footer{
  margin-top:34px;border-top:1px solid var(--border);padding:22px 0 40px;
  color:var(--text-dim);font-size:12.5px;
}
/* ---------------------------------------------------------------------------
   页脚统一导航行（第一百九十六轮续五 · 用户七条决策 #3）
   —— 全站横向串联的唯一入口：每一页（分类页 / 详情页 / 分类总览页 / 首页预渲染正文）都有，
      且只列**真的会写出文件**的页面（判据在 main/site-footer.js）。
   ⚠️ footer 原来的 `display:flex;justify-content:space-between` 在本轮**去掉了**：
      那时页脚只有「站名 + 副信息」两个裸 span，靠 flex 分列两端；现在多了一行导航行，
      分列改由 .fmeta 自己承担（结构从「一行两块」变成「两行块」，观感不变）。
   --------------------------------------------------------------------------- */
.fnav{display:flex;flex-wrap:wrap;align-items:center;gap:2px 6px;margin-bottom:14px}
.fnav-link{color:var(--text-dim);text-decoration:none;transition:color .15s}
.fnav-link:hover{color:var(--accent);text-decoration:none}
.fsep{color:var(--text-dim);opacity:.55}
.fmeta{display:flex;justify-content:space-between;flex-wrap:wrap;gap:10px}
/* 分类总览页（categories/index.html）的一张一级分类卡：
   卡本体直接复用 .cc（与书签卡同一套语言），卡下方是该分类的子分类条（.csubs / .chip 同分类页 hero）。 */
.catgrp{display:flex;flex-direction:column;min-width:0}
.catgrp .cc{flex:1}
.catgrp .csubs{margin-top:8px}

@media (max-width:900px){
  .cols{grid-template-columns:1fr;gap:26px}
  aside{position:static}
  .rgrid{grid-template-columns:1fr}
  .hmain{flex-direction:column;gap:18px}
  .hleft{width:100%}
  .hprev{flex:none;width:100%;max-width:520px}
  .hlogo{width:64px;height:64px}
  .hlogo img{width:44px;height:44px}
  h1{font-size:22px}
  .wrap{padding:0 16px}
}

/* ===== 以下为 mdLite 输出的 .kb-md-* 类（自 renderer/styles.css 抽取） ===== */
:root{--app-fs-k:1}
/* —— README markdown 渲染（mdLite 输出） —— */
.kb-md {
  font-size: calc(13.2px * var(--app-fs-k));
  line-height: 1.72;
  color: var(--text);
  word-break: break-word;
}
.kb-md-h {
  margin: 16px 0 8px;
  font-weight: 600;
  line-height: 1.35;
  color: var(--text);
}
h1.kb-md-h {
  font-size: calc(19px * var(--app-fs-k));
}
h2.kb-md-h {
  font-size: calc(17px * var(--app-fs-k));
  padding-bottom: 5px;
  border-bottom: 1px solid var(--border);
}
h3.kb-md-h {
  font-size: calc(15px * var(--app-fs-k));
}
h4.kb-md-h,
h5.kb-md-h,
h6.kb-md-h {
  font-size: calc(13.5px * var(--app-fs-k));
}
.kb-md-p {
  margin: 9px 0;
}
.kb-md-a {
  color: var(--accent);
  text-decoration: none;
}
.kb-md-a:hover {
  text-decoration: underline;
}
.kb-md-code {
  padding: 1px 5px;
  border-radius: 4px;
  background: var(--bg-soft);
  font-size: calc(12.2px * var(--app-fs-k));
  font-family: ui-monospace, SFMono-Regular, Consolas, monospace;
}
.kb-md-pre {
  margin: 10px 0;
  padding: 10px 12px;
  border-radius: 8px;
  background: var(--bg-soft);
  border: 1px solid var(--border);
  overflow-x: auto;
}
.kb-md-pre code {
  font-size: calc(12.2px * var(--app-fs-k));
  line-height: 1.6;
  font-family: ui-monospace, SFMono-Regular, Consolas, monospace;
  white-space: pre;
}
.kb-md-quote {
  margin: 10px 0;
  padding: 4px 12px;
  border-left: 3px solid var(--border);
  color: var(--text-dim);
}
.kb-md-list {
  margin: 8px 0;
  padding-left: 22px;
}
.kb-md-list li {
  margin: 3px 0;
}
.kb-md-hr {
  margin: 14px 0;
  border: none;
  border-top: 1px solid var(--border);
}
.kb-md-table {
  width: 100%;
  border-collapse: collapse;
  margin: 10px 0;
  font-size: calc(12.4px * var(--app-fs-k));
}
.kb-md-table th,
.kb-md-table td {
  border: 1px solid var(--border);
  padding: 5px 8px;
  text-align: left;
}
.kb-md-table th {
  background: var(--bg-soft);
  font-weight: 600;
}
.kb-md-img {
  max-width: 100%;
  border-radius: 6px;
}

/* —— 源码内联 HTML 路径新增的标签（README 里的 <details> / <kbd> 等）——
   ⚠️ 其余标签（p / h1-6 / a / img / pre / code / table / ul / ol / hr / blockquote）由 mdLite
   的 sanitizer 统一补上 .kb-md-* 类名，直接命中上面的规则，两条路径视觉一致。 */
.kb-md-details {
  margin: 9px 0;
  padding: 6px 10px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--bg-soft);
}
.kb-md-summary {
  cursor: pointer;
  font-weight: 600;
  user-select: none;
}
.kb-md-summary:hover {
  color: var(--accent);
}
.kb-md-kbd {
  padding: 1px 5px;
  border: 1px solid var(--border);
  border-bottom-width: 2px;
  border-radius: 4px;
  background: var(--bg-soft);
  font-size: calc(12px * var(--app-fs-k));
  font-family: ui-monospace, SFMono-Regular, Consolas, monospace;
}
/* 源码 HTML 里的裸容器（div / span / center / section / figure）不需要额外间距 */
.kb-md center {
  display: block;
}

/* ===== 手工追加（不随上面两段抽取覆盖） =====
   demo 的 .hlogo 里**恒有 <img>**（它的数据总有图标），所以它没写首字母降级样式；
   本项目的网址**可能没有图标**（icon 为空 / 抓不到 favicon）⇒ 必须补一条，
   否则 <i> 会以斜体默认字渲染，粗体大写 I 看上去像个斜杠（第 157 轮真实渲染截图实见）。 */
.hlogo i {
  font-style: normal;
  font-size: 26px;
  font-weight: 600;
  color: var(--accent);
  line-height: 1;
}

/* ===== 分类页（第一百六十九轮）=====
   与详情页**共用本文件**：外壳（header / .wrap / .hbar / .crumb / .tbtn / footer / 配色变量）
   一行都不重写 —— 两页的外观天然不会漂移。这里只补分类页独有的三段：
   分类头（.chero）· 子分类条（.csubs / .chip）· 卡片网格（.cgrid / .cc）。
   ⚠️ 本段与上面的 .hlogo i 一样是**手工追加**（不随 demo 抽取覆盖）。
   ⚠️ 卡片内部的 .rlogo / .rt / .rd 直接复用详情页「相关推荐」那套（同名同义）。 */
.chero{padding:34px 0 26px}
.chero h1{font-size:26px}
.hmeta + .csubs{margin-top:14px}
.csubs{display:flex;flex-wrap:wrap;gap:8px}
.chip{
  display:inline-flex;align-items:center;gap:6px;padding:4px 11px;border-radius:999px;
  font-size:12.5px;background:var(--panel);border:1px solid var(--border);
  color:var(--text-dim);text-decoration:none;transition:.15s;
}
.chip:hover{border-color:var(--accent);color:var(--accent);text-decoration:none}
.chip i{font-style:normal;font-size:11px;opacity:.7}

/* 标签云容器（第一百九十七轮 · 用户令第 5 条 tags/<id>.html + tags/index.html）。
   复用分类页那颗 .chip（同名同义：小圆角胶囊 + 命中数角标），本段只负责容器排版：
   换行、间距、**baseline 对齐**（各标签字号不同，按基线对齐才不会高低跳动）。
   字号由模板按命中数量级内联在 <a style="font-size:Npx"> 上 ⇒ 内联优先于 .chip 的基础字号。 */
.tagcloud{display:flex;flex-wrap:wrap;gap:9px 11px;align-items:baseline;margin:28px 0 0}

/* 分类变成链接后的两处（详情页 hero 的 .tag / 侧栏基本信息行 / 子分类条）
   —— 不补这两条，a:hover 会给小圆角胶囊加下划线，看着像样式坏了 */
a.tag{text-decoration:none}
a.tag:hover{text-decoration:none;border-color:var(--accent)}
.kv .kv-a{color:var(--accent);text-decoration:none}
.kv .kv-a:hover{text-decoration:underline}
.kv .kv-sep{color:var(--text-dim);opacity:.6}

.cgrid{
  display:grid;grid-template-columns:repeat(auto-fill,minmax(258px,1fr));
  gap:14px;padding:30px 0 6px;
}
.cc{
  display:flex;gap:12px;padding:14px;border-radius:var(--radius);background:var(--panel);
  border:1px solid var(--border);transition:.15s;text-decoration:none;color:inherit;min-width:0;
}
.cc:hover{border-color:var(--accent);transform:translateY(-1px);text-decoration:none}
.cinfo-wrap{min-width:0;flex:1}
.cempty{
  margin:30px 0 6px;padding:28px 16px;text-align:center;color:var(--text-dim);
  border:1px dashed var(--border);border-radius:var(--radius);font-size:13px;
}

@media (max-width:900px){
  .cgrid{grid-template-columns:1fr}
  .chero{padding:26px 0 20px}
  .chero h1{font-size:21px}
}

/* ===== 独立页（第一百九十六轮续六 · 用户七条决策 #4）=====
   关于页 about.html · 友链页 friends.html · 404.html 三页共用本文件。
   外壳（.hero/.chero · .crumb · .wrap · h1 · .hmeta · footer）与分类页**逐字同构**，一行不重写。
   这里只补三页独有的两段：站长名片（.pcard 一族）· 统计格（.pstats / .pstat）。
   ⚠️ 其余一律复用既有类名，不另造长得差不多的：
      · 友链卡 → .cgrid / .cc / .rlogo / .rt / .rd（与分类页同一套卡片语言）
      · 动作按钮（申请友链 / 404 出口）→ .acts / .btn / .btn.primary（详情页那套）
      · 404 提示框 → .cempty
   ⚠️ 本段与上面「分类页」那段一样是**手工追加**（不随 demo 抽取覆盖）。 */

/* 站长名片：头像 + 名字 + 简介。左右布局，窄屏也不换行（信息量小，换行反而更松散） */
.pcard{
  display:flex;align-items:center;gap:16px;margin:30px 0 0;padding:20px;
  border-radius:var(--radius);background:var(--panel);border:1px solid var(--border);min-width:0;
}
/* 头像位：与 .hlogo 同一套（盒 + 定尺寸 img + <i> 首字降级）。
   ⚠️ <i> 那两条必须写：站点没配 logo 时 logoBlock 退回 <i>首字</i>，
      不写就会以斜体默认字渲染（第 157 轮真实截图踩过，见上面 .hlogo i 的注释）。 */
.pav{
  width:56px;height:56px;flex:none;border-radius:14px;background:var(--panel-hover);
  border:1px solid var(--border);display:grid;place-items:center;overflow:hidden;
}
.pav img{width:38px;height:38px;object-fit:contain;display:block}
.pav i{font-style:normal;font-size:22px;font-weight:600;color:var(--accent);line-height:1}
.pinfo{flex:1;min-width:0}
.pname{font-size:18px;font-weight:600;letter-spacing:.2px;line-height:1.35}
.pdesc{margin-top:6px;font-size:13.5px;line-height:1.75;color:var(--text-dim)}

/* 统计格：自适应网格；每格「大数字 + 小标签」。
   minmax(132px,1fr) 的取值：四个统计（收录 / 分类 / 标签 / 友链）在 .wrap 的 1132px 里
   落成一行；窄屏自动退到 2 列 / 1 列，不需要额外断点。 */
.pstats{
  display:grid;grid-template-columns:repeat(auto-fill,minmax(132px,1fr));
  gap:12px;margin:16px 0 0;
}
.pstat{
  padding:13px 16px;border-radius:var(--radius);background:var(--panel);
  border:1px solid var(--border);min-width:0;
}
.pstat b{
  display:block;font-size:20px;font-weight:600;color:var(--accent);line-height:1.35;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.pstat span{display:block;margin-top:3px;font-size:12.5px;color:var(--text-dim)}

/* ==========================================================================
   社交分享按钮组（第一百七十七轮 · 用户令）
   --------------------------------------------------------------------------
   与 .acts 同一套视觉语言（--panel 底 + --border 边 + hover 变 --accent），
   但整体小一档：它是**次要动作**，不该和「访问网站」抢注意力。
   刻意只用文字标签、不画品牌 logo —— 手绘的假 logo 比文字更糟（既不准又难维护），
   而这里每个平台名本身就已经足够自解释。
   ========================================================================== */
.shares{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin-top:14px}
.sh-lbl{font-size:12.5px;color:var(--text-dim);margin-right:2px}
.sh{
  display:inline-flex;align-items:center;height:30px;padding:0 12px;border-radius:8px;
  font-size:12.5px;font-family:inherit;line-height:1;white-space:nowrap;cursor:pointer;transition:.15s;
  border:1px solid var(--border);background:var(--panel);color:var(--text-dim);text-decoration:none;
}
.sh:hover{border-color:var(--accent);color:var(--accent);text-decoration:none}
.sh:focus-visible{outline:2px solid var(--accent);outline-offset:1px}
/* 无 JS 时 <a data-sh> 拿不到 href（PAGE_JS 才拼）⇒ 不可点。
   给一个「未启用」的观感，避免看起来像按钮坏了。button 不受影响。 */
.sh:not([href]):not(button){opacity:.55;cursor:default}
.sh:not([href]):not(button):hover{border-color:var(--border);color:var(--text-dim)}
/* 操作结果提示：**持久**（不自动消失）。
   用户偏好持久提示优先于瞬时 toast；「已复制」这类反馈留着不影响阅读，
   而一闪而过的 toast 很容易被错过（正是本轮 UX 纪律的一条）。 */
.sh-tip{font-size:12.5px;line-height:1.6;color:var(--accent);margin-top:7px}
.sh-tip:empty{display:none}

@media (max-width:900px){
  /* 窄屏：平台名允许折行，按钮不压缩内边距（内边距压到 0 会让文字贴边） */
  .shares{gap:6px}
  .sh{padding:0 10px}
}


/* ==========================================================================
   与「独立页壳」共存（第一百九十六轮）

   壳（renderer/src/export/ExportPageShell.vue）把完整的 renderer/styles.css 引进了本页 ——
   那是壳的组件样式（.sh-* / .ss-* / .confirm-dialog …）唯一的存在处，不引壳就是一排无样式的裸按钮。
   但那份样式表里有几条**全局规则**，它们是给「应用内窗口」与「首页导出页」写的，直接落到本页会把
   独立页打坏。下面每条都是对某一条具体规则的显式反制，而不是「保险起见加一点样式」。

   ⚠️ 生效方式：本文件由 detailCss() **内联在 <head>**，而壳的样式表是 <head> 里的
      <link rel="stylesheet">（排在 <style> 之前，见 site-detail.js 的 head 拼装顺序）。
      同特异性下后写的赢 ⇒ 下面这些规则天然覆盖 styles.css 里的同名规则，不需要 !important。
      ⚠️ 顺序一旦被改（<link> 挪到 <style> 之后），这一整段就会失效且**不会报错**。
   ========================================================================== */

/* ① 文档滚动：styles.css 的 `html, body { height:100%; overflow:hidden }` 是给应用内窗口写的
      （那里滚动由 #content 内部容器承担）。落到本页 = **整页彻底不能滚** —— 正文比视口长时
      下半截永远看不到，而这在桌面浏览器上表现为「页面加载完了但内容截断」，极难归因到一条 CSS。
      本页是文档滚动（阅读进度条、目录高亮、回到顶部全都按 window.scrollY 算），必须还原。 */
html,body{height:auto;overflow:visible}

/* ② 文字可选中：styles.css 的 `body { user-select:none }` 是桌面应用的习惯（拖拽卡片时不想选中文字）。
      导出页是给浏览器看的普通网页，不能选中文字属于可用性缺陷 —— 壳里的 export.css 对首页导出页
      做了同样一条反制；独立页不经过导出首页，所以这里必须自己写一份。 */
body{user-select:text;-webkit-user-select:text}

/* ③ #content：壳刻意复用了首页的骨架 #app > #main > #content（styles.css 里针对这三级的布局规则
      是基准，其中 #content 的 22px 横向内边距正是 SiteSearchHero 与 .sh-topnav 用 -22px 负 margin
      做「满幅渐变」时抵消的那个数）。但首页把滚动交给 #content 这个**内部容器**，本页是文档滚动：
      · flex:1 会在文档流里产生多余高度（那是给「窗口高 − 顶栏」的容器算的）；
      · overflow-y:auto 会把滚动吃进 #content ⇒ window.scrollY 恒为 0 ⇒ 进度条、目录高亮、
        .sh-topnav 的吸顶态全部失效；
      · padding-bottom:40px 是给首页正文留的，本页正文自带下边距，再加一层就是双层留白。
      ⚠️ 特异性：#cbx-shell-root #content = 两个 id > styles.css 的 `#content` = 一个 id ⇒ 稳定生效。
      ⚠️ 横向 22px **必须保留**（那是 hero 满幅的抵消数，去掉它 hero 会横向溢出视口）。 */
#cbx-shell-root #content{
  flex:none;
  overflow:visible;
  padding-bottom:0;
}

/* ④ 窄屏必须跟着 styles.css 的媒体查询一起走：那里 #content 的 22px 会变成 12px。
      上面的规则特异性更高 ⇒ 会把那条媒体查询一起盖掉 ⇒ 必须在这里补一份同样的断点，
      否则窄屏下 hero 横向溢出 10px（22 − 12）。 */
@media (max-width:767.98px){
  #cbx-shell-root #content{padding-left:12px;padding-right:12px}
}

/* ⑤ #app / #main：走纵向自然流即可。首页靠 flex:1 把 #content 撑成内部滚动区，本页没有这个需求，
      留着反而在文档滚动下产生多余高度。 */
#cbx-shell-root #app,
#cbx-shell-root #main{display:block;flex:none}

/* ⑥ 壳的挂载点本身不占位：壳渲染出的内容（顶栏 + hero + 右下浮钮 + 底部 Dock + 全局层）
      全部要么在文档流里（顶栏/hero），要么是 fixed / Teleport 到 body 的（浮钮 / Dock / 弹窗）。
      这里只兜一条：挂载点若因脚本未执行而空着，也别在正文上方留出一段空白。 */
#cbx-shell:empty{display:none}

/* ===== 站点地图页 sitemap.html（第一百九十八轮 · 用户令第 6 条）=====
   人类可读的全站索引：站级页面一行 + 按一级分类分组的全部条目链接。
   ⚠️ 刻意**不复用** .cgrid / .cc 卡片：本页一页要列上千条，卡片在 4 列下会把文档拉到几万像素
      （爬虫不在乎，人打不开）。这里是**紧凑多列列表** —— 一列 13px 行高 1.5，四列并排。
   ⚠️ 列数用 columns 而不是 grid：columns 会自动把高度摊平（列表短的分组不会留一大块空白），
      而 break-inside:avoid 保证单条不被劈成两半。
   ⚠️ 断点沿用本文件既有约定（900 一档、560 一档补齐手机单列）。 */
.smg{margin:0 0 26px}
.smg-h{margin:0 0 10px;font-size:15px;font-weight:600;color:var(--text);line-height:1.4}
.smg-h em{font-style:normal;font-weight:400;color:var(--text-dim);font-size:12px;margin-left:7px}
.smg ul{list-style:none;margin:0;padding:0;columns:4;column-gap:20px}
.smg li{margin:0 0 6px;break-inside:avoid;font-size:13px;line-height:1.5}
.smg a{color:var(--text-dim);text-decoration:none;transition:.15s}
.smg a:hover{color:var(--accent);text-decoration:none}
.smg small{color:var(--text-dim);opacity:.6;margin-left:5px;font-size:11px}
/* 站级页面那一行（首页 / 分类总览 / 标签 / 关于 / 友链 / 搜索）—— 与分组列表区分开，用胶囊标签 */
.smg-top{display:flex;flex-wrap:wrap;gap:8px;margin:26px 0 30px}
.smg-top a{
  display:inline-block;padding:5px 12px;border-radius:99px;font-size:13px;
  border:1px solid var(--border);background:var(--bg-soft);color:var(--text-dim);text-decoration:none;
}
.smg-top a:hover{border-color:var(--accent);color:var(--accent);text-decoration:none}
@media (max-width:900px){
  .smg ul{columns:2}
}
@media (max-width:560px){
  .smg ul{columns:1}
}

/* ============================================================================
   站内搜索页（第一百九十九轮 · 用户令第 6 条）
   与 .smg-top（站点地图页的胶囊）刻意同形不同类名：那边是 sitemap 页自己的类名，
   这里复用同一套视觉但互不影响（改一处不会牵动另一页）。
   结果项做成整块可点（a.sr-it 包住标题 / 域名 / 描述 / 分类标签），
   与首页卡片同一交互直觉：鼠标落在任意位置都能点，不必瞄准标题。
   ============================================================================ */
.sr{margin:0 0 26px}
.sr-bar{display:flex;gap:10px}
.sr-input{
  flex:1;min-width:0;padding:11px 15px;border-radius:11px;
  border:1px solid var(--border);background:var(--bg-soft);color:var(--text);
  font-size:15px;font-family:inherit;outline:none;transition:border-color .15s;
}
.sr-input:focus{border-color:var(--accent)}
.sr-input::placeholder{color:var(--text-dim);opacity:.75}
.sr-n{margin:11px 0 0;font-size:12px;color:var(--text-dim);line-height:1.5}
.sr-list{margin:13px 0 0}
.sr-it{
  display:block;padding:12px 14px;margin:0 0 8px;border-radius:11px;
  border:1px solid var(--border);background:var(--bg-soft);text-decoration:none;transition:border-color .15s;
}
.sr-it:hover{border-color:var(--accent);text-decoration:none}
.sr-it b{display:block;font-size:14px;font-weight:600;color:var(--text);line-height:1.45}
.sr-host{display:inline-block;margin-top:3px;font-size:12px;color:var(--text-dim)}
.sr-desc{
  margin:6px 0 0;font-size:13px;line-height:1.6;color:var(--text-dim);
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;
}
.sr-meta{margin:7px 0 0;font-size:12px;color:var(--text-dim);opacity:.85}
.sr-empty{
  margin:14px 0 0;padding:15px;border-radius:11px;border:1px dashed var(--border);
  font-size:13px;color:var(--text-dim);text-align:center;line-height:1.6;
}
.sr-browse{margin:30px 0 0;padding-top:22px;border-top:1px solid var(--border)}
.sr-sec-h{margin:0 0 10px;font-size:14px;font-weight:600;color:var(--text)}
.sr-sec-h em{font-style:normal;font-weight:400;color:var(--text-dim);font-size:12px;margin-left:7px}
.sr-chips{display:flex;flex-wrap:wrap;gap:8px;margin:0 0 22px}
.sr-chips a{
  display:inline-block;padding:5px 12px;border-radius:99px;font-size:13px;
  border:1px solid var(--border);background:var(--bg-soft);color:var(--text-dim);text-decoration:none;
}
.sr-chips a:hover{border-color:var(--accent);color:var(--accent);text-decoration:none}
