/* ==========================================================================
   09GUA Design System — Tokens
   ========================================================================== */
/* --------------------------------------------------------------------------
   FRONTEND_PRODUCT_EXPERIENCE_V3 §十七 —— 一套 token，两个主题。

   为什么是「重定义 token」而不是「第二份 CSS」
   ------------------------------------------
   这个主题的样式表早就是 token 驱动的：全文 265 处 var(--ed-*)，:root 只有
   一处。也就是说 Light/Dark 缺的从来不是一套新样式，只是缺**第二组值**。
   写第二份完整 CSS 会立刻产生两份会各自漂移的版式，那正是 §九 明确禁止的。

   默认是 LIGHT（Owner §八）：裸 :root 就是日间，所以一个没有 JS、没有
   localStorage、第一次来的访客拿到的必然是日间，不需要任何脚本参与。
   DARK 只在 html[data-theme="dark"] 下覆盖颜色 —— 覆盖的**只有颜色**，
   圆角 / 容器宽度 / 字体 / header 高度一个都不重复，它们与主题无关。

   金色在两个主题里不是同一个值，这是必须的而不是随意的
   ----------------------------------------------------
   品牌金 #cf9f52 在深色底上对比度 8.4:1，在白底上只有 2.3:1 —— 照搬到日间
   就是一行读不清的字。日间用同一色相更深的琥珀金 #8b5f1b —— 深到「金字压在
   10% 金底的当前导航项上」也过 4.5:1，那是日间对比度最紧的一处，仍然是黑金体系，不是换品牌。金色**底**上的文字色单独抽成
   --ed-gold-ink：夜间是深墨、日间是纸白，否则「深金底 + 深字」会在日间
   变成第二处读不清的地方。

   --ed-on-media-* 三个 token 刻意**不随主题变**：它们盖在封面图 / 播放器 /
   Hero 渐变上，那底下是一张照片，不是页面背景。让它们跟着日间变浅，等于
   把白字放到白蒙层上 —— 时长角标与分类角标此前正是用 var(--ed-text) 写的，
   一旦有了日间主题那就会立刻不可读。
   -------------------------------------------------------------------------- */
:root {
	/* LIGHT（默认）—— 2026-09-30 定稿：浅灰底 + 白卡片 + 玫粉点缀（参考同类站；前一版粉色铺底被否）。
	   --ed-gold* 名字保留（全站 265 处引用），值现在是粉色。 */
	--ed-bg: #f4f5f7;
	--ed-bg-soft: #eceef1;
	--ed-card: #ffffff;
	--ed-card-hover: #fafbfc;
	--ed-border: #e3e5ea;
	--ed-border-soft: #eceef1;

	--ed-text: #191d27;
	--ed-text-muted: #626975;
	--ed-text-faint: #666d79;

	--ed-gold: #d6246e;
	--ed-gold-hover: #b81d5d;
	--ed-gold-soft: #ee9dbd;
	--ed-gold-ink: #ffffff;
	--ed-gold-bg: rgba(214, 36, 110, 0.1);

	--ed-danger: #b03229;
	--ed-danger-bg: rgba(176, 50, 41, 0.1);

	--ed-shadow-card: 0 1px 2px rgba(20, 24, 33, 0.06);
	--ed-shadow-lift: 0 10px 24px rgba(20, 24, 33, 0.1);
	--ed-header-bg: rgba(255, 255, 255, 0.92);
	--ed-overlay-backdrop: rgba(20, 24, 33, 0.45);

	/* 主题无关：盖在图片 / 视频 / 渐变上的前景与底色。 */
	--ed-on-media: #ffffff;
	--ed-on-media-muted: rgba(255, 255, 255, 0.7);
	--ed-on-media-bg: rgba(10, 10, 12, 0.75);
	--ed-on-media-bg-strong: rgba(0, 0, 0, 0.72);
	/* 盖在封面上的粉色字（分类角标）。不随主题变：底下永远是深色蒙层，
	   日间那枚深玫粉 --ed-gold 压在黑底上读不清。 */
	--ed-on-media-accent: #ff6a9c;

	/* CATEGORY_TOP4_REAL_VIEWS §七.3 —— 封面右上角的名次角标。
	   与 --ed-on-media 同组，因为它同样是**盖在图片上**的前景：图片本身
	   不跟着主题变，所以这两枚角标在 light / dark 下必须是同一个样子，
	   否则夜间模式下会出现一枚亮色角标压在一张亮色封面上。
	   热度用橙红（Owner 给的三个选项之一），置顶用黑金 —— 两者一眼可分，
	   而不是靠读四个小字才知道是哪一种。 */
	--ed-rank-hot-bg: #d93a1e;
	--ed-rank-hot-ink: #ffffff;

	/* 主题无关：形状与排版。 */
	--ed-radius-sm: 6px;
	--ed-radius-md: 12px;
	--ed-radius-lg: 20px;

	--ed-container: 1200px;
	--ed-content-width: 800px;

	--ed-font: -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei",
		"Segoe UI", Helvetica, Arial, sans-serif;

	--ed-header-height: 64px;

	color-scheme: light;
}

html[data-theme="dark"] {
	/* DARK（默认）—— 2026-09-30 定稿：纯黑底 + 中性深灰卡片 + 亮玫粉点缀。 */
	--ed-bg: #0b0b0c;
	--ed-bg-soft: #141415;
	--ed-card: #1b1a1c;
	--ed-card-hover: #232124;
	--ed-border: #2b292c;
	--ed-border-soft: #1f1e20;

	--ed-text: #f2f2f2;
	--ed-text-muted: #a6a3a7;
	--ed-text-faint: #99959a;

	--ed-gold: #ff4886;
	--ed-gold-hover: #ff6a9c;
	--ed-gold-soft: #8c3a58;
	--ed-gold-ink: #16060d;
	--ed-gold-bg: rgba(255, 72, 134, 0.14);

	--ed-danger: #d1483f;
	--ed-danger-bg: rgba(209, 72, 63, 0.12);

	--ed-shadow-card: 0 1px 0 rgba(0, 0, 0, 0.4);
	--ed-shadow-lift: 0 10px 28px rgba(0, 0, 0, 0.55);
	--ed-header-bg: rgba(11, 11, 12, 0.92);
	--ed-overlay-backdrop: rgba(0, 0, 0, 0.6);

	color-scheme: dark;
}

/* ==========================================================================
   Reset / Base
   ========================================================================== */
*,
*::before,
*::after {
	box-sizing: border-box;
}

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

body {
	margin: 0;
	background: var(--ed-bg);
	color: var(--ed-text);
	font-family: var(--ed-font);
	font-size: 16px;
	line-height: 1.6;
	overflow-x: hidden;
}

img {
	max-width: 100%;
	display: block;
}

a {
	color: inherit;
	text-decoration: none;
}

ul {
	margin: 0;
	padding: 0;
	list-style: none;
}

h1, h2, h3, h4, p {
	margin: 0 0 0.6em;
}

button {
	font-family: inherit;
	cursor: pointer;
}

.screen-reader-text {
	position: absolute;
	width: 1px;
	height: 1px;
	overflow: hidden;
	clip: rect(1px, 1px, 1px, 1px);
	white-space: nowrap;
}

.ed-container {
	max-width: var(--ed-container);
	margin: 0 auto;
	padding: 0 20px;
}

/* ==========================================================================
   Header
   ========================================================================== */
.ed-header {
	position: sticky;
	top: 0;
	z-index: 100;
	height: var(--ed-header-height);
	display: flex;
	align-items: center;
	background: var(--ed-header-bg);
	backdrop-filter: saturate(140%) blur(8px);
	border-bottom: 1px solid var(--ed-border);
}

.ed-header__inner {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 24px;
	width: 100%;
}

.ed-logo,
.ed-logo a {
	display: flex;
	flex-direction: column;
	line-height: 1.1;
	flex-shrink: 0;
}

.ed-logo__en {
	font-size: 20px;
	font-weight: 700;
	letter-spacing: 0.5px;
	color: var(--ed-text);
}

.ed-logo__cn {
	font-size: 11px;
	color: var(--ed-gold);
	letter-spacing: 1px;
}

.ed-nav {
	display: none;
}

.ed-nav__list {
	display: flex;
	align-items: center;
	gap: 4px;
}

.ed-nav__link {
	display: inline-block;
	padding: 8px 12px;
	border-radius: var(--ed-radius-sm);
	color: var(--ed-text-muted);
	font-size: 14px;
	white-space: nowrap;
	transition: color 0.15s ease, background-color 0.15s ease;
}

.ed-nav__link:hover,
.ed-nav__link:focus-visible {
	color: var(--ed-text);
	background: var(--ed-card);
}

.ed-nav__link.is-active {
	color: var(--ed-gold);
	background: var(--ed-gold-bg);
}

.ed-header__actions {
	display: flex;
	align-items: center;
	gap: 8px;
	flex-shrink: 0;
}

.ed-icon-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 38px;
	height: 38px;
	border: 1px solid var(--ed-border);
	background: var(--ed-bg-soft);
	border-radius: var(--ed-radius-sm);
	color: var(--ed-text);
}

.ed-icon-btn:hover {
	background: var(--ed-card);
	border-color: var(--ed-gold-soft);
}

.ed-icon-btn svg {
	width: 18px;
	height: 18px;
}

.ed-hamburger {
	display: inline-flex;
}

/* Mobile nav drawer */
.ed-mobile-nav {
	position: fixed;
	inset: 0;
	z-index: 200;
	visibility: hidden;
	pointer-events: none;
}

.ed-mobile-nav.is-open {
	visibility: visible;
	pointer-events: auto;
}

.ed-mobile-nav__backdrop {
	position: absolute;
	inset: 0;
	background: var(--ed-overlay-backdrop);
	opacity: 0;
	transition: opacity 0.2s ease;
}

.ed-mobile-nav.is-open .ed-mobile-nav__backdrop {
	opacity: 1;
}

.ed-mobile-nav__panel {
	position: absolute;
	top: 0;
	right: 0;
	height: 100%;
	width: min(78vw, 320px);
	background: var(--ed-bg-soft);
	border-left: 1px solid var(--ed-border);
	padding: 20px;
	transform: translateX(100%);
	transition: transform 0.25s ease;
	overflow-y: auto;
}

.ed-mobile-nav.is-open .ed-mobile-nav__panel {
	transform: translateX(0);
}

.ed-mobile-nav__header {
	display: flex;
	justify-content: space-between;
	align-items: center;
	margin-bottom: 16px;
}

.ed-mobile-nav__list {
	display: flex;
	flex-direction: column;
	gap: 2px;
}

.ed-mobile-nav__link {
	display: block;
	padding: 12px 10px;
	border-radius: var(--ed-radius-sm);
	color: var(--ed-text);
	font-size: 16px;
	border-bottom: 1px solid var(--ed-border-soft);
}

.ed-mobile-nav__link.is-active {
	color: var(--ed-gold);
}

.ed-mobile-search {
	margin-top: 16px;
	/* OWNER OPERATIONS CLOSURE §三十 —— 抽屉里的搜索区从「一行表单」变成
	   「表单 + 历史 / 热搜面板」两块。原来的横向 flex 会把面板并排塞在
	   搜索按钮右边；改成纵向，表单自己内部的横向布局由 .ed-search-form
	   负责，与桌面遮罩一致。 */
	display: flex;
	flex-direction: column;
	gap: 8px;
}

.ed-mobile-search input {
	flex: 1;
}

/* Search box (shared) */
.ed-search-form {
	display: flex;
	gap: 8px;
	width: 100%;
}

.ed-search-form input[type="search"] {
	flex: 1;
	/* FRONTEND OWNER UX FINAL CLOSURE §三十五 —— 移动抽屉搜索按钮溢出。
	   flex 项目的 min-width 默认是 auto，对 <input type="search"> 来说那是
	   浏览器给的固有尺寸（size 属性默认 20 字符，约 170–200px + padding）。
	   于是 flex: 1 只能让它长，不能让它缩：375px 下抽屉里「输入框 + 搜索
	   按钮」加起来超出面板约 11.5px，360px 下约 23.2px。
	   min-width: 0 解除那个下限，输入框重新可以收缩。空间够的断点上完全
	   没有可观察的变化 —— flex: 1 本来就已经把它撑满了。 */
	min-width: 0;
	background: var(--ed-bg);
	border: 1px solid var(--ed-border);
	color: var(--ed-text);
	border-radius: var(--ed-radius-sm);
	padding: 10px 12px;
	font-size: 15px;
}

.ed-search-form input[type="search"]:focus {
	outline: none;
	border-color: var(--ed-gold-soft);
}

.ed-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	padding: 10px 18px;
	border-radius: var(--ed-radius-sm);
	background: var(--ed-gold);
	color: var(--ed-gold-ink);
	font-weight: 600;
	font-size: 14px;
	border: none;
}

.ed-btn:hover {
	background: var(--ed-gold-hover);
}

.ed-btn--ghost {
	background: transparent;
	color: var(--ed-text);
	border: 1px solid var(--ed-border);
}

.ed-btn--ghost:hover {
	border-color: var(--ed-gold-soft);
	color: var(--ed-gold);
}

/* Search overlay (desktop) */
.ed-search-overlay {
	position: fixed;
	inset: 0;
	z-index: 200;
	visibility: hidden;
	pointer-events: none;
}

.ed-search-overlay.is-open {
	visibility: visible;
	pointer-events: auto;
}

.ed-search-overlay__backdrop {
	position: absolute;
	inset: 0;
	background: var(--ed-overlay-backdrop);
	opacity: 0;
	transition: opacity 0.2s ease;
}

.ed-search-overlay.is-open .ed-search-overlay__backdrop {
	opacity: 1;
}

.ed-search-overlay__panel {
	position: relative;
	max-width: 640px;
	margin: 12vh auto 0;
	padding: 0 20px;
	transform: translateY(-12px);
	opacity: 0;
	transition: transform 0.2s ease, opacity 0.2s ease;
}

.ed-search-overlay.is-open .ed-search-overlay__panel {
	transform: translateY(0);
	opacity: 1;
}

.ed-search-overlay__box {
	background: var(--ed-card);
	border: 1px solid var(--ed-border);
	border-radius: var(--ed-radius-md);
	padding: 16px;
}

/* ==========================================================================
   Layout helpers
   ========================================================================== */
.ed-main {
	min-height: 60vh;
	padding-bottom: 60px;
}

.ed-section {
	padding: 36px 0;
}

.ed-section__head {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	margin-bottom: 18px;
	gap: 12px;
}

.ed-section__title {
	font-size: 20px;
	font-weight: 700;
	display: flex;
	align-items: center;
	gap: 8px;
}

.ed-section__title::before {
	content: "";
	display: inline-block;
	width: 4px;
	height: 18px;
	background: var(--ed-gold);
	border-radius: 2px;
}

.ed-section__more {
	font-size: 13px;
	color: var(--ed-text-muted);
}

.ed-section__more:hover {
	color: var(--ed-gold);
}

.ed-grid {
	display: grid;
	grid-template-columns: 1fr;
	gap: 16px;
}

.ed-layout {
	display: grid;
	grid-template-columns: 1fr;
	gap: 32px;
}

.ed-layout__aside {
	display: flex;
	flex-direction: column;
	gap: 28px;
}

/* ==========================================================================
   Hero
   ========================================================================== */
.ed-hero {
	padding: 24px 0 8px;
}

.ed-hero__grid {
	display: grid;
	grid-template-columns: 1fr;
	gap: 14px;
}

.ed-hero__main {
	position: relative;
	border-radius: var(--ed-radius-lg);
	overflow: hidden;
	border: 1px solid var(--ed-border);
	background: var(--ed-card);
	aspect-ratio: 16 / 9;
	display: block;
}

