/* ==========================================================================
   组件层
   --------------------------------------------------------------------------
   只消费 tokens.css 中的变量，不写死颜色与尺寸。
   主题通过覆盖变量与追加规则来改变外观，不必修改本文件。
   ========================================================================== */

/* --- 布局 ---------------------------------------------------------------- */

.layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-8);
  padding: var(--space-8) 0;
}

@media (min-width: 992px) {
  .layout {
    grid-template-columns: minmax(0, 1fr) var(--sidebar-width);
  }
}

.layout__main { min-width: 0; }

/* 侧栏始终按内容取高（不被栅格拉伸）：吸附切换不会改变盒子尺寸，
   side-dock 岛屿的 ResizeObserver 也就不会陷入「加类→变尺寸→重算→撤类」
   的反馈循环；offsetHeight 量到的才是真实内容高度。 */
.layout__side { align-self: start; }

/* 窄屏沉底 */
@media (max-width: 991px) {
  .layout__side { order: 2; }
}

/* 宽屏下侧栏「吸附」是有条件的（is-docked 由 side-dock 岛屿按需添加）：
   侧栏自身比视口矮时才吸附在页头下方；比视口高还硬吸附，
   底部区块会被钉在折叠线以下永远露不全（文字只剩一半，实测踩过）。
   文章页不吸附：侧栏已按正文长度裁剪，跟着页面自然滚动。 */
@media (min-width: 992px) {
  .layout__side.is-docked {
    position: sticky;
    top: 76px;
  }
}

/* 认证页、错误页与标签汇总页没有辅助浏览诉求：
   侧栏只会把短内容挤在左栏、留出大片空白，因此整页收成单列居中。
   PageName 与模板同名，body 类名形如 page-login / page-404。
   标签云铺满整行更好看，故仅隐藏侧栏不限制宽度。 */
.page-login .layout, .page-register .layout, .page-forgot .layout,
.page-reset .layout, .page-userset .layout, .page-404 .layout {
  grid-template-columns: minmax(0, 1fr);
  max-width: 760px;
  margin-inline: auto;
}
.page-login .layout__side, .page-register .layout__side,
.page-forgot .layout__side, .page-reset .layout__side,
.page-userset .layout__side, .page-404 .layout__side,
.page-tags .layout__side {
  display: none;
}

/* --- 首页幻灯片 ---------------------------------------------------------- */
/* 基础形态是横向 scroll-snap：无 JS 也能滑动/触摸切换；
   JS 只叠加自动播放、圆点与箭头。 */

.carousel {
  position: relative;
  margin: var(--space-5) 0 0;
}

.carousel__track {
  display: flex;
  gap: 0;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  border-radius: var(--radius-xl);
  border: 1px solid var(--border);
  /* 幻灯片可能是任意截图，用极浅的中性底兜底，
     避免图还没加载出来时闪一片纯白/纯黑 */
  background: var(--bg-muted);
  box-shadow: var(--shadow-md);
  scrollbar-width: none;
}
.carousel__track::-webkit-scrollbar { display: none; }

.carousel__slide {
  flex: 0 0 100%;
  scroll-snap-align: start;
  position: relative;
  min-width: 0;
  aspect-ratio: 16 / 6;
}
@media (max-width: 767px) {
  .carousel__slide { aspect-ratio: 16 / 10; }
}

.carousel__link {
  position: absolute;
  inset: 0;
  display: block;
  color: #fff;
}
.carousel__img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* 遮罩：让任意截图上方都能压住文字；无封面时用品牌渐变兜底。
   分两层的理由：单层「整体压暗」会把截图压得灰扑扑的，而单层
   「只压底部」在截图本身很亮（比如浅色终端）时标题仍然看不清。
   这里上半段只做极轻的顶部压暗（保图片观感 + 压住右上角控件），
   下半段快速加深到近乎不透明（保标题可读性）。 */
