/* ==========================================================================
   装修情报站 · 前台样式
   所有颜色 / 圆角 / 字体 / 间距都来自主题变量（由 lib/themes.mjs 注入 :root），
   因此切换主题预设或覆盖主色时，本文件不需要任何改动。
   ========================================================================== */

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--c-bg);
  color: var(--c-text);
  font-family: var(--font-sans);
  font-size: var(--fs-base);
  line-height: var(--lh-base);
  -webkit-font-smoothing: antialiased;
  /* 全站兜底：上游内容里的超长不可断串（网址、连续英文、编号串）不得撑破版面 */
  overflow-wrap: break-word;
}

img { max-width: 100%; height: auto; display: block; }
/*
 * 链接色：默认继承所在容器的颜色（正文色）；皮肤里写 `linkColor` 时用 `--link-color` 统一指定
 * （参考站那类「链接不是蓝色、而是近黑 #262626」的做法）。悬停仍然是主色，与参考站一致。
 * 正文里的站内链接（.article__body a）另有一条更具体的规则，仍然是主色带下划线。
 */
a { color: var(--link-color, inherit); text-decoration: none; }
a:hover { color: var(--c-primary); }
h1, h2, h3, h4 { font-family: var(--font-title); color: var(--c-heading); line-height: 1.35; margin: 0; }
p { margin: 0; }
ul, ol { margin: 0; padding: 0; }
button { font: inherit; cursor: pointer; }
input, select, textarea { font: inherit; }

:focus-visible { outline: 2px solid var(--c-primary); outline-offset: 2px; }

/*
 * 内容区左右留白。抽成令牌是为了让**全幅块**（通栏大图带、通栏引导块）里的文字也能跟正文对齐：
 * 它们不在 .container.page 里，靠内层 .container 的左右内边距对齐；而内层元素往往还要给自己加
 * 上下留白，写成 padding 简写就会把容器的左右内边距一起清零（真实反馈：「通栏大图带的标题和摘要
 * 都贴了左边界」）。所以内层的上下留白一律写长写，左右留白要显式给回来时用 var(--gutter)。
 */
:root { --gutter: 20px; }
.container { width: 100%; max-width: var(--container); margin: 0 auto; padding: 0 var(--gutter); }

/* 仅供屏幕阅读器与结构层次使用（例如栏目页的列表标题） */
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

.skip-link {
  position: absolute; left: -9999px; top: 0; z-index: 100;
  background: var(--c-primary); color: var(--c-primary-fg); padding: 10px 18px; border-radius: 0 0 var(--radius-sm) 0;
}
.skip-link:focus { left: 0; }

/* ------------------------------------------------------------------ 按钮 */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  padding: 11px 22px; border-radius: var(--radius-sm);
  border: 1px solid var(--c-border); background: var(--c-surface); color: var(--c-heading);
  font-weight: 600; transition: background .16s ease, border-color .16s ease, transform .16s ease;
}
.btn:hover { border-color: var(--c-primary); color: var(--c-primary); }
.btn--primary {
  background: var(--c-primary); border-color: var(--c-primary); color: var(--c-primary-fg);
}
.btn--primary:hover { color: var(--c-primary-fg); filter: brightness(1.08); transform: translateY(-1px); }

.tag {
  display: inline-block; padding: 2px 9px; border-radius: 999px;
  background: color-mix(in srgb, var(--c-primary) 10%, var(--c-surface));
  color: var(--c-primary); font-size: 12px; line-height: 1.7;
}

/* ------------------------------------------------------------------ 页头 */
.site-header {
  position: var(--nav-position); top: 0; z-index: 40;
  background: color-mix(in srgb, var(--c-surface) 92%, transparent);
  backdrop-filter: saturate(1.4) blur(10px);
  border-bottom: 1px solid var(--c-border);
}
.site-header__inner { display: flex; align-items: center; gap: 26px; min-height: 68px; }

.brand { display: flex; align-items: center; gap: 11px; flex: 0 0 auto; }
.brand__mark {
  width: 40px; height: 40px; border-radius: var(--radius-sm);
  background: var(--c-primary); color: var(--c-primary-fg);
  display: grid; place-items: center; font-size: 20px; font-weight: 700; font-family: var(--font-title);
}
.brand__text { display: flex; flex-direction: column; line-height: 1.25; }
.brand__name { font-size: 17px; font-family: var(--font-title); color: var(--c-heading); }
.brand__slogan { font-size: 12px; color: var(--c-muted); }

.nav { display: flex; align-items: center; gap: 4px; flex: 1 1 auto; flex-wrap: wrap; }
.nav a {
  padding: 8px 13px; border-radius: var(--radius-sm); font-weight: 600;
  color: var(--c-text); white-space: nowrap; transition: .16s ease;
}
.nav a:hover { background: color-mix(in srgb, var(--c-primary) 8%, transparent); color: var(--c-primary); }
.nav a.is-active { color: var(--c-primary); background: color-mix(in srgb, var(--c-primary) 10%, transparent); }

.header__tools { display: flex; align-items: center; gap: 10px; margin-left: auto; }

.nav-toggle {
  display: none; border: 1px solid var(--c-border); background: var(--c-surface);
  border-radius: var(--radius-sm); padding: 8px; color: var(--c-heading);
}
.nav-toggle svg { width: 20px; height: 20px; display: block; }

/* 页头居中：标志与导航各占一行并居中。窄屏由媒体查询收回（那里导航本就是收起式） */
.t-header-centered .site-header__inner { flex-wrap: wrap; justify-content: center; row-gap: 4px; padding-top: 12px; padding-bottom: 10px; }
.t-header-centered .brand { flex: 1 0 100%; justify-content: center; }
.t-header-centered .nav { order: 3; flex: 1 0 100%; justify-content: center; }
.t-header-centered .header__tools { order: 4; margin-left: 0; }

main { display: block; min-height: 60vh; }

/* ------------------------------------------------------------------ 首屏 */
/* 首屏三种形态（body 上的 t-hero-* 类切换）：
   standard = 渐变底 + 大标题（默认）；cover = 头条封面铺满 + 压暗 + 白字；compact = 无底色省一屏 */
.hero {
  background:
    radial-gradient(1100px 420px at 12% -10%, color-mix(in srgb, var(--c-primary) 16%, transparent), transparent 68%),
    linear-gradient(180deg, color-mix(in srgb, var(--c-primary) 7%, var(--c-bg)), var(--c-bg));
  border-bottom: 1px solid var(--c-border);
  padding: 54px 0 46px;
}
.hero__inner { display: flex; flex-direction: column; align-items: flex-start; gap: 16px; }
.hero__badge {
  display: inline-block; padding: 5px 14px; border-radius: 999px; font-size: 13px;
  background: color-mix(in srgb, var(--c-primary) 12%, var(--c-surface)); color: var(--c-primary); font-weight: 600;
}

/* 紧凑首屏：去掉底色与渐变，只留文字，省下近一屏高度 */
.t-hero-compact .hero { background: var(--c-surface); padding: 26px 0 22px; }
.t-hero-compact .hero__inner { gap: 8px; }
.t-hero-compact .hero__title { font-size: calc(clamp(22px, 2.6vw, 30px) * var(--title-scale)); }
.t-hero-compact .hero__subtitle { font-size: 14.5px; }