.ed-hero__main img {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

.ed-hero__overlay {
	position: absolute;
	inset: 0;
	background: linear-gradient(180deg, rgba(10, 10, 12, 0) 40%, rgba(10, 10, 12, 0.92) 100%);
	display: flex;
	flex-direction: column;
	justify-content: flex-end;
	padding: 20px;
}

.ed-hero__cat {
	display: inline-block;
	align-self: flex-start;
	padding: 4px 10px;
	border-radius: var(--ed-radius-sm);
	background: var(--ed-gold);
	color: var(--ed-gold-ink);
	font-size: 12px;
	font-weight: 700;
	margin-bottom: 10px;
}

.ed-hero__title {
	font-size: 22px;
	font-weight: 700;
	color: var(--ed-on-media);
	margin-bottom: 8px;
	line-height: 1.4;
}

.ed-hero__meta {
	color: var(--ed-on-media-muted);
	font-size: 13px;
}

.ed-hero__sub {
	display: grid;
	grid-template-columns: 1fr;
	gap: 12px;
}

.ed-hero__sub-item {
	position: relative;
	display: flex;
	gap: 12px;
	align-items: center;
	border: 1px solid var(--ed-border);
	background: var(--ed-card);
	border-radius: var(--ed-radius-md);
	padding: 10px;
}

.ed-hero__sub-thumb {
	width: 96px;
	aspect-ratio: 16 / 9;
	border-radius: var(--ed-radius-sm);
	overflow: hidden;
	flex-shrink: 0;
	background: var(--ed-bg-soft);
}

.ed-hero__sub-thumb img {
	width: 100%;
	height: 100%;
	object-fit: cover;
}

.ed-hero__sub-body {
	min-width: 0;
}

.ed-hero__sub-cat {
	font-size: 11px;
	color: var(--ed-gold);
	margin-bottom: 4px;
}

.ed-hero__sub-title {
	font-size: 14px;
	font-weight: 600;
	overflow: hidden;
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
}

/* --------------------------------------------------------------------------
   OWNER_EBOOK_HOMEPAGE_LAYOUT §三 / §五 —— 小说分类页顶部的热门版图

   骨架与首页 Hero **是同一套**（同一个 partial、同一组 class），所以这里只有
   三类差异，没有第二套布局：

     1. 封面     .ed-hero__main / .ed-hero__sub-thumb 里放的是两层框而不是
                 一个 <img>，需要给框本身一个定位上下文与比例。
     2. 桌面比例 首页是 1.5fr 1fr（60/40）；Owner 要小说是 65/35，
                 也就是 1.85fr 1fr。只在 ≥1024 生效。
     3. 副标题   .ed-hero__book / .ed-hero__sub-meta 两行小字（作者 · N 章 +
                 真实阅读量），首页那一支没有。

   平板与手机**一条新规则都不需要**：首页 Hero 在 640 起就把侧栏变成 2×2、
   在 640 以下是单列，而 .ed-hero__sub-item 本身就是「左小图 + 右文字」的
   flex 横条 —— 那正好就是 Owner 要的平板 2×2 与手机四张横向小卡。
   复用它而不是另写，这就是「复用首页 Hero 的布局结构」的字面意思。
   -------------------------------------------------------------------------- */

/* 主图：任何视口都是 16:9。
   v1 在手机上给的是 1:1、桌面是 aspect-ratio:auto + min-height:360 —— 配上
   contain 前景，横版封面缩在中间、四周一圈模糊暗底。Owner 判定 FAIL 的第一
   条就是它。现在框是 16:9、前景 cover，封面**填满**槽位。 */
.ed-hero--ebook .ed-hero__main {
	aspect-ratio: 16 / 9;
}

/* 两层框在 .ed-hero__main 里要撑满整块（它自己是 absolute inset:0）。 */
.ed-hero--ebook .ed-hero__main .ed-cover {
	position: absolute;
	inset: 0;
}

/* 遮罩要盖在封面之上 —— 两层框是 absolute，所以给遮罩一个更高的层级。

   渐变比首页那一支重一档：小说封面**自己带书名**，而且几乎都压在画面中下部，
   站内标题直接叠上去两行字会互相咬（Owner §七.9「文字不得覆盖图片主体」）。
   这里加的是一条**底部带**，上面 34% 完全透明 —— 不是 Owner 禁止的「整张
   厚重黑幕」。 */
.ed-hero--ebook .ed-hero__overlay {
	z-index: 2;
	background: linear-gradient(180deg, rgba(10, 10, 12, 0) 34%, rgba(10, 10, 12, 0.58) 62%, rgba(10, 10, 12, 0.95) 100%);
	padding: 16px;
}

/* 手机上主图只有约 197px 高，22px 的标题会吃掉一半。 */
.ed-hero--ebook .ed-hero__title {
	font-size: 18px;
	margin-bottom: 6px;
}

/* 主图标题最多两行（Owner §五.3）。首页那一支书名短、从来不换行，所以这条
   只挂在 ebook 上，不动视频 Hero 的排版。 */
.ed-hero--ebook .ed-hero__title {
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
}

/* --------------------------------------------------------------------------
   侧栏四本：手机与平板是 2 × 2 的**竖版小卡**（Owner §七.4）。

   v1 在这一档沿用了首页的「左小图 + 右文字」横条，390 上四条又长又松散 ——
   Owner §十一 把它单独列为不得判 PASS 的一条。2×2 每张约 150px 宽，横条结构
   在这个宽度下图文两边都挤，所以这一档换成图在上、字在下。
   ≥1024 再切回单列横条（那一档右侧只有约 400px，横条才是对的）。
   -------------------------------------------------------------------------- */
.ed-hero--ebook .ed-hero__sub {
	grid-template-columns: repeat(2, 1fr);
	gap: 12px;
}

.ed-hero--ebook .ed-hero__sub-item {
	flex-direction: column;
	align-items: stretch;
	gap: 8px;
	padding: 8px;
}

/* 四张小封面统一 16:9、统一填满 —— Owner §七.5「图片比例和高度一致」。 */
.ed-hero--ebook .ed-hero__sub-thumb {
	position: relative;
	width: 100%;
	aspect-ratio: 16 / 9;
}

.ed-hero--ebook .ed-hero__sub-body {
	display: flex;
	flex-direction: column;
	gap: 4px;
	min-width: 0;
}

/* 作者 · N 章。一行，超出省略 —— 卡片高度必须与书名长短无关。 */
.ed-hero__book {
	display: inline-block;
	max-width: 100%;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

/* 手机与平板的辅助卡只留「标题 + 一项最重要数据」（Owner §七.6）：
   作者·章节数在这一档收起来，阅读量留下。≥1024 再放回去。 */
.ed-hero--ebook .ed-hero__sub-meta .ed-hero__book {
	display: none;
}

.ed-hero--ebook .ed-hero__meta {
	display: flex;
	align-items: center;
	gap: 12px;
	flex-wrap: wrap;
}

.ed-hero__sub-meta {
	display: flex;
	align-items: center;
	gap: 10px;
	font-size: 12px;
	color: var(--ed-text-faint);
	min-width: 0;
}

/* 书名两行、meta 一行，内容不同也不改变高度。 */
.ed-hero--ebook .ed-hero__sub-title {
	font-size: 13px;
	line-height: 1.4;
	min-height: calc(2 * 1.4em);
}

/* 热门区与下方「全部小说」之间的呼吸（Owner §六.3：32–40px）。 */
.ed-hero--ebook {
	padding: 20px 0 0;
}

.ed-section__head--archive {
	margin-top: 36px;
}

.ed-empty {
	border: 1px dashed var(--ed-border);
	border-radius: var(--ed-radius-lg);
	padding: 48px 20px;
	text-align: center;
	color: var(--ed-text-muted);
}

.ed-empty__title {
	color: var(--ed-text);
	font-size: 16px;
	font-weight: 600;
	margin-bottom: 6px;
}

/* ==========================================================================
   Card components
   ========================================================================== */
.ed-card {
	display: flex;
	flex-direction: column;
	background: var(--ed-card);
	border: 1px solid var(--ed-border);
	border-radius: var(--ed-radius-md);
	overflow: hidden;
	box-shadow: var(--ed-shadow-card);
	height: 100%;
	transition: border-color 0.15s ease, transform 0.15s ease;
}

.ed-card:hover {
	border-color: var(--ed-gold-soft);
}

.ed-card__thumb {
	position: relative;
	aspect-ratio: 16 / 9;
	background: var(--ed-bg-soft);
	overflow: hidden;
}

.ed-card__thumb img {
	width: 100%;
	height: 100%;
	object-fit: cover;
}

/* --------------------------------------------------------------------------
   OWNER_EBOOK_HOMEPAGE_LAYOUT §四 —— 两层封面框

   为什么需要它：站上的小说封面**不是一个比例**。实测 38 本里既有 1280×720
   的横版 letterbox 成品，也有 1200×1800 的竖版原封（post 2265）。一个槽位
   只能有一个比例，所以无论槽位是 16:9 还是 2:3，总有一种封面被裁掉三分之一 ——
   Owner 在验收时点名的就是被上下裁掉的那张竖版。

   两层把「槽位比例」与「图片比例」解耦：
     .ed-cover__bg  同一张图 cover + 模糊放大，负责**填满**槽位（纯装饰）
     .ed-cover__fg  同一张图 contain，负责**完整显示**（这才是内容）

   同一个 URL，浏览器只下载一次，第二个 <img> 命中缓存。
   底层 scale(1.1) 是为了让 blur 的边缘不露出槽位边界。

   视频卡不走这里 —— 它仍然是 .ed-card__thumb img 那条既有规则。
   -------------------------------------------------------------------------- */
.ed-cover {
	position: absolute;
	inset: 0;
	display: block;
	overflow: hidden;
	background: var(--ed-bg-soft);
}

/* 选择器里带上 .ed-cover 不是为了好看，是**必须**的：站上既有的
   `.ed-hero__main img` 与 `.ed-card__thumb img` 都是 (0,1,1)，会盖掉单类的
   `.ed-cover__fg` (0,1,0)。第一版就是这么栽的 —— CSS 写着 contain，
   1440 实拍量出来仍然是 cover，竖版封面照样被裁。 */
/* 底层：伪元素背景。inset 负值让 blur 的边缘不露出槽位，而伪元素**不是**
   一个会被 getBoundingClientRect() 量到的盒子，所以它不会像第一版那两个
   <img> 一样在 320px 上「伸到视口外面」。 */
.ed-cover::before {
	content: "";
	position: absolute;
	inset: -12%;
	background-image: var(--ed-cover-bg);
	background-size: cover;
	background-position: center;
	filter: blur(18px) saturate(1.15) brightness(0.7);
}

/* 选择器里带上 .ed-cover 不是为了好看，是**必须**的：站上既有的
   `.ed-hero__main img` 与 `.ed-card__thumb img` 都是 (0,1,1)，会盖掉单类的
   `.ed-cover__fg` (0,1,0)。第一版就是这么栽的 —— CSS 写着 contain，
   1440 实拍量出来仍然是 cover，竖版封面照样被裁。 */
/* --------------------------------------------------------------------------
   OWNER_EBOOK_VISUAL §五.3 —— 前景从 contain 改为 cover。

   v1 是 contain：一张 1280×720 的横版封面放进接近正方形的槽里，只画到中间
   一条，上下两块交给模糊底 —— Owner 的原话是「四周出现大面积黑色空洞」。
   本轮 Owner 的裁定是「图片必须完整覆盖可视区域 …… 使用 object-fit:cover」。

   object-position = center 48%，这个数字是**量出来的**，不是猜的：

   38 本里只有 2 本是竖版（2406 / 2265，都是 1200×1800，都出自更早那个
   sanitiser）。把这两张按 5% 一条横带测平均亮度，结果是 0–30% 与 70–100%
   两段恒为 26（同一个深色值），画面本体只在 30%–70% 之间 —— 也就是说这两张
   「竖版封面」其实是一张 16:9 的画**上下补黑**填进 2:3 的框。Owner 在 v1
   截图上看到的黑边，有一半是**源文件自带的**，不是 CSS 造出来的。

   16:9 的窗口在 1800 高里占 37.5%，落在 48% 上覆盖 29.75%–67.25%，正好吃住
   整段画面本体，只在顶边差 0.25%（换算到 460px 的框里约 1px）。剩下 36 张是
   1280×720 的精确 16:9，object-position 对它们不产生任何裁切。

   取 48% 而不是 50%：书名普遍略高于画面中线，两个百分点把它整个留在框里。

   模糊底 .ed-cover::before 保留：cover 之后它平时看不见，但在图片尚未加载
   或加载失败时它仍然是那本书自己的颜色，而不是一块死灰。
   -------------------------------------------------------------------------- */
.ed-cover .ed-cover__fg {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	display: block;
	margin: 0;
	border-radius: 0;
	object-fit: cover;
	object-position: center 48%;
}

.ed-card__cat {
	position: absolute;
	top: 8px;
	left: 8px;
	padding: 3px 8px;
	border-radius: var(--ed-radius-sm);
	background: var(--ed-on-media-bg);
	color: var(--ed-on-media-accent);
	font-size: 11px;
	font-weight: 600;
	/* CATEGORY_TOP4_REAL_VIEWS §七.5 / §七.7 —— 左上角这一枚现在有了一个
	   右上角的邻居。320px 下每张卡只有约 134px 宽，一个长分类名会顶到
	   名次角标下面去。给它一个上限并用省略号收尾：两枚角标各占一角，
	   任何宽度下都不重叠。完整分类名在卡片正文的面包屑与详情页里都在，
	   这里截断不丢信息。 */
	max-width: 46%;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

/* --------------------------------------------------------------------------
   CATEGORY_TOP4_REAL_VIEWS §七 —— 封面右上角的名次角标

   .ed-card__rank--hot   「热度最高」：本分类真实浏览量 / 真实阅读量前 4
                         （OWNER_FRONTEND_CORRECTION §二.4 —— 「人工置顶」
                         那一档已从公开前台整个删除，后台能力一个没动）

   位置是**右上角**，与左上角的分类胶囊对称（Owner §七.1 / §七.2）。
   它压不到播放按钮：那一枚是 inset:0 的居中 flex，几何上在卡片正中。
   它也压不到左下角的「N 个视频」与右下角的时长 —— 三者分别在另外三个角。

   nowrap + 不收缩：Owner §七.7 明确「手机端不得换行、溢出或缩小到无法阅读」。
   四个汉字在 11px 下是 44px，加上内边距 56px，在 320px 那一档的 134px 卡片上
   占 42%，与左上角那枚 46% 的上限加起来仍然留得下中间的空隙。
   -------------------------------------------------------------------------- */
.ed-card__rank {
	position: absolute;
	top: 8px;
	right: 8px;
	z-index: 2;
	padding: 3px 8px;
	border-radius: var(--ed-radius-sm);
	font-size: 11px;
	font-weight: 700;
	line-height: 1.5;
	letter-spacing: 0.02em;
	white-space: nowrap;
	pointer-events: none;
}

.ed-card__rank--hot {
	background: var(--ed-rank-hot-bg);
	color: var(--ed-rank-hot-ink);
}


/* A 类横条流的封面块用的是 .ed-feed__thumb，它同样是 position: relative，
   所以同一枚角标直接生效 —— 不写第二套定位。 */
.ed-feed__thumb .ed-card__rank {
	top: 8px;
	right: 8px;
}

.ed-card__body {
	padding: 12px 14px 14px;
	display: flex;
	flex-direction: column;
	gap: 6px;
	flex: 1;
}

/* OPERATOR CLOSURE §三十五 / §四十二 —— 关键词 chip。
 *
 * 一行，不换行，超出的第三个 chip 被裁掉而不是把卡片撑高：卡片高度必须稳定，
 * 否则同一行的四张卡会因为关键词数量不同而参差（§四十二）。
 * flex + overflow:hidden 做这件事，不用 JS。
 *
 * 单个 chip 自己再设 max-width + 省略号，于是「一个意外的长词」只会让那一个
 * chip 变成 "长词…"，不会顶掉它旁边的两个（§四十二：必要时 truncate）。
 * 完整文字留在 title 属性里，鼠标悬停与读屏软件都拿得到（§四十二 最后一句）。
 *
 * 配色走 09GUA 自己的 token：--ed-gold-bg 底 + --ed-gold 字，与分类胶囊
 * （.ed-card__cat）同一套语言。不引入参考站的粉色（§三十五）。
 */
.ed-card__chips {
	display: flex;
	gap: 6px;
	overflow: hidden;
	white-space: nowrap;
	/* 空的时候也占住这一行的高度。卡片高度必须与「这条内容有没有关键词」无关，
	 * 否则同一屏里有 chip 和没 chip 的卡会差出一整行（390 实测 38px），
	 * 网格看起来就是坏的。真实浏览器验收的 KW-12 就是这么抓到的。 */
	min-height: 20px;
}

.ed-chip {
	display: inline-block;
	/* flex: 0 1 auto + min-width: 0 —— **收缩**而不是溢出。
	 *
	 * 第一版写的是 flex: 0 0 auto（不收缩）+ 容器 overflow: hidden，指望
	 * 「放不下就裁掉」。390 实测下那等于第三个 chip 被拦腰切断：它仍然占着
	 * 96px 的宽度，只是超出的部分看不见 —— 读者看到的是半个词。
	 *
	 * 允许收缩之后，三个 chip 会各自让出宽度，每一个用自己的省略号收尾，
	 * 三个都完整可见地存在（§四十二：必要时 truncate / max-width）。
	 * min-width: 0 是必须的：flex 子项默认 min-width:auto，那会让
	 * text-overflow 永远不生效。 */
	flex: 0 1 auto;
	min-width: 0;
	max-width: 96px;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	padding: 2px 8px;
	border-radius: 999px;
	background: var(--ed-gold-bg);
	color: var(--ed-gold);
	font-size: 11px;
	line-height: 16px;
	font-weight: 600;
}

.ed-card__title {
	font-size: 15px;
	font-weight: 600;
	line-height: 1.4;
	overflow: hidden;
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
}

.ed-card:hover .ed-card__title {
	color: var(--ed-gold);
}

.ed-card__excerpt {
	font-size: 13px;
	color: var(--ed-text-muted);
	overflow: hidden;
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
}

.ed-card__meta {
	margin-top: auto;
	display: flex;
	gap: 10px;
	font-size: 12px;
	color: var(--ed-text-faint);
}

/* List card (今日吃瓜 stream) */
.ed-card-list {
	display: flex;
	gap: 14px;
	padding: 14px 0;
	border-bottom: 1px solid var(--ed-border-soft);
}

.ed-card-list:last-child {
	border-bottom: none;
}

.ed-card-list__thumb {
	/* FRONTEND V2-I1 §八：128px 曾经在所有断点恒定 —— 手机上占比过大，
	   桌面上又太小。clamp 让它跟着容器走，两头都不牺牲。 */
	width: clamp(104px, 30%, 168px);
	flex-shrink: 0;
	aspect-ratio: 16 / 9;
	border-radius: var(--ed-radius-sm);
	overflow: hidden;
	background: var(--ed-bg-soft);
}

.ed-card-list__thumb img {
	width: 100%;
	height: 100%;
	object-fit: cover;
}

.ed-card-list__body {
	min-width: 0;
	display: flex;
	flex-direction: column;
	gap: 6px;
}

.ed-card-list__title {
	font-size: 15px;
	font-weight: 600;
	overflow: hidden;
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
}

.ed-card-list:hover .ed-card-list__title {
	color: var(--ed-gold);
}

.ed-card-list__excerpt {
	font-size: 13px;
	color: var(--ed-text-muted);
	overflow: hidden;
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
}

.ed-card-list__meta {
	display: flex;
	gap: 10px;
	font-size: 12px;
	color: var(--ed-text-faint);
}

/* Rank card (热门排行) */
.ed-rank-list {
	display: flex;
	flex-direction: column;
	gap: 2px;
}

.ed-rank-item {
	display: flex;
	align-items: center;
	gap: 12px;
	padding: 10px 4px;
	border-bottom: 1px solid var(--ed-border-soft);
}

.ed-rank-item:last-child {
	border-bottom: none;
}

.ed-rank-item__num {
	width: 22px;
	flex-shrink: 0;
	text-align: center;
	font-weight: 700;
	font-size: 14px;
	color: var(--ed-text-faint);
}

.ed-rank-item:nth-child(1) .ed-rank-item__num {
	color: var(--ed-gold);
}

.ed-rank-item:nth-child(2) .ed-rank-item__num,
.ed-rank-item:nth-child(3) .ed-rank-item__num {
	color: var(--ed-text-muted);
}

.ed-rank-item__title {
	font-size: 14px;
	overflow: hidden;
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
}

.ed-rank-item:hover .ed-rank-item__title {
	color: var(--ed-gold);
}

/* Tags block */
.ed-tag-cloud {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
}

.ed-tag {
	padding: 6px 12px;
	border-radius: 999px;
	border: 1px solid var(--ed-border);
	color: var(--ed-text-muted);
	font-size: 13px;
}

.ed-tag:hover {
	border-color: var(--ed-gold-soft);
	color: var(--ed-gold);
}

/* Video placeholder card */
.ed-video-card {
	position: relative;
}

.ed-video-card__play {
	position: absolute;
	inset: 0;
	display: flex;
	align-items: center;
	justify-content: center;
}

.ed-video-card__play svg {
	width: 44px;
	height: 44px;
	color: var(--ed-on-media);
	opacity: 0.85;
}

.ed-video-card__play--sm svg {
	width: 26px;
	height: 26px;
}

.ed-video-card__duration {
	position: absolute;
	right: 8px;
	bottom: 8px;
	padding: 2px 6px;
	border-radius: var(--ed-radius-sm);
	background: var(--ed-on-media-bg);
	color: var(--ed-on-media);
	font-size: 11px;
	font-weight: 600;
}

/* aside widget block */
.ed-aside-block {
	background: var(--ed-bg-soft);
	border: 1px solid var(--ed-border);
	border-radius: var(--ed-radius-md);
	padding: 16px;
}

/* ==========================================================================
   Breadcrumb
   ========================================================================== */
.ed-breadcrumb {
	font-size: 13px;
	color: var(--ed-text-muted);
	margin-bottom: 18px;
	display: flex;
	flex-wrap: wrap;
	gap: 6px;
}

.ed-breadcrumb a:hover {
	color: var(--ed-gold);
}

.ed-breadcrumb__sep {
	color: var(--ed-text-faint);
}

/* ==========================================================================
   Archive / Category
   ========================================================================== */
.ed-archive-head {
	padding: 28px 0 8px;
	border-bottom: 1px solid var(--ed-border);
	margin-bottom: 24px;
}

/* --------------------------------------------------------------------------
   FRONTEND_TRUST_FOOTER_CATEGORY_VISUAL_CLEANUP §五 / §六 —— 分类页顶部留白。

   .ed-archive-head 在分类页上已经整块不渲染（见 archive-loop.php），连同它
   的 28+8 内边距和 24 外边距一起没了。但 .ed-main 本身没有上内边距，所以
   如果什么都不补，内容流会直接贴在 sticky header 下沿。

   这里给的是 20px —— 刚好一口气，而不是把删掉的 60px 换个名字再加回来。
   Owner 要的是「进入分类页后第一眼尽快看到内容」，净收益是 40px 左右。
   /hot/ 用同一个数字（.ed-single 原来是 28px 上内边距）。
   -------------------------------------------------------------------------- */
/* 双类选择器不是装饰：单类的 .ed-archive--flush 会被后面 @media (min-width:768px)
   里那条 .ed-container { padding: 0 28px } 的简写整个覆盖掉 padding-top（同优先级、
   位置更靠后），实测桌面端补的 20px 一点没生效。.ed-single--flush 同理 ——
   .ed-single { padding: 28px 0 60px } 就写在这段下面。 */
/* --------------------------------------------------------------------------
   FRONTEND_TRUST（Owner 追加裁定 §七）—— 视频分类页的宽版容器。

   Owner 的判定是「内容区太窄、左右留白太多、像普通 WordPress 模板站」，
   目标内容宽度 1280–1360，并要求「优先复用现有 container token」。

   所以这里既不新建第二个容器类，也不动 :root 的 1200px（那会把首页、单篇、
   静态页全部一起加宽，§十三 明确要求首页保持锁定）。做法是在 body 上重定义
   --ed-container —— .ed-container 全都是 body 的后代，于是 header、内容网格、
   footer 在这一类页面上一起变宽，三者仍然左右对齐。只加宽内容区会让导航比
   第一张卡窄 60px，那看起来就是个 bug。

   1320 取的是 Owner 区间 1280–1360 的中点：1440 视口下内容 1264px（1320 减
   两侧 28 内边距），比原来的 1144 宽 120px，四列每卡从 269px 涨到 299px。
   -------------------------------------------------------------------------- */
body.ed-layout--wide {
	--ed-container: 1320px;
}

.ed-container.ed-archive--flush {
	padding-top: 20px;
}

.ed-single.ed-single--flush {
	padding-top: 20px;
}

.ed-archive-head__title {
	font-size: 24px;
	font-weight: 700;
	margin-bottom: 6px;
}

.ed-archive-head__desc {
	color: var(--ed-text-muted);
	font-size: 14px;
	max-width: 700px;
}

/* --------------------------------------------------------------------------
   分页（Owner 追加裁定 §十 / §十一）。

   Owner 裁定：保留分页，不做无限滚动、不做第二套 AJAX Load More —— 现阶段
   优先稳定、SEO、查询可控、用户定位清楚。所以这里**没有动任何后端**：
   paginate_links() 的参数、URL 形状、query context 一个字都没改。

   改的只有观感。原来是 36px 高、13px 浅灰、左对齐挤在角落的一排小按钮，
   典型的默认 WordPress 样子；现在与 card system 对齐：居中、44px 触达高度
   （移动端最小可点面积）、圆角与卡片同一档、当前页用品牌金实心。
   -------------------------------------------------------------------------- */
.ed-pagination {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	align-items: center;
	gap: 8px;
	margin-top: 36px;
	padding-top: 28px;
	border-top: 1px solid var(--ed-border-soft);
}

.ed-pagination a,
.ed-pagination span {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 44px;
	height: 44px;
	padding: 0 14px;
	border-radius: var(--ed-radius-md);
	border: 1px solid var(--ed-border);
	background: var(--ed-card);
	color: var(--ed-text);
	font-size: 14px;
	font-weight: 600;
	transition: border-color 0.15s ease, color 0.15s ease, background 0.15s ease;
}

.ed-pagination a:hover {
	border-color: var(--ed-gold);
	color: var(--ed-gold);
	background: var(--ed-card-hover);
}

.ed-pagination a:focus-visible {
	outline: 2px solid var(--ed-gold);
	outline-offset: 2px;
}

/* 省略号不是一个可点目标，别让它长得像按钮。 */
.ed-pagination .dots {
	border-color: transparent;
	background: none;
	color: var(--ed-text-muted);
	min-width: 24px;
	padding: 0 4px;
}

.ed-pagination .current {
	background: var(--ed-gold);
	color: var(--ed-gold-ink);
	border-color: var(--ed-gold);
	font-weight: 700;
}

/* ==========================================================================
   Single article
   ========================================================================== */
.ed-single {
	padding: 28px 0 60px;
}

.ed-single__wrap {
	max-width: var(--ed-content-width);
	margin: 0 auto;
}

.ed-single__cat {
	display: inline-block;
	padding: 4px 10px;
	border-radius: var(--ed-radius-sm);
	background: var(--ed-gold-bg);
	color: var(--ed-gold);
	font-size: 12px;
	font-weight: 600;
	margin-bottom: 12px;
}

.ed-single__title {
	font-size: 26px;
	line-height: 1.4;
	font-weight: 700;
	margin-bottom: 14px;
}

.ed-single__meta {
	display: flex;
	flex-wrap: wrap;
	gap: 14px;
	color: var(--ed-text-muted);
	font-size: 13px;
	padding-bottom: 18px;
	border-bottom: 1px solid var(--ed-border);
	margin-bottom: 20px;
}

.ed-single__thumb {
	border-radius: var(--ed-radius-lg);
	overflow: hidden;
	margin-bottom: 24px;
	border: 1px solid var(--ed-border);
}

.ed-single__thumb img {
	width: 100%;
	display: block;
}

.ed-single__video {
	position: relative;
	border-radius: var(--ed-radius-lg);
	overflow: hidden;
	margin-bottom: 24px;
	border: 1px solid var(--ed-border);
	background: #000;
}

.ed-single__video video,
.ed-single__video iframe {
	width: 100%;
	/* STEP 5B-1: real ratio comes from --ed-video-ratio (set inline in
	   single.php from the attachment's actual width/height); 16/9 is only
	   the fallback for external oembed videos with no known dimensions. */
	aspect-ratio: var(--ed-video-ratio, 16 / 9);
	display: block;
}

/* Portrait/square videos must not stretch to the full content width on
   desktop/tablet (STEP 5B-1) — landscape keeps the pre-existing full-width
   behaviour. On narrow mobile viewports the cap is lifted back to 100% so
   the player still fills the available width instead of looking tiny. */
.ed-single__video--portrait,
.ed-single__video--square {
	max-width: 100%;
}

@media (min-width: 640px) {
	.ed-single__video--portrait {
		max-width: 420px;
		margin-left: auto;
		margin-right: auto;
	}

	.ed-single__video--square {
		max-width: 480px;
		margin-left: auto;
		margin-right: auto;
	}
}

.ed-single__video-duration {
	position: absolute;
	right: 10px;
	bottom: 10px;
	padding: 3px 8px;
	border-radius: var(--ed-radius-sm);
	background: var(--ed-on-media-bg);
	color: var(--ed-on-media);
	font-size: 12px;
	font-weight: 600;
}

.ed-single__source {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
	align-items: center;
	margin: 4px 0 20px;
	padding: 10px 14px;
	border-radius: var(--ed-radius-md);
	background: var(--ed-bg-soft);
	border: 1px solid var(--ed-border);
	color: var(--ed-text-muted);
	font-size: 13px;
}

.ed-single__source a {
	color: var(--ed-gold);
}

.ed-hot-archive__grid {
	margin: 8px 0 28px;
}

.ed-single__content {
	font-size: 16px;
	line-height: 1.9;
	color: var(--ed-text);
}

.ed-single__content p {
	margin: 0 0 1.2em;
}

.ed-single__content h2,
.ed-single__content h3 {
	margin: 1.6em 0 0.8em;
	font-weight: 700;
}

.ed-single__content img {
	border-radius: var(--ed-radius-md);
	margin: 1em 0;
}

.ed-single__content a {
	color: var(--ed-gold);
	text-decoration: underline;
}

.ed-single__content blockquote {
	margin: 1.2em 0;
	padding: 12px 16px;
	border-left: 3px solid var(--ed-gold);
	background: var(--ed-bg-soft);
	color: var(--ed-text-muted);
}

.ed-single__tags {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
	margin: 28px 0;
}

.ed-single__report {
	margin: 20px 0 0;
}

/* ==========================================================================
   Brand / legal page content blocks (About, Contact, Submit, Report,
   DMCA, Privacy, Terms, 18+, Official — used inside .ed-single__content)
   ========================================================================== */
.ed-page-lead {
	font-size: 17px;
	line-height: 1.8;
	color: var(--ed-text-muted);
	margin: 0 0 28px;
}

.ed-page-block {
	background: var(--ed-card);
	border: 1px solid var(--ed-border);
	border-radius: var(--ed-radius-lg);
	padding: 20px 22px;
	margin: 0 0 18px;
}

.ed-page-block__title {
	font-size: 16px;
	font-weight: 700;
	color: var(--ed-gold);
	margin: 0 0 12px;
}

.ed-page-block p:last-child {
	margin-bottom: 0;
}

.ed-page-block code {
	display: inline-block;
	max-width: 100%;
	overflow-wrap: anywhere;
	background: var(--ed-bg-soft);
	border: 1px solid var(--ed-border);
	border-radius: var(--ed-radius-sm);
	padding: 6px 10px;
	color: var(--ed-gold);
	font-size: 13px;
}

.ed-page-block ul {
	margin: 0;
	padding: 0;
}

.ed-page-block li {
	position: relative;
	padding-left: 18px;
	margin-bottom: 8px;
	font-size: 14.5px;
	line-height: 1.7;
	color: var(--ed-text);
}

.ed-page-block li:last-child {
	margin-bottom: 0;
}

.ed-page-block li::before {
	content: "";
	position: absolute;
	left: 2px;
	top: 0.7em;
	width: 5px;
	height: 5px;
	border-radius: 50%;
	background: var(--ed-gold);
}

.ed-page-notice {
	border: 1px solid var(--ed-danger);
	background: var(--ed-danger-bg);
	border-radius: var(--ed-radius-md);
	padding: 16px 18px;
	margin: 0 0 18px;
	font-size: 14.5px;
	line-height: 1.75;
	color: var(--ed-text);
}

.ed-page-notice strong {
	color: var(--ed-danger);
}

.ed-page-notice ul {
	margin: 10px 0 0;
	padding: 0;
}

.ed-page-notice li {
	position: relative;
	padding-left: 18px;
	margin-bottom: 6px;
}

.ed-page-notice li::before {
	content: "";
	position: absolute;
	left: 2px;
	top: 0.7em;
	width: 5px;
	height: 5px;
	border-radius: 50%;
	background: var(--ed-danger);
}

/* --------------------------------------------------------------------------
   FRONTEND_TRUST §二十四 / §二十五 —— 页内联系方式。

   .ed-page-contact 是插件 [edgua_contact_channel] 短代码的输出容器（一个
   <div>）。此前它只在页面最底部孤零零地出现一次，里面就一个裸 @商务账号，
   用户根本看不出那是 Telegram。现在它被放进「商务合作 / 内容合作」卡片里，
   和一句「Telegram ✈️」并排 —— 所以它必须能参与同一行的排版。

   改成 inline-flex 而不是去动插件：账号值仍然只有 edgua_site_settings 一个
   来源，短代码一个字符没碰（§三十四 的 Theme/Plugin 边界）。
   -------------------------------------------------------------------------- */
.ed-page-contact {
	display: inline-flex;
	align-items: center;
}

.ed-page-contact a {
	font-weight: 600;
	color: var(--ed-gold);
	overflow-wrap: anywhere;
}

.ed-page-contact a:hover {
	text-decoration: underline;
}

.ed-page-block__contact {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 4px 8px;
	margin: 12px 0 0;
	font-size: 14.5px;
	line-height: 1.7;
}

.ed-page-block__contact-label {
	font-weight: 700;
	color: var(--ed-text);
	flex-shrink: 0;
}

.ed-page-placeholder {
	border: 1px dashed var(--ed-border);
	border-radius: var(--ed-radius-md);
	padding: 14px 16px;
	margin: 0 0 18px;
	font-size: 14px;
	color: var(--ed-text-faint);
	background: var(--ed-bg-soft);
}

.ed-page-meta {
	color: var(--ed-text-faint);
	font-size: 12.5px;
	margin-top: 32px;
	padding-top: 16px;
	border-top: 1px solid var(--ed-border);
}

.ed-single__nav {
	display: grid;
	/* FRONTEND V2-I1：基础是单列。过去基础规则就是 1fr 1fr，手机上两个
	   长标题各占半屏，只能靠 ellipsis 截断，谁都读不出下一篇是什么。
	   两列从 640px 起（见 Responsive 段）。 */
	grid-template-columns: 1fr;
	gap: 12px;
	margin: 28px 0;
}

.ed-single__nav-item {
	border: 1px solid var(--ed-border);
	border-radius: var(--ed-radius-md);
	padding: 12px 14px;
	min-width: 0;
}

.ed-single__nav-item.is-next {
	text-align: right;
}

.ed-single__nav-label {
	font-size: 11px;
	color: var(--ed-text-faint);
	margin-bottom: 4px;
}

.ed-single__nav-title {
	font-size: 13px;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.ed-single__nav-item:hover .ed-single__nav-title {
	color: var(--ed-gold);
}

.ed-related {
	margin-top: 36px;
}

/* ==========================================================================
   Search
   ========================================================================== */
.ed-search-page {
	padding: 28px 0 60px;
}

.ed-search-page__head {
	margin-bottom: 24px;
}

.ed-search-page__title {
	font-size: 22px;
	font-weight: 700;
}

.ed-search-page__title mark {
	background: none;
	color: var(--ed-gold);
}

/* ==========================================================================
   404
   ========================================================================== */
.ed-404 {
	padding: 60px 0;
	text-align: center;
}

.ed-404__code {
	font-size: 72px;
	font-weight: 800;
	color: var(--ed-gold);
	line-height: 1;
	margin-bottom: 8px;
}

.ed-404__title {
	font-size: 20px;
	margin-bottom: 8px;
}

.ed-404__desc {
	color: var(--ed-text-muted);
	margin-bottom: 24px;
}

.ed-404__search {
	max-width: 480px;
	margin: 0 auto 32px;
}

.ed-404__actions {
	display: flex;
	justify-content: center;
	gap: 12px;
	margin-bottom: 40px;
	flex-wrap: wrap;
}

.ed-404__hot {
	text-align: left;
	max-width: 800px;
	margin: 0 auto;
}

/* ==========================================================================
   Footer
   ========================================================================== */
.ed-footer {
	background: var(--ed-bg-soft);
	border-top: 1px solid var(--ed-border);
	padding: 40px 0 24px;
	margin-top: 40px;
}

/* --------------------------------------------------------------------------
   FRONTEND_TRUST_FOOTER_CATEGORY_VISUAL_CLEANUP §十三 —— 页脚字重与对比度。

   Owner 的原话是「底部信息栏这些字体都搞成加粗加黑」。照字面做成
   font-weight: 900 是错的：一整块全是最粗，层级反而消失，读起来是一堵墙。
   Owner 真正在抱怨的是**看不清** —— 之前整个页脚只有品牌那三行用了
   --ed-text，其余全部是 --ed-text-muted / --ed-text-faint 的 13px 常规字重，
   在 Light 的 #efede8 暖白底上是一片糊掉的浅灰。

   所以这里做的是分档，不是一刀切：
     栏目标题        14px / 700 / --ed-text        最重，四列的锚点
     官方联系 label  13px / 700 / --ed-text        与账号同一行，靠字重分开
     官方账号        13.5px / 600 / --ed-text      半粗，深色，可点
     普通链接        13.5px / 500 / --ed-text      从 muted 提到正文色
     品牌            20px / 700                    仍然最醒目
     底栏            12.5px / --ed-text-muted      稍弱但仍清晰（原来是 faint）
   两个主题共用这一套规则，颜色全部走 token，所以 Dark 自动跟着换值。
   -------------------------------------------------------------------------- */
.ed-footer__top {
	display: grid;
	grid-template-columns: 1fr;
	gap: 28px;
	margin-bottom: 28px;
}

.ed-footer__brand-en {
	font-size: 20px;
	font-weight: 700;
}

.ed-footer__brand-cn {
	color: var(--ed-gold);
	font-size: 12px;
	margin: 4px 0 10px;
}

.ed-footer__domain {
	color: var(--ed-text-muted);
	font-size: 12px;
	font-weight: 600;
}

/* 品牌列此前只有三行短字（最宽约 95px），在桌面四列里必然留下一整片死白。
   补的这一句不是填充物：它就是 /terms/「内容性质」那一条的一句话版本，
   说的是这个站是什么。它让第一列有了和其他三列相当的内容体量。 */
.ed-footer__brand-desc {
	margin: 12px 0 0;
	font-size: 13px;
	line-height: 1.75;
	color: var(--ed-text-muted);
	max-width: 30em;
}

.ed-footer__col-title {
	font-size: 14px;
	color: var(--ed-text);
	margin-bottom: 14px;
	font-weight: 700;
}

.ed-footer__links {
	display: flex;
	flex-direction: column;
	gap: 10px;
}

.ed-footer__links a {
	font-size: 13.5px;
	font-weight: 500;
	color: var(--ed-text);
}

.ed-footer__links a:hover {
	color: var(--ed-gold);
}

/* --------------------------------------------------------------------------
   官方信息列（Owner 追加裁定 §一 / §二 / §三）。

   上一版这里有一整套 .ed-footer__contact* ：label 一段、图标一段、@handle
   一段，三段拼在一行。Owner 判定「仍然信息过密」，并裁定不再视觉显示账号 ——
   于是这一列变成了纯文字链接列，和「关于 09GUA」「安全与规则」完全同构，
   那套规则整块删掉（不是留着不用：留着的死规则下一个人读起来会以为还在生效）。

   共用 .ed-footer__links 之后自动拿到统一的行高、字重与列间距，也不会再因为
   @商务账号 与 @官方频道 长度差一倍而撑动列宽（§三 最后一条）。
   这里只补一条外链的可达性：键盘 focus 必须看得见。
   -------------------------------------------------------------------------- */
.ed-footer__links a:focus-visible {
	outline: 2px solid var(--ed-gold);
	outline-offset: 3px;
	border-radius: 2px;
}

.ed-footer__bottom {
	border-top: 1px solid var(--ed-border);
	padding-top: 18px;
	display: flex;
	flex-direction: column;
	gap: 10px;
	font-size: 12.5px;
	color: var(--ed-text-muted);
}

.ed-footer__age-gate {
	display: inline-block;
	padding: 3px 8px;
	border: 1px solid var(--ed-border);
	border-radius: var(--ed-radius-sm);
	color: var(--ed-text-muted);
	width: fit-content;
}

/* ==========================================================================
   Demo badge
   ========================================================================== */
.ed-demo-badge {
	display: inline-block;
	padding: 2px 7px;
	border-radius: var(--ed-radius-sm);
	background: var(--ed-danger-bg);
	color: var(--ed-danger);
	font-size: 11px;
	font-weight: 700;
	margin-right: 6px;
	vertical-align: middle;
}

.ed-badge-submission {
	display: inline-block;
	padding: 2px 7px;
	border-radius: var(--ed-radius-sm);
	background: var(--ed-gold-bg);
	color: var(--ed-gold);
	font-size: 11px;
	font-weight: 700;
	margin-right: 6px;
	vertical-align: middle;
}

/* ==========================================================================
   FRONTEND V2-I1 — A/B grids, article layout, unified cards, comments
   ========================================================================== */

/* --------------------------------------------------------------------------
   A/B 网格（§三 D-7 / §十）

   .ed-grid--article  A 类文章流：Mobile 1 / Tablet 2 / Desktop 3
   .ed-grid--video    B 类视频资源：Mobile 2 / Tablet 2 / Desktop 4

   两条基线都写在这里（mobile-first），断点里只写升列。B 类在手机上就是
   2 列 —— 375px 下每卡约 159px，16:9 缩略图足以辨认画面，标题 15px 两行
   放得下 18–20 个汉字；1 列会让每屏只剩约 2 个视频，与「视频资源网格」
   的产品定位不符。A 类反过来：文章要读，Mobile 保持单列大图。
   -------------------------------------------------------------------------- */
.ed-grid--article {
	grid-template-columns: 1fr;
}

.ed-grid--video {
	grid-template-columns: repeat(2, 1fr);
	gap: 12px;
}

/* B 类卡片在手机上更窄，标题给到 15px 保证两行可读（Discovery §17.3
   记的「移动端 14–15px 中文偏小」）。 */
.ed-grid--video .ed-card__title {
	font-size: 15px;
	line-height: 1.45;
}

/* --------------------------------------------------------------------------
   CATEGORY_TOP4_REAL_VIEWS §九 —— 电子书封面网格（第三种版式）

   mobile-first，断点里只写升列：

     320–767    2 列   ← 这条基线
     768–1023   3 列
     1024–1279  4 列
     ≥1280      5 列

   手机就是 2 列而不是 1 列：Owner 的原话是「普通手机继续一排一本」属于
   禁止项。320px 下容器可用 280px，两列每张 134px，一张 16:9 封面高 75px，
   书名 14px 两行放得下 16–18 个汉字。

   没有任何 min-width / 固定列宽 / overflow-x：列宽全部是 1fr，所以任何
   视口下都不会产生横向滚动（Owner §九 禁止项第 2 条）。
   -------------------------------------------------------------------------- */
.ed-grid--ebook {
	grid-template-columns: repeat(2, 1fr);
	gap: 12px;
}

/* OWNER_FRONTEND_CORRECTION §七.A.7 —— 重复的小说卡片视觉 CSS 已删除。
   这里曾经覆写 .ed-grid--ebook 下的 .ed-card__title 字号、.ed-card__body
   内边距与 .ed-card__meta 字号。Owner 要的是「真正复用首页普通卡片组件」，
   而那三条覆写恰恰是「看起来一样、实际两套」的那一半。删掉之后书卡与
   视频卡用的是**同一组**卡片视觉规则，一个字节都不差。

   只保留下面这一条语义差异：书卡的 meta 是「日期 + 真实阅读量」，两项都可能
   被 2 列窄卡挤到换行。nowrap 让它们留在同一行（Owner 上一轮 §十 的要求），
   不改字号、不改内边距 —— 它不是视觉分叉，是一条防换行的约束。 */
.ed-grid--ebook .ed-card__meta {
	flex-wrap: nowrap;
	white-space: nowrap;
}

/* OWNER_EBOOK_VISUAL §六.1「标题最多两行，日期固定在卡片底部，卡片整体高度
   一致」**不需要**为小说网格新写规则 —— 站上既有的卡片组件已经做到了：
   .ed-card 是 height:100% 的 flex 列（整行等高）、.ed-card__title 已经
   clamp 到 2 行、.ed-card__meta 是 margin-top:auto（永远贴卡片底）。
   1440 实测同一排五张卡的 meta 顶边全部落在 y=727，书名一行还是两行都一样。

   这里刻意**不加**一条只作用于小说网格的标题 min-height 覆写：那会让书卡
   与视频卡重新分叉，正是 Owner 上一轮 §七.A.7 裁掉的那半（既有断言 S-10
   钉着它）。两条 Owner 裁定在这里没有冲突 —— 复用既有机制两条都满足。 */

/* 真实阅读量胶囊。与热度胶囊 .ed-metric 共用同一套排版，只是图标不同 ——
   两者在同一张卡上不会同时出现（视频卡只有热度，电子书卡只有阅读量）。 */
.ed-metric--reads {
	display: inline-flex;
	align-items: center;
	gap: 4px;
}

/* --------------------------------------------------------------------------
   A-CLASS HORIZONTAL FEED（FRONTEND OWNER UX FINAL CLOSURE / Owner Req. A）

   今日吃瓜 / 热门大瓜 / 情色小说 / Ed戒赌吧 四个 surface 共用这一套。
   .ed-grid--article 没有被删 —— 搜索结果页仍然用它（§三十一：Search 版式
   保持现状），所以那条契约还在，只是 A 类栏目页不再走它。

   形态（§九 方案 B）：宽横图 + 信息区形成一整条。
   Mobile 是「封面满宽 + 信息在下」的单列；768 起变成「左封面 + 右信息」
   的横条。两者都是**单列纵向流**，任何断点上都不会出现第二列 ——
   这正是 Owner 否决三列小卡网格时要的东西。

   为什么封面用固定比例的定宽块而不是满宽大图：container 是 1200px，
   一张真正满宽的 16:9 封面高 675px，一屏放不下两条。§九 明确要求
   「不造成巨大图片无限拉长」。
   -------------------------------------------------------------------------- */
.ed-feed {
	display: grid;
	grid-template-columns: 1fr;
	gap: 0;
}

.ed-feed__item {
	display: grid;
	grid-template-columns: 1fr;
	gap: 12px;
	padding: 18px 0;
	border-bottom: 1px solid var(--ed-border-soft);
	align-items: start;
}

.ed-feed__item:first-child {
	padding-top: 4px;
}

.ed-feed__item:last-child {
	border-bottom: none;
}

.ed-feed__thumb {
	position: relative;
	aspect-ratio: 16 / 9;
	border-radius: var(--ed-radius-md);
	overflow: hidden;
	background: var(--ed-bg-soft);
	border: 1px solid var(--ed-border);
}

.ed-feed__thumb img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
	transition: transform 0.25s ease;
}

.ed-feed__item:hover .ed-feed__thumb {
	border-color: var(--ed-gold-soft);
}

.ed-feed__item:hover .ed-feed__thumb img {
	transform: scale(1.02);
}

.ed-feed__body {
	/* min-width: 0 是网格子项能收缩的前提。没有它，长标题会把这一列
	   撑出容器 —— 与抽屉搜索框那笔债同一个成因。 */
	min-width: 0;
	display: flex;
	flex-direction: column;
	gap: 8px;
}

.ed-feed__top {
	display: flex;
	align-items: center;
	gap: 8px;
	min-height: 0;
}

.ed-feed__cat {
	display: inline-block;
	padding: 3px 9px;
	border-radius: var(--ed-radius-sm);
	background: var(--ed-gold-bg);
	color: var(--ed-gold);
	font-size: 12px;
	font-weight: 600;
	line-height: 1.5;
}

.ed-feed__title {
	margin: 0;
	font-size: 17px;
	font-weight: 600;
	line-height: 1.5;
	color: var(--ed-text);
	overflow: hidden;
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
}

.ed-feed__item:hover .ed-feed__title {
	color: var(--ed-gold);
}

.ed-feed__excerpt {
	font-size: 14px;
	color: var(--ed-text-muted);
	overflow: hidden;
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
}

.ed-feed__meta {
	margin-top: auto;
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 14px;
	font-size: 13px;
	color: var(--ed-text-faint);
}

/* --------------------------------------------------------------------------
   单文章两栏布局（§十一）

   Mobile 单列，DOM 顺序即阅读顺序；Desktop 左正文 + 右相关视频侧栏。
   侧栏没有内容时 single.php 根本不渲染 <aside>，并给容器加 --solo，
   否则 grid 会留下一条空列把正文挤窄。
   -------------------------------------------------------------------------- */
.ed-article-layout {
	display: grid;
	grid-template-columns: 1fr;
	gap: 32px;
	align-items: start;
}

.ed-article-layout__main {
	min-width: 0;
}

.ed-article-layout__aside {
	min-width: 0;
	display: flex;
	flex-direction: column;
	gap: 24px;
}

/* --------------------------------------------------------------------------
   COMPACT_VIDEO —— 侧栏紧凑视频卡（§八）
   缩略图宽度用 clamp 而不是 card-list 那样钉死 128px：侧栏在 1024 和
   1440 下宽度不同，固定值两头不讨好。
   -------------------------------------------------------------------------- */
.ed-compact-list {
	display: flex;
	flex-direction: column;
	gap: 14px;
}

.ed-compact-card {
	display: flex;
	gap: 12px;
	align-items: flex-start;
	padding-bottom: 14px;
	border-bottom: 1px solid var(--ed-border-soft);
}

.ed-compact-card:last-child {
	border-bottom: none;
	padding-bottom: 0;
}

.ed-compact-card__thumb {
	position: relative;
	width: clamp(96px, 30%, 132px);
	flex-shrink: 0;
	aspect-ratio: 16 / 9;
	border-radius: var(--ed-radius-sm);
	overflow: hidden;
	background: var(--ed-bg-soft);
}

.ed-compact-card__thumb img {
	width: 100%;
	height: 100%;
	object-fit: cover;
}

.ed-compact-card__body {
	min-width: 0;
	display: flex;
	flex-direction: column;
	gap: 6px;
}

.ed-compact-card__title {
	font-size: 14px;
	font-weight: 600;
	line-height: 1.45;
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
}

.ed-compact-card:hover .ed-compact-card__title {
	color: var(--ed-gold);
}

.ed-compact-card__meta {
	font-size: 12px;
	color: var(--ed-text-muted);
}

/* 多视频角标（edgua_video_count() > 1 时）。与时长角标同一视觉语言，
   放在左下角避免和右下角的时长重叠。 */
.ed-video-card__count {
	position: absolute;
	left: 8px;
	bottom: 8px;
	padding: 2px 7px;
	border-radius: 999px;
	background: var(--ed-on-media-bg-strong);
	color: var(--ed-on-media);
	font-size: 11px;
	line-height: 1.6;
}

/* --------------------------------------------------------------------------
   「大家正在看」全宽区（§十一）
   -------------------------------------------------------------------------- */
.ed-popular {
	margin-top: 40px;
	padding-top: 28px;
	border-top: 1px solid var(--ed-border);
}

/* --------------------------------------------------------------------------
   免责声明（§十三）。插件在 the_content @25 输出，主题只负责它长什么样。
   -------------------------------------------------------------------------- */
.ed-disclaimer {
	display: block;
	margin-top: 28px;
	padding: 14px 16px;
	border: 1px solid var(--ed-border);
	border-left: 3px solid var(--ed-gold);
	border-radius: var(--ed-radius-sm);
	background: var(--ed-bg-soft);
}

.ed-disclaimer__text {
	margin: 0;
	font-size: 13px;
	line-height: 1.8;
	color: var(--ed-text-muted);
}

/* --------------------------------------------------------------------------
   评论区（§十四）
   -------------------------------------------------------------------------- */
.ed-comments {
	margin-top: 40px;
	padding-top: 28px;
	border-top: 1px solid var(--ed-border);
	max-width: var(--ed-content-width);
}

.ed-comment-list,
.ed-comment-list .children {
	list-style: none;
	margin: 0;
	padding: 0;
}

.ed-comment-list .children {
	margin-left: 20px;
	padding-left: 16px;
	border-left: 1px solid var(--ed-border-soft);
}

.ed-comment {
	padding: 16px 0;
	border-bottom: 1px solid var(--ed-border-soft);
}

.ed-comment__body {
	display: flex;
	gap: 12px;
	align-items: flex-start;
}

.ed-comment__avatar img {
	border-radius: 50%;
	display: block;
}

.ed-comment__main {
	min-width: 0;
	flex: 1;
}

.ed-comment__meta {
	display: flex;
	flex-wrap: wrap;
	gap: 10px;
	align-items: baseline;
	font-size: 13px;
	margin-bottom: 6px;
}

.ed-comment__author {
	font-weight: 600;
}

.ed-comment__date {
	color: var(--ed-text-muted);
	font-size: 12px;
}

.ed-comment__text {
	font-size: 14px;
	line-height: 1.8;
	word-break: break-word;
}

.ed-comment__text a {
	word-break: break-all;
}

/* 待审核状态必须看得见 —— 看不见就会被反复重复提交（§十四 / D-1）。 */
.ed-comment--held {
	opacity: 0.75;
}

.ed-comment__held-notice {
	margin: 0 0 6px;
	font-size: 12px;
	color: var(--ed-gold);
}

.ed-comment__actions {
	margin-top: 8px;
	font-size: 13px;
}

.ed-comments__closed {
	font-size: 13px;
	color: var(--ed-text-muted);
}

.ed-comment-form {
	margin-top: 24px;
}

.ed-comment-form__notes {
	font-size: 13px;
	color: var(--ed-text-muted);
	margin-bottom: 12px;
}

.ed-comment-form__field label,
.ed-comment-form .comment-form-author label,
.ed-comment-form .comment-form-email label,
.ed-comment-form .comment-form-url label {
	display: block;
	font-size: 13px;
	margin-bottom: 6px;
}

.ed-comment-form textarea,
.ed-comment-form input[type="text"],
.ed-comment-form input[type="email"],
.ed-comment-form input[type="url"] {
	width: 100%;
	max-width: 100%;
	box-sizing: border-box;
	padding: 10px 12px;
	border: 1px solid var(--ed-border);
	border-radius: var(--ed-radius-sm);
	background: var(--ed-bg-soft);
	color: inherit;
	font: inherit;
}

.ed-comment-form p {
	margin-bottom: 14px;
}


/* --------------------------------------------------------------------------
   搜索面板：历史搜索 + 热门搜索
   （OWNER OPERATIONS CLOSURE §三十 / §七十七）

   用的是 09GUA 自己的设计语言 —— 同一套 --ed-* token、同一个 Brand Gold、
   同一个圆角芯片、同一套 LIGHT/DARK。参考站给的是**交互结构**
   （搜索 -> 历史 -> 热搜），不是它的品牌色、字体或文案，§七十七 对此写得
   很明确。所以这里没有一个硬编码的颜色值，全部走变量，DARK 因此自动成立。
   -------------------------------------------------------------------------- */
.ed-search-panel {
	display: flex;
	flex-direction: column;
	gap: 18px;
}

/* 面板只在真的有内容时才把自己与上面的输入框隔开。两块都空（没有历史、
   也没有热搜数据）时它是一个零高度的空 div，不会在输入框下面留一道
   莫名其妙的空白。 */
.ed-search-panel:not(:empty) {
	margin-top: 16px;
}

.ed-search-panel__block[hidden] {
	display: none !important;
}

.ed-search-panel__head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 12px;
	margin-bottom: 10px;
}

.ed-search-panel__title {
	font-size: 13px;
	font-weight: 600;
	color: var(--ed-text-muted);
	margin: 0;
}

.ed-search-panel__clear {
	background: none;
	border: 0;
	padding: 0;
	font-size: 12px;
	color: var(--ed-text-faint);
	cursor: pointer;
	/* 触摸目标：12px 的文字本身只有约 17px 高，加上垂直 padding 才够
	   §七十六 的移动端验收。用 padding 而不是 min-height，是为了不把
	   它上面那一行标题的基线推歪。 */
	padding: 4px 2px;
}

.ed-search-panel__clear:hover,
.ed-search-panel__clear:focus-visible {
	color: var(--ed-gold);
}

/* 芯片列表。与 .ed-hot-searches__list 形状一致但另起一个名字：那一个
   属于搜索结果页的「大家都在搜」区块，这一个属于搜索面板，两者将来
   完全可能各自调间距。共用的是 token，不是选择器。 */
.ed-chips {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
	list-style: none;
	margin: 0;
	padding: 0;
}

.ed-chips__item {
	display: inline-flex;
	align-items: stretch;
	max-width: 100%;
}

.ed-chip {
	display: inline-flex;
	align-items: center;
	padding: 6px 12px;
	border-radius: 999px;
	border: 1px solid var(--ed-border);
	background: var(--ed-bg-soft);
	color: var(--ed-text-muted);
	font-size: 13px;
	line-height: 1.4;
	max-width: 100%;
	overflow-wrap: anywhere;
}

.ed-chip:hover,
.ed-chip:focus-visible {
	border-color: var(--ed-gold-soft);
	color: var(--ed-gold);
}

/* 可删除的历史芯片：词本身与 × 是两个独立的可点目标，所以它们是
   两个元素而不是一个带伪元素的按钮 —— 后者会让「点词去搜索」与
   「点 × 删掉」共用一个 hit area，手机上必然误触。 */
.ed-chips__item--removable .ed-chip {
	border-top-right-radius: 0;
	border-bottom-right-radius: 0;
	border-right: 0;
}

.ed-chip__remove {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 28px;
	padding: 0 8px;
	border: 1px solid var(--ed-border);
	border-left: 0;
	border-top-right-radius: 999px;
	border-bottom-right-radius: 999px;
	background: var(--ed-bg-soft);
	color: var(--ed-text-faint);
	font-size: 14px;
	line-height: 1;
	cursor: pointer;
}

.ed-chip__remove:hover,
.ed-chip__remove:focus-visible {
	border-color: var(--ed-gold-soft);
	color: var(--ed-gold);
}

/* 遮罩里的面板可能比视口高（10 个历史 + 10 个热搜）。让盒子自己滚，
   而不是让整页滚 —— 遮罩打开时 body 的 overflow 被 main.js 设成 hidden，
   页面根本滚不动，不给盒子滚动就等于下半截拿不到。 */
.ed-search-overlay__box {
	max-height: 76vh;
	overflow-y: auto;
}

/* --------------------------------------------------------------------------
   搜索表单变体（§十六）。收敛后形状由 searchform.php 统一给出，这里只
   调不同位置的宽度。
   -------------------------------------------------------------------------- */
.ed-search-form--page {
	max-width: 520px;
	margin-bottom: 24px;
}

.ed-404__search .ed-search-form--page {
	margin-left: auto;
	margin-right: auto;
}

/* ==========================================================================
   Responsive
   ========================================================================== */
@media (min-width: 640px) {
	.ed-hero__sub {
		grid-template-columns: repeat(2, 1fr);
	}

	.ed-grid--2 {
		grid-template-columns: repeat(2, 1fr);
	}

	/* 上/下一篇：横向空间够了才并排。 */
	.ed-single__nav {
		grid-template-columns: 1fr 1fr;
	}
}

@media (min-width: 768px) {
	.ed-container {
		padding: 0 28px;
	}

	.ed-grid--3 {
		grid-template-columns: repeat(3, 1fr);
	}

	/* A 类文章流：平板起 2 列。这条只服务搜索结果页 —— A 类栏目页已经
	   换成 .ed-feed 横条流（Owner Requirement A），不再经过这里。 */
	.ed-grid--article {
		grid-template-columns: repeat(2, 1fr);
	}

	/* A-CLASS FEED：平板起变成「左封面 + 右信息」的一整条。
	   封面用 clamp 跟着容器走，不钉死像素 —— 768 与 1440 的可用宽度差了
	   将近一倍，一个固定值两头都不讨好（与 .ed-card-list__thumb 同一条
	   理由，那里已经踩过一次）。仍然是**单列**：这里改的是每一条内部的
	   排布，不是把流变成网格。 */
	.ed-feed__item {
		grid-template-columns: clamp(200px, 32%, 340px) 1fr;
		gap: 18px;
		padding: 20px 0;
	}

	.ed-feed__title {
		font-size: 18px;
	}

	/* 电子书：平板 3 列（Owner §九）。768 容器可用 712px，每张 224px，
	   比手机上那个已验收的 134px 宽了 67%，书名一行能多放 6 个字。
	   写出来而不是靠继承：「平板是几列」是一条产品决定。 */
	.ed-grid--ebook {
		grid-template-columns: repeat(3, 1fr);
		gap: 16px;
	}

	/* B 类：平板 3 列（FRONTEND_PRODUCT_EXPERIENCE_V3 §二十四）。
	   此前是 2 列 —— 768 上每卡 356px，一张 16:9 封面高 200px，一屏只剩
	   两行半，信息密度比手机还低。3 列每卡 227px，仍然远宽于手机上那个
	   已经验收过的 159px。写出来而不是靠继承，理由与原来那条注释相同：
	   「Tablet 是几列」是一条产品决定。 */
	.ed-grid--video {
		grid-template-columns: repeat(3, 1fr);
		gap: 16px;
	}

	/* FRONTEND_TRUST_FOOTER_CATEGORY_VISUAL_CLEANUP §十四 —— 平板 2 列 / 2 列。

	   四列在这里放不下：768 减去容器 56 内边距、减去三条 32 的列间隙，
	   每列只剩约 154px，而「官方频道 ✈ @官方频道」这一行本身就要
	   205px —— 结果是每一条官方账号都被折成两行，读起来比手机还差。
	   2×2 每列约 292px，四条内容全部一行放得下。四列从 1024 起。 */
	.ed-footer__top {
		grid-template-columns: repeat(2, minmax(0, 1fr));
		gap: 28px 32px;
	}

	.ed-footer__bottom {
		flex-direction: row;
		align-items: center;
		justify-content: space-between;
	}
}

@media (min-width: 1024px) {
	/* FRONTEND_TRUST_FOOTER_CATEGORY_VISUAL_CLEANUP §十一 / §十四 —— 桌面四列。

	   上一轮把 1.6 : 1 : 1 的偏置配额改成了等宽三列，理由是品牌列拿了 484px 而它的
	   内容只有 95px。等宽解决了「偏置配额」，但没有解决根因：**列的配额和
	   列的内容体量对不上**。Owner 在正式站上仍然看到中间一片死白。

	   本轮四列的配额是按各列内容的实测宽度定的（1440：容器 1144，左右各
	   28 内边距，三条 32px 列间隙 → 可分配约 992px）：
	     品牌      1.15fr ≈ 265px  —— 品牌三行 + 一句站点说明，说明会折两行
	     官方信息  1.15fr ≈ 265px  —— 最长一行「官方频道 ✈ @官方频道」
	                                 实测约 205px，是四列里最宽的内容
	     关于 09GUA 0.75fr ≈ 173px —— 四条四字链接，天然最窄，就给它最窄
	     安全与规则 0.95fr ≈ 219px —— 最长「平台规则与服务条款」约 117px
	   也就是说没有任何一列的空余接近「一整列宽」，Owner 看到的那种「中间少
	   了一列」的读感在结构上不再成立。

	   用 minmax(0, Nfr) 而不是裸 Nfr：网格项里有会换行的长文本与
	   overflow-wrap:anywhere 的账号串，裸 fr 的 min-content 下限会让某一列
	   顶开容器造成横向溢出。 */
	.ed-footer__top {
		grid-template-columns:
			minmax(0, 1.15fr)
			minmax(0, 1.15fr)
			minmax(0, 0.75fr)
			minmax(0, 0.95fr);
		gap: 32px;
	}

	/* 十项导航一上来，横向预算立刻变紧：把 header 三块之间的间距从 24
	   收到 14。收的是本来就有的空白，不是字号 —— 与下面 .ed-nav__link
	   那条注释同一个理由。 */
	.ed-header__inner {
		gap: 14px;
	}

	/* 桌面主导航从 1024 开始平铺十项（§十一，一个栏目都不折叠）。
	   汉堡按钮**不在这里**隐藏 —— 见 1280 那一段：1024–1279 上官方入口 /
	   主题 / 账户装在抽屉里，把它藏掉等于把那三样一起藏掉。 */
	.ed-nav {
		display: block;
	}

	/* FRONTEND-PRODUCTION-CLOSURE —— 十个栏目在窄桌面上靠间距收紧塞下，
	   不靠把其中四个藏进下拉。

	   .ed-container 的 max-width 是 1200px，所以 1280 与 1440 的导航可用
	   宽度其实是同一个值，真正紧的只有 1024–1279 这一段：视口比 container
	   还窄，两侧还要各去掉 28px 的 padding。这里只动 padding 与 gap ——
	   字号保持 14px，字距一点没压。缩字号是「让它挤进去」，收间距是
	   「本来就有的空白少留一点」，前者会让整条导航在最需要读的那个宽度上
	   变得最难读。 */
	.ed-nav__list {
		gap: 0;
	}

	.ed-nav__link {
		padding-left: 9px;
		padding-right: 9px;
	}

	.ed-hero__grid {
		grid-template-columns: 1.5fr 1fr;
	}

	.ed-hero__sub {
		grid-template-columns: 1fr;
	}

	/* FRONTEND_PRODUCT_EXPERIENCE_V3 §十九 / §二十 —— Hero 右侧底部的空洞。
	
	   实测（真实 Chromium，1440/1280）：左侧大卡 291px 高、右侧四条 390px
	   高，两列底边差 99px —— 那 99px 就是 Owner 在 Production 截图上看到的
	   那块空白。根因不是数据（1+4 一直是对的），是**两列各自决定自己的高度**：
	   左列由 aspect-ratio 定死，右列由四条内容累加，两个数没有任何理由相等。
	
	   修法是让其中一列不再自己决定高度。选左列：取消它的 aspect-ratio，
	   它就退回 grid 默认的 align-self: stretch，高度跟着行高走，而行高由
	   右侧四条的自然高度决定 —— 于是左右底边**必然**对齐，且在任何视口宽度、
	   任何字号、任何标题行数下都对齐，不需要为每个断点手算一个比例。
	
	   封面图本来就是 position:absolute + inset:0 + object-fit:cover，所以
	   它自动填满新的高度，不会拉伸变形。实测比例落在 1.7~1.8 之间（接近
	   16:9），比原来的 21/9 更接近一张常规封面的构图。
	
	   Hero 的数据、优先级、去重起点身份、LCP 属性（eager + fetchpriority=
	   high）全部没有被这条规则碰到 —— 它只是一条 CSS 高度规则。 */
	.ed-hero__main {
		aspect-ratio: auto;
	}

	/* ----------------------------------------------------------------------
	   OWNER_EBOOK_VISUAL §五.3 / §五.4 —— 桌面热门区

	   2fr : 1fr = 66.7% : 33.3%，落在 Owner 要的 66–69 / 31–34 区间里。

	   高度：主图自己是 16:9，并给一个 460px 上限（Owner §五.3 建议
	   420–460）。1440 上容器 1264，主图 831 宽 → 16:9 会到 467，被上限收到
	   460，比例 1.81 —— 仍然是「接近 16:9」，但页面第一屏不会被一张图吃掉。

	   侧栏用 grid-template-rows: repeat(4, 1fr) + height:100%：四张卡各占
	   行高的四分之一，于是**四卡等高、三个间距一致、与主图底边严格对齐**
	   全部由布局自己保证，不靠任何手算的像素。v1 那条 min-height:360 +
	   aspect-ratio:auto 做不到这件事 —— 它让两列各自决定高度。
	   ---------------------------------------------------------------------- */
	.ed-hero--ebook .ed-hero__grid {
		grid-template-columns: 2fr 1fr;
		gap: 18px;
		align-items: stretch;
	}

	.ed-hero--ebook .ed-hero__main {
		aspect-ratio: 16 / 9;
		max-height: 460px;
	}

	.ed-hero--ebook .ed-hero__sub {
		grid-template-columns: 1fr;
		grid-template-rows: repeat(4, 1fr);
		gap: 12px;
		height: 100%;
	}

	/* 这一档右侧只有约 400px，横条（左封面 + 右文字）比竖版小卡更省高度，
	   四张才装得进主图的高度里。 */
	.ed-hero--ebook .ed-hero__sub-item {
		flex-direction: row;
		align-items: center;
		gap: 12px;
		padding: 10px;
		min-height: 0;
		overflow: hidden;
	}

	/* 封面占卡片宽度的 34%（Owner §五.4：32%–36%）。 */
	.ed-hero--ebook .ed-hero__sub-thumb {
		width: 34%;
		max-width: 150px;
		flex-shrink: 0;
	}

	.ed-hero--ebook .ed-hero__sub-title {
		font-size: 14px;
	}

	/* 桌面卡片装得下，作者 · N 章放回来 —— 仍然只有一行。 */
	.ed-hero--ebook .ed-hero__sub-meta .ed-hero__book {
		display: inline-block;
	}

	.ed-hero--ebook .ed-hero__title {
		font-size: 26px;
	}

	.ed-grid--4 {
		grid-template-columns: repeat(4, 1fr);
	}

	/* B 类桌面 4 列（D-7）—— 这正是 Discovery §17.2 记的那个缺口：
	   分类页此前用 ed-grid--3，永远升不到 4。

	   这条规则**是首页 B 类栏目在 1024–1279 上的唯一来源**（首页的 5 列只从
	   1280 起）。归档页那一轮把它整块搬去 1200 时，首页在 1024–1279 会静默
	   退回 3 列 —— 与 Owner「首页组成保持锁定」冲突。所以它留在这里不动，
	   归档页自己的密度规则改为挂在 body.ed-layout--wide 上，见文件后面
	   「视频网格密度 V2」那一段。 */
	.ed-grid--video {
		grid-template-columns: repeat(4, 1fr);
	}

	/* --------------------------------------------------------------------
	   首页栏目：电脑端收起第 6 张（2026-09-24，Owner）

	   栏目现在取 6 条（edgua_homepage_section_count），因为手机 2 列、
	   平板 3 列下 5 条都会剩一行孤零零的卡 —— 那正是 Owner 截图里
	   的那个缺口。6 条在手机是 2+2+2、平板是 3+3，两边都满。

	   电脑端 Owner 要求一点不改（4 列下仍然是 4+1），所以第 6 张
	   在这一档收起。**只能用断点，不能按 User-Agent 在服务端分叉**：
	   那是 cloaking，本仓明令禁止（inc/age-gate.php 文件头），且
	   red_google_brand_entity_live 的 U 组要求普通 UA 与 Googlebot 零差异。

	   挂在 .ed-grid--home-section 而不是 .ed-grid--video：后者分类归档页
	   也在用，那里一页几十条，收起第 6 张会把归档页打残。
	   -------------------------------------------------------------------- */
	.ed-grid--home-section > :nth-child(n + 6) {
		display: none;
	}

	/* 电子书：小桌面 4 列（Owner §九）。1024 容器 1024-40=984px，
	   每张 233px —— 与平板那一档接近，但一屏能看到的书从 9 本变成 16 本，
	   这正是把一排一本改成网格要换来的东西。 */
	.ed-grid--ebook {
		grid-template-columns: repeat(4, 1fr);
	}

	/* A 类桌面 3 列的舒适文章布局。同上：只服务搜索结果页。 */
	.ed-grid--article {
		grid-template-columns: repeat(3, 1fr);
	}

	/* A-CLASS FEED 在桌面上**仍然是单列纵向流**。
	   这一条写出来而不是靠继承：Owner 否决的正是「A 类在桌面上变成多列
	   小卡网格」，所以「桌面是几列」是一条产品决定，不该只存在于
	   「上面没写别的」这个事实里（与 .ed-grid--video 在 768 上那条
	   同一个理由）。 */
	.ed-feed {
		grid-template-columns: 1fr;
	}

	.ed-feed__item {
		grid-template-columns: clamp(260px, 30%, 380px) 1fr;
		gap: 22px;
		padding: 22px 0;
	}

	.ed-feed__title {
		font-size: 19px;
	}

	.ed-layout {
		grid-template-columns: 2.2fr 1fr;
	}

	/* 单文章：左正文 + 右相关视频侧栏（§十一）。 */
	.ed-article-layout {
		grid-template-columns: minmax(0, 2.2fr) minmax(0, 1fr);
	}

	/* 侧栏没有内容时不留空列，正文回到全宽居中 —— 与今天的单栏页
	   完全一样。 */
	.ed-article-layout--solo {
		grid-template-columns: 1fr;
	}

	/* 侧栏跟随滚动。top 留出 64px 的 sticky header + 20px 呼吸。 */
	.ed-aside-block--sticky {
		position: sticky;
		top: 84px;
	}

	.ed-single__nav {
		grid-template-columns: 1fr 1fr;
	}
}

/* ==========================================================================
   FRONTEND_TRUST（Owner 追加裁定 §七 / §八）—— 视频分类页网格密度 V2
   ==========================================================================
   全部挂在 body.ed-layout--wide 上，也就是**只有 B 类视频分类归档页**。
   首页那五个视频栏目用的是同一个 .ed-grid--video 类，但它们不带这个 body
   class，所以下面一条规则都吃不到 —— §十三：不要因为分类页改了就把首页
   一起改掉。

   Owner §八 的逐档要求：≥1200 四列 / 768–1199 三列 / 480–767 两列 /
   ≤479 两列优先。后两档就是 .ed-grid--video 的 mobile-first 基线（2 列），
   768 那一档是既有的通用规则（3 列），所以这里只需要写两条：把归档页在
   1024–1199 从通用的 4 列降回 3 列，以及 1200 起的四列大卡。
   ========================================================================== */
@media (min-width: 1024px) and (max-width: 1199px) {
	/* 归档页在这一档降回 3 列。通用规则从 1024 就升到 4 列，那是首页栏目
	   要的密度；对归档页来说 1024 容器只有 968px，四列每卡 227px —— 比手机
	   上那个已验收的 159px 大不了多少，正是 Owner 说的「像普通模板站」。
	   三列每卡 311px，卡片明显更大方。 */
	body.ed-layout--wide .ed-grid--video {
		grid-template-columns: repeat(3, 1fr);
	}
}

@media (min-width: 1200px) {
	/* 1200 起容器吃满 1264px（--ed-container 在这一类页面上是 1320），
	   四列每卡 299px —— 比加宽前的 269px 大一圈，这才是 Owner 要的观感。
	   写成显式的 repeat(4,1fr) 而不是靠继承：「桌面是几列」是一条产品决定，
	   与这份文件里 .ed-feed / .ed-grid--video 那两条注释同一个理由。

	   没有改成 6 列小卡：Owner 明确「要的是更大方，不是更密小图」。 */
	body.ed-layout--wide .ed-grid--video {
		grid-template-columns: repeat(4, 1fr);
		gap: 20px;
	}
}


@media (min-width: 1280px) {
	/* 电子书：大桌面 5 列（Owner §九）。容器在这一档吃满 1200px，
	   减去 40 内边距与四条 18 间隙，每张 217px。
	   每页 20 本因此正好是 5 × 4 的一整块，最后一行不会缺角
	   （见 inc/archive-query.php 的 edgua_ebook_archive_per_page()）。 */
	.ed-grid--ebook {
		grid-template-columns: repeat(5, 1fr);
		gap: 18px;
	}

	/* 顶栏这时装得下全部入口，抽屉不再需要。 */
	.ed-hamburger {
		display: none;
	}

	.ed-header__inner {
		gap: 24px;
	}

	.ed-account {
		display: block;
	}

	a.ed-account-btn {
		display: inline-flex;
	}

	/* container 在这里已经吃满 1200px，导航有余量，间距回到常规值。 */
	.ed-nav__list {
		gap: 4px;
	}

	.ed-nav__link {
		padding-left: 12px;
		padding-right: 12px;
	}
}

/* ==========================================================================
   SEARCH V2-I1 — Hero / Hot Searches / Filters / Summary
   （§四 的页面结构；§三十六 的 375 / 768 / 1024 / 1440 验收）

   全部复用既有 token，没有新增一个颜色变量：搜索页不是一个独立的视觉
   系统，它是 Frontend V2 的一个页面。
   ========================================================================== */
.ed-search-hero {
	margin-bottom: 24px;
}

/* 标题与表单之间的节奏由 hero 统一给，所以 §十六 那条 margin-bottom
   在搜索页要让位，否则会和 hero 的间距叠加成一个 48px 的空洞。 */
.ed-search-hero .ed-search-form--page {
	margin-bottom: 0;
}

.ed-search-page__title {
	margin-bottom: 16px;
	/* 长关键词（用户可以搜 100 个字）不能把标题撑出容器。
	   body 是 overflow-x:hidden，所以撑出去的部分会被直接裁掉而不是滚动。 */
	overflow-wrap: anywhere;
}

/* --------------------------------------------------------------------------
   Hot Searches（§十七 / §三十五）
   -------------------------------------------------------------------------- */
.ed-hot-searches {
	margin-bottom: 24px;
}

.ed-hot-searches__title {
	font-size: 14px;
	font-weight: 600;
	color: var(--ed-text-muted);
	margin-bottom: 10px;
}

.ed-hot-searches__list {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
	list-style: none;
	margin: 0;
	padding: 0;
}

.ed-hot-search__link {
	display: inline-flex;
	align-items: center;
	padding: 6px 12px;
	border-radius: 999px;
	border: 1px solid var(--ed-border);
	background: var(--ed-bg-soft);
	color: var(--ed-text-muted);
	font-size: 13px;
	line-height: 1.4;
	/* 关键词可能很长；不换行会把芯片挤出屏幕。 */
	max-width: 100%;
	overflow-wrap: anywhere;
}

.ed-hot-search__link:hover,
.ed-hot-search__link:focus-visible {
	border-color: var(--ed-gold-soft);
	color: var(--ed-gold);
}

/* 置顶项给一点点视觉重量。这**不是**热度指示器，也不显示任何数字——
   它只是说明这一项是运营选出来的。 */
.ed-hot-search__link.is-pinned {
	border-color: var(--ed-gold-soft);
	color: var(--ed-gold);
	background: var(--ed-gold-bg);
}

/* --------------------------------------------------------------------------
   Filter / Sort bar（§六 / §七 / §八）

   Mobile 纵向堆叠：375px 下把「类型 3 项 + 排序 3 项 + 分类下拉」挤成一行
   一定会溢出。堆叠之后每组自己在组内 wrap，永远不会横向滚动。
   -------------------------------------------------------------------------- */
.ed-search-filters {
	display: flex;
	flex-direction: column;
	gap: 12px;
	padding: 14px 16px;
	margin-bottom: 16px;
	border: 1px solid var(--ed-border);
	border-radius: var(--ed-radius-md);
	background: var(--ed-bg-soft);
}

.ed-search-filters__group {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 8px;
	margin: 0;
}

.ed-search-filters__label {
	font-size: 13px;
	color: var(--ed-text-faint);
	flex: 0 0 auto;
	min-width: 34px;
}

.ed-search-chip {
	display: inline-flex;
	align-items: center;
	padding: 5px 14px;
	border-radius: 999px;
	border: 1px solid var(--ed-border);
	color: var(--ed-text-muted);
	font-size: 13px;
	line-height: 1.5;
}

.ed-search-chip:hover,
.ed-search-chip:focus-visible {
	border-color: var(--ed-gold-soft);
	color: var(--ed-gold);
}

.ed-search-chip.is-active {
	background: var(--ed-gold);
	border-color: var(--ed-gold);
	color: var(--ed-gold-ink);
	font-weight: 600;
}

.ed-search-filters__cat select {
	background: var(--ed-bg);
	border: 1px solid var(--ed-border);
	color: var(--ed-text);
	border-radius: var(--ed-radius-sm);
	padding: 7px 10px;
	font-size: 13px;
	/* 375px 下分类名最长 4 个汉字 + 箭头，160px 足够；
	   不设上限会让 select 在 flex 里抢走整行。 */
	max-width: 180px;
}

.ed-search-filters__cat select:focus {
	outline: none;
	border-color: var(--ed-gold-soft);
}

.ed-search-filters__apply {
	padding: 7px 14px;
	font-size: 13px;
}

/* --------------------------------------------------------------------------
   Summary（§四）
   -------------------------------------------------------------------------- */
.ed-search-summary {
	font-size: 13px;
	color: var(--ed-text-faint);
	margin-bottom: 16px;
}

.ed-search-empty-input {
	margin-top: 8px;
}

/* 键盘可达性（§三十七）：芯片和热搜都是 <a>，焦点环必须看得见。 */
.ed-search-chip:focus-visible,
.ed-hot-search__link:focus-visible {
	outline: 2px solid var(--ed-gold);
	outline-offset: 2px;
}

@media (min-width: 768px) {
	.ed-search-page__title {
		font-size: 26px;
	}

	/* 平板起筛选栏排成一行：三组加起来约 620px，768px 容器放得下，
	   放不下的部分继续在组内 wrap，不会溢出。 */
	.ed-search-filters {
		flex-direction: row;
		flex-wrap: wrap;
		align-items: center;
		gap: 20px;
	}
}

@media (max-width: 479px) {
	/* CATEGORY_TOP4_REAL_VIEWS §七.7 —— 最窄那一档（320–479）的两枚角标。
	   两列网格下每张卡只有约 134px。字号不再往下压（Owner 明确禁止
	   「缩小到无法阅读」），压的是内边距与左上角那枚的宽度上限：
	   「热度最高」四个字在 11px 下仍然完整、仍然一行。 */
	.ed-card__rank,
	.ed-card__cat {
		padding: 2px 6px;
	}

	.ed-card__cat {
		max-width: 40%;
	}

	/* §三十五：Desktop 10 / Mobile 8。同一个数据集、同一条 SQL，
	   差异只由这一条规则控制——移动端不另发一次查询。 */
	.ed-hot-searches__item:nth-child(n + 9) {
		display: none;
	}
}

/* ==========================================================================
   STATISTICS-I1 —— 展示热度胶囊（DISPLAY HEAT）
   ==========================================================================
   卡片与单文章 meta 行里那个 "👁 11.1K"。

   它出现在四种容器里（.ed-card__meta / .ed-card-list__meta /
   .ed-compact-card__meta / .ed-single__meta），四者都已经是 flex + gap，
   所以这里不需要 margin —— 只描述胶囊自己，间距由容器负责。这是本主题
   一贯的分工，加 margin 会在某一个容器里和 gap 叠加成双倍间距。

   图标用 currentColor 并继承父级字号：meta 行在卡片上是 12px、在单文章页
   是 13px，写死尺寸会让其中一处的图标与文字对不齐。 */
.ed-metric {
	display: inline-flex;
	align-items: center;
	gap: 4px;
	white-space: nowrap;
	font-variant-numeric: tabular-nums;
}

.ed-metric__icon {
	width: 1.15em;
	height: 1.15em;
	flex: 0 0 auto;
	/* 光学对齐：眼睛图标的视觉重心比文字基线略高，不压一点会显得在飘。 */
	position: relative;
	top: 0.5px;
	opacity: 0.85;
}

/* 单文章 meta 行的字号比卡片大一档，胶囊跟着走即可，不另设尺寸。 */
.ed-single__meta .ed-metric {
	gap: 5px;
}

/* ==========================================================================
   ADS-I1 —— 广告位（横幅 / 浮动 / Pre-roll）
   ==========================================================================

   三条约束贯穿这一整段：

   1. 广告必须看得出是广告，但不能抢走主体。
      .ed-ad__label 是一个独立的、始终可见的 DOM 标签，不是图片 alt 里的一句话
      —— 读屏用户和视觉用户拿到的是同一条声明。

   2. 素材完整优先于容器整齐（OWNER CREATIVE UPDATE §九）。
      容器比例来自素材自己的宽高（--ed-ad-ratio，由模板内联下发），
      素材用 object-fit: contain 完整展示。GIF 是第一版的主形态，
      裁掉它的一角很可能就裁掉了广告主要说的那句话。

   3. 层级严格服从站上既有的 z-index：
      .ed-header 100 / .ed-mobile-nav 200 / .ed-search-overlay 200。
      （原本还有一层 .ed-nav__submenu 120，随 FRONTEND-PRODUCTION-CLOSURE
      取消桌面下拉一并删掉；浮动广告本来就低于它下面的 header，结论不变。）
      浮动广告取 90，低于全部三个。于是移动端抽屉或搜索遮罩打开时，
      那两个 inset:0 的遮罩天然盖住浮层 —— 不需要写任何「打开菜单时隐藏广告」
      的联动代码，少一条会失效的耦合。
*/

.ed-ad {
	position: relative;
	display: block;
	margin: 0 0 24px;
	background: var(--ed-bg-soft);
	border: 1px solid var(--ed-border);
	border-radius: var(--ed-radius-lg);
	overflow: hidden;
}

.ed-ad-wrap {
	margin-top: 24px;
}

/* 广告标识。左上角小标签，够清楚但不喧宾夺主。 */
.ed-ad__label {
	position: absolute;
	top: 8px;
	left: 8px;
	z-index: 2;
	padding: 2px 8px;
	font-size: 11px;
	line-height: 1.6;
	letter-spacing: 0.5px;
	color: #fff;
	background: rgba(0, 0, 0, 0.55);
	border-radius: 999px;
	pointer-events: none;
}

.ed-ad__link {
	display: block;
	line-height: 0;
}

/* 容器高度在素材加载前就由 aspect-ratio 占住 —— 这个位不产生 CLS。
   比例来自素材真实宽高；拿不到时退回一个保守的横幅比例。 */
.ed-ad__media {
	display: block;
	width: 100%;
	height: auto;
	aspect-ratio: var(--ed-ad-ratio, 8 / 1);
	object-fit: contain;
	background: var(--ed-bg-soft);
}

/* --------------------------------------------------------------------------
   浮动广告：桌面右下角卡片
   -------------------------------------------------------------------------- */
.ed-ad--floating {
	position: fixed;
	right: 20px;
	bottom: 20px;
	left: auto;
	z-index: 90;
	width: 300px;
	max-width: calc(100vw - 40px);
	max-height: 15vh;
	margin: 0;
	box-shadow: 0 8px 28px rgba(0, 0, 0, 0.18);
	animation: ed-ad-float-in 0.18s ease-out both;
}

@keyframes ed-ad-float-in {
	from { opacity: 0; }
	to   { opacity: 1; }
}

.ed-ad--floating .ed-ad__media {
	max-height: 15vh;
}

/* 内容视频播放时移动端浮层自动让位（ads.js 加 .is-hidden）。
   用 visibility 而不是 display:none：元素仍然占位，恢复时不会触发重排。 */
.ed-ad--floating.is-hidden {
	visibility: hidden;
	opacity: 0;
}

/* 关闭按钮。44×44 的最小点击区是移动端的下限，比图标本身大得多是有意的。 */
.ed-ad__close {
	position: absolute;
	top: 0;
	right: 0;
	z-index: 3;
	width: 44px;
	height: 44px;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 0;
	font-size: 20px;
	line-height: 1;
	color: #fff;
	background: rgba(0, 0, 0, 0.55);
	border: 0;
	border-radius: 0 0 0 var(--ed-radius-lg);
	cursor: pointer;
}

.ed-ad__close:focus-visible {
	outline: 2px solid var(--ed-accent, #fff);
	outline-offset: -2px;
}

/* --------------------------------------------------------------------------
   Pre-roll：覆盖在内容播放器之上的独立广告层
   --------------------------------------------------------------------------
   .ed-single__video 已经是 position: relative + overflow: hidden，
   所以这一层用 inset:0 就能精确盖住播放器，且不会溢出圆角。
   z-index 只有 2：它是播放器内部的局部层叠，不参与全站层级。
   全屏时浏览器把 <video> 元素本身送进 top layer，这一层自然不可见 ——
   那是原生行为，不需要额外处理。
*/
.ed-ad-preroll {
	position: absolute;
	inset: 0;
	z-index: 2;
	background: #000;
}

.ed-single__video .ed-ad-preroll__video {
	width: 100%;
	height: 100%;
	aspect-ratio: auto;
	object-fit: contain;
	display: block;
}

.ed-ad-preroll__label {
	position: absolute;
	top: 8px;
	left: 8px;
	padding: 2px 8px;
	font-size: 11px;
	color: #fff;
	background: rgba(0, 0, 0, 0.55);
	border-radius: 999px;
	pointer-events: none;
}

/* 片头倒计时。
   ADS PRE-ROLL HOURLY 把 5 秒从「之后可以跳过」改成了硬上限，于是原来那个
   .ed-ad-preroll__skip 按钮没有了可用的一刻，被这个纯展示的倒计时取代。
   它 pointer-events: none —— 不可点、不可聚焦，因此不可能形成焦点陷阱，
   也不会挡住底下播放器的任何区域。 */
.ed-ad-preroll__count {
	position: absolute;
	right: 12px;
	bottom: 56px;
	padding: 2px 10px;
	font-size: 12px;
	font-variant-numeric: tabular-nums;
	color: #fff;
	background: rgba(0, 0, 0, 0.55);
	border-radius: 999px;
	pointer-events: none;
}

/* --------------------------------------------------------------------------
   移动端：浮动广告切成底部通栏
   --------------------------------------------------------------------------
   768px 复用主题既有断点，不引入第五个断点。
   safe-area 是必须的：没有它，iPhone 上这条通栏会被 home indicator 压掉一截。
   这是全站第一处 env(safe-area-inset-*)。
*/

/* ==========================================================================
   P7 BUNNY EBOOK READER V2 —— 连续下滑阅读
   ==========================================================================

   三块新东西，各自解决一个 V1 里没有的问题：

   1. `.ed-reader__toc` 是一个 `<details>` 抽屉。它**不遮挡正文** —— 收起时
      只占一个按钮的高度，展开时把正文往下推而不是盖住它。桌面端贴在阅读区
      上方并限高滚动，移动端是同样的形状（一个 75 条的目录在手机上必须能滚，
      否则「选任意一章」这件事在最后几章上根本做不到）。
   2. `.ed-reader__chapter` 是流里的一节。第一章由服务端渲染，后面的由运行时
      追加成**同样**的结构，所以两者在页面上没有任何视觉差别。
   3. `.ed-reader__series-break` 是跨作品分隔。它必须比章节标题更重 —— 读者
      在这里换了一部作品，而那不是「下一章」。
   ========================================================================== */

.ed-reader__toc {
	margin: 0 auto 20px;
	max-width: var(--ed-content-width);
	border: 1px solid var(--ed-border);
	border-radius: var(--ed-radius-md);
	background: var(--ed-bg-soft);
}

.ed-reader__toc-toggle {
	display: flex;
	align-items: center;
	gap: 10px;
	padding: 12px 16px;
	font-weight: 600;
	color: var(--ed-text);
	cursor: pointer;
	list-style: none;
}

.ed-reader__toc-toggle::-webkit-details-marker {
	display: none;
}

.ed-reader__toc-toggle::before {
	content: "\2630";
	font-size: 14px;
	opacity: 0.7;
}

.ed-reader__toc-count {
	margin-left: auto;
	font-size: 12px;
	font-weight: 400;
	color: var(--ed-text-muted);
}

.ed-reader__toc-body {
	max-height: 52vh;
	overflow-y: auto;
	padding: 0 16px 12px;
	border-top: 1px solid var(--ed-border);
}

.ed-reader__toc-group-title {
	margin: 14px 0 8px;
	font-size: 13px;
	color: var(--ed-text-muted);
}

.ed-reader__toc-list {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: 2px 16px;
	margin: 0;
	padding: 0;
	list-style: none;
}

.ed-reader__toc-item a {
	display: flex;
	gap: 8px;
	padding: 6px 8px;
	border-radius: var(--ed-radius-sm);
	color: var(--ed-text);
	text-decoration: none;
	font-size: 14px;
}

.ed-reader__toc-item a:hover {
	background: var(--ed-bg);
}

.ed-reader__toc-item.is-current a {
	background: var(--ed-bg);
	font-weight: 600;
	color: var(--ed-accent);
}

.ed-reader__toc-no {
	flex: none;
	color: var(--ed-text-muted);
	font-size: 12px;
	line-height: 20px;
}

.ed-reader__toc-title {
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.ed-reader__chapter + .ed-reader__chapter,
.ed-reader__series-break + .ed-reader__chapter {
	margin-top: 40px;
	padding-top: 28px;
	border-top: 1px solid var(--ed-border);
}

.ed-reader__series-break {
	max-width: var(--ed-content-width);
	margin: 48px auto 8px;
	padding: 20px 16px;
	text-align: center;
	border-top: 2px solid var(--ed-border);
	border-bottom: 2px solid var(--ed-border);
}

.ed-reader__series-end {
	margin: 0 0 6px;
	font-size: 15px;
	color: var(--ed-text-muted);
	letter-spacing: 0.08em;
}

.ed-reader__series-next {
	margin: 0;
	font-size: 19px;
	font-weight: 600;
	color: var(--ed-text);
}

.ed-reader__sentinel {
	height: 1px;
}

.ed-reader__status {
	max-width: var(--ed-content-width);
	margin: 24px auto;
	padding: 16px;
	text-align: center;
	color: var(--ed-text-muted);
	border: 1px dashed var(--ed-border);
	border-radius: var(--ed-radius-md);
}

.ed-reader__status-text {
	margin: 0 0 10px;
}

.ed-reader__status-text:last-child {
	margin-bottom: 0;
}

/*
 * `[hidden]` 必须真的藏住。
 *
 * 浏览器的 UA 样式表给 `[hidden]` 的是 `display: none`，而**任何**作者规则里的
 * `display` 都比它优先级高。`.ed-btn` 声明了 `display: inline-flex`，于是
 * `retryButton.hidden = true` 在 DOM 上完全正确，按钮却照样画出来 ——
 * 实测：最后一章底部同时出现「全书结束」和一个「重试」按钮，而那时候没有任何
 * 东西可以重试。
 *
 * 这不是给这一个按钮打补丁：状态区里任何用 `hidden` 切换的东西都会踩同一个坑，
 * 所以规则挂在容器上。
 */
.ed-reader__status [hidden],
.ed-reader__status[hidden] {
	display: none !important;
}

@media (max-width: 767px) {
	.ed-ad--floating {
		right: 0;
		left: 0;
		bottom: 0;
		width: auto;
		max-width: none;
		max-height: none;
		border-radius: 0;
		border-left: 0;
		border-right: 0;
		border-bottom: 0;
		padding-bottom: env(safe-area-inset-bottom);
	}

	.ed-ad--floating .ed-ad__media {
		max-height: 60px;
	}

	/* 底部通栏会压住页面最后一段。给页脚一个**固定**的额外内边距，
	   与浮层同时生效 —— 等素材加载完再撑开才会产生真正的 CLS。 */
	.ed-ad--floating ~ .ed-footer {
		padding-bottom: calc(72px + env(safe-area-inset-bottom));
	}

	/* 移动端播放器上的倒计时要避开原生控件栏。 */
	.ed-ad-preroll__count {
		bottom: 48px;
	}
}

/* --------------------------------------------------------------------------
   prefers-reduced-motion
   --------------------------------------------------------------------------
   如实记账：GIF **自身的帧动画无法被 CSS 停止**，那是解码器行为。
   所以这里能做到的、也是全部要做到的，是 09GUA 自己不再叠加任何运动 ——
   没有 slide、没有 bounce、没有 pulse、没有 zoom、没有闪动，
   连上面那个 0.18 秒的淡入也在这里被关掉。
     GIF_INTRINSIC_ANIMATION_REDUCED_MOTION_CONTROL = UNSUPPORTED
     CUSTOM_CONTAINER_MOTION_REDUCED = YES
*/
@media (prefers-reduced-motion: reduce) {
	.ed-ad--floating {
		animation: none;
	}

	.ed-ad--floating.is-hidden {
		transition: none;
	}
}

/* ==========================================================================
   18+ AGE GATE（FRONTEND OWNER UX FINAL CLOSURE / Owner Requirement B）

   显示规则整条挂在 html.ed-js 之下（§二十四）
   -------------------------------------------
   .ed-age-gate 的默认状态是 display: none。只有 header.php 里那段内联脚本
   成功执行、给 <html> 加上 .ed-js 之后，遮罩才会显示。于是：

     JS 关掉  -> .ed-js 永远不存在 -> 这个遮罩恒不显示；No-JS 读者改由文件
                 下方那一组 html:not(.ed-js) 规则 + <noscript> 里的独立闸门
                 接管（AGE-GATE-NOJS-CLOSURE）。
     JS 打开  -> 遮罩与页面同一帧绘制，读者看不到内容闪现。

   两条路径互斥，而且都会真的挡住人：scripting enabled 时浏览器根本不解析
   <noscript> 的内容，所以正常 JS 读者不可能看到两个 gate。

   底层页面照常渲染（§二十三）
   ---------------------------
   遮罩是一层不透明的 position: fixed 覆盖物，**不改变底层 DOM**。
   搜索引擎拿到的 title / canonical / robots / 正文与读者确认之后拿到的
   完全一致 —— 人被挡住，语义没有被挡住。
   ========================================================================== */
.ed-age-gate {
	display: none;
}

.ed-js .ed-age-gate {
	display: flex;
	position: fixed;
	inset: 0;
	z-index: 9999;
	align-items: center;
	justify-content: center;
	padding: 20px;
	/* 不透明。半透明遮罩在一个成人内容闸门上是错的 —— 它让被挡住的内容
	   依然可辨认，等于没挡。 */
	background: var(--ed-bg);
	overflow-y: auto;
	-webkit-overflow-scrolling: touch;
}

/* 未确认时锁住背景滚动（§二十一）。
   锁只挂在这个 class 上，JS 在确认时把 class 摘掉就是完整还原 ——
   不会留下一个 inline 的 overflow: hidden 让全站再也滚不动。
   同样挂在 .ed-js 之下：JS 关掉时绝不能把页面锁死。 */
.ed-js body.ed-age-gate-pending {
	overflow: hidden;
}

.ed-age-gate__card {
	width: 100%;
	max-width: 460px;
	background: var(--ed-card);
	border: 1px solid var(--ed-border);
	border-top: 2px solid var(--ed-gold);
	border-radius: var(--ed-radius-lg);
	padding: 32px 26px 26px;
	text-align: center;
	box-shadow: var(--ed-shadow-lift);
}

.ed-age-gate__brand {
	display: flex;
	align-items: baseline;
	justify-content: center;
	gap: 8px;
	margin-bottom: 20px;
}

.ed-age-gate__brand-en {
	font-size: 24px;
	font-weight: 800;
	letter-spacing: 1.5px;
	color: var(--ed-gold);
}

.ed-age-gate__brand-cn {
	font-size: 15px;
	color: var(--ed-text-muted);
}

.ed-age-gate__title {
	margin: 0 0 14px;
	font-size: 20px;
	font-weight: 700;
	color: var(--ed-text);
}

.ed-age-gate__desc {
	margin: 0 0 24px;
	font-size: 14px;
	line-height: 1.8;
	color: var(--ed-text-muted);
	text-align: left;
}

.ed-age-gate__actions {
	display: flex;
	flex-direction: column;
	gap: 10px;
}

.ed-age-gate__btn {
	width: 100%;
	padding: 13px 18px;
	font-size: 15px;
	/* min-width: 0 —— 与抽屉搜索框同一条纪律：flex 项目要能收缩。
	   360px 下两个按钮的文案都不短，缺了它就会顶出卡片。 */
	min-width: 0;
}

.ed-age-gate__btn--enter {
	font-weight: 700;
}

/* 拒绝后的封锁状态（§二十）。没有跳转，所以页面上不存在任何可以被
   改写成跳转目标的值 —— open redirect 在结构上不可能发生。 */
.ed-age-gate__blocked {
	margin-top: 6px;
	padding: 18px 14px;
	border: 1px dashed var(--ed-border);
	border-radius: var(--ed-radius-md);
	color: var(--ed-text);
	font-size: 15px;
	font-weight: 600;
}

.ed-age-gate__blocked:focus {
	outline: 2px solid var(--ed-gold-soft);
	outline-offset: 2px;
}

.ed-age-gate__blocked-sub {
	margin: 6px 0 0;
	font-size: 13px;
	font-weight: 400;
	color: var(--ed-text-muted);
}

.ed-age-gate__legal {
	margin: 22px 0 0;
	font-size: 12px;
	color: var(--ed-text-faint);
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: center;
	gap: 8px;
}

.ed-age-gate__legal a {
	color: var(--ed-text-muted);
}

.ed-age-gate__legal a:hover {
	color: var(--ed-gold);
}

/* No-JS 提示条（§二十四）。只有 <noscript> 里才会出现它，所以它不需要
   任何显示条件 —— 浏览器已经替我们判断过了。 */
.ed-age-noscript {
	padding: 12px 20px;
	background: var(--ed-gold-bg);
	border-bottom: 1px solid var(--ed-gold-soft);
	color: var(--ed-text);
	font-size: 13px;
	line-height: 1.7;
	text-align: center;
}

.ed-age-noscript a {
	color: var(--ed-gold);
	text-decoration: underline;
}

/* ==========================================================================
   No-JS AGE GATE（AGE-GATE-NOJS-CLOSURE）

   判别式为什么是 html:not(.ed-js)
   -------------------------------
   .ed-js 由 header.php 的内联脚本添加，所以「它不存在」本身就是纯 CSS 里
   唯一能表达「这个浏览器没在执行 JS」的形式。上一版把封锁能力整条挂在
   .ed-js **之下**，于是 JS 一关，封锁跟着一起消失 —— 那就是本轮修的洞。

   为什么是 display:none 而不是再盖一层
   ------------------------------------
   No-JS 环境下没有 focus trap 可用（那需要 JS）。一层 position:fixed 的
   覆盖物只挡得住眼睛和鼠标：它背后的链接、按钮、表单仍然在 tab 顺序里，
   Tab / Shift+Tab / Enter 一路就能操作它们，页面也仍然能滚。把它们从渲染
   树里摘掉之后，这些路径不是被拦截了，是**不存在**了 —— 不可聚焦、不可
   点击、不占位、不参与滚动。这是纯 HTML/CSS 能给出的唯一硬保证。

   :not(noscript) 是为了让闸门自己留下来：<noscript> 的内容在 scripting
   disabled 时被正常渲染，闸门就活在那里面。

   SEO 为什么不受影响（§十七 / §十八）
   -----------------------------------
   这几条只影响**浏览器端的渲染**，响应体一个字节都没变。Googlebot 渲染时
   执行 JS，.ed-js 会被打上，这几条对它根本不匹配；即使某次是不执行 JS 的
   纯 HTML 抓取，那时外部 CSS 压根没参与，抓到的仍是完整页面。这条路上
   没有一处按 User-Agent 分叉。
   ========================================================================== */
html:not(.ed-js) body.ed-age-gate-pending > :not(noscript) {
	display: none !important;
}

/* 摘掉内容之后页面本来也没什么可滚的，锁住是为了消灭 iOS 上那点橡皮筋
   回弹 —— 那会让人瞥见闸门边缘之外的东西。 */
html:not(.ed-js) body.ed-age-gate-pending {
	overflow: hidden;
}

/* 闸门本体。不透明 —— 半透明遮罩在一个成人内容闸门上是错的。
   z-index 比 .ed-age-gate 高一级，纯粹是为了两者的层级关系读一眼就清楚；
   它们实际上永远不会同时存在。 */
.ed-age-noscript-gate {
	position: fixed;
	inset: 0;
	z-index: 10000;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 20px;
	background: var(--ed-bg);
	overflow-y: auto;
	-webkit-overflow-scrolling: touch;
}

/* 表单在这里就是 JS 版那个 .ed-age-gate__actions 容器 —— 复用同一条 flex
   规则，两个按钮的排布、间距、收缩行为一个像素都不差。 */
.ed-age-noscript-gate .ed-age-gate__actions {
	margin: 0;
}

/* 拒绝之后那一页（inc/age-gate.php 的 edgua_age_gate_render_blocked）。
   它是一份独立的极简文档，只引这一个样式表，所以居中要自己做。 */
.ed-age-blocked-page {
	min-height: 100vh;
	margin: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 20px;
	background: var(--ed-bg);
}

/* ==========================================================================
   FRONTEND_PRODUCT_EXPERIENCE_V3 —— Header 官方入口 / 主题切换 / 账户
   ========================================================================== */

.ed-header__socials {
	display: none;
	align-items: center;
	gap: 6px;
}

/* 官方三入口在 1280 以上直接进顶栏；1024–1279 收进抽屉。
 
   这个断点是量出来的，不是选出来的，中间还纠正过一次自己的测量：
 
     第一版写的是一个新造的 1200px 断点。为了避免多一个断点，改成 1024
     并「实测」了一次 —— 但那次只量了 .ed-nav__list，看到它在 1024 上仍是
     单行 715px 就下了结论。那个口径是不完整的：真正装不下的是右边整块
     .ed-header__actions（搜索 + 三个官方 + 主题 + 账户），它在 1024 上从
     x=866 一直撑到 1130，溢出视口 106px，连 TikTok 图标和主题开关都被
     body 的 overflow-x:hidden 裁掉了。
 
     所以 1024 确实放不下，而 1200 又是一个不该新增的第五断点。最终解法是
     用既有的 1280：1280 以上顶栏放得下（实测无溢出），1024–1279 那一段则
     **保留汉堡按钮**，官方入口 / 主题 / 账户全部在抽屉里 —— 它们在那一段
     宽度上不会消失，只是换了一个入口。主导航在 1024 仍然十项平铺，
     一个栏目都没有被折叠（§十一）。 */
@media (min-width: 1280px) {
	.ed-header__socials {
		display: inline-flex;
	}
}

.ed-icon-btn--social svg {
	width: 17px;
	height: 17px;
}

/* 主题切换：两个图标都在 DOM 里，由当前 data-theme 决定显示哪一个。
   日间显示月亮（点它去夜间），夜间显示太阳。用 CSS 选而不是 JS 换
   innerHTML —— 后者会在脚本执行前露出一个错的图标。 */
.ed-theme-toggle__sun {
	display: none;
}

.ed-theme-toggle__moon {
	display: inline-flex;
}

html[data-theme="dark"] .ed-theme-toggle__sun {
	display: inline-flex;
}

html[data-theme="dark"] .ed-theme-toggle__moon {
	display: none;
}

/* 无 JS 时整个切换入口不渲染：偏好存在 localStorage 里，没有 JS 就既
   写不进去也读不出来，一个点了没反应的开关比没有开关更糟。 */
html:not(.ed-js) .ed-theme-toggle {
	display: none !important;
}

/* --------------------------------------------------------------------------
   账户下拉（原生 details/summary）
   -------------------------------------------------------------------------- */
/* 账户入口：**默认不在顶栏**，只有 1280 以上才直接出现（与官方三入口同一
   条规则）。
 
   理由是量出来的：本轮往 .ed-header__actions 里加了主题开关与账户两个
   38px 的按钮，那一块从 ~100px 长到 176px。1024 上可用宽度只有 968，
   而 logo(80) + 十项导航(715) + actions(176) + 两个 24px 的 gap 已经是
   1019 —— header 被撑破 46px，TikTok 图标与主题开关直接被 body 的
   overflow-x:hidden 裁掉。
 
   把账户收进抽屉（连同官方三入口）之后 actions 回到 130px，加上把
   header 的 gap 从 24 收到 14，1024 上的总需求落到 953 < 968，留有余量。
   移动端本来就走抽屉，所以这条基线规则对它也是对的 —— 顶栏因此在每一个
   小于 1280 的宽度上都只有「搜索 / 主题 / 菜单」三个按钮，形状一致。 */
.ed-account,
a.ed-account-btn {
	display: none;
}

.ed-account {
	position: relative;
}

.ed-account > summary {
	list-style: none;
	padding: 0;
	overflow: hidden;
}

.ed-account > summary::-webkit-details-marker,
.ed-account > summary::marker {
	display: none;
	content: "";
}

.ed-account__avatar {
	width: 100%;
	height: 100%;
	border-radius: 50%;
	object-fit: cover;
}

.ed-account__menu {
	position: absolute;
	top: calc(100% + 8px);
	right: 0;
	z-index: 120;
	min-width: 200px;
	padding: 6px;
	background: var(--ed-card);
	border: 1px solid var(--ed-border);
	border-radius: var(--ed-radius-md);
	box-shadow: var(--ed-shadow-lift);
}

.ed-account__head {
	display: flex;
	align-items: center;
	gap: 10px;
	padding: 8px 10px 10px;
	border-bottom: 1px solid var(--ed-border-soft);
	margin-bottom: 6px;
}

.ed-account__head .ed-account__avatar {
	width: 32px;
	height: 32px;
	flex-shrink: 0;
}

.ed-account__name {
	font-weight: 600;
	font-size: 14px;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.ed-account__item {
	display: flex;
	align-items: center;
	gap: 10px;
	padding: 9px 10px;
	border-radius: var(--ed-radius-sm);
	font-size: 14px;
	color: var(--ed-text);
}

.ed-account__item svg {
	width: 16px;
	height: 16px;
	flex-shrink: 0;
	color: var(--ed-text-muted);
}

.ed-account__item:hover {
	background: var(--ed-bg-soft);
	color: var(--ed-gold);
}

.ed-account__item:hover svg {
	color: var(--ed-gold);
}

.ed-account__item--logout {
	border-top: 1px solid var(--ed-border-soft);
	margin-top: 4px;
	padding-top: 11px;
}

/* --------------------------------------------------------------------------
   抽屉里的整行入口（官方渠道 / 主题 / 账户共用同一个形状）
   -------------------------------------------------------------------------- */
.ed-mobile-nav__sep {
	height: 1px;
	background: var(--ed-border-soft);
	margin: 12px 0;
}

.ed-mobile-nav__socials,
.ed-mobile-nav__account {
	display: flex;
	flex-direction: column;
}

.ed-social-row {
	display: flex;
	align-items: center;
	gap: 12px;
	width: 100%;
	padding: 11px 4px;
	border: 0;
	background: transparent;
	color: var(--ed-text);
	font-family: inherit;
	font-size: 15px;
	text-align: left;
}

.ed-social-row:hover {
	color: var(--ed-gold);
}

.ed-social-row--static {
	color: var(--ed-text-muted);
	pointer-events: none;
}

.ed-social-row__icon {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 22px;
	height: 22px;
	flex-shrink: 0;
}

.ed-social-row__icon svg,
.ed-social-row__icon img {
	width: 19px;
	height: 19px;
	border-radius: 50%;
}

.ed-social-row__label {
	flex: 1 1 auto;
	min-width: 0;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.ed-social-row__handle {
	color: var(--ed-text-faint);
	font-size: 13px;
	flex-shrink: 0;
}

/* 抽屉里的主题行：两组 sun/moon 的显隐规则与顶栏那个按钮共用同一条
   （见上面 html[data-theme] 的选择器），这里只补 flex 布局。 */
.ed-theme-toggle--row .ed-theme-toggle__sun,
.ed-theme-toggle--row .ed-theme-toggle__moon {
	align-items: center;
}

/* ==========================================================================
   收藏按钮（§六十二）
   ========================================================================== */
.ed-fav-form {
	display: inline-block;
	margin: 0;
}

.ed-fav-btn {
	display: inline-flex;
	align-items: center;
	gap: 7px;
	padding: 8px 14px;
	border: 1px solid var(--ed-border);
	border-radius: 999px;
	background: var(--ed-bg-soft);
	color: var(--ed-text);
	font-family: inherit;
	font-size: 14px;
	line-height: 1.4;
}

.ed-fav-btn svg {
	width: 16px;
	height: 16px;
	color: var(--ed-text-faint);
	transition: color 0.15s ease;
}

.ed-fav-btn:hover {
	border-color: var(--ed-gold-soft);
	color: var(--ed-gold);
}

.ed-fav-btn:hover svg,
.ed-fav-btn.is-on svg {
	color: var(--ed-gold);
}

.ed-fav-btn.is-on {
	border-color: var(--ed-gold-soft);
	background: var(--ed-gold-bg);
	color: var(--ed-gold);
}

/* ==========================================================================
   会员页面（登录 / 注册 / 找回 / 账户 / 收藏 / 历史）
   ========================================================================== */
.ed-auth {
	display: flex;
	justify-content: center;
	padding: 40px 0 64px;
}

.ed-auth__card {
	width: 100%;
	max-width: 420px;
	padding: 28px 22px 24px;
	background: var(--ed-card);
	border: 1px solid var(--ed-border);
	border-top: 2px solid var(--ed-gold);
	border-radius: var(--ed-radius-lg);
	box-shadow: var(--ed-shadow-card);
}

.ed-auth__brand {
	text-align: center;
	margin-bottom: 6px;
}

.ed-auth__title {
	font-size: 20px;
	font-weight: 700;
	text-align: center;
	margin-bottom: 4px;
}

.ed-auth__sub {
	color: var(--ed-text-muted);
	font-size: 13px;
	text-align: center;
	margin-bottom: 20px;
}

.ed-auth__foot {
	margin-top: 18px;
	padding-top: 16px;
	border-top: 1px solid var(--ed-border-soft);
	text-align: center;
	color: var(--ed-text-muted);
	font-size: 13px;
}

.ed-auth__foot a {
	color: var(--ed-gold);
}

/* 表单字段 */
.ed-field {
	margin-bottom: 14px;
}

.ed-field__label {
	display: block;
	margin-bottom: 6px;
	font-size: 13px;
	font-weight: 600;
	color: var(--ed-text);
}

.ed-field__hint {
	margin-top: 6px;
	font-size: 12px;
	color: var(--ed-text-faint);
	line-height: 1.5;
}

.ed-input {
	width: 100%;
	padding: 11px 12px;
	border: 1px solid var(--ed-border);
	border-radius: var(--ed-radius-sm);
	background: var(--ed-bg-soft);
	color: var(--ed-text);
	font-family: inherit;
	font-size: 15px;
}

.ed-input:focus,
.ed-icon-btn:focus-visible,
.ed-btn:focus-visible,
.ed-fav-btn:focus-visible,
.ed-social-row:focus-visible {
	outline: 2px solid var(--ed-gold);
	outline-offset: 2px;
}

.ed-input::placeholder {
	color: var(--ed-text-faint);
}

/* 输入框 + 右侧按钮（随机用户名 / 显示密码）。按钮在框内右侧，
   所以框本身不需要为按钮留一段 padding-right 的魔法数字。 */
.ed-field__combo {
	display: flex;
	gap: 8px;
	align-items: stretch;
}

.ed-field__combo .ed-input {
	flex: 1 1 auto;
	min-width: 0;
}

.ed-field__btn {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	flex-shrink: 0;
	padding: 0 12px;
	border: 1px solid var(--ed-border);
	border-radius: var(--ed-radius-sm);
	background: var(--ed-bg-soft);
	color: var(--ed-text-muted);
	font-family: inherit;
	font-size: 13px;
	white-space: nowrap;
}

.ed-field__btn:hover {
	border-color: var(--ed-gold-soft);
	color: var(--ed-gold);
}

.ed-field__btn svg {
	width: 15px;
	height: 15px;
}

.ed-field__row {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 12px;
	margin: 4px 0 18px;
	font-size: 13px;
}

.ed-check {
	display: inline-flex;
	align-items: center;
	gap: 7px;
	color: var(--ed-text-muted);
}

.ed-field__row a {
	color: var(--ed-gold);
}

.ed-btn--block {
	display: block;
	width: 100%;
	text-align: center;
}

/* 提示条：错误 / 中性通知，统一一套（§八十四） */
.ed-alert {
	padding: 11px 13px;
	border-radius: var(--ed-radius-sm);
	font-size: 13.5px;
	line-height: 1.6;
	margin-bottom: 16px;
}

.ed-alert--error {
	background: var(--ed-danger-bg);
	border: 1px solid var(--ed-danger);
	color: var(--ed-danger);
}

.ed-alert--notice {
	background: var(--ed-gold-bg);
	border: 1px solid var(--ed-gold-soft);
	color: var(--ed-text);
}

.ed-alert ul {
	margin: 0;
	padding-left: 18px;
	list-style: disc;
}

/* --------------------------------------------------------------------------
   账户内页：左侧菜单 + 右侧内容
   -------------------------------------------------------------------------- */
.ed-member-layout {
	display: grid;
	grid-template-columns: 1fr;
	gap: 24px;
	padding: 28px 0 56px;
}

.ed-member-nav {
	display: flex;
	flex-wrap: wrap;
	gap: 6px;
	align-content: start;
}

.ed-member-nav__item {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	padding: 9px 13px;
	border: 1px solid var(--ed-border);
	border-radius: var(--ed-radius-sm);
	background: var(--ed-card);
	font-size: 14px;
}

.ed-member-nav__item svg {
	width: 16px;
	height: 16px;
	color: var(--ed-text-muted);
}

.ed-member-nav__item:hover {
	border-color: var(--ed-gold-soft);
	color: var(--ed-gold);
}

.ed-member-nav__item.is-active {
	background: var(--ed-gold-bg);
	border-color: var(--ed-gold-soft);
	color: var(--ed-gold);
}

.ed-member-nav__item.is-active svg {
	color: var(--ed-gold);
}

.ed-member__title {
	font-size: 22px;
	font-weight: 700;
	margin-bottom: 4px;
}

.ed-member__count {
	color: var(--ed-text-muted);
	font-size: 13px;
	margin-bottom: 18px;
}

.ed-member-info {
	border: 1px solid var(--ed-border);
	border-radius: var(--ed-radius-md);
	background: var(--ed-card);
	padding: 4px 18px;
}

.ed-member-info__row {
	display: flex;
	flex-wrap: wrap;
	gap: 8px 16px;
	padding: 14px 0;
	border-bottom: 1px solid var(--ed-border-soft);
	font-size: 14px;
}

.ed-member-info__row:last-child {
	border-bottom: 0;
}

.ed-member-info__key {
	width: 120px;
	flex-shrink: 0;
	color: var(--ed-text-muted);
}

.ed-member-info__val {
	min-width: 0;
	word-break: break-all;
}

@media (min-width: 1024px) {
	.ed-member-layout {
		grid-template-columns: 200px minmax(0, 1fr);
		gap: 32px;
	}

	.ed-member-nav {
		flex-direction: column;
		flex-wrap: nowrap;
	}

	.ed-member-nav__item {
		width: 100%;
	}
}

/* ==========================================================================
   §二十三 —— 首页 B 类视频栏目：宽桌面 5 列
   ==========================================================================
   Owner 定的每栏 5 条，在 1280+ 上正好排成一行，一个栏目一屏之内看得完。
   1024 那一段维持 4 列：container 减去 padding 只有 968px，5 列每卡
   175px，16:9 封面高不到 100px，标题 15px 两行会挤成三四个字一行 ——
   §二十三 明确说了不能为了机械 5 列把 Card 做坏。归档页不受这条影响，
   它继续是 4 列（§二十四）。 */
@media (min-width: 1280px) {
	.ed-section--home-guochan .ed-grid--video,
	.ed-section--home-tanhua .ed-grid--video,
	.ed-section--home-madou .ed-grid--video,
	.ed-section--home-tangxin .ed-grid--video,
	.ed-section--home-sex-tips .ed-grid--video {
		grid-template-columns: repeat(5, 1fr);
	}
}

/* ==========================================================================
   §三十三 —— Card hover（克制：位移 + 边框 + 封面轻微推近）
   ========================================================================== */
@media (hover: hover) and (min-width: 1024px) {
	.ed-card--video {
		transition: transform 0.18s ease, border-color 0.18s ease, box-shadow 0.18s ease;
	}

	.ed-card--video:hover {
		transform: translateY(-3px);
		border-color: var(--ed-gold-soft);
		box-shadow: var(--ed-shadow-lift);
	}

	.ed-card--video .ed-card__thumb img {
		transition: transform 0.25s ease;
	}

	.ed-card--video:hover .ed-card__thumb img {
		transform: scale(1.03);
	}

	.ed-feed__item {
		transition: border-color 0.18s ease;
	}
}

/* ==========================================================================
   §三十四 —— 版式稳定：图片加载前后卡片不跳
   ==========================================================================
   .ed-card__thumb 早就有 aspect-ratio，但里面的 <img> 在加载完成前高度
   是 0，于是「有图」和「没图」两种状态下缩略图容器的**背景**不同，视觉上
   会闪一下。给容器一个中性底色 + 让 img 撑满容器，加载前后占位完全一致。 */
.ed-card__thumb,
.ed-feed__thumb {
	background: var(--ed-bg-soft);
}

.ed-card__thumb img,
.ed-feed__thumb img {
	width: 100%;
	height: 100%;
	object-fit: cover;
}


/* OPERATOR CLOSURE §二十五 —— 站内信收件箱与未读徽标。
 *
 * 未读用左侧金色竖条 + 略深的底，不用红点：09GUA 的语义色里红是风险
 * （--ed-danger），把「有新消息」画成红色会和内容风险标记撞语义。
 */
.ed-member-nav__badge {
	margin-left: auto;
	min-width: 18px;
	padding: 0 5px;
	border-radius: 999px;
	background: var(--ed-gold);
	color: var(--ed-gold-ink);
	font-size: 11px;
	line-height: 18px;
	text-align: center;
	font-weight: 700;
}

.ed-msg-toolbar {
	display: flex;
	justify-content: flex-end;
	margin-bottom: 12px;
}

.ed-msg-list {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-direction: column;
	gap: 10px;
}

.ed-msg {
	border: 1px solid var(--ed-border);
	border-left: 3px solid transparent;
	border-radius: var(--ed-radius-md);
	background: var(--ed-card);
	padding: 12px 14px;
}

.ed-msg.is-unread {
	border-left-color: var(--ed-gold);
	background: var(--ed-card-hover);
}

.ed-msg__head {
	display: flex;
	align-items: center;
	gap: 8px;
	flex-wrap: wrap;
}

.ed-msg__title {
	font-size: 15px;
	font-weight: 600;
	margin: 0;
}

.ed-msg__time {
	margin-left: auto;
	font-size: 12px;
	color: var(--ed-text-faint);
	white-space: nowrap;
}

.ed-msg__body {
	margin: 8px 0 0;
	font-size: 14px;
	line-height: 1.6;
	color: var(--ed-text-muted);
	overflow-wrap: anywhere;
}

.ed-msg__foot {
	display: flex;
	gap: 8px;
	margin-top: 10px;
}

.ed-msg__foot:empty {
	display: none;
}

/* ==========================================================================
   P7 BUNNY EBOOK READER V1 —— 电子书父作品页与逐章阅读页
   ==========================================================================

   两条与既有 single.php 刻意不同的地方：

   1. 封面是一个 **16:9 的横版槽**（V2 改；V1 是 2:3 竖版书封），且**有上限
      宽度**。single.php 的 `edgua-hero` 特色图是满宽的，那正是 Owner 在
      post 2265 上看到的「巨大封面」——这里仍然不是那个。桌面端 440px，与右
      侧的书名 / 作者 / 字数 / 章节数 / 开始阅读组成一个平衡的两列。
   2. 阅读区宽度收到 --ed-content-width 以内，行高 1.9。长篇中文正文的可读
      性由行长和行距决定，而不是由字号 —— 一行 80 个汉字的正文放大字号只会
      更难读。
   ========================================================================== */

.ed-ebook {
	padding: 24px 0 48px;
}

.ed-ebook__head {
	display: grid;
	grid-template-columns: 440px minmax(0, 1fr);
	gap: 28px;
	align-items: start;
	margin: 16px 0 28px;
}

/*
 * V2：封面槽是 **16:9 横版**。
 *
 * 比例是**槽位**的属性，不是图片的属性 —— #1103 在 Bunny 上仍然是那张
 * 1200×1800 的竖图，一个字节都没动，也没有任何派生图被生成出来。横版是
 * `aspect-ratio` + `object-fit: cover` 在浏览器里做的一次中心裁切。
 *
 * `object-position: center` 是明写的，不是靠默认值：它恰好等于默认值，但
 * 「书名在图的中上部，所以裁切必须居中」是一条**产品决定**，而产品决定不
 * 该由某个属性的默认值来承担 —— 那种依赖在别人改一行 CSS 时会静默消失。
 */
.ed-ebook__cover {
	aspect-ratio: 16 / 9;
	overflow: hidden;
	border-radius: var(--ed-radius-md);
	background: var(--ed-bg-soft);
	box-shadow: var(--ed-shadow-card);
}

.ed-ebook__cover-img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: center;
	display: block;
}

.ed-ebook__cover-img--placeholder {
	object-fit: contain;
	padding: 24px;
	opacity: 0.6;
}

.ed-ebook__title {
	margin: 0 0 10px;
	font-size: 26px;
	line-height: 1.35;
	color: var(--ed-text);
}

.ed-ebook__author {
	margin: 0 0 10px;
	font-size: 14px;
	color: var(--ed-text-muted);
}

.ed-ebook__label {
	color: var(--ed-text-faint);
	margin-right: 6px;
}

.ed-ebook__author-name {
	color: var(--ed-text);
	font-weight: 600;
}

.ed-ebook__facts {
	display: flex;
	flex-wrap: wrap;
	gap: 6px 16px;
	margin: 0 0 12px;
	padding: 0;
	list-style: none;
	font-size: 13px;
	color: var(--ed-text-muted);
}

.ed-ebook__tags {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
	margin: 0 0 16px;
}

.ed-ebook__tag {
	font-size: 13px;
	color: var(--ed-gold);
	text-decoration: none;
}

.ed-ebook__tag:hover {
	color: var(--ed-gold-hover);
}

.ed-ebook__section-title {
	margin: 28px 0 12px;
	font-size: 18px;
	color: var(--ed-text);
}

.ed-ebook__intro-body {
	max-width: var(--ed-content-width);
	font-size: 15px;
	line-height: 1.85;
	color: var(--ed-text-muted);
}

/* --------------------------------------------------------------------------
   电子书详情页固定「阅读提示」（P1）。

   这里**没有**第二套卡片系统：容器同时带着 .ed-disclaimer，边框、圆角、
   内边距、底色、字色全部由那个既有组件给出。本段只补三件它不该知道的事 ——
   在这条页面里的垂直节奏、版心宽度上限、以及长串的换行策略。

   颜色一个都不写，所以日间 / 夜间是自动的：:root 与 html[data-theme="dark"]
   已经各给了一组 token，这条规则只要不硬编码色值就同时成立。

   刻意不是弹窗：没有 position: fixed，没有 z-index，没有遮罩。站级 age gate
   已经承担了「打断一次」的角色，一段阅读提示再打断一次只会变成噪音。
   -------------------------------------------------------------------------- */
.ed-ebook__notice {
	margin: 28px 0 0;
	max-width: var(--ed-content-width);
	/* 书名、外文原名、长 URL 都可能出现在同一段里；没有这一条时 320px 上
	   会出现横向滚动条，而横向滚动条在正文区里永远是缺陷。 */
	overflow-wrap: anywhere;
}

.ed-ebook__notice-text {
	/* 比 .ed-disclaimer__text 的 13px 略大一点：这段话是要被读完的，
	   不是页脚那种「存在即可」的法务小字。仍然小于正文，不抢焦点。 */
	font-size: 13.5px;
}

.ed-ebook__notice-link {
	color: var(--ed-gold);
	text-decoration: underline;
	text-underline-offset: 2px;
}

.ed-ebook__notice-link:hover {
	color: var(--ed-gold-hover);
}

.ed-ebook__group {
	margin-bottom: 22px;
}

.ed-ebook__group-title {
	display: flex;
	align-items: baseline;
	gap: 10px;
	margin: 0 0 8px;
	font-size: 15px;
	color: var(--ed-text);
	border-left: 3px solid var(--ed-gold);
	padding-left: 10px;
}

.ed-ebook__group-count {
	font-size: 12px;
	font-weight: 400;
	color: var(--ed-text-faint);
}

.ed-ebook__chapters {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
	gap: 2px 16px;
	margin: 0;
	padding: 0;
	list-style: none;
}

.ed-ebook__chapter a {
	display: flex;
	gap: 8px;
	padding: 7px 4px;
	font-size: 14px;
	color: var(--ed-text-muted);
	text-decoration: none;
	border-bottom: 1px solid var(--ed-border-soft);
}

.ed-ebook__chapter a:hover {
	color: var(--ed-gold);
	background: var(--ed-card-hover);
}

.ed-ebook__chapter-no {
	flex: 0 0 auto;
	color: var(--ed-text-faint);
	font-variant-numeric: tabular-nums;
}

.ed-ebook__chapter-title {
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.ed-ebook__empty {
	color: var(--ed-text-faint);
	font-size: 14px;
}

/* --- 阅读页 --------------------------------------------------------- */

.ed-reader {
	max-width: var(--ed-content-width);
	padding: 20px 0 56px;
}

.ed-reader__crumbs {
	font-size: 13px;
	color: var(--ed-text-faint);
	margin-bottom: 14px;
}

.ed-reader__crumbs a {
	color: var(--ed-text-muted);
	text-decoration: none;
}

.ed-reader__crumb-sep {
	margin: 0 6px;
}

.ed-reader__no {
	margin: 0 0 4px;
	font-size: 13px;
	color: var(--ed-gold);
}

.ed-reader__title {
	margin: 0 0 22px;
	font-size: 22px;
	line-height: 1.4;
	color: var(--ed-text);
}

.ed-reader__body {
	font-size: 17px;
	/* 长篇中文的可读性来自行距和行长，不是字号。 */
	line-height: 1.95;
	color: var(--ed-text);
	overflow-wrap: anywhere;
}

.ed-reader__body p {
	margin: 0 0 1.1em;
	/* 中文长篇的首行缩进用 CSS 做，不用全角空格做：模板已经把行首的排版
	   空白 trim 掉了，因为那是排版，不是内容。 */
	text-indent: 2em;
}

.ed-reader__unavailable {
	padding: 20px;
	border: 1px dashed var(--ed-border);
	border-radius: var(--ed-radius-md);
	color: var(--ed-text-faint);
	text-align: center;
}

.ed-reader__pager {
	display: grid;
	grid-template-columns: 1fr auto 1fr;
	gap: 12px;
	align-items: stretch;
	margin-top: 36px;
	padding-top: 20px;
	border-top: 1px solid var(--ed-border);
}

.ed-reader__pager-link {
	display: flex;
	flex-direction: column;
	justify-content: center;
	gap: 3px;
	padding: 10px 12px;
	border: 1px solid var(--ed-border);
	border-radius: var(--ed-radius-sm);
	background: var(--ed-card);
	color: var(--ed-text);
	font-size: 13px;
	text-decoration: none;
	min-width: 0;
}

.ed-reader__pager-link--next {
	text-align: right;
}

.ed-reader__pager-link--toc {
	justify-content: center;
	align-items: center;
	white-space: nowrap;
}

.ed-reader__pager-link--disabled {
	color: var(--ed-text-faint);
	background: transparent;
	border-style: dashed;
	justify-content: center;
	align-items: center;
}

.ed-reader__pager-dir {
	color: var(--ed-text-faint);
	font-size: 12px;
}

.ed-reader__pager-title {
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

@media (max-width: 767px) {
	/* V2：移动端封面是内容区 100% 宽，仍然 16:9 —— 于是它变成单列。 */
	.ed-ebook__head {
		grid-template-columns: 1fr;
		gap: 16px;
	}

	.ed-ebook__title {
		font-size: 20px;
	}

	.ed-ebook__chapters {
		grid-template-columns: 1fr;
	}

	.ed-reader__body {
		font-size: 16px;
		line-height: 1.9;
	}

	.ed-reader__pager {
		grid-template-columns: 1fr;
	}

	.ed-reader__pager-link--next {
		text-align: left;
	}

	/* 手机上两列目录会把「第 12 章 房东太太」挤成两个字。 */
	.ed-reader__toc-list {
		grid-template-columns: 1fr;
	}

	.ed-reader__toc-body {
		max-height: 60vh;
	}
}

/* 今日吃瓜：帖子里的全部图片，纵向排开（Owner 2026-09-29「图都不要少」）。
   外观跟 .ed-single__thumb 同一套：圆角、细边框、满宽。 */
.ed-single__gallery {
	display: flex;
	flex-direction: column;
	gap: 12px;
	margin-bottom: 24px;
}

.ed-single__gallery-item {
	margin: 0;
	border-radius: var(--ed-radius-lg);
	overflow: hidden;
	border: 1px solid var(--ed-border);
}

.ed-single__gallery-item img {
	width: 100%;
	height: auto;
	display: block;
}

/* Owner 2026-09-30：同一广告位多条广告「全部一起显示」。
   横幅：一组内每条之间 10px，整组末尾保留原来的 24px。
   浮动：一个浮层里逐条叠放；桌面整层最高 60vh（超出可滚），单条仍按原规则缩放。 */
.ed-ad-stack {
	margin-bottom: 24px;
}

.ed-ad-stack > .ed-ad {
	margin-bottom: 10px;
}

.ed-ad-stack > .ed-ad:last-child {
	margin-bottom: 0;
}

.ed-ad--floating.ed-ad-float-multi {
	max-height: 60vh;
	overflow-y: auto;
}

.ed-ad-float-multi .ed-ad__item + .ed-ad__item {
	border-top: 1px solid var(--ed-border);
}

/* 卡片关键词标签（Owner 2026-09-30：手机上三个显示不全、很别扭）。
   搜索页那组 .ed-chip（6px 12px / 13px）写在后面，把卡片里的小标签也撑大了，
   这里按卡片作用域收回来；手机只显示前两个、居中。 */
.ed-card__chips .ed-chip {
	padding: 2px 8px;
	font-size: 11px;
	line-height: 16px;
	border: 0;
	background: var(--ed-gold-bg);
	color: var(--ed-gold);
	max-width: 96px;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	display: inline-block;
}

@media (max-width: 767px) {
	.ed-card__chips {
		justify-content: center;
	}

	.ed-card__chips > :nth-child(n+3) {
		display: none;
	}

	.ed-card__chips .ed-chip {
		max-width: calc(50% - 3px);
		padding: 3px 7px;
		font-size: 12px;
	}
}

/* ==========================================================================
   电子书阅读页排版（Owner 2026-09-30：「跟 xbookcn 比还是很大差距，包括手机版」）
   --------------------------------------------------------------------------
   1. .ed-reader 的 padding: 20px 0 覆盖了 .ed-container 的左右 20px ——
      手机上正文直接贴到屏幕边缘。补回两侧留白。
   2. 段距 1.1em → 0.75em：段与段之间不再像空了一整行，读起来连贯。
   3. 正文不用纯白 / 纯黑：夜间暖灰白、日间深灰，长时间阅读不刺眼。
   4. 章节标题居中、加分隔线；阅读栏宽收到 720px（一行约 38 字）。
   ========================================================================== */
.ed-reader {
	--ed-reader-ink: #2c2a2d;
	max-width: 760px;
	padding: 24px 20px 64px;
}

html[data-theme="dark"] .ed-reader {
	--ed-reader-ink: #d9d4d7;
}

.ed-reader__head {
	text-align: center;
	margin: 12px 0 28px;
	padding-bottom: 20px;
	border-bottom: 1px solid var(--ed-border-soft);
}

.ed-reader__no {
	font-size: 12px;
	letter-spacing: 0.12em;
	color: var(--ed-text-faint);
	margin-bottom: 8px;
}

.ed-reader__title {
	margin: 0;
	font-size: 24px;
	font-weight: 700;
	letter-spacing: 0.02em;
}

.ed-reader__body {
	font-size: 18px;
	line-height: 2;
	letter-spacing: 0.02em;
	color: var(--ed-reader-ink);
	text-align: justify;
}

.ed-reader__body p {
	margin: 0 0 0.75em;
}

.ed-reader__chapter + .ed-reader__chapter {
	margin-top: 56px;
}

@media (max-width: 767px) {
	.ed-reader {
		padding: 16px 18px 56px;
	}

	.ed-reader__head {
		margin: 8px 0 22px;
		padding-bottom: 16px;
	}

	.ed-reader__title {
		font-size: 21px;
	}

	.ed-reader__body {
		font-size: 17.5px;
		line-height: 1.95;
	}
}