.carousel__shade {
  position: absolute;
  inset: 0;
  background:
    linear-gradient(180deg,
      color-mix(in srgb, #000 26%, transparent) 0%,
      color-mix(in srgb, #000 8%, transparent) 26%,
      transparent 46%),
    linear-gradient(180deg,
      transparent 34%,
      color-mix(in srgb, #000 42%, transparent) 62%,
      color-mix(in srgb, #000 84%, transparent) 88%,
      color-mix(in srgb, #000 90%, transparent) 100%);
}
.carousel__slide--plain .carousel__shade {
  background: linear-gradient(135deg, var(--brand-600), var(--brand-500) 55%, var(--accent-500));
}

.carousel__body {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  padding: var(--space-6) var(--space-8);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}
@media (max-width: 767px) {
  .carousel__body { padding: var(--space-4); }
}

.carousel__badges { display: flex; flex-wrap: wrap; gap: var(--space-2); }
/* 幻灯片压在图上，胶囊用半透明白底保证可读性 */
.carousel__badges .badge {
  background: color-mix(in srgb, #fff 22%, transparent);
  color: #fff;
  border-color: color-mix(in srgb, #fff 34%, transparent);
  backdrop-filter: blur(4px);
  text-shadow: 0 1px 2px color-mix(in srgb, #000 40%, transparent);
}

/* 阴影写成「近处硬阴影 + 远处大扩散」两层：
   近处那层负责描边、远处那层负责把文字从杂乱截图背景里拎出来，
   只给远处大模糊时小字号的元信息会糊成一团。 */
.carousel__title {
  margin: 0;
  font-size: var(--text-2xl);
  line-height: var(--leading-snug);
  color: #fff;
  text-shadow:
    0 1px 2px color-mix(in srgb, #000 55%, transparent),
    0 2px 14px color-mix(in srgb, #000 45%, transparent);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
@media (max-width: 767px) {
  .carousel__title { font-size: var(--text-lg); -webkit-line-clamp: 2; }
}

.carousel__excerpt {
  margin: 0;
  max-width: 46rem;
  color: color-mix(in srgb, #fff 88%, transparent);
  font-size: var(--text-sm);
  line-height: var(--leading-normal);
  text-shadow:
    0 1px 2px color-mix(in srgb, #000 50%, transparent),
    0 2px 12px color-mix(in srgb, #000 40%, transparent);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
@media (max-width: 767px) {
  .carousel__excerpt { display: none; }
}

.carousel__meta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
  color: color-mix(in srgb, #fff 78%, transparent);
  font-size: var(--text-xs);
  font-variant-numeric: tabular-nums;
  text-shadow: 0 1px 3px color-mix(in srgb, #000 50%, transparent);
}

.carousel__nav {
  position: absolute;
  right: var(--space-4);
  top: var(--space-4);
  display: flex;
  align-items: center;
  gap: var(--space-2);
}
.carousel__arrow {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border: 1px solid color-mix(in srgb, #fff 30%, transparent);
  border-radius: var(--radius-md);
  background: color-mix(in srgb, #000 28%, transparent);
  color: #fff;
  cursor: pointer;
  backdrop-filter: blur(4px);
  transition: background var(--dur-fast) var(--ease-out);
}
.carousel__arrow:hover { background: color-mix(in srgb, #000 45%, transparent); }
.carousel__arrow .icon { width: 18px; height: 18px; }

.carousel__dots { display: flex; align-items: center; gap: 6px; }
.carousel__dot {
  width: 8px;
  height: 8px;
  padding: 0;
  border: none;
  border-radius: var(--radius-pill);
  background: color-mix(in srgb, #fff 45%, transparent);
  cursor: pointer;
  transition: width var(--dur-base) var(--ease-out), background var(--dur-fast) var(--ease-out);
}
.carousel__dot.is-active {
  width: 20px;
  background: #fff;
}

/* --- 通用元素 ------------------------------------------------------------ */

/* 内联 SVG 图标（由 icon 模板函数输出，1em 跟随文字大小） */
.icon {
  width: 1em;
  height: 1em;
  flex-shrink: 0;
  vertical-align: -0.125em;
}

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-height: 40px;
  padding: 0 var(--space-5);
  border: 1px solid transparent;
  border-radius: var(--radius-md);
  background: var(--brand-500);
  color: var(--text-on-brand);
  font-size: var(--text-sm);
  font-weight: 500;
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease-out),
              transform var(--dur-fast) var(--ease-out);
}
.btn .icon { width: 16px; height: 16px; }
.btn:hover { background: var(--brand-600); color: var(--text-on-brand); }
.btn:active { transform: translateY(1px); }

.btn--ghost {
  background: transparent;
  border-color: var(--border-strong);
  color: var(--text-body);
}
.btn--ghost:hover { background: var(--bg-muted); color: var(--text-strong); }

.badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  height: 22px;
  padding: 0 var(--space-2);
  border-radius: var(--radius-sm);
  background: var(--bg-muted);
  color: var(--text-muted);
  font-size: var(--text-xs);
  font-weight: 500;
  line-height: 1;
  white-space: nowrap;
}
.badge .icon { width: 12px; height: 12px; }
.badge--cat {
  background: color-mix(in srgb, var(--badge-color, var(--brand-500)) 14%, transparent);
  color: var(--badge-color, var(--brand-500));
}
.badge--top {
  background: color-mix(in srgb, var(--danger) 14%, transparent);
  color: var(--danger);
  border-color: color-mix(in srgb, var(--danger) 30%, transparent);
}
/* 精选：品牌色胶囊，与置顶（红）区分开 */
.badge--featured {
  background: color-mix(in srgb, var(--brand-500) 14%, transparent);
  color: var(--brand-500);
  border: 1px solid color-mix(in srgb, var(--brand-500) 30%, transparent);
}
.badge { border: 1px solid transparent; }

.tag {
  display: inline-flex;
  align-items: center;
  height: 26px;
  padding: 0 var(--space-3);
  border-radius: var(--radius-pill);
  background: var(--bg-muted);
  color: var(--text-muted);
  font-size: var(--text-xs);
  transition: background var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
}
.tag:hover { background: var(--brand-500); color: var(--text-on-brand); }

.section-title {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin: var(--space-8) 0 var(--space-4);
  padding-left: var(--space-3);
  border-left: 3px solid var(--brand-500);
  font-size: var(--text-xl);
}
.section-title .icon { width: 18px; height: 18px; color: var(--brand-500); }

/* --- 页头（配合 header-bar 岛屿：滚动后收起阴影） ---------------------- */

.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: color-mix(in srgb, var(--bg-surface) 88%, transparent);
  backdrop-filter: saturate(180%) blur(12px);
  border-bottom: 1px solid var(--border);
  transition: box-shadow var(--dur-base) var(--ease-out);
}
.site-header.is-scrolled { box-shadow: var(--shadow-md); }

.site-header__inner {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  min-height: 64px;
  /* 内嵌搜索下拉的定位基准：面板钉在页头右端（放大镜）正下方 */
  position: relative;
}

/* --- 站名 Logo 字标 -----------------------------------------------
   两级结构：得意黑主标（高级精致蓝渐变 + 流光扫过），
   完整站名里剩下的段落以 10px 小字缀在主标右下，形成「品牌 + 注脚」的排印层次。
   完整样式只在此处定义（base.css 留有说明注释），渐变色值走 tokens.css 的
   --logo-grad-*，亮暗主题各自成套。 */
.site-logo {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  flex-shrink: 1;
  min-width: 0;
  text-decoration: none;
}
.site-logo__lockup {
  display: flex;
  flex-direction: column;
  align-items: flex-end; /* 小字贴主标右缘，而不是居中挂一条 */
  min-width: 0;
}
.site-logo__text {
  font-family: var(--font-logo);
  font-weight: 400;
  font-size: 22px;
  letter-spacing: .02em;
  line-height: 1.12;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
  /* 双层背景都裁进字形：底层是精致蓝渐变，上层是斜向白色流光。
     流光层 3 倍宽，靠 background-position 从左外扫到右外，
     扫完即出画，循环重启时无跳变。 */
  background-image:
    linear-gradient(115deg, transparent 42%, var(--logo-sheen) 50%, transparent 58%),
    linear-gradient(115deg, var(--logo-grad-a) 0%, var(--logo-grad-b) 48%, var(--logo-grad-c) 100%);
  background-size: 300% 100%, 100% 100%;
  background-position: 130% 0, 0 0;
  background-repeat: no-repeat;
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
  animation: logo-sheen 5.2s linear infinite;
}
.site-logo__sub {
  font-size: 10px;
  font-weight: 500;
  letter-spacing: .16em;
  line-height: 1.2;
  margin-top: 2px;
  color: var(--logo-sub-color);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
}
/* 小字尾部一枚呼吸点：像扫描指示灯一样缓慢明灭，呼应站点的安全主题 */
.site-logo__sub::after {
  content: "";
  display: inline-block;
  width: 4px;
  height: 4px;
  margin-left: 5px;
  border-radius: 50%;
  background: var(--logo-grad-c);
  vertical-align: 1px;
  animation: logo-blink 2.4s ease-in-out infinite;
}
@keyframes logo-sheen {
  0% { background-position: 130% 0, 0 0; }
  34% { background-position: -10% 0, 0 0; }
  100% { background-position: -10% 0, 0 0; }
}
@keyframes logo-blink {
  0%, 100% { opacity: .9; }
  50% { opacity: .15; }
}
/* 悬停：流光加亮、盾标轻转，给人「可点」的反馈但不夸张 */
.site-logo:hover .site-logo__text {
  filter: brightness(1.08) saturate(1.06);
}
.site-logo__img {
  width: 34px;
  height: 34px;
  border-radius: var(--radius-md);
  flex-shrink: 0;
  transition: transform var(--dur-base) var(--ease-out);
}
.site-logo:hover .site-logo__img {
  transform: rotate(-6deg) scale(1.06);
}
/* 极少数不支持 background-clip:text 的环境回退成品牌色实字，
   并清掉裁切相关的填充色，否则文字会被透明填充吃掉 */
@supports not (background-clip: text) {
  .site-logo__text {
    background-image: none;
    -webkit-text-fill-color: initial;
    color: var(--brand-600);
  }
  .site-logo__text { animation: none; }
}
/* 尊重「减少动态效果」偏好：流光停在画外，呼吸点定住 */
@media (prefers-reduced-motion: reduce) {
  .site-logo__text {
    animation: none;
    background-position: 130% 0, 0 0;
  }
  .site-logo__sub::after {
    animation: none;
    opacity: .7;
  }
  .site-logo:hover .site-logo__img { transform: none; }
}
/* 窄屏：图标按钮 + 汉堡菜单之外的空间有限，字号降一档并截断超长站名 */
@media (max-width: 767px) {
  .site-logo__text { font-size: 20px; }
  .site-logo__sub { font-size: 9px; letter-spacing: .1em; }
}
/* 更窄的屏：页头整体收紧一档，给「主标 + 小字」让出完整宽度，
   避免小字被省略号截断；40px 的图标按钮仍在可点尺寸范围内 */
@media (max-width: 479px) {
  .site-header__inner { gap: 12px; }
  .site-header__actions { gap: 2px; }
  .site-header__actions .icon-btn { width: 40px; height: 40px; }
  .site-logo__img { width: 30px; height: 30px; }
  .site-logo__text { font-size: 20px; }
  .site-logo__sub { font-size: 8.5px; letter-spacing: .05em; margin-top: 1px; }
}

.site-nav { flex: 1; min-width: 0; }
.site-nav__list {
  display: none;
  align-items: center;
  /* gap 从 4px 提到 6px：条目之间原本挤成一片，看不出分组。
     再配合下面的左侧细分隔线，导航才有「一段一段」的节奏感，
     而不是一串连读的文字。 */
  gap: var(--space-2);
  margin: 0;
  padding: 0;
  list-style: none;
}
@media (min-width: 992px) {
  .site-nav__list { display: flex; }
}

.site-nav__item { position: relative; }
/* 相邻条目之间插一条极淡的竖线，作为分组提示。
   放在 item 上而不是 a 上，这样悬停高亮块不会把线盖住。 */
.site-nav__item + .site-nav__item::before {
  content: "";
  position: absolute;
  left: calc(var(--space-2) / -2 - .5px);
  top: 50%;
  width: 1px;
  height: 15px;
  transform: translateY(-50%);
  background: var(--border);
  pointer-events: none;
}
.site-nav__item > a {
  display: block;
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-md);
  color: var(--text-body);
  font-size: var(--text-sm);
  font-weight: 500;
  white-space: nowrap;
  transition: background var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
}
.site-nav__item > a:hover { background: var(--bg-muted); color: var(--text-strong); }
.site-nav__item.is-active > a { color: var(--brand-500); background: color-mix(in srgb, var(--brand-500) 10%, transparent); }

/* 有子菜单的项：文字右侧一个下拉箭头（内联 SVG，不引图标字体）。
   悬停/展开时旋转 180°，让「可展开」这件事在视觉上成立。 */
.site-nav__caret {
  margin-left: var(--space-1);
  vertical-align: -2px;
  opacity: .55;
  transition: transform var(--dur-fast) var(--ease-out), opacity var(--dur-fast) var(--ease-out);
}
.site-nav__item > a:hover .site-nav__caret { opacity: .9; }
.site-nav__item:hover > a .site-nav__caret,
.site-nav__item:focus-within > a .site-nav__caret,
.site-nav__item.is-active > a .site-nav__caret {
  transform: rotate(180deg);
  opacity: 1;
}

/* 二级菜单：桌面端悬停展开。focus-within 让键盘用户也能进入 */
.site-nav__sub {
  position: absolute;
  top: 100%;
  left: 0;
  min-width: 168px;
  margin: 0;
  padding: var(--space-2);
  list-style: none;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  opacity: 0;
  visibility: hidden;
  transform: translateY(-4px);
  transition: opacity var(--dur-fast) var(--ease-out),
              transform var(--dur-fast) var(--ease-out),
              visibility var(--dur-fast);
}
.site-nav__item:hover > .site-nav__sub,
.site-nav__item:focus-within > .site-nav__sub {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
}
.site-nav__sub a {
  display: block;
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-md);
  color: var(--text-body);
  font-size: var(--text-sm);
  white-space: nowrap;
}
.site-nav__sub a:hover { background: var(--bg-muted); color: var(--brand-500); }
.site-nav__sub .is-active a { color: var(--brand-500); }

.site-header__actions { display: flex; align-items: center; gap: var(--space-1); }

.site-header__menu-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  margin-left: calc(var(--space-2) * -1);
  border: none;
  border-radius: var(--radius-md);
  background: transparent;
  cursor: pointer;
}
.site-header__menu-btn:hover { background: var(--bg-muted); }
@media (min-width: 992px) {
  .site-header__menu-btn { display: none; }
}

.icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border: none;
  border-radius: var(--radius-md);
  background: transparent;
  color: var(--text-muted);
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
}
.icon-btn:hover { background: var(--bg-muted); color: var(--text-strong); }
.icon-btn .icon { width: 20px; height: 20px; }

/* 主题切换按钮：三枚图标按 data-theme-mode 显示其一 */
.theme-switch .icon { display: none; }
html[data-theme-mode="light"] .theme-switch .icon-sun { display: block; }
html[data-theme-mode="dark"] .theme-switch .icon-moon { display: block; }
html[data-theme-mode="system"] .theme-switch .icon-monitor { display: block; }

/* --- 面包屑 -------------------------------------------------------------- */

.breadcrumb { margin-bottom: var(--space-4); }
.breadcrumb__list {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: var(--text-sm);
  color: var(--text-muted);
}
.breadcrumb__item + .breadcrumb__item::before {
  content: "/";
  margin-right: var(--space-2);
  color: var(--border-strong);
}
.breadcrumb__item .icon { width: 14px; height: 14px; margin-right: 2px; }

/* --- 首页 Hero ----------------------------------------------------------- */
/* 紧凑横幅：站点名 + 关键词胶囊。原来的整段描述是 SEO 关键词串，
   直接当副标题又长又难看；拆成胶囊后既保留了信息又不占地方。 */

.hero { padding: var(--space-4) 0 var(--space-2); }

.hero__panel {
  position: relative;
  overflow: hidden;
  display: flex;
  align-items: center;
  gap: var(--space-6);
  padding: var(--space-6) var(--space-8);
  background:
    radial-gradient(120% 180% at 100% 0%,
      color-mix(in srgb, var(--brand-500) 16%, transparent), transparent 55%),
    radial-gradient(90% 150% at 0% 100%,
      color-mix(in srgb, var(--accent-500) 10%, transparent), transparent 50%),
    var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-xs);
}

.hero__intro {
  flex: 1 1 auto;
  min-width: 0;
}


/* 旋转标签球（侧栏区块）：透明的 canvas，文字颜色随主题 token，
   球体不加底色，浮在侧栏卡片上。
   注意：整组 .widget--sphere 规则放在 .widget 之后（见文件下方「侧栏区块」
   一节），因为 .widget 的 padding 简写会覆盖同优先级的 padding-left/right。 */
.sphere-box {
  display: flex;
  justify-content: center;
  /* 上下留一点呼吸感，让球体不贴着标题分隔线与卡片底边 */
  padding: var(--space-1) 0 var(--space-2);
}
.sphere-box canvas {
  width: 100%;
  max-width: 284px;
  aspect-ratio: 1;
  height: auto;
  cursor: pointer;
}

/* 无标签时的后备水印 */
.hero__mark {
  position: absolute;
  right: var(--space-6);
  top: 50%;
  transform: translateY(-50%) rotate(-8deg);
  color: var(--brand-500);
  opacity: .08;
  pointer-events: none;
}
.hero__mark .icon {
  width: 130px;
  height: 130px;
  stroke-width: 1.5;
}

.hero__title {
  margin: 0 0 var(--space-3);
  font-size: var(--text-2xl);
  /* 中文标题不适合负字距（会显得挤），改用极小的正字距 */
  letter-spacing: .01em;
}

.hero__keywords {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin: 0;
  padding: 0;
  list-style: none;
}
.hero__keywords li {
  padding: 3px var(--space-3);
  border-radius: var(--radius-pill);
  background: color-mix(in srgb, var(--brand-500) 9%, transparent);
  color: color-mix(in srgb, var(--brand-500) 78%, var(--text-body));
  font-size: var(--text-xs);
  line-height: 1.7;
  white-space: nowrap;
  transition: background var(--dur-fast) var(--ease-out);
}
.hero__keywords li:hover {
  background: color-mix(in srgb, var(--brand-500) 18%, transparent);
}

.hero__subtitle {
  max-width: 48rem;
  margin: 0 auto;
  color: var(--text-muted);
  font-size: var(--text-base);
}

/* --- 页面标题 ------------------------------------------------------------ */

.page-head { margin-bottom: var(--space-6); }
.page-head__title {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin: 0 0 var(--space-2);
  font-size: var(--text-2xl);
}
.page-head__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border-radius: var(--radius-md);
  background: color-mix(in srgb, var(--brand-500) 10%, transparent);
  color: var(--brand-500);
}
.page-head__icon .icon { width: 19px; height: 19px; }
.page-head__desc { margin: 0; color: var(--text-muted); font-size: var(--text-sm); }

/* --- 文章卡片 ------------------------------------------------------------ */

.post-list {
  display: grid;
  gap: var(--space-5);
}

/* 宽屏下默认仍是单列：一行一张卡片，阅读动线更清楚。
   想要多列由主题的「卡片列数」配置覆盖（html[data-opt-card-columns="2|3"]）。 */
@media (min-width: 768px) {
  .post-list { grid-template-columns: minmax(0, 1fr); }
  .post-list--compact { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

.post-card {
  display: flex;
  flex-direction: column;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-xs);
  overflow: hidden;
  transition: transform var(--dur-base) var(--ease-out),
              box-shadow var(--dur-base) var(--ease-out),
              border-color var(--dur-base) var(--ease-out);
}
.post-card:hover {
  transform: translateY(-2px);
  box-shadow: var(--shadow-lg);
  border-color: var(--border-strong);
}

.post-card__cover {
  display: block;
  aspect-ratio: 16 / 9;
  background: var(--bg-muted);
  overflow: hidden;
}
/* 卡片封面在悬停时会整体放大 3%，所以它不能带自己的圆角
   （父级 overflow:hidden 负责裁切），否则放大瞬间会在角落露出白边 */
.post-card__cover img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform var(--dur-slow) var(--ease-out);
}
.post-card:hover .post-card__cover img { transform: scale(1.03); }

/* 宽屏下卡片改为「左图右文」的横向版式。
   --------------------------------------------------------------------------
   为什么改：列表一行一张卡片时，如果封面仍占满整行宽度（16:9 铺满），
   一张截图就有 500px 高，一屏放不下两张卡片，滚动全被图片占据。
   横向版式让缩略图固定 300px 宽、文字在右侧，一屏能看到 3–4 条，
   这也是同类技术博客列表页的通行做法。
   窄屏（<768px）保持上图下文：手机上横向排会把文字挤成一列窄条。 */
@media (min-width: 768px) {
  .post-card--with-cover {
    flex-direction: row;
    align-items: stretch;
  }
  .post-card--with-cover .post-card__cover {
    flex: 0 0 300px;
    aspect-ratio: auto;
    align-self: stretch;
    min-height: 100%;
  }
  .post-card--with-cover .post-card__body {
    padding: var(--space-5) var(--space-6);
    justify-content: center;
  }
  /* 列数配置为 2/3 时给不出 300px 的图，退回「上图下文」更合适 */
  html[data-opt-card-columns="2"] .post-card--with-cover,
  html[data-opt-card-columns="3"] .post-card--with-cover {
    flex-direction: column;
  }
  html[data-opt-card-columns="2"] .post-card--with-cover .post-card__cover,
  html[data-opt-card-columns="3"] .post-card--with-cover .post-card__cover {
    flex: none;
    aspect-ratio: 16 / 9;
  }
}

/* 无封面文章的占位缩略块：淡淡的盾徽水印，避免列表出现参差的空洞 */
.post-card__cover--fallback {
  display: flex;
  align-items: center;
  justify-content: center;
  color: color-mix(in srgb, var(--brand-500) 40%, var(--bg-muted));
  background:
    radial-gradient(120% 160% at 20% 0%,
      color-mix(in srgb, var(--brand-500) 10%, transparent), transparent 60%),
    var(--bg-muted);
}

/* 窄屏回退到上图下文时，水印块不需要 16:9 那么高 */
@media (max-width: 767px) {
  .post-card__cover--fallback { aspect-ratio: auto; height: 110px; }
}

/* 「相关文章」迷你卡片：小方图 + 两行标题，3~4 列自适应。
   之前复用整块 post-card（16:9 大封面），一张卡片快一屏高，
   相关文章区比正文还长，喧宾夺主。 */
.related-grid {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  gap: var(--space-3);
}
.related-card {
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  overflow: hidden;
  transition: border-color var(--dur-fast) var(--ease-out),
              box-shadow var(--dur-fast) var(--ease-out);
}
.related-card:hover {
  border-color: color-mix(in srgb, var(--brand-500) 45%, var(--border));
  box-shadow: var(--shadow-sm);
}
.related-card__link {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-3) var(--space-2) var(--space-2);
  color: inherit;
  text-decoration: none;
  min-width: 0;
}
.related-card__thumb {
  flex: 0 0 56px;
  width: 56px;
  height: 56px;
  border-radius: var(--radius-sm);
  object-fit: cover;
  background: var(--bg-muted);
}
.related-card__thumb--fallback {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: color-mix(in srgb, var(--brand-500) 45%, var(--bg-muted));
}
.related-card__thumb--fallback .icon { width: 20px; height: 20px; }
.related-card__body {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 3px;
}
.related-card__title {
  font-size: var(--text-sm);
  line-height: 1.4;
  color: var(--text-body);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.related-card__link:hover .related-card__title { color: var(--brand-500); }
.related-card__meta {
  font-size: var(--text-xs);
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
}

.post-card__body {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-5);
  flex: 1;
}

.post-card__meta-top {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

.post-card__title {
  margin: 0;
  font-size: var(--text-lg);
  line-height: var(--leading-snug);
}
.post-card__title a {
  color: var(--text-strong);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.post-card__title a:hover { color: var(--brand-500); }

.post-card__excerpt {
  margin: 0;
  color: var(--text-muted);
  font-size: var(--text-sm);
  line-height: var(--leading-normal);
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.post-card__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3);
  margin-top: auto;
  padding-top: var(--space-3);
  border-top: 1px solid var(--border);
  color: var(--text-muted);
  font-size: var(--text-xs);
  font-variant-numeric: tabular-nums;
}
.post-card__meta > * {
  display: inline-flex;
  align-items: center;
  gap: 4px;
}
.post-card__meta .icon { width: 13px; height: 13px; opacity: .85; }

/* --- 分页 ---------------------------------------------------------------- */

.pagination {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  margin-top: var(--space-8);
  justify-content: center;
}
.pagination__item {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 36px;
  height: 36px;
  padding: 0 var(--space-3);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--bg-surface);
  color: var(--text-body);
  font-size: var(--text-sm);
  transition: all var(--dur-fast) var(--ease-out);
}
.pagination__item:hover { border-color: var(--brand-500); color: var(--brand-500); }
.pagination__item.is-active {
  background: var(--brand-500);
  border-color: var(--brand-500);
  color: var(--text-on-brand);
  font-weight: 500;
  box-shadow: 0 2px 8px color-mix(in srgb, var(--brand-500) 35%, transparent);
}
.pagination__item.is-disabled { opacity: .45; cursor: not-allowed; }
.pagination__ellipsis { color: var(--text-muted); }
.pagination__info {
  margin: var(--space-3) 0 0;
  text-align: center;
  color: var(--text-muted);
  font-size: var(--text-xs);
  font-variant-numeric: tabular-nums;
}
.pagination__item .icon { width: 14px; height: 14px; }

/* --- 空状态与错误页 ------------------------------------------------------ */

.empty, .error-page {
  padding: var(--space-16) var(--space-6);
  text-align: center;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: 0 1px 2px rgba(0,0,0,.04), 0 12px 40px -24px rgba(0,0,0,.18);
}
.empty__icon { margin: 0 0 var(--space-4); }
.empty__icon .icon {
  width: 44px;
  height: 44px;
  color: color-mix(in srgb, var(--brand-500) 40%, var(--text-muted));
}
.empty__title { margin: 0 0 var(--space-2); font-size: var(--text-xl); color: var(--text-strong); }
.empty__hint { margin: 0 0 var(--space-5); color: var(--text-muted); font-size: var(--text-sm); }
.empty__actions, .error-page__actions {
  display: flex; flex-wrap: wrap; gap: var(--space-3); justify-content: center;
}

.error-page__code {
  margin: 0;
  font-size: 96px;
  font-weight: 800;
  line-height: 1;
  letter-spacing: .04em;
  background: linear-gradient(135deg,
      var(--brand-500),
      color-mix(in srgb, var(--brand-500) 30%, transparent));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.error-page__title {
  font-size: var(--text-2xl, 1.5rem);
  font-weight: 700;
}
.error-page__title { margin: var(--space-3) 0 var(--space-2); }
.error-page__message { margin: 0 0 var(--space-6); color: var(--text-muted); }

/* --- 侧边栏 -------------------------------------------------------------- */
/* 侧栏区块整体收紧：首页 8 个区块全开时总高度要与正文相当，
   每个区块省下的一点留白乘以 8 就是几百像素的失衡。 */

.widget {
  padding: var(--space-4);
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-xs);
}
.widget + .widget { margin-top: var(--space-4); }

/* 标签球区块：左右内边距收到 8px。
   侧栏列固定 300px，减去 .widget 默认左右各 16px 只剩 268px，
   球体被压小后标签更容易挤在一起。标签球是纯图形、没有文字段落，
   不需要普通区块的文字内边距，把省下的 16px 让给球体直径。
   这条必须写在 .widget 之后：两者同为单类选择器，
   .widget 的 padding 简写会覆盖先出现的 padding-left/right。 */
.widget--sphere {
  overflow: hidden;
  padding-left: var(--space-2);
  padding-right: var(--space-2);
}

.widget__title {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin: 0 0 var(--space-3);
  padding-bottom: var(--space-2);
  border-bottom: 1px solid var(--border);
  font-size: var(--text-base);
  /* 区块标题用中黑体（500）：在 700 的正文标题旁边更轻盈 */
  font-weight: 500;
}
/* 图标替代原先的色条：品牌色线性图标与标题文字并排 */
.widget__title .icon {
  width: 16px;
  height: 16px;
  color: var(--brand-500);
}
.widget__more {
  margin: var(--space-2) 0 0;
  padding-top: var(--space-2);
  border-top: 1px dashed var(--border);
  font-size: var(--text-xs);
  text-align: center;
}
.widget__more a {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  color: var(--text-muted);
}
.widget__more a:hover { color: var(--brand-500); }
.widget__more .icon { width: 12px; height: 12px; }

.cat-list, .archive-list, .link-list, .stats-list {
  margin: 0;
  padding: 0;
  list-style: none;
}
.cat-list li + li, .archive-list li + li, .link-list li + li { margin-top: 2px; }

.cat-list a, .archive-list a {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  padding: 5px var(--space-2);
  border-radius: var(--radius-md);
  color: var(--text-body);
  font-size: var(--text-sm);
  transition: background var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
}
.cat-list a:hover, .archive-list a:hover {
  background: var(--bg-muted);
  color: var(--brand-500);
}
.cat-list__count, .archive-list__count {
  flex-shrink: 0;
  min-width: 22px;
  padding: 0 var(--space-2);
  border-radius: var(--radius-pill);
  background: var(--bg-muted);
  color: var(--text-muted);
  font-size: var(--text-xs);
  line-height: 18px;
  text-align: center;
}
/* 分类焦点轮播（cat-sweep 岛屿）：高亮依次扫过，提示"这里还有更多内容" */
.cat-list li.is-spot a {
  background: color-mix(in srgb, var(--brand-500) 9%, transparent);
  color: var(--brand-500);
}
.cat-list li.is-spot .cat-list__count {
  background: var(--brand-500);
  color: var(--text-on-brand);
}

/* 分类多时一列排完会把侧栏拉得比正文还长（实测 21 个分类 800px 高），
   宽屏下两列排布，高度几乎减半；子分类保留原有的缩进前缀。 */
@media (min-width: 992px) {
  .widget--categories .cat-list {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 2px var(--space-1);
  }
  .widget--categories .cat-list li + li { margin-top: 0; }
  .widget--categories .cat-list a { padding-left: 0; padding-right: 0; }
}

.mini-list { margin: 0; padding: 0; list-style: none; counter-reset: mini; font-variant-numeric: tabular-nums; }
.mini-list__item {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
  padding: 6px 0;
  font-size: var(--text-sm);
}
.mini-list__item + .mini-list__item { border-top: 1px dashed var(--border); }
.mini-list__rank {
  flex-shrink: 0;
  width: 18px;
  height: 18px;
  border-radius: var(--radius-sm);
  background: var(--bg-muted);
  color: var(--text-muted);
  font-size: var(--text-xs);
  font-weight: 500;
  line-height: 18px;
  text-align: center;
}
/* 前三名用品牌色突出，这是列表里唯一需要"排名感"的地方 */
.mini-list__item:nth-child(-n+3) .mini-list__rank {
  background: var(--brand-500);
  color: var(--text-on-brand);
}
.mini-list__link {
  flex: 1;
  min-width: 0;
  color: var(--text-body);
  display: -webkit-box;
  -webkit-line-clamp: 1;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.mini-list__link:hover { color: var(--brand-500); }
.mini-list__time { flex-shrink: 0; color: var(--text-muted); font-size: var(--text-xs); }

.tag-cloud { display: flex; flex-wrap: wrap; gap: var(--space-1) var(--space-2); }
.tag-cloud__item {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  padding: 2px var(--space-2);
  border-radius: var(--radius-pill);
  background: var(--bg-muted);
  color: var(--text-body);
  transition: all var(--dur-fast) var(--ease-out);
}
.tag-cloud__item:hover { background: var(--brand-500); color: var(--text-on-brand); }
/* 字号随文章数加权，档位由服务端算好 */
.tag-cloud__item--w1 { font-size: var(--text-xs); }
.tag-cloud__item--w2 { font-size: var(--text-xs); }
.tag-cloud__item--w3 { font-size: var(--text-sm); }
.tag-cloud__item--w4 { font-size: var(--text-base); }
.tag-cloud__item--w5 { font-size: var(--text-lg); font-weight: 500; }
.tag-cloud__count { color: var(--text-muted); font-size: var(--text-xs); }
.tag-cloud__item:hover .tag-cloud__count { color: inherit; opacity: .8; }
.tag-cloud--page { gap: var(--space-3); }

.comment-mini { margin: 0; padding: 0; list-style: none; }
/* 评论锚点（#comment-{id}）跳转时避开吸顶页头 */
.comment { scroll-margin-top: 80px; }

/* --- 侧栏滚动区块（最新评论 / 热门文章） ----------------------------------
   视口固定高度由 JS 按条目高度设置，轨道装「原列表 + 复制份」实现无缝循环。
   两种节奏：评论逐条步进（transition 由 JS 内联控制），
   热门文章线性匀速（widget-marquee 关键帧）。悬停一律暂停。 */
.widget-ticker { overflow: hidden; position: relative; }
.widget-ticker__track {
  display: flex;
  flex-direction: column;
}
.widget-ticker__track > ul,
.widget-ticker__track > ol {
  flex: none;
  width: 100%;
  margin: 0;
}
.widget-ticker:hover .widget-ticker__track { animation-play-state: paused; }
@keyframes widget-marquee {
  to { transform: translateY(-50%); }
}
/* 「减少动效」的处理在 JS 岛屿入口短路（不复制列表、不设高度、不启动动画），
   CSS 这里不做 !important 覆盖：它会压掉 JS 写入的内联高度与动画，
   让滚动区块在减少动效的机器上连 ?_motion=1 预览都无法工作（实测踩过）。 */
.comment-mini__item { padding: var(--space-2) 0; font-size: var(--text-sm); }
.comment-mini__item + .comment-mini__item { border-top: 1px dashed var(--border); }
/* 整条评论可点：直达文章里的对应评论 */
.comment-mini__link {
  display: block;
  color: inherit;
  text-decoration: none;
  border-radius: var(--radius-sm);
  transition: background var(--dur-fast) var(--ease-out);
}
a.comment-mini__link:hover { background: var(--bg-muted); }
a.comment-mini__link:hover .comment-mini__author { color: var(--brand-500); }
.comment-mini__author { margin: 0; font-weight: 500; color: var(--text-strong); }
.comment-mini__text {
  margin: 2px 0 0;
  color: var(--text-muted);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.comment-mini__meta {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-top: 3px;
  min-width: 0;
}
.comment-mini__post {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  min-width: 0;
  font-size: var(--text-xs);
  color: var(--brand-500);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.comment-mini__post .icon { width: 11px; height: 11px; flex-shrink: 0; }
.comment-mini__time { color: var(--text-muted); font-size: var(--text-xs); flex-shrink: 0; margin-left: auto; }

/* 友链：图标 + 名称。没有图标的友链用名称首字符的圆角块占位，
   比一列裸文字更有辨识度，也和后台的图标字段对得上。 */
.link-list a {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: 4px var(--space-2);
  border-radius: var(--radius-md);
  color: var(--text-body);
  font-size: var(--text-sm);
  transition: background var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
}
.link-list a:hover { background: var(--bg-muted); color: var(--brand-500); }
.link-list__name {
  flex: 1;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.link-list__icon {
  flex-shrink: 0;
  width: 20px;
  height: 20px;
  border-radius: var(--radius-sm);
  object-fit: cover;
}
.link-list__icon--letter {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: color-mix(in srgb, var(--brand-500) 14%, transparent);
  color: var(--brand-500);
  font-size: var(--text-xs);
  font-weight: 500;
  line-height: 1;
}
.link-list__ext {
  flex-shrink: 0;
  color: var(--text-muted);
  opacity: 0;
  transition: opacity var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
}
.link-list__ext .icon { width: 13px; height: 13px; }
.link-list a:hover .link-list__ext { opacity: 1; color: var(--brand-500); }

/* 侧栏友链的图片模式：一行一个图标，名称靠悬停的 title 与 alt 提供。
   图标放大到 28px，一行一个才看得清是什么站点。 */
.link-list--logo a { padding: 5px var(--space-2); }
.link-list--logo .link-list__icon {
  width: 28px;
  height: 28px;
  border-radius: var(--radius-md);
}
.link-list__name-fallback {
  flex: 1;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.stats-list {
  display: grid;
  /* 7 项数字按 4+3 两行排：比 3 列多出的一行只有 1 项好看 */
  grid-template-columns: repeat(4, 1fr);
  gap: var(--space-3);
  text-align: center;
  font-variant-numeric: tabular-nums;
}
.stats-list__num { display: block; font-size: var(--text-lg); font-weight: 500; color: var(--brand-500); }
.stats-list__label { display: block; color: var(--text-muted); font-size: var(--text-xs); }

/* --- 热点标签球下方的二维码 ------------------------------------------------ */
/* 图片地址来自后台设置 sidebar.qrcode_image，留空整块不渲染 */
.sphere-qrcode {
  margin: var(--space-4) 0 0;
  display: flex;
  justify-content: center;
}
.sphere-qrcode img {
  width: 148px;
  height: auto;
  padding: 6px;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-xs);
}

/* --- 文章详情 ------------------------------------------------------------ */

.post {
  padding: var(--space-6);
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
}
@media (min-width: 768px) {
  .post { padding: var(--space-10); }
}

.post__header { margin-bottom: var(--space-6); }
.post__title {
  margin: 0 0 var(--space-4);
  font-size: var(--text-3xl);
  line-height: var(--leading-tight);
  letter-spacing: -0.02em;
}
.post__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-4);
  color: var(--text-muted);
  font-size: var(--text-sm);
  font-variant-numeric: tabular-nums;
}
.post__meta > * {
  display: inline-flex;
  align-items: center;
  gap: 5px;
}
.post__meta .icon { width: 14px; height: 14px; opacity: .85; }
.post__cats { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-top: var(--space-3); }

.post__toc {
  margin-bottom: var(--space-6);
  padding: var(--space-4) var(--space-5);
  background: var(--bg-muted);
  border-radius: var(--radius-md);
  font-size: var(--text-sm);
}

.post__footer { margin-top: var(--space-8); }
.post__tags {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  padding-top: var(--space-5);
  border-top: 1px solid var(--border);
}
.post__tags-label {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  color: var(--text-muted);
  font-size: var(--text-sm);
}
.post__tags-label .icon { width: 14px; height: 14px; }

.post__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  margin-top: var(--space-5);
}

.post__copyright {
  margin-top: var(--space-5);
  padding: var(--space-4);
  background: var(--bg-muted);
  border-left: 3px solid var(--brand-500);
  border-radius: 0 var(--radius-md) var(--radius-md) 0;
  color: var(--text-muted);
  font-size: var(--text-xs);
  line-height: var(--leading-normal);
}
.post__copyright p { margin: 0; }

.post-nav {
  display: grid;
  gap: var(--space-3);
  margin-top: var(--space-6);
}
@media (min-width: 768px) {
  .post-nav { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
.post-nav__item {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  padding: var(--space-4) var(--space-5);
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  transition: border-color var(--dur-fast) var(--ease-out), box-shadow var(--dur-fast) var(--ease-out);
}
.post-nav__item:not(.is-empty):hover { border-color: var(--brand-500); box-shadow: var(--shadow-sm); }
.post-nav__item.is-empty { background: transparent; border-style: dashed; }
.post-nav__label { color: var(--text-muted); font-size: var(--text-xs); }
.post-nav__title {
  color: var(--text-strong);
  font-size: var(--text-sm);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.related { margin-top: var(--space-10); }

/* --- 评论 ---------------------------------------------------------------- */

.comments { margin-top: var(--space-10); }
.comment-list { margin: 0; padding: 0; list-style: none; }
.comment-list--child { margin: var(--space-3) 0 0 var(--space-5); }

.comment {
  padding: var(--space-4);
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
}
.comment + .comment { margin-top: var(--space-3); }
.comment--child { background: var(--bg-muted); }

.comment__head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3);
  margin-bottom: var(--space-2);
}
.comment__author { font-weight: 500; color: var(--text-strong); font-size: var(--text-sm); }
.comment__time { color: var(--text-muted); font-size: var(--text-xs); }
.comment__body {
  color: var(--text-body);
  font-size: var(--text-sm);
  line-height: var(--leading-normal);
  overflow-wrap: anywhere;
  /* 评论按纯文本存储与输出，换行靠 CSS 呈现：
     不加这句的话用户敲的回车会被 HTML 折叠掉，整段挤成一行 */
  white-space: pre-line;
}
.comments__empty, .comments__closed {
  padding: var(--space-6);
  text-align: center;
  color: var(--text-muted);
  font-size: var(--text-sm);
  background: var(--bg-surface);
  border: 1px dashed var(--border);
  border-radius: var(--radius-lg);
}

/* --- 归档 ---------------------------------------------------------------- */

.archive__year { margin-bottom: var(--space-8); }
.archive__year-title {
  display: flex;
  align-items: baseline;
  gap: var(--space-3);
  margin: 0 0 var(--space-4);
  font-size: var(--text-xl);
}
.archive__year-count { color: var(--text-muted); font-size: var(--text-sm); font-weight: 400; }
.archive__months {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
  gap: var(--space-3);
  margin: 0;
  padding: 0;
  list-style: none;
}
.archive__month a {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-3) var(--space-4);
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  color: var(--text-body);
  font-size: var(--text-sm);
  transition: all var(--dur-fast) var(--ease-out);
}
.archive__month a:hover {
  border-color: var(--brand-500);
  color: var(--brand-500);
  box-shadow: var(--shadow-sm);
}
.archive__month-count { color: var(--text-muted); font-size: var(--text-xs); }

/* 页面容器 */
.page {
  padding: var(--space-6);
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
}
@media (min-width: 768px) { .page { padding: var(--space-10); } }

/* --- 页脚 ----------------------------------------------------------------
   分层结构：主区（品牌列 + 导航列 + 合规列）→ 友情链接条 → 版权栏。
   颜色全部走 token：三套主题只覆盖变量，页脚样式自动跟随。
   顶部一条品牌渐变发丝线，与全站「品牌渐变只做点缀」的语言一致。 */

.site-footer {
  margin-top: var(--space-16);
  background: color-mix(in srgb, var(--bg-muted) 42%, var(--bg-surface));
  border-top: 1px solid var(--border);
}
/* 渐变发丝线：footer 顶部的唯一装饰 */
.site-footer::before {
  content: "";
  display: block;
  height: 2px;
  background: linear-gradient(90deg,
    transparent,
    color-mix(in srgb, var(--brand-500) 60%, transparent) 30%,
    color-mix(in srgb, var(--accent-500) 60%, transparent) 70%,
    transparent);
}

.site-footer__main {
  display: grid;
  gap: var(--space-8);
  padding: var(--space-8) 0 var(--space-8);
}
@media (min-width: 768px) {
  .site-footer__main {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--space-8) var(--space-10);
  }
  /* 平板：品牌块整行铺开，两列并排在下一行 */
  .site-footer__brand { grid-column: 1 / -1; }
}
@media (min-width: 992px) {
  .site-footer__main { grid-template-columns: 1.5fr 1fr 1fr; }
  /* 没有合规信息时收缩成两列，不给他列留空位 */
  .site-footer--two-cols .site-footer__main { grid-template-columns: 1.5fr 1fr; }
  .site-footer__brand { grid-column: auto; }
}

/* 品牌列 */
.site-footer__name {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0 0 var(--space-4);
  font-size: var(--text-lg);
  font-weight: 500;
  letter-spacing: -.01em;
  color: var(--text-strong);
}
.site-footer__logo,
.site-footer__name .icon {
  width: 30px;
  height: 30px;
  flex-shrink: 0;
  border-radius: 8px;
  object-fit: contain;
}
.site-footer__name .icon { color: var(--brand-500); }

/* 关键词胶囊：站点描述本身是 SEO 关键词串，整段渲染就是一堵字墙，
   拆成小胶囊既保留信息又透气（模板侧已截到 12 个） */
.site-footer__kws {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 0 0 var(--space-5);
  padding: 0;
  list-style: none;
  max-width: 46ch;
}
.site-footer__kws li {
  padding: 3px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  color: var(--text-muted);
  font-size: 12px;
  line-height: 1.7;
  transition: color var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out);
}
.site-footer__kws li:hover {
  color: var(--brand-500);
  border-color: color-mix(in srgb, var(--brand-500) 40%, var(--border));
}
.site-footer__desc {
  margin: 0 0 var(--space-5);
  max-width: 52ch;
  color: var(--text-muted);
  font-size: var(--text-sm);
  line-height: 1.75;
  /* 无关键词时的整段简介：三行截断，完整内容在 meta description 里 */
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.site-footer__rss { margin: 0; }
.site-footer__rss a {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 16px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-pill);
  background: var(--bg-surface);
  color: var(--text-body);
  font-size: var(--text-xs);
  font-weight: 500;
  transition: border-color var(--dur-fast) var(--ease-out),
              color var(--dur-fast) var(--ease-out),
              background var(--dur-fast) var(--ease-out);
}
.site-footer__rss a:hover {
  border-color: var(--brand-500);
  color: var(--brand-500);
  background: color-mix(in srgb, var(--brand-500) 6%, var(--bg-surface));
}
.site-footer__rss .icon { width: 14px; height: 14px; }

/* 链接列（导航 / 合规） */
.site-footer__col { min-width: 0; }
.site-footer__heading {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0 0 var(--space-4);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: .12em;
  color: var(--text-strong);
}
/* 列标题前的小渐变短杠：与卡片标题同一套视觉语言 */
.site-footer__heading::before {
  content: "";
  width: 12px;
  height: 3px;
  border-radius: var(--radius-pill);
  background: linear-gradient(90deg, var(--brand-500), var(--accent-500));
}
.site-footer__list {
  margin: 0;
  padding: 0;
  list-style: none;
}
.site-footer__list li + li { margin-top: var(--space-2); }
.site-footer__list a {
  color: var(--text-muted);
  font-size: var(--text-sm);
  transition: color var(--dur-fast) var(--ease-out);
}
.site-footer__list a:hover { color: var(--brand-500); }
.site-footer__list .icon { width: 13px; height: 13px; margin-right: 4px; vertical-align: -2px; }

/* --- 页脚友情链接：胶囊芯片行 ------------------------------------------- */

.site-footer__links {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2) var(--space-3);
  padding-top: var(--space-6);
  padding-bottom: var(--space-6);
  border-top: 1px solid var(--border);
  font-size: var(--text-xs);
}
.site-footer__links-title { margin-right: var(--space-2); }
.site-footer__links-title .icon { width: 14px; height: 14px; color: var(--brand-500); }

.footer-links {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin: 0;
  padding: 0;
  list-style: none;
}
.footer-links a {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  background: var(--bg-surface);
  color: var(--text-muted);
  transition: border-color var(--dur-fast) var(--ease-out),
              color var(--dur-fast) var(--ease-out),
              background var(--dur-fast) var(--ease-out);
}
.footer-links a:hover {
  border-color: color-mix(in srgb, var(--brand-500) 45%, var(--border));
  color: var(--brand-500);
  background: color-mix(in srgb, var(--brand-500) 5%, var(--bg-surface));
}
.footer-links__icon {
  width: 16px;
  height: 16px;
  border-radius: var(--radius-sm);
  object-fit: cover;
  flex-shrink: 0;
}
.footer-links__icon--letter {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: color-mix(in srgb, var(--brand-500) 14%, transparent);
  color: var(--brand-500);
  font-size: 10px;
  font-weight: 500;
  line-height: 1;
}
/* 图片模式：只有图标，没有文字，所以给图标留大一点，否则整行像一排小点 */
.footer-links--logo { gap: var(--space-2); }
.footer-links--logo a { padding: 4px; }
.footer-links--logo .footer-links__icon {
  width: 26px;
  height: 26px;
  border-radius: 8px;
}
/* 图片模式里没配图标、也抓不到站点图标的链接：退回名称文字，
   不留空位也不显示裂图 */
.footer-links--logo .footer-links__name-fallback {
  padding: 0 8px;
  color: var(--text-muted);
}

/* --- 页脚 ----------------------------------------------------------------
   极简三件事：友情链接（图标 + 文字）+ 一条元信息行（RSS 订阅 / 备案号）。
   磨砂玻璃底 + 顶部渐变发丝线，与后台同一套设计语言。
   （旧版的多列品牌区/关键词胶囊已按需求移除，样式一并清理。） */

.site-footer {
  margin-top: var(--space-16);
  background: color-mix(in srgb, var(--bg-muted) 42%, var(--bg-surface));
  border-top: 1px solid var(--border);
}
.site-footer::before {
  content: "";
  display: block;
  height: 2px;
  background: linear-gradient(90deg,
    transparent,
    color-mix(in srgb, var(--brand-500) 60%, transparent) 30%,
    color-mix(in srgb, var(--accent-500) 60%, transparent) 70%,
    transparent);
}

/* 友情链接：芯片行，图标 + 文字（图标缺失时只显示文字，不留空位） */
.site-footer__links {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2) var(--space-3);
  max-width: 1080px;
  margin-inline: auto;
  padding: var(--space-5) var(--space-4);
  font-size: 12px;
}
.site-footer__links-title {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  margin-right: var(--space-2);
  color: var(--text-strong);
  font-weight: 500;
}
.site-footer__links-title .icon { width: 14px; height: 14px; color: var(--brand-500); }

.footer-links {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin: 0;
  padding: 0;
  list-style: none;
}
.footer-links a {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 4px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  background: var(--bg-surface);
  color: var(--text-body);
  font-size: 12px;
  transition: border-color var(--dur-fast) var(--ease-out),
              color var(--dur-fast) var(--ease-out),
              background var(--dur-fast) var(--ease-out);
}
.footer-links a:hover {
  border-color: color-mix(in srgb, var(--brand-500) 45%, var(--border));
  color: var(--brand-500);
  background: color-mix(in srgb, var(--brand-500) 5%, var(--bg-surface));
}
.footer-links__icon {
  width: 16px;
  height: 16px;
  border-radius: 5px;
  object-fit: cover;
  flex-shrink: 0;
}
.footer-links__icon--letter {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: color-mix(in srgb, var(--brand-500) 14%, transparent);
  color: var(--brand-500);
  font-size: 10px;
  font-weight: 500;
  line-height: 1;
}
/* 图标加载失败被 link-icons.js 换成首字块时保持尺寸 */
.footer-links__name-fallback { color: var(--text-muted); }

/* 元信息行：RSS 订阅在左，备案号在右 */
.site-footer__bar { border-top: 1px solid var(--border); }
.site-footer__bar-inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2) var(--space-5);
  max-width: 1080px;
  margin-inline: auto;
  padding: var(--space-4) var(--space-4);
}
.site-footer__rss {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: var(--text-muted);
  font-size: 12px;
  transition: color var(--dur-fast) var(--ease-out);
}
.site-footer__rss:hover { color: var(--brand-500); }
.site-footer__rss .icon { width: 13px; height: 13px; }
.site-footer__beian {
  color: var(--text-muted);
  font-size: 12px;
}
.site-footer__beian a { color: var(--text-muted); }
.site-footer__beian a:hover { color: var(--brand-500); }

/* --------------------------------------------------------------------------
   文章附件下载区（前台文章页）
   作者在后台给文章上传了附件时出现，位置在正文之后、版权信息之前。
   -------------------------------------------------------------------------- */
.post-attachments {
  margin-top: var(--space-6);
  padding: var(--space-4) var(--space-5);
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-xs);
}
.post-attachments__title {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0 0 var(--space-3);
  font-size: 15px;
  font-weight: 500;
  color: var(--text-strong);
}
.post-attachments__title .icon { width: 16px; height: 16px; color: var(--brand-500); }
.post-attachments__list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.post-attachment {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 8px 12px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--bg-inset);
  transition: border-color var(--dur-fast) var(--ease-out), background var(--dur-fast) var(--ease-out);
}
.post-attachment:hover {
  border-color: color-mix(in srgb, var(--brand-500) 35%, var(--border));
  background: color-mix(in srgb, var(--brand-500) 3%, var(--bg-inset));
}
.post-attachment__ext {
  flex-shrink: 0;
  padding: 2px 8px;
  border-radius: 6px;
  background: color-mix(in srgb, var(--brand-500) 12%, transparent);
  color: var(--brand-500);
  font-size: 10.5px;
  font-weight: 500;
  letter-spacing: .05em;
  text-transform: uppercase;
}
.post-attachment__name {
  flex: 1;
  min-width: 0;
  color: var(--text-body);
  font-size: 13px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.post-attachment__name:hover { color: var(--brand-500); }
.post-attachment__size {
  flex-shrink: 0;
  color: var(--text-muted);
  font-size: 11.5px;
  font-variant-numeric: tabular-nums;
}
.post-attachment__btn {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  flex-shrink: 0;
  padding: 4px 13px;
  border-radius: var(--radius-pill);
  background: var(--brand-500);
  color: #fff;
  font-size: 12px;
  transition: filter var(--dur-fast) var(--ease-out);
}
.post-attachment__btn:hover {
  color: #fff;
  filter: brightness(1.1);
}
.post-attachment__btn .icon { width: 13px; height: 13px; }

/* --- 移动端抽屉与搜索弹层（岛屿接管后填充内容） ------------------------ */

.drawer {
  position: fixed;
  inset: 0 auto 0 0;
  z-index: 100;
  width: min(84vw, 320px);
  background: var(--bg-surface);
  box-shadow: var(--shadow-xl);
  transform: translateX(-100%);
  transition: transform var(--dur-base) var(--ease-out);
  overflow-y: auto;
}
.drawer.is-open { transform: translateX(0); }
.drawer[hidden] { display: none; }
/* 桌面端守卫：抽屉只在有汉堡按钮的窄屏有意义。
   若在窄屏打开抽屉后窗口被拉宽（转屏、拖拽分屏），
   没有这条规则抽屉会一直悬在左侧且无法关闭。 */
@media (min-width: 992px) {
  .drawer { display: none; }
}

/* 站内搜索：内嵌下拉面板。
   容器是页头 inner（见 .site-header__inner 的 position:relative），
   面板钉在放大镜所在的右侧下方，不遮罩、不锁滚动。 */
.search-drop {
  position: absolute;
  top: calc(100% + 10px);
  right: var(--space-4);
  z-index: 60;
  /* 宽度相对页头容器解析：100vw 会把滚动条也算进去，
     在有滚动条的窗口上会让面板歪出对称边距 */
  width: min(calc(100% - 2 * var(--space-4)), 380px);
  padding: var(--space-4);
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
}
.search-drop[hidden] { display: none; }
.search-drop__form { position: relative; }
.search-drop__icon {
  position: absolute;
  left: var(--space-3);
  top: 50%;
  transform: translateY(-50%);
  display: inline-flex;
  color: var(--text-muted);
  pointer-events: none;
}
.search-drop__icon .icon { width: 16px; height: 16px; }
.search-drop__input {
  width: 100%;
  height: 40px;
  padding: 0 var(--space-3) 0 calc(var(--space-8) - 6px);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-md);
  background: var(--bg-body);
  color: var(--text-body);
  font-size: var(--text-sm);
}
.search-drop__input:focus { border-color: var(--brand-500); outline: none; }
.search-drop__hint { margin: var(--space-2) 0 0; color: var(--text-muted); font-size: var(--text-xs); }

/* --- 正文排版 ------------------------------------------------------------ */
/* 技术博客的核心是代码与中文都要好读，这部分单独成节 */

.post__content, .page .post__content {
  max-width: var(--content-max);
  font-size: var(--text-lg);
  line-height: var(--leading-relaxed);
  color: var(--text-body);
  overflow-wrap: break-word;
}

.post__content > * + * { margin-top: var(--space-5); }
.post__content p { margin: 0; }

.post__content h2, .post__content h3, .post__content h4 {
  margin-top: var(--space-10);
  margin-bottom: var(--space-4);
  scroll-margin-top: 80px; /* 锚点跳转时避开吸顶页头 */
}
.post__content h2 { font-size: var(--text-2xl); }
.post__content h3 { font-size: var(--text-xl); }

.post__content a {
  border-bottom: 1px solid color-mix(in srgb, var(--brand-500) 40%, transparent);
}
.post__content a:hover { border-bottom-color: var(--brand-500); }

.post__content img {
  display: block;
  max-width: 100%;
  height: auto;
  margin: var(--space-5) auto;
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);
}
.post__content .aligncenter { margin-left: auto; margin-right: auto; }
.post__content .alignleft { margin-left: 0; }
.post__content .alignright { margin-right: 0; }

.post__content ul, .post__content ol { padding-left: 1.5em; }
.post__content li + li { margin-top: var(--space-2); }

.post__content blockquote {
  margin: var(--space-6) 0;
  padding: var(--space-4) var(--space-5);
  background: var(--bg-muted);
  border-left: 3px solid var(--brand-500);
  border-radius: 0 var(--radius-md) var(--radius-md) 0;
  color: var(--text-muted);
}
.post__content blockquote p:last-child { margin-bottom: 0; }

.post__content hr {
  margin: var(--space-10) 0;
  border: none;
  border-top: 1px solid var(--border);
}

/* 行内代码：与正文区分但不刺眼 */
.post__content :not(pre) > code {
  padding: .15em .4em;
  border-radius: var(--radius-sm);
  background: var(--bg-muted);
  color: var(--color-code-inline, var(--danger));
  font-size: .9em;
  overflow-wrap: anywhere;
}

/* 表格：移动端横向滚动，不撑破布局 */
.post__content table {
  display: block;
  width: 100%;
  overflow-x: auto;
  border-collapse: collapse;
  font-size: var(--text-sm);
}
.post__content th, .post__content td {
  padding: var(--space-3);
  border: 1px solid var(--border);
  text-align: left;
}
.post__content thead th { background: var(--bg-muted); font-weight: 500; }
.post__content tbody tr:nth-child(even) { background: color-mix(in srgb, var(--bg-muted) 50%, transparent); }

/* 代码块。
   结构由服务端清洗统一为 <pre class="code-block"><code class="language-x">，
   见 docs/PLAN.md §2.6。这里只负责外观，高亮由 highlight.js 在客户端补上。 */
.post__content pre {
  position: relative;
  margin: var(--space-6) 0;
  padding: var(--space-4) var(--space-5);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--color-code-bg);
  color: var(--color-code-fg);
  font-size: var(--text-sm);
  line-height: 1.7;
  overflow-x: auto;
  tab-size: 4;
}
.post__content pre code {
  display: block;
  padding: 0;
  background: none;
  color: inherit;
  font-size: inherit;
  white-space: pre;
}

/* 代码块右上角工具区（复制按钮等），由 code-tools 岛屿填充 */
.post__content pre .code-tools {
  position: absolute;
  top: var(--space-2);
  right: var(--space-2);
  display: flex;
  gap: var(--space-1);
}

@media (max-width: 767px) {
  /* 移动端正文略小、行高略紧，避免一屏看不到几行 */
  .post__content { font-size: var(--text-base); }
  .post { padding: var(--space-4); }
  .post__title { font-size: var(--text-2xl); }
}