/* 大图封面首屏：用头条封面做背景，压暗后压白字 */
.hero--cover {
  position: relative;
  min-height: 400px;
  display: flex;
  align-items: flex-end;
  padding: 0;
  border-bottom: 0;
  background-color: #10161a;
  background-image:
    linear-gradient(180deg, rgba(8,12,16,.25) 0%, rgba(8,12,16,.62) 55%, rgba(8,12,16,.88) 100%),
    var(--hero-image);
  background-size: cover;
  background-position: center;
}
.hero--cover .hero__inner { padding-top: 120px; padding-bottom: 46px; gap: 14px; }
.hero--cover .hero__title { color: #fff; text-shadow: 0 2px 18px rgba(0,0,0,.45); }
.hero--cover .hero__subtitle { color: rgba(255,255,255,.86); }
.hero--cover .hero__badge {
  background: rgba(255,255,255,.16); color: #fff;
  border: 1px solid rgba(255,255,255,.3); backdrop-filter: blur(4px);
}

.hero__title { font-size: calc(clamp(28px, 4.4vw, 46px) * var(--title-scale)); letter-spacing: -.5px; max-width: 22em; }
.hero__subtitle { color: var(--c-muted); max-width: 44em; font-size: 16px; }

/* ------------------------------------------------------------------ 布局 */
.page { padding: var(--block-gap) 20px calc(var(--block-gap) * 1.6); }
.layout { display: grid; grid-template-columns: minmax(0, 1fr) var(--side-w); gap: calc(var(--gap) * 1.4); align-items: start; }
.layout--noside { grid-template-columns: minmax(0, 1fr); }
.layout__main { min-width: 0; display: flex; flex-direction: column; gap: var(--block-gap); }
.layout__side { display: flex; flex-direction: column; gap: var(--gap); position: sticky; top: 84px; }

/* 侧栏在左：整列换边（.layout--noside 时保持单栏不动） */
.t-side-left .layout:not(.layout--noside) { grid-template-columns: var(--side-w) minmax(0, 1fr); }
.t-side-left .layout:not(.layout--noside) .layout__side { order: -1; }

/* ------------------------------------------------------------------ 面包屑 */
.crumbs { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; color: var(--c-muted); font-size: 13px; margin-bottom: 16px; padding-top: 16px; }
.crumbs a:hover { color: var(--c-primary); }
.crumbs__sep { color: var(--c-border); }
.crumbs__current { color: var(--c-text); }

/* ---------------------------------------------------------------- 页头标题 */
.page-head { border-bottom: 1px solid var(--c-border); padding-bottom: 16px; margin-bottom: 4px; }
.page-head__title { font-size: calc(27px * var(--title-scale)); }
.page-head__desc { color: var(--c-muted); margin-top: 8px; }
.page-head__notice {
  display: flex; align-items: center; gap: 7px; margin-top: 12px;
  padding: 9px 14px; border-radius: var(--radius-sm); font-size: 13px;
  background: color-mix(in srgb, var(--c-accent) 14%, var(--c-surface)); color: var(--c-muted);
}
.page-head__notice svg { width: 15px; height: 15px; flex: 0 0 auto; }

/* ---------------------------------------------------------------- 头条区 */
/* 三种版式（由 body 上的 t-feature-* 类切换）：
   lead3 = 一大三小（默认）；full = 通栏大图头条 + 三块并排次条；duo = 两栏等宽。
   次条行数按内容高度估算：头条卡约 500px 时三块各约 160px，正好铺满而不留大片空白。 */
.feature { display: grid; grid-template-columns: 1.35fr 1fr; gap: var(--gap); align-items: stretch; }
.feature__lead { min-width: 0; display: flex; }
.feature__lead .card { width: 100%; }
.feature__side { display: grid; grid-template-rows: repeat(3, 1fr); gap: var(--gap); min-width: 0; }
.feature__side .card { min-height: 0; }
.feature__side .card__link { height: 100%; }

/* 通栏头条：头条占整行，次条在其下并排三块，四块同高 */
.t-feature-full .feature { grid-template-columns: minmax(0, 1fr); }
.t-feature-full .feature__side { grid-template-rows: none; grid-template-columns: repeat(3, minmax(0, 1fr)); }
.t-feature-full .feature__lead .card__media { aspect-ratio: 21/9; }

/* 两栏等宽：头条列与次条列各占一半，头条图更方正 */
.t-feature-duo .feature { grid-template-columns: 1fr 1fr; }
.t-feature-duo .feature__lead .card__media { aspect-ratio: 4/3; }

/* 块里明确选的两种版式（类挂在 <section> 上，与上面那几个主题 body 类互不干扰）。
   这两档此前只写在块选项里、样式表里一条规则都没有：选「三列等宽」实际排出的是
   两列骨架 + 一张孤零零的第三张卡，「横滑一列」排出来的是一摞竖着堆、连间距都没有的卡片。
   写完这一段的断言见 check-layout.mjs（按模板 JSON 推导，选了三列就量三列）。 */
.feature.feature--trio { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.feature.feature--scroll { display: block; }
/*
 * 横滑轨道用 flex 而不是 grid：`grid-auto-columns: minmax(0, 58%)` 在「列数不确定」的栅格里
 * 百分比算不出确定值，轨道会被当成 auto 再被拉伸铺满，实测 5 张卡各 141px、既不滚也不像首屏。
 * flex 的 flex-basis 百分比按容器宽度解析，是确定值，卡片按 58% 排出去、由轨道横向滚动。
 */
.feature--scroll .feature__rail {
  display: flex; gap: var(--gap); align-items: stretch;
  overflow-x: auto; overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory; padding: 6px 2px 12px;
}
.feature--scroll .feature__rail > .card { flex: 0 0 58%; scroll-snap-align: start; }

/*
 * 轮播（swiper）：一屏一条 + 圆点 + 自动播放，幻灯片是「大图压字」那张解剖。
 *
 * 轨道用**原生横向滚动 + scroll-snap**（不是 JS 换 transform）：脚本没加载时它就是一个能手滑的
 * 横向列表，内容照样看得全；手机上手指一划就是原生惯性滚动。JS（public/site.js）只做三件事 ——
 * 点圆点调 scrollTo、滚动时把当前页码同步到圆点、按 data-interval 自动翻页。
 * 没有左右箭头：翻页靠圆点、手滑与方向键（箭头压在这么大的图上只会挡画面）。
 */
.feature.feature--swiper { display: block; position: relative; }
.feature--swiper .swiper__viewport {
  overflow-x: auto; overflow-y: hidden; scroll-snap-type: x mandatory;
  scrollbar-width: none; border-radius: var(--radius-lg);
}
/* 隐藏滚动条：轮播靠圆点表达进度，再压一条滚动条就脏了（Firefox 走 scrollbar-width，其余走这里） */
.feature--swiper .swiper__viewport::-webkit-scrollbar { display: none; }
.feature--swiper .swiper__viewport:focus-visible { outline: 2px solid var(--c-primary); outline-offset: 3px; }
.feature--swiper .swiper__track { display: flex; }
.feature--swiper .swiper__slide { flex: 0 0 100%; min-width: 0; scroll-snap-align: start; }
.feature--swiper .swiper__slide > .card { width: 100%; }
/*
 * 轮播里的卡片就是「大图压字」那张解剖（.card--overlay），这里补三件它自己不知道的事：
 *   · 一屏一条时卡片要有英雄区的高度（列表里 260px 够，轮播里太扁）；
 *   · 区域这么大，标题得跟着放大（列表里的压字卡 17px 压在 260px 的图上正好，压在 380px 上就小了）；
 *   · 标题与摘要各多留一行：字号大了以后两行很容易把长标题截掉。
 *
 * 高度默认跟着视口走（240–420px）；皮肤里写 `swiperHeight: 300`（36氪资讯那套，参考站的轮播
 * 就是 300px）时用 `--swiper-h` 固定下来 —— 一屏一条的轮播高度是版面的定调尺寸，
 * 三栏布局里 26vw 会偏得离谱。
 */
.feature--swiper .card--overlay { min-height: var(--swiper-h, clamp(240px, 26vw, 420px)); }
.feature--swiper .card--overlay .card__body { min-height: var(--swiper-h, clamp(240px, 26vw, 420px)); }
.feature--swiper .card__title { font-size: calc(clamp(20px, 2.1vw, 30px) * var(--title-scale)); -webkit-line-clamp: 3; }
.feature--swiper .card__summary { font-size: 14px; -webkit-line-clamp: 3; }
/* 圆点：中间一条，当前页拉长成胶囊 */
.feature--swiper .swiper__dots { display: flex; align-items: center; justify-content: center; gap: 8px; margin-top: 12px; }
.feature--swiper .swiper__dot {
  width: 8px; height: 8px; padding: 0; cursor: pointer; border: 0; border-radius: 999px;
  background: color-mix(in srgb, var(--c-heading) 22%, transparent); transition: width .18s ease, background .18s ease;
}
.feature--swiper .swiper__dot:hover { background: color-mix(in srgb, var(--c-heading) 40%, transparent); }
.feature--swiper .swiper__dot.is-active { width: 22px; background: var(--c-primary); }

/* ------------------------------------------------------------------ 区块 */
.section { display: flex; flex-direction: column; gap: calc(var(--gap) * .8); }
.section__head {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  border-bottom: 1px solid var(--c-border); padding: 10px 0;
}
.section__title { font-size: calc(20px * var(--title-scale)); position: relative; padding-left: 13px; }
.section__title::before,
.related__title::before {
  content: ''; position: absolute; left: 0; top: 50%; transform: translateY(-50%);
  width: 4px; height: 17px; border-radius: 2px; background: var(--c-primary);
}

/* 栏目标题样式：色条（默认）/ 下划线 / 纯文字。
   类名不加 body 前缀，后台「模板风格」的预览块复用同一批类名，预览与前台不会走偏。 */
.t-title-underline :is(.section__title, .related__title, .widget__title) { padding-left: 0; padding-bottom: 9px; }
.t-title-underline :is(.section__title, .related__title)::before { display: none; }
.t-title-underline :is(.section__title, .related__title, .widget__title)::after {
  content: ''; position: absolute; left: 0; bottom: 0; width: 36px; height: 3px;
  border-radius: 2px; background: var(--c-primary);
}
.t-title-plain :is(.section__title, .related__title) { padding-left: 0; }
.t-title-plain :is(.section__title, .related__title)::before { display: none; }
/* 块自带的栏题样式：与主题那套同名，只是挂在 <section> 上（作用域写法一致，直接复用） */
.section.t-title-underline .section__title { padding-left: 0; padding-bottom: 9px; }
.section.t-title-underline .section__title::before { display: none; }
.section.t-title-underline .section__title::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: 0; height: 2px;
  background: var(--c-border);
}
.section.t-title-underline .section__title a::after { content: none; }
.section.t-title-underline .section__title a { position: relative; }
.section.t-title-plain .section__title { padding-left: 0; }
.section.t-title-plain .section__title::before { display: none; }

/* 首屏居中 */
.t-hero-center .hero__inner { align-items: center; text-align: center; }
.t-hero-center .hero__title { max-width: 26em; }
.t-hero-center .hero__subtitle { margin-left: auto; margin-right: auto; }
.t-hero-center .hero__badge { align-self: center; }
.section__more { display: inline-flex; align-items: center; gap: 2px; color: var(--c-muted); font-size: 13px; }
.section__more svg { width: 15px; height: 15px; }
.section__more:hover { color: var(--c-primary); }

/* ------------------------------------------------------------------ 卡片 */
.post-list { display: grid; gap: var(--gap); }
/* 列数取自内联变量 --list-cols（块选项 / 主题 / 栏目自己的设置都写它）。
   多列呈现方式必须在这里列全：漏掉一个容器，那个呈现方式的列数设置就会被无声忽略。
   单列呈现方式（左图右文 / 右图左文 / 纯文字 / 编号榜单）默认一列，
   明确选了列数时（.t-cols-set）再读变量 —— 这一条必须写在单列规则后面，靠两个类压过它。 */
.post-list--card,
.post-list--overlay,
.post-list--compact { grid-template-columns: var(--list-cols); }
.post-list--media, .post-list--media-right, .post-list--text, .post-list--numbered { grid-template-columns: minmax(0, 1fr); }
.post-list.t-cols-set { grid-template-columns: var(--list-cols); }
/* 「右图左文」：缩略图贴右、尺寸比左图小一些，是社区信息流（掘金那类）的常见排法 */
@media (min-width: 641px) {
  .post-list--media-right .card--media .card__link { flex-direction: row-reverse; }
  .post-list--media-right .card--media .card__media { flex: 0 0 176px; min-height: 112px; aspect-ratio: 16/9; }
}

.card {
  background: var(--card-bg); border: var(--card-border); box-shadow: var(--card-shadow);
  border-radius: var(--radius); overflow: hidden; display: flex;
  transition: transform .18s ease, box-shadow .18s ease, border-color .18s ease;
}
.card:hover { transform: translateY(-3px); box-shadow: 0 12px 30px color-mix(in srgb, var(--c-heading) 12%, transparent); border-color: color-mix(in srgb, var(--c-primary) 35%, var(--c-border)); }
/*
 * 只高亮标题的悬停（皮肤里写 `hover: 'title'`，见 lib/themes.mjs）：卡片与封面都不动，
 * 鼠标落在卡片任何位置都把标题染成主色。参考站实测就是这样 —— 卡片 transform 始终是 none、
 * 也没有投影，标题悬停后从 rgb(51,51,51) 变成 rgb(51,119,255)，封面不放大。
 * 三条都要显式写回：只清 transform 的话，投影与封面缩放会留下来，看起来仍像「卡片在动」。
 */
.t-hover-title .card:hover { transform: none; box-shadow: var(--card-shadow); border-color: var(--c-border); }
.t-hover-title .card:hover .card__media img { transform: none; }
.t-hover-title .card:hover .card__title { color: var(--c-primary); }
.card__link { display: flex; flex-direction: column; width: 100%; }
.card__media { position: relative; aspect-ratio: var(--cover-ratio); overflow: hidden; background: color-mix(in srgb, var(--c-primary) 8%, var(--c-bg)); }
.card__media img { width: 100%; height: 100%; object-fit: cover; transition: transform .35s ease; }
.card:hover .card__media img { transform: scale(1.04); }
.card__body { padding: var(--card-pad); display: flex; flex-direction: column; gap: 8px; flex: 1; }
/*
 * 列表卡片的左右内边距默认跟随 --card-pad，皮肤可以把 --list-pad 设成 0 让文字与封面左右齐平
 * （腾讯资讯那类白底扁平信息流：卡片没有边框投影，全靠图片左边缘对齐成一条竖线）。
 * 只作用于「封面在上」的列表卡片与头条卡：左图右文 / 右图左文要留出与缩略图的间距，
 * 压字卡的文字压在图上更需要内边距。
 */
.post-list--card .card__body,
.feature .card--lead .card__body { padding-left: var(--list-pad); padding-right: var(--list-pad); }
.card__channel { font-size: 12px; font-weight: 600; color: var(--c-primary); letter-spacing: .4px; }
/*
 * 卡片标题 / 摘要 / meta 三个文字层：默认分别是 700（标题的浏览器默认粗体）、`--c-muted`、
 * `--c-muted`；皮肤里写 `titleWeight` / `summaryColor` / `metaColor` 时用对应的令牌覆盖
 * （参考站：标题 500、摘要 #787878、meta #a7a7a7）。
 */
.card__title { font-size: calc(17px * var(--title-scale)); font-weight: var(--title-weight, 700); display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.card__summary { color: var(--summary-color, var(--c-muted)); font-size: 13.5px; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
/*
 * 图文卡片没有封面时：摘要补上封面那块位置，但只在**整行**处截断。
 *
 * 有封面的卡片不显示摘要（见 lib/site.mjs 的 card()），同一行里的无封面卡片会被栅格拉到同样高，
 * 摘要少了两行的话卡片中间就空一块、元信息孤零零贴底。
 *
 * 早先的做法是 flex:1 + aspect-ratio：让摘要盒子正好占满封面那块高度。问题是那个高度不是行高的
 * 整数倍，超出的文字被 overflow 裁在**半行**上（实测 6.49 / 5.81 / 7.34 行，最后一行只露一半）。
 * 现在改成固定行数上限：-webkit-line-clamp 只在整行处断开并补省略号，永不切半行；
 * 行数由服务端按列数写进 --nocover-lines（列数越多卡片越窄、能放的行数越少），
 * 剩下的那点空间交给 .meta（margin-top:auto 自然贴底）。
 */
.card--nocover .card__summary { -webkit-line-clamp: var(--nocover-lines, 6); }
.card__tags { display: flex; gap: 6px; flex-wrap: wrap; margin-top: auto; }

/*
 * 左图右文：缩略图是**被卡片高度撑满的框**，图片自己不参与卡片高度计算。
 *
 * 原来这里写的是 `height: 100%`。卡片高度由内容决定（栅格行高 = 该行内容最高的一张卡），
 * 于是 `height: 100%` 解析成 auto，缩略图退回**图片自身比例**：上游图片有 4:3、1:1、16:9、竖图……
 * 一行里最高的那张图就把整行撑高，同一页的行高于是忽高忽低（实测 182 / 224 / 192 / 238 混着出现，
 * 真实反馈：「第一行，第二行，最后一行的高度都不一样」）。
 * 把图片改成绝对定位后它不再参与卡片的固有高度计算：卡片高度只由文字决定，
 * 缩略图跟着卡片高度拉伸（object-fit: cover 裁切），`min-height` 只是文字特别短时的下限。
 */
.card--media .card__link { flex-direction: row; }
.card--media .card__media { flex: 0 0 240px; aspect-ratio: auto; min-height: 148px; }
.card--media .card__media img { position: absolute; inset: 0; }
.card--media .card__title { font-size: 18px; -webkit-line-clamp: 2; }

/* 纯文字 */
.card--text { background: transparent; border: 0; border-bottom: 1px solid var(--c-border); border-radius: 0; box-shadow: none; }
.card--text:hover { transform: none; box-shadow: none; }
.card--text .card__body { padding: 16px 2px; }

/* 头条 */
.card--lead { border-radius: var(--radius-lg); }
.card--lead .card__media { aspect-ratio: 16/9; }
.card--lead .card__body { padding: calc(var(--card-pad) + 4px); gap: 10px; }
.card--lead .card__title { font-size: calc(clamp(20px, 2.4vw, 26px) * var(--title-scale)); -webkit-line-clamp: 3; }
.card--lead .card__summary { font-size: 14.5px; -webkit-line-clamp: 3; }

/* 次条：与头条等高排列，标题贴顶、元信息贴底；摘要让卡片在更高的版式下也不空 */
.card--minor { background: var(--c-surface); }
.card--minor .card__body { gap: 6px; }
.card--minor .card__title { font-size: calc(16.5px * var(--title-scale)); -webkit-line-clamp: 3; }
.card--minor .card__summary { font-size: 13px; -webkit-line-clamp: 2; }
.card--minor .meta { margin-top: auto; }
.meta { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; color: var(--meta-color, var(--c-muted)); font-size: 12.5px; margin-top: auto; padding-top: 4px; }
.meta__item { display: inline-flex; align-items: center; gap: 5px; }
.meta__item svg { width: 14px; height: 14px; opacity: .85; }

/* ---------------------------------------------------------------- 侧栏 */
.widget { background: var(--c-surface); border: 1px solid var(--c-border); border-radius: var(--radius); padding: var(--card-pad); }
.widget__title { display: flex; align-items: center; gap: 7px; font-size: calc(16px * var(--title-scale)); margin-bottom: 12px; position: relative; }
.widget__title svg { width: 17px; height: 17px; color: var(--c-accent); }

.rank-list { list-style: none; display: flex; flex-direction: column; }
.rank-list__item { display: flex; align-items: flex-start; gap: 9px; padding: 9px 0; border-bottom: 1px dashed var(--c-border); font-size: 14px; }
.rank-list__item:last-child { border-bottom: 0; }
.rank-list__item a { flex: 1; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.rank-list__no {
  flex: 0 0 20px; height: 20px; border-radius: var(--radius-sm); display: grid; place-items: center;
  background: color-mix(in srgb, var(--c-heading) 8%, transparent); color: var(--c-muted);
  font-size: 12px; font-weight: 700; margin-top: 2px;
}
.rank-list__item.is-top .rank-list__no { background: var(--c-primary); color: var(--c-primary-fg); }

/* ------------------------------------------------------------------ 分页 */
.pager { display: flex; align-items: center; justify-content: center; gap: 8px; flex-wrap: wrap; padding-top: 8px; }
.pager__nav { display: inline-flex; align-items: center; gap: 4px; padding: 8px 14px; border: 1px solid var(--c-border); border-radius: var(--radius-sm); background: var(--c-surface); font-size: 14px; }
.pager__nav svg { width: 15px; height: 15px; }
.pager__nav.is-disabled { opacity: .45; pointer-events: none; }
.pager__pages { display: flex; gap: 6px; }
.pager__link {
  min-width: 36px; height: 36px; padding: 0 10px; display: inline-grid; place-items: center;
  border: 1px solid var(--c-border); border-radius: var(--radius-sm); background: var(--c-surface); font-size: 14px;
}
.pager__link.is-current { background: var(--c-primary); border-color: var(--c-primary); color: var(--c-primary-fg); font-weight: 700; }
/* 游标式分页：没有页码，「回到最新」和「下一页」各站一边 */
.pager--cursor { justify-content: space-between; }

/* ------------------------------------------------------------------ 状态块 */
.state {
  background: var(--c-surface); border: 1px dashed var(--c-border); border-radius: var(--radius);
  padding: 40px 24px; text-align: center; display: flex; flex-direction: column; align-items: center; gap: 10px;
}
.state--error { border-color: color-mix(in srgb, #dc2626 40%, var(--c-border)); }
.state__icon { color: var(--c-muted); }
.state__icon svg { width: 34px; height: 34px; }
.state--error .state__icon { color: #c2410c; }
.state__title { font-size: 18px; }
.state__title--page { font-size: calc(24px * var(--title-scale)); }
.state__text { color: var(--c-muted); max-width: 40em; }

/* ------------------------------------------------------------------ 文章页 */
.article { background: var(--c-surface); border: 1px solid var(--c-border); border-radius: var(--radius); padding: calc(var(--card-pad) * 1.5); }
.article__head { display: flex; flex-direction: column; gap: 12px; }
.article__channel { font-size: 13px; font-weight: 700; color: var(--c-primary); }
.article__title { font-size: calc(clamp(23px, 3.2vw, 32px) * var(--title-scale)); line-height: 1.35; }
.article__meta { display: flex; gap: 16px; flex-wrap: wrap; color: var(--meta-color, var(--c-muted)); font-size: 13px; border-bottom: 1px solid var(--c-border); padding-bottom: 14px; }
.article__cover { margin: 20px 0 0; border-radius: var(--radius-sm); overflow: hidden; }
.article__lead {
  margin-top: 20px; padding: 16px 18px; border-left: 3px solid var(--c-primary);
  background: color-mix(in srgb, var(--c-primary) 6%, var(--c-bg)); color: var(--c-muted); border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
}
.article__tags { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 26px; }
.article__source { margin-top: 20px; display: flex; align-items: center; gap: 6px; font-size: 13.5px; color: var(--c-muted); }
.article__source svg { width: 15px; height: 15px; }
.article__source a { color: var(--c-primary); text-decoration: underline; text-underline-offset: 3px; }

/* 正文排版：面向上游返回的 HTML，覆盖常见标签 */
/* overflow-wrap: anywhere 而不是 break-word：它同时参与「最小内容宽度」计算，因此即使
   超长串出现在 flex / grid 列里也不会把列撑宽——上游正文里这类串很常见（脚注里的完整网址、
   连续英文、编号串）。代码块与表格另有 white-space: pre / overflow-x: auto，不受影响。 */
.article__body { margin-top: 22px; font-size: calc(var(--fs-base) + 1px); overflow-wrap: anywhere; }
.article__body > * + * { margin-top: 1.1em; }
.article__body p { line-height: 1.9; }
.article__body h2 { font-size: 20px; margin-top: 2em; padding-left: 12px; position: relative; }
.article__body h2::before { content: ''; position: absolute; left: 0; top: .28em; bottom: .28em; width: 4px; border-radius: 2px; background: var(--c-primary); }
.article__body h3 { font-size: 17px; margin-top: 1.6em; }
.article__body ul, .article__body ol { padding-left: 1.4em; display: flex; flex-direction: column; gap: .5em; }
.article__body li { line-height: 1.85; }
.article__body a { color: var(--c-primary); text-decoration: underline; text-underline-offset: 3px; }
.article__body img { border-radius: var(--radius-sm); margin: 1.4em auto; }
.article__body blockquote {
  /* 引用条用品牌色（不再是通用边框色），底色给一层淡淡的品牌底，一眼能和正文分开 */
  border-left: 4px solid color-mix(in srgb, var(--c-primary) 62%, var(--c-border));
  padding: 14px 18px 14px 20px;
  margin: 1.7em 0;
  color: color-mix(in srgb, var(--c-text) 78%, var(--c-muted));
  background: color-mix(in srgb, var(--c-primary) 6%, var(--c-surface));
  border-radius: var(--radius-sm);
}
/* 引用里的多段之间要有间距：全局 p{margin:0}，正文那条 > * + * 只管直属子元素 */
.article__body blockquote > * + * { margin-top: .75em; }
.article__body blockquote > :first-child { margin-top: 0; }
.article__body blockquote > :last-child { margin-bottom: 0; }
/* 引用里的图片不要被色块框住显得脏：铺满引用宽度，去掉左右多余空白 */
.article__body blockquote img { margin: .9em 0; }
/* 引用里的标题降一档，别比正文标题还抢眼 */
.article__body blockquote h2, .article__body blockquote h3 { font-size: 1.02em; margin-top: 1em; padding-left: 0; }
.article__body blockquote h2::before { display: none; }
/* 落款（<cite> / 常见的中文「——某人」） */
.article__body blockquote cite, .article__body blockquote footer {
  display: block; margin-top: .6em; font-style: normal; font-size: 13px; color: var(--c-muted);
}
/* 引用套引用：往里缩一点，条更细 */
.article__body blockquote blockquote {
  border-left-width: 3px; padding: 10px 14px; margin-top: 1em;
  background: color-mix(in srgb, var(--c-primary) 4%, transparent);
}
.article__body figure { margin: 1.4em 0; }
.article__body figcaption { text-align: center; color: var(--c-muted); font-size: 13px; margin-top: 8px; }
.article__body code { background: color-mix(in srgb, var(--c-heading) 7%, transparent); padding: 2px 6px; border-radius: 4px; font-size: .92em; }
.article__body pre { background: color-mix(in srgb, var(--c-heading) 6%, transparent); padding: 14px 16px; border-radius: var(--radius-sm); overflow-x: auto; }
.article__body pre code { background: transparent; padding: 0; }
/* 原文里「锚文本就是网址」的长链接同样要能断行，否则会把正文列撑宽 */
.article__body a { overflow-wrap: anywhere; word-break: break-word; }
.article__body table { width: 100%; border-collapse: collapse; font-size: 14px; display: block; overflow-x: auto; }
.article__body th, .article__body td { border: 1px solid var(--c-border); padding: 10px 12px; text-align: left; }
.article__body th { background: color-mix(in srgb, var(--c-primary) 7%, var(--c-surface)); font-weight: 700; }
.article__body hr { border: 0; border-top: 1px solid var(--c-border); margin: 2em 0; }

/* -------------------------------------------------------------- 相关阅读 */
.related { display: flex; flex-direction: column; gap: calc(var(--gap) * .8); }
.related__title { font-size: calc(19px * var(--title-scale)); padding-left: 13px; position: relative; }
/* 相关阅读的卡片更小：多列呈现方式在这里改自适应；块里明确写了列数就按块里的（.t-cols-set 放行） */
.related .post-list--card:not(.t-cols-set),
.related .post-list--overlay:not(.t-cols-set),
.related .post-list--compact:not(.t-cols-set) { grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); }

/* ------------------------------------------------------------------ 页脚 */
.site-footer { background: var(--c-surface); border-top: 1px solid var(--c-border); margin-top: var(--block-gap); padding: calc(var(--block-gap) * 1.2) 0 22px; }
.site-footer__grid { display: grid; grid-template-columns: 1.6fr 1fr 1fr 1.2fr; gap: calc(var(--gap) * 1.2); }
.site-footer__about p { color: var(--c-muted); font-size: 13.5px; margin-top: 12px; max-width: 34em; }
.site-footer__brand { display: flex; align-items: center; gap: 10px; }
.site-footer__brand .brand__mark { width: 34px; height: 34px; font-size: 17px; }
.site-footer h4 { font-size: 15px; margin-bottom: 12px; }
.site-footer__links { display: flex; flex-direction: column; gap: 9px; font-size: 14px; color: var(--c-muted); }
.site-footer__links a:hover { color: var(--c-primary); }
.site-footer__contact { list-style: none; display: flex; flex-direction: column; gap: 10px; font-size: 13.5px; color: var(--c-muted); }
.site-footer__contact li { display: flex; align-items: flex-start; gap: 8px; }
.site-footer__contact svg { width: 15px; height: 15px; flex: 0 0 auto; margin-top: 3px; }
.site-footer__bottom {
  margin-top: 30px; padding-top: 18px; border-top: 1px solid var(--c-border);
  display: flex; gap: 16px; flex-wrap: wrap; align-items: center;
  color: var(--c-muted); font-size: 13px;
}
.site-footer__source { color: var(--c-muted); }

/* 预览提示条（只有管理员开了站点预览才出现）：固定贴在底部，不动页头与页脚的排版 */
.preview-bar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 50;
  display: flex; align-items: center; justify-content: center; gap: 10px; flex-wrap: wrap;
  padding: 10px 16px; font-size: 13.5px;
  background: #1f2937; color: #f8fafc; box-shadow: 0 -2px 12px rgba(15, 23, 42, .22);
}
.preview-bar b { color: #fbbf24; }
.preview-bar span { opacity: .92; }
/* 版式预览时被站点配置挡住的块（提示条上的第二行说明） */
.preview-bar__warn { flex-basis: 100%; text-align: center; font-size: 12.5px; color: #fcd34d; opacity: .95; }
.preview-bar a { color: #f8fafc; text-decoration: underline; }
/* 给提示条留出位置，免得盖住页脚最后一行与返回顶部按钮 */
body:has(.preview-bar) { padding-bottom: 46px; }
/* 提示条可能有两行（版式预览 + 被挡住的块说明），多留一点底部空间 */
body:has(.preview-bar__warn) { padding-bottom: 74px; }

/* 友情链接：整行铺开的一排文字链，条数多时自动换行；网址本身很长也要能断，不能把页脚撑宽 */
.site-footer__friend { margin-top: 28px; padding-top: 20px; border-top: 1px solid var(--c-border); }
.friend-links {
  list-style: none; display: flex; flex-wrap: wrap; gap: 9px 22px;
  font-size: 13.5px; color: var(--c-muted);
}
.friend-links li { min-width: 0; max-width: 100%; }
.friend-links a { color: var(--c-muted); overflow-wrap: anywhere; }
.friend-links a:hover { color: var(--c-primary); }

.to-top {
  position: fixed; right: 22px; bottom: 22px; z-index: 30;
  width: 42px; height: 42px; border-radius: 50%;
  border: 1px solid var(--c-border); background: var(--c-surface); color: var(--c-heading);
  display: grid; place-items: center; box-shadow: var(--shadow); opacity: 0; pointer-events: none;
  transition: opacity .2s ease, transform .2s ease;
}
.to-top.is-visible { opacity: 1; pointer-events: auto; }
.to-top:hover { transform: translateY(-2px); }
.to-top svg { width: 18px; height: 18px; }

/* -------------------------------------------------------------- 响应式 */
/* 结构性排版在窄屏要让位：固定列数与左右分栏在手机上会把内容压扁或挤出横向滚动，
   因此这些 t-* 规则必须在媒体查询里显式收回（它们的优先级高于基础规则）。 */
@media (max-width: 1080px) {
  .layout { grid-template-columns: minmax(0, 1fr) 290px; gap: var(--gap); }
  .t-side-left .layout:not(.layout--noside) { grid-template-columns: 290px minmax(0, 1fr); }
  .site-footer__grid { grid-template-columns: 1.4fr 1fr 1fr; }
  .site-footer__grid > div:last-child { grid-column: 1 / -1; }
}

@media (max-width: 980px) {
  .layout,
  .t-side-left .layout:not(.layout--noside) { grid-template-columns: minmax(0, 1fr); }
  /* 侧栏在左的站点，手机上仍让内容在前（热门排行不该压在正文上面） */
  .t-side-left .layout:not(.layout--noside) .layout__side { order: 0; }
  .layout__side { position: static; }
  .feature,
  .t-feature-duo .feature,
  .t-feature-full .feature { grid-template-columns: minmax(0, 1fr); }
  /* 块里选的「三列等宽」也要在平板宽度收回单列（它的优先级高于上面那条基础规则） */
  .feature.feature--trio { grid-template-columns: minmax(0, 1fr); }
  /* 平板宽度把「沿用」来的列数交回自适应（免得卡片被压扁）；明确填了列数（.t-cols-set）就按填的排 */
  .post-list--card:not(.t-cols-set),
  .post-list--overlay:not(.t-cols-set),
  .post-list--compact:not(.t-cols-set) { grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); }
  /* 「固定 1 列」在这里按回单列：上面这条自适应规则会把固定列数改掉，
     而单列是一种明确想要的版式（大图列表流），不该在平板宽度上突然变成两三列 */
  .t-list-one .post-list--card:not(.t-cols-set),
  .t-list-one .post-list--overlay:not(.t-cols-set),
  .t-list-one .post-list--compact:not(.t-cols-set) { grid-template-columns: minmax(0, 1fr); }
}

@media (max-width: 860px) {
  /* 居中页头在窄屏收回：此时导航本来就是收起式，居中会把按钮挤到奇怪的位置 */
  .t-header-centered .brand { flex: 0 1 auto; justify-content: flex-start; }
  .t-header-centered .nav { order: 3; justify-content: flex-start; }
  .t-header-centered .header__tools { order: 2; margin-left: auto; }
  /* 收起的导航仍是一个 flex 项，会占出一条零高度的第二行：它一旦参与行距与行高分配，
     第一行（标志 + 站点名 + 汉堡按钮）就会被顶到页头上沿（顶部 3px、底部 19px）。
     所以窄屏的行距交给「展开态导航自己的内边距」，并且第一行固定贴内容盒顶部
     （上下留白在文件末尾的窄屏块里统一给，那里能压住 .container 的 padding 简写）。 */
  .site-header__inner { flex-wrap: wrap; min-height: 62px; gap: 12px; row-gap: 0; align-content: flex-start; }
  .nav-toggle { display: grid; place-items: center; }
  .nav {
    order: 3; flex: 1 0 100%; flex-direction: column; align-items: stretch; gap: 2px;
    max-height: 0; overflow: hidden; transition: max-height .24s ease;
  }
  /* 展开态：底部留白由页头自己给，导航只负责与第一行拉开 8px */
  .nav.is-open { max-height: 60vh; overflow-y: auto; padding: 8px 0 0; }
  /* 导航项保留四周 11px 内边距（点按高亮更好点、更好按）。代价是文字比标志图形右缩进 11px，
     但链接盒子仍与内容盒左边缘对齐 —— 页头实测按「盒子对齐 + 缩进不超过 14px」来把关。 */
  .nav a { padding: 11px; }
  .brand__slogan { display: none; }
}

@media (max-width: 640px) {
  :root { --card-pad: 16px; --gutter: 16px; }
  .page { padding-left: var(--gutter); padding-right: var(--gutter); }
  .container { padding: 0 var(--gutter); }
  .post-list--card,
  .post-list--overlay,
  .post-list--compact { grid-template-columns: minmax(0, 1fr); }
  /* 手机上连「明确填了列数」的列表也收回单列：390px 宽排两列，图文卡片会被压成一条缝 */
  .post-list.t-cols-set { grid-template-columns: minmax(0, 1fr); }
  .t-feature-full .feature__side { grid-template-columns: minmax(0, 1fr); }
  /* 手机上横滑轨道里的卡片占满整宽，一屏一张，滑动即翻页 */
  .feature--scroll .feature__rail > .card { flex: 0 0 86%; }
  .card--media .card__link { flex-direction: column; }
  .card--media .card__media { flex: none; width: 100%; aspect-ratio: var(--cover-ratio); min-height: 0; }
  .article { padding: 20px 16px; }
  .hero { padding: 36px 0 32px; }
  .site-footer__grid { grid-template-columns: 1fr; gap: 26px; }
  .to-top { right: 14px; bottom: 14px; }
}

/* 窄屏页头的上下留白固定为 11px（= (62 - 40) / 2），且不随导航展开而改变：
   展开前第一行在 11px 处、展开后还在 11px 处，标志与汉堡按钮都不会往上跳。
   这一段放在 .container 的 padding 简写之后，才能压住它在 ≤640 下的 0 上下内边距。 */
@media (max-width: 860px) {
  .site-header__inner { padding-top: 11px; padding-bottom: 11px; }
  .t-header-centered .site-header__inner { padding-top: 11px; padding-bottom: 11px; row-gap: 0; }
}

/* ============================================================ 版式块与外壳
 * 这一段的规则全部服务于 lib/blocks.mjs + lib/layout.mjs：卡片解剖、块的样式、
 * 以及五种页面外壳的骨架。默认模板用不到它们，所以老站点看起来与升级前一致。 */

/* --- 卡片解剖：压字 / 编号 / 紧凑 --- */
/*
 * 大图压字：文字作为一整块贴在卡片底部（标题在最上面会离元信息老远，中间空一大块）。
 *
 * 三件事缺一不可：
 *   · `.card__link` 用列的 flex —— 默认的 display:block 时 body 只有自己的 min-height，
 *     同一行卡片被栅格拉高后 body 不会跟着长，文字就飘在卡片中间；
 *   · `.card__body` 撑满卡片 + justify-content:flex-end，文字整体沉到底部；
 *   · 取消 `.meta` / `.card__tags` 的 margin-top:auto —— 那个自动外边距会把空档全吃掉，
 *     于是 justify-content 无空可推，标题与摘要又被顶回卡片上沿（实测标题距顶 25px、
 *     距底 191px，中间空 117px）。
 * 没有封面图时也要有底色：白底配白字会变成一片空白。
 */
.card--overlay {
  position: relative; overflow: hidden; min-height: 260px;
  background: linear-gradient(160deg, color-mix(in srgb, var(--c-primary) 52%, #111a2b), #0d1420);
}
.card--overlay .card__link { display: flex; flex-direction: column; }
.card--overlay .card__media { position: absolute; inset: 0; aspect-ratio: auto; }
.card--overlay .card__media::after {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(8,12,16,.15), rgba(8,12,16,.78));
}
.card--overlay .card__body { position: relative; z-index: 1; color: #fff; padding: calc(var(--card-pad) * 1.2); flex: 1; justify-content: flex-end; min-height: 260px; }
.card--overlay .card__body > .meta,
.card--overlay .card__body > .card__tags { margin-top: 0; }
.card--overlay .card__title, .card--overlay .card__channel { color: #fff; }
.card--overlay .card__summary, .card--overlay .meta, .card--overlay .meta__item { color: rgba(255,255,255,.86); }
/* 有封面时不写摘要（见 lib/site.mjs 的 ANATOMY），所以摘要只出现在没封面的压字卡上：
   行数上限交给 .card--nocover（--nocover-lines），这里只管把它顶上去填满卡片。 */
.card--overlay.card--nocover .card__summary { -webkit-line-clamp: var(--nocover-lines, 6); }

.post-list--numbered { counter-reset: rank; }
/* 编号榜单：序号是一列，正文是另一列；整行有内边距，正文不再贴边 */
.card--numbered .card__link {
  display: grid; grid-template-columns: 34px minmax(0, 1fr); align-items: center; gap: 12px;
  padding: calc(var(--card-pad) * .7) var(--card-pad);
}
.card__rank {
  display: grid; place-items: center; width: 26px; height: 26px;
  border-radius: 6px; font-weight: 700; font-size: 14px;
  background: color-mix(in srgb, var(--c-primary) 12%, transparent); color: var(--c-primary);
}
.card--numbered .card__body { padding: 0; gap: 6px; }
.card--numbered .card__title { -webkit-line-clamp: 2; }
.card--numbered:nth-child(-n+3) .card__rank { background: var(--c-primary); color: var(--c-primary-fg); }

.card--compact .card__body { padding: calc(var(--card-pad) * .62) calc(var(--card-pad) * .8); }
.card--compact .card__title { font-size: calc(15px * var(--title-scale)); }

/* --- 栏目胶囊行（tabs 块） --- */
.tabs { display: flex; flex-wrap: wrap; gap: 8px 10px; padding: 4px 0 14px; border-bottom: 1px solid var(--c-border); margin-bottom: 18px; }
.tabs__item { font-size: 14px; color: var(--c-muted); }
.tabs--pills .tabs__item { padding: 5px 13px; border-radius: 999px; background: color-mix(in srgb, var(--c-heading) 6%, transparent); }
.tabs--pills .tabs__item.is-active { background: var(--c-primary); color: var(--c-primary-fg); }
.tabs--underline .tabs__item { padding: 5px 2px; }
.tabs--underline .tabs__item.is-active { color: var(--c-primary); box-shadow: inset 0 -2px 0 var(--c-primary); }
.tabs--plain .tabs__item.is-active { color: var(--c-primary); font-weight: 700; }

/* --- 排行榜块 --- */
.rank-board { list-style: none; display: flex; flex-direction: column; }
.rank-board__item { display: flex; align-items: baseline; gap: 10px; padding: 9px 0; border-bottom: 1px solid var(--c-border); }
.rank-board__item:last-child { border-bottom: 0; }
.rank-board__no { flex: 0 0 auto; color: var(--c-muted); font-size: 13px; font-variant-numeric: tabular-nums; }
.rank-board--big .rank-board__no { font-size: 18px; font-weight: 800; min-width: 26px; }
.rank-board--big .rank-board__item.is-top .rank-board__no { color: var(--c-primary); }
.rank-board__meta { margin-left: auto; color: var(--c-muted); font-size: 12.5px; }

/* --- 标签云块 --- */
.tag-cloud { display: flex; flex-wrap: wrap; gap: 8px 10px; }
.tag-cloud__item { font-size: 13px; padding: 4px 11px; border-radius: 999px; background: color-mix(in srgb, var(--c-heading) 6%, transparent); color: var(--c-muted); }
a.tag-cloud__item:hover { color: var(--c-primary); }
.tag-cloud--cloud .tag-cloud__item { font-size: inherit; padding: 2px 4px; background: transparent; }
.tag-cloud--cloud .tag-cloud__item:nth-child(3n) { font-size: 17px; color: var(--c-heading); }
.tag-cloud--cloud .tag-cloud__item:nth-child(4n) { font-size: 20px; font-weight: 700; }

/* --- 通栏大图带 --- */
.band--cover {
  /* 兜底底色：文章没有封面图时 --band-image 不存在，白底 + 白字会变成一片空白 */
  background-color: color-mix(in srgb, var(--c-primary) 42%, #0b1220);
  background-image: linear-gradient(180deg, rgba(8,12,16,.35), rgba(8,12,16,.82)), var(--band-image, none);
  background-position: center; background-size: cover; background-repeat: no-repeat;
  color: #fff; display: flex; align-items: flex-end;
}
.band--short { min-height: 260px; }
.band--medium { min-height: 380px; }
.band--tall { min-height: 520px; }
/*
 * 大图带的内层：**只给上下留白**。
 *
 * 这里曾经写的是 padding: 34px 0 —— 简写会把 .container 的左右内边距一起清零，于是带子里的
 * 标题与摘要贴到内容区最左边，比同页每个区块的标题都往左 20px（真实反馈：「通栏大图带的标题和
 * 摘要都贴了左边界」）。用上下长写就只加留白、不动容器给的左右内边距（≤640 时是 16px）。
 */
.band__inner { padding-top: 34px; padding-bottom: 34px; }
.band__link { display: block; max-width: 46em; }
.band__channel { font-size: 13px; opacity: .88; }
.band__title { font-family: var(--font-title); font-size: calc(28px * var(--title-scale)); color: #fff; margin-top: 6px; }
.band__summary { margin-top: 8px; color: rgba(255,255,255,.86); }

/* --- 数据条 / 引导块 / 提示条 / 自定义片段 --- */
.stat-row { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--gap); }
.stat-row--cards .stat { background: var(--c-surface); border: 1px solid var(--c-border); border-radius: var(--radius); padding: calc(var(--card-pad) * .8); }
.stat { display: flex; flex-direction: column; gap: 2px; }
.stat b { font-family: var(--font-title); font-size: calc(22px * var(--title-scale)); color: var(--c-heading); }
.stat span { color: var(--c-muted); font-size: 13px; }

.cta--card { background: var(--c-surface); border: 1px solid var(--c-border); border-radius: var(--radius); padding: calc(var(--card-pad) * 1.2); }
.cta--inline { border-top: 1px solid var(--c-border); border-bottom: 1px solid var(--c-border); }
.cta--band { background: color-mix(in srgb, var(--c-primary) 8%, var(--c-surface)); }
.cta__inner { display: flex; align-items: center; gap: 18px; flex-wrap: wrap; padding: 18px 0; }
.cta--card .cta__inner { padding: 0; }
/*
 * 通栏引导块是全幅块（不在 .container.page 里），内层 .container 的左右内边距必须留着，
 * 否则标题与按钮会贴到内容区最左边（与通栏大图带同一个坑）。上下留白用长写，左右用 --gutter。
 */
.cta--band .cta__inner { padding: 18px var(--gutter); }
.cta__text { display: flex; flex-direction: column; gap: 4px; flex: 1 1 22em; }
.cta__text b { font-family: var(--font-title); color: var(--c-heading); font-size: calc(17px * var(--title-scale)); }
.cta__text span { color: var(--c-muted); font-size: 13.5px; }

.notice { display: flex; align-items: flex-start; gap: 8px; border-radius: var(--radius-sm); padding: 12px 14px; font-size: 13.5px; }
.notice--info { background: color-mix(in srgb, var(--c-primary) 7%, var(--c-surface)); color: var(--c-text); }
.notice--warn { background: color-mix(in srgb, #f59e0b 14%, var(--c-surface)); color: var(--c-text); }
.notice svg { flex: 0 0 auto; margin-top: 2px; }

.raw-block--center { text-align: center; }

/* --- 侧栏部件（channels / tags / subscribe） --- */
.widget__links { display: flex; flex-direction: column; gap: 8px; font-size: 14px; }
.widget__text { color: var(--c-muted); font-size: 13.5px; }

/* --- 侧栏模块的几种列表（最新更新 / 栏目文章 / 数据小卡） --- */
.widget__list { list-style: none; display: flex; flex-direction: column; font-size: 14px; }
.widget__list-item { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; padding: 8px 0; border-bottom: 1px dashed var(--c-border); }
.widget__list-item:last-child { border-bottom: 0; }
.widget__list-item a { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.widget__time { color: var(--c-muted); font-size: 12px; white-space: nowrap; }
.widget__list--stats { flex-direction: row; flex-wrap: wrap; gap: 12px; }
.widget__stat { display: flex; flex-direction: column; gap: 2px; min-width: 64px; }
.widget__stat b { font-size: calc(18px * var(--title-scale)); color: var(--c-heading); }
.widget__stat span { color: var(--c-muted); font-size: 12.5px; }
.widget__links--head { margin-top: 10px; align-items: flex-end; }
/**
 * 「发布地址」模块 = 链接池：一行一条稿件标题，标题本身就是外链地址。
 * 只列标题（不带站点名、时间），所以每行就是一行文字 —— 不需要胶囊，也不需要两行结构。
 */
.widget__list--published { font-size: 14px; }
.widget__published { padding: 8px 0; border-bottom: 1px dashed var(--c-border); }
.widget__published:last-child { border-bottom: 0; }
.widget__published-title { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
/* 热门阅读的「大号数字」档：前三名高亮，序号更大 */
.rank-list--big .rank-list__no { width: 30px; height: 30px; font-size: 15px; border-radius: 8px; }
.rank-list--big .rank-list__item { font-size: 15px; }
.rank-list__meta { color: var(--c-muted); font-size: 12px; white-space: nowrap; }

/* --- 首屏：块的形态类（沿用主题时不加这些类） --- */
.hero--compact { background: var(--c-surface); padding: 26px 0 22px; }
.hero--compact .hero__inner { gap: 8px; }
.hero--standard { background: var(--c-surface); }
.hero--center .hero__inner { align-items: center; text-align: center; }

/* --- 页面外壳 --- */
/* 左侧导航轨：栏目竖排在左，内容在右。窄屏收回成顶部一行 */
.shell--rail, .shell--docs { display: grid; grid-template-columns: var(--rail-w, 200px) minmax(0, 1fr); gap: 26px; width: 100%; max-width: var(--container); margin: 0 auto; padding: 22px var(--gutter) 0; }
.shell__rail { position: relative; }
.rail-nav { display: flex; flex-direction: column; gap: 2px; position: sticky; top: 84px; }
.rail-nav a { padding: 9px 12px; border-radius: var(--radius-sm); color: var(--link-color, var(--c-text)); font-size: 14px; font-weight: 600; }
.rail-nav a:hover { background: color-mix(in srgb, var(--c-primary) 8%, transparent); color: var(--c-primary); }
.rail-nav a.is-active { background: color-mix(in srgb, var(--c-primary) 12%, transparent); color: var(--c-primary); }
/* 左侧轨道外壳里，页头不再重复一行导航 */
.shell-rail .site-header .nav, .shell-docs .site-header .nav { display: none; }
.shell-docs { --rail-w: 240px; }

/*
 * 左侧品牌栏（36氪式三栏）：标志与栏目一起放在左列，页头整行不再渲染 ——
 * DOM 里左列是 .shell__rail（品牌 + 导航），中间是 .shell__body，右侧栏由 .layout__side 提供，
 * 于是正好是「左 / 中 / 右」三栏。左列整列吸顶（品牌与菜单都跟着走），窄屏收回成顶部一行。
 *
 * 两处尺寸都跟参考站对齐过：左列宽度 200px 是默认值，皮肤可以压到 125px（`--rail-w`，36氪那类
 * 左列只放标志与菜单）；列间距 26px 与 rail / docs 两种外壳一致（原来写 34px，左列与中间之间
 * 空得比参考站宽）。
 */
.shell--brandrail { display: grid; grid-template-columns: var(--rail-w, 200px) minmax(0, 1fr); gap: 26px; width: 100%; max-width: var(--container); margin: 0 auto; padding: 26px var(--gutter) 0; align-items: start; }
.shell--brandrail .shell__rail { position: sticky; top: 26px; align-self: start; display: flex; flex-direction: column; gap: 20px; }
.shell--brandrail .rail-nav { position: static; }
/*
 * 左列只有 125px，标志居中、栏目名**右对齐**：名字贴着左列的右边缘排成一列，
 * 点起来还是整列宽的可点区域（只把文字右对齐，不把链接盒子也缩到文字宽）。
 * 窄屏时左列收成顶部一行，链接盒子各自贴着文字，右对齐看不出区别也不碍事。
 */
.shell--brandrail .rail-nav a { text-align: right; }
/*
 * 右侧栏的吸顶偏移要跟着改：默认那个 top: 84px 是给「顶部 68px 页头」留的位置，
 * 这套外壳没有页头，84px 会把侧栏从视口顶部往下推 84px —— 页面一打开，右栏就比中栏低一截。
 * 改成与左列同一个偏移，两边齐平，滚动时也一起吸顶。
 */
.shell--brandrail .layout__side { top: 26px; }
/*
 * 中间那一列里的 .container.page 不再自己留左右内边距：这套外壳自己已经有 gutter 与列间距了，
 * 再叠一层 20px 会让「左列 → 中间」的空隙变成 26+20=46px（真实反馈：左列与中间区域之间空得
 * 比参考站宽），中间内容也白白窄了 40px。去掉之后空隙就是外壳那一条 26px，中间宽度全给正文。
 */
.shell--brandrail .container.page { padding-left: 0; padding-right: 0; }
/*
 * 左列很窄（36氪那类只有 125px）时标志横排会挤成一团，所以品牌栏里的标志改成上下两行、**居中**：
 * 第一行是标志块，第二行是站名与标语。左列自己那 125px 里横排是放不下的（标志块 34px + 间距 +
 * 站名），叠放之后不管站名多长都只占一行文字的高度，看上去也是一个规规矩矩的 logo。
 * 注意这里动的是 .brand--rail 自己的对齐（它被拉满整列宽），不是 .shell__rail 的 align-items ——
 * 后者会把下面的菜单也一起收缩居中。
 */
.brand--rail { flex-direction: column; align-items: center; gap: 8px; }
.brand--rail .brand__mark { width: 34px; height: 34px; font-size: 16px; }
.brand--rail .brand__text { align-items: center; text-align: center; }
.brand--rail .brand__name { font-size: 16px; text-align: center; }
.brand--rail .brand__slogan { text-align: center; }

/* 居中信息流：没有侧栏、容器更窄 */
.shell-feed .layout, .shell-feed .layout__main { display: block; }
.shell-feed .container.page { max-width: 860px; }

/*
 * 信息流细线分隔（皮肤里写 `listDivider: 'line'`，如 36氪风格）。
 *
 * 扁平卡片（白底、无描边、无投影）之间没有视觉分界，一屏十几条会糊成一片；参考站那种做法是
 * 每条之间一条 1px 浅线。行间距交给内边距，所以栅格 gap 归零。
 */
.t-list-line .post-list { gap: 0; }
.t-list-line .post-list > .card { border: 0; border-bottom: 1px solid var(--c-border); border-radius: 0; box-shadow: none; background: transparent; }
.t-list-line .post-list > .card:last-child { border-bottom: 0; }
.t-list-line .post-list > .card > .card__link { padding-top: 16px; padding-bottom: 16px; }

@media (max-width: 980px) {
  .shell--rail, .shell--docs, .shell--brandrail { grid-template-columns: minmax(0, 1fr); }
  .shell__rail { position: static; }
  .rail-nav { flex-direction: row; flex-wrap: wrap; gap: 6px; position: static; }
  .shell-rail .site-header .nav, .shell-docs .site-header .nav { display: flex; }
  /* 品牌栏窄屏变成顶部一行：标志在左、菜单折行跟在后面 */
  .shell--brandrail { gap: 14px; padding-top: 18px; }
  .shell--brandrail .shell__rail { position: static; flex-direction: row; align-items: center; flex-wrap: wrap; gap: 10px 16px; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}
