更多
diff --git a/src/styles/overrides/drama-tiles.css b/src/styles/overrides/drama-tiles.css
new file mode 100644
index 0000000..705fcc4
--- /dev/null
+++ b/src/styles/overrides/drama-tiles.css
@@ -0,0 +1,209 @@
+/* 短剧卡片统一外观(全站共用,加载在页面样式之后):
+ 直角偏小的封面 + 细描边,集数/状态角标放封面右下,悬停时封面上浮并出现底部强调条,
+ 标题下方为斜杠分隔的题材行。选择器带父级类名,覆盖各页面零特异性的局部卡片样式。 */
+
+.hk-drama-card {
+ gap: 8px;
+}
+
+.hk-drama-card .hk-drama-card__cover {
+ border-radius: 6px;
+ border: 1px solid rgba(255, 255, 255, 0.08);
+ box-shadow: 0 6px 18px rgba(0, 0, 0, 0.28);
+ background-image:
+ linear-gradient(180deg, rgba(0, 0, 0, 0) 58%, rgba(0, 0, 0, 0.72) 100%),
+ var(--cover);
+ transition:
+ transform 220ms ease,
+ border-color 220ms ease,
+ box-shadow 220ms ease;
+}
+
+/* 悬停遮罩:去掉居中圆形“立即播放”,改为左下角三角播放键 + 底部强调条 */
+.hk-drama-card .hk-drama-card__cover::before {
+ inset: auto 0 0 0;
+ height: 3px;
+ border-radius: 0;
+ background: var(--accent);
+ opacity: 0;
+ transform: scaleX(0);
+ transform-origin: left center;
+ transition:
+ opacity 220ms ease,
+ transform 260ms ease;
+}
+
+.hk-drama-card .hk-drama-card__cover::after {
+ top: auto;
+ left: 10px;
+ bottom: 12px;
+ width: 30px;
+ height: 30px;
+ padding: 0;
+ border-radius: 50%;
+ background: var(--accent) url("/static/images/play.svg") 55% 50% / 12px 12px no-repeat;
+ box-shadow: 0 4px 12px rgba(255, 15, 83, 0.45);
+ content: "";
+ transform: translateY(6px);
+}
+
+.hk-drama-card .hk-drama-card__cover:focus-visible {
+ border-color: rgba(255, 15, 83, 0.6);
+ box-shadow: 0 10px 24px rgba(0, 0, 0, 0.4);
+}
+
+.hk-drama-card .hk-drama-card__cover:focus-visible::before {
+ transform: scaleX(1);
+}
+
+.hk-drama-card .hk-drama-card__cover:focus-visible::after {
+ transform: translateY(0);
+}
+
+@media (hover: hover) and (pointer: fine) {
+ .hk-drama-card .hk-drama-card__cover:hover {
+ border-color: rgba(255, 15, 83, 0.6);
+ box-shadow: 0 10px 24px rgba(0, 0, 0, 0.4);
+ transform: translateY(-4px);
+ }
+
+ .hk-drama-card .hk-drama-card__cover:hover::before {
+ transform: scaleX(1);
+ }
+
+ .hk-drama-card .hk-drama-card__cover:hover::after {
+ transform: translateY(0);
+ }
+
+ /* 悬停时播放键接管封面底部,角标淡出避免窄卡片上重叠 */
+ .hk-drama-card .hk-drama-card__cover:hover .hk-drama-card__eps {
+ opacity: 0;
+ }
+}
+
+/* 封面右下角:集数 · 连更/完结 */
+.hk-drama-card .hk-drama-card__eps {
+ position: absolute;
+ right: 8px;
+ bottom: 9px;
+ z-index: 2;
+ display: inline-flex;
+ align-items: center;
+ gap: 2px;
+ max-width: calc(100% - 16px);
+ padding: 2px 7px 2px 6px;
+ border-radius: 4px;
+ background: rgba(10, 10, 12, 0.62);
+ -webkit-backdrop-filter: blur(6px);
+ backdrop-filter: blur(6px);
+ color: rgba(255, 255, 255, 0.9);
+ font-size: 11px;
+ font-weight: 500;
+ line-height: 16px;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ pointer-events: none;
+ transition: opacity 180ms ease;
+}
+
+.hk-drama-card .hk-drama-card__eps b {
+ color: #ffffff;
+ font-size: 12px;
+ font-weight: 700;
+}
+
+.hk-drama-card .hk-drama-card__eps::before {
+ width: 6px;
+ height: 6px;
+ margin-right: 4px;
+ flex: none;
+ border-radius: 50%;
+ background: var(--text-dim);
+ content: "";
+}
+
+.hk-drama-card .hk-drama-card__eps[data-status="serial"]::before {
+ background: var(--success);
+ box-shadow: 0 0 0 2px rgba(61, 201, 138, 0.25);
+}
+
+/* 标题与题材行 */
+.hk-drama-card .hk-drama-card__title {
+ font-size: 15px;
+ font-weight: 600;
+ line-height: 21px;
+ letter-spacing: 0.2px;
+}
+
+.hk-drama-card .hk-drama-card__title a {
+ color: inherit;
+ transition: color 160ms ease;
+}
+
+.hk-drama-card .hk-drama-card__title a:hover {
+ color: var(--accent);
+}
+
+.hk-drama-card .hk-drama-card__genres {
+ display: block;
+ margin: -2px 0 0;
+ color: var(--text-dim);
+ font-size: 12px;
+ line-height: 18px;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+
+.hk-drama-card .hk-drama-card__genres a {
+ color: var(--text-muted);
+ transition: color 160ms ease;
+}
+
+.hk-drama-card .hk-drama-card__genres a:hover {
+ color: var(--accent);
+}
+
+.hk-drama-card .hk-drama-card__genre-sep {
+ margin: 0 5px;
+ color: rgba(255, 255, 255, 0.22);
+}
+
+@media (max-width: 768px) {
+ .hk-drama-card {
+ gap: 6px;
+ }
+
+ .hk-drama-card .hk-drama-card__eps {
+ right: 5px;
+ bottom: 5px;
+ gap: 1px;
+ max-width: calc(100% - 10px);
+ padding: 1px 5px 1px 4px;
+ font-size: 10px;
+ }
+
+ .hk-drama-card .hk-drama-card__eps::before {
+ width: 5px;
+ height: 5px;
+ margin-right: 3px;
+ }
+
+ .hk-drama-card .hk-drama-card__eps b {
+ font-size: 11px;
+ }
+
+ .hk-drama-card .hk-drama-card__title {
+ font-size: 14px;
+ line-height: 20px;
+ }
+
+ .hk-drama-card .hk-drama-card__genres {
+ font-size: 11px;
+ }
+
+ .hk-drama-card .hk-drama-card__genre-sep {
+ margin: 0 3px;
+ }
+}
diff --git a/src/styles/pages/playback.css b/src/styles/pages/playback.css
index c943b0e..5179194 100644
--- a/src/styles/pages/playback.css
+++ b/src/styles/pages/playback.css
@@ -1941,3 +1941,369 @@
border-radius: 12px;
}
}
+
+/* ===== 2026-10 播放页改版:主栏 + 右侧人气排行、信息表、EP 选集格、英文眉标题 ===== */
+:where(html[data-hk-page-styles~="playback"]) .hk-playback-body {
+ display: grid;
+ grid-template-columns: minmax(0, 1fr) 340px;
+ align-items: start;
+ gap: 28px;
+}
+
+:where(html[data-hk-page-styles~="playback"]) .hk-playback-body__main {
+ min-width: 0;
+ display: flex;
+ flex-direction: column;
+ gap: 20px;
+}
+
+:where(html[data-hk-page-styles~="playback"]) .hk-playback-body__aside {
+ position: sticky;
+ top: 92px;
+ min-width: 0;
+}
+
+:where(html[data-hk-page-styles~="playback"]) .hk-playback-body__aside .hk-playback-hot {
+ width: auto;
+}
+
+/* 面包屑:轻量文字链,当前项强调色 */
+:where(html[data-hk-page-styles~="playback"]) .hk-playback-breadcrumb .hk-breadcrumb__item {
+ color: var(--text-dim);
+}
+
+:where(html[data-hk-page-styles~="playback"]) .hk-playback-breadcrumb a.hk-breadcrumb__item:hover {
+ color: var(--text);
+}
+
+:where(html[data-hk-page-styles~="playback"]) .hk-playback-breadcrumb .hk-breadcrumb__item.hk-is-current {
+ color: var(--accent);
+}
+
+/* 区块标题:英文眉 + 中文标题,取代原竖条装饰 */
+:where(html[data-hk-page-styles~="playback"]) .hk-section-heading {
+ display: flex;
+ flex-direction: column;
+ gap: 2px;
+ min-width: 0;
+}
+
+:where(html[data-hk-page-styles~="playback"]) .hk-section-eyebrow {
+ display: inline-flex;
+ align-items: center;
+ gap: 6px;
+ color: var(--accent);
+ font-family: Inter, var(--font);
+ font-size: 10px;
+ font-weight: 700;
+ line-height: 14px;
+ letter-spacing: 2px;
+}
+
+:where(html[data-hk-page-styles~="playback"]) .hk-section-eyebrow::before {
+ width: 14px;
+ height: 1px;
+ background: currentColor;
+ content: "";
+}
+
+:where(html[data-hk-page-styles~="playback"]) :is(.hk-playback-synopsis__title, .hk-playback-episodes__title, .hk-playback-like__title, .hk-playback-hot__title, .hk-playback-related__title)::before {
+ display: none;
+}
+
+:where(html[data-hk-page-styles~="playback"]) :is(.hk-playback-synopsis__title, .hk-playback-episodes__title, .hk-playback-like__title, .hk-playback-hot__title, .hk-playback-related__title) {
+ margin: 0;
+ font-size: 18px;
+ font-weight: 600;
+ line-height: 26px;
+}
+
+:where(html[data-hk-page-styles~="playback"]) .hk-playback-synopsis__head,
+:where(html[data-hk-page-styles~="playback"]) .hk-playback-hot__head,
+:where(html[data-hk-page-styles~="playback"]) .hk-playback-like__head,
+:where(html[data-hk-page-styles~="playback"]) .hk-playback-related__head {
+ align-items: flex-end;
+}
+
+/* 信息区与选集面板:实色面板 + 顶部强调线,替代渐变卡片 */
+:where(html[data-hk-page-styles~="playback"]) .hk-playback-info,
+:where(html[data-hk-page-styles~="playback"]) .hk-playback-episodes {
+ background: var(--bg-elevated);
+ border: 1px solid var(--line-soft);
+ border-top: 2px solid var(--accent);
+ border-radius: 10px;
+}
+
+:where(html[data-hk-page-styles~="playback"]) .hk-playback-meta__eyebrow {
+ margin: 0;
+ display: inline-flex;
+ align-items: center;
+ gap: 8px;
+ color: var(--text-muted);
+ font-size: 13px;
+ line-height: 20px;
+}
+
+:where(html[data-hk-page-styles~="playback"]) .hk-playback-meta__eyebrow span {
+ padding: 1px 8px;
+ border-radius: 4px;
+ color: #ffffff;
+ font-size: 12px;
+ font-weight: 600;
+ background: var(--accent);
+}
+
+:where(html[data-hk-page-styles~="playback"]) .hk-playback-meta__title {
+ font-size: 26px;
+ line-height: 34px;
+ letter-spacing: 0.3px;
+}
+
+/* 信息表 */
+:where(html[data-hk-page-styles~="playback"]) .hk-playback-facts {
+ margin: 4px 0 0;
+ display: flex;
+ flex-wrap: wrap;
+ overflow: hidden;
+ border: 1px solid var(--line-soft);
+ border-radius: 8px;
+}
+
+:where(html[data-hk-page-styles~="playback"]) .hk-playback-facts__item {
+ flex: 1 1 112px;
+ min-width: 0;
+ margin: 0 -1px -1px 0;
+ padding: 9px 12px;
+ border-right: 1px solid var(--line-soft);
+ border-bottom: 1px solid var(--line-soft);
+}
+
+:where(html[data-hk-page-styles~="playback"]) .hk-playback-facts__item--wide {
+ flex-basis: 224px;
+}
+
+:where(html[data-hk-page-styles~="playback"]) .hk-playback-facts dt {
+ color: var(--text-dim);
+ font-size: 11px;
+ line-height: 16px;
+ letter-spacing: 1px;
+}
+
+:where(html[data-hk-page-styles~="playback"]) .hk-playback-facts dd {
+ margin: 2px 0 0;
+ color: var(--text);
+ font-size: 14px;
+ font-weight: 500;
+ line-height: 20px;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+
+:where(html[data-hk-page-styles~="playback"]) .hk-playback-facts dd[data-status="serial"] {
+ color: var(--success);
+}
+
+:where(html[data-hk-page-styles~="playback"]) .hk-playback-facts .hk-playback-meta__tag {
+ color: var(--text);
+}
+
+:where(html[data-hk-page-styles~="playback"]) .hk-playback-facts a.hk-playback-meta__tag:hover {
+ color: var(--accent);
+}
+
+/* 简介标题较长时,“展开”按钮保持单行不被挤压 */
+:where(html[data-hk-page-styles~="playback"]) .hk-playback-synopsis__head {
+ gap: 12px;
+}
+
+:where(html[data-hk-page-styles~="playback"]) .hk-playback-synopsis__more {
+ flex-shrink: 0;
+ white-space: nowrap;
+}
+
+/* 简介标签:描边胶囊,无井号 */
+:where(html[data-hk-page-styles~="playback"]) .hk-playback-synopsis {
+ border-top-style: solid;
+ border-top-color: var(--line-soft);
+}
+
+:where(html[data-hk-page-styles~="playback"]) .hk-playback-synopsis__tag {
+ padding: 2px 10px;
+ border: 1px solid var(--line);
+ border-radius: 999px;
+ background: transparent;
+}
+
+:where(html[data-hk-page-styles~="playback"]) .hk-playback-synopsis__tag::before {
+ content: none;
+}
+
+:where(html[data-hk-page-styles~="playback"]) a.hk-playback-synopsis__tag:hover {
+ border-color: rgba(255, 15, 83, 0.5);
+ background: transparent;
+ color: var(--accent);
+}
+
+/* EP 选集格:上方小号 EP,下方两位集号;当前集为描边强调 */
+:where(html[data-hk-page-styles~="playback"]) .hk-playback-episodes__grid {
+ display: grid;
+ grid-template-columns: repeat(auto-fill, minmax(64px, 1fr));
+ gap: 8px;
+}
+
+:where(html[data-hk-page-styles~="playback"]) .hk-playback-ep {
+ width: auto;
+ height: 54px;
+ flex-direction: column;
+ gap: 1px;
+ border-radius: 6px;
+ border: 1px solid var(--line-soft);
+ background: rgba(255, 255, 255, 0.03);
+ transition: border-color 160ms ease, background 160ms ease;
+}
+
+:where(html[data-hk-page-styles~="playback"]) .hk-playback-ep__label {
+ color: var(--text-dim);
+ font-family: Inter, var(--font);
+ font-size: 9px;
+ font-weight: 700;
+ line-height: 12px;
+ letter-spacing: 1.5px;
+}
+
+:where(html[data-hk-page-styles~="playback"]) .hk-playback-ep__num {
+ font-family: Inter, var(--font);
+ font-size: 17px;
+ font-weight: 700;
+ line-height: 20px;
+}
+
+:where(html[data-hk-page-styles~="playback"]) a.hk-playback-ep:hover {
+ border-color: rgba(255, 255, 255, 0.25);
+}
+
+:where(html[data-hk-page-styles~="playback"]) .hk-playback-ep.hk-is-active {
+ color: var(--accent);
+ background: rgba(255, 15, 83, 0.08);
+ border-color: var(--accent);
+ box-shadow: none;
+}
+
+:where(html[data-hk-page-styles~="playback"]) .hk-playback-ep.hk-is-active .hk-playback-ep__label {
+ color: var(--accent);
+}
+
+/* 主栏内的相似短剧网格 */
+:where(html[data-hk-page-styles~="playback"]) .hk-playback-body__main > .hk-playback-like {
+ padding: 4px 0 0;
+}
+
+:where(html[data-hk-page-styles~="playback"]) .hk-playback-body__main .hk-playback-like__grid {
+ display: grid;
+ grid-template-columns: repeat(6, minmax(0, 1fr));
+ gap: 20px 14px;
+}
+
+:where(html[data-hk-page-styles~="playback"]) .hk-playback-body__main .hk-drama-card--play {
+ width: auto;
+ min-width: 0;
+}
+
+/* 人气排行:大号斜体序号,前三名渐变字 */
+:where(html[data-hk-page-styles~="playback"]) .hk-playback-hot {
+ border-radius: 10px;
+ border: 1px solid var(--line-soft);
+}
+
+:where(html[data-hk-page-styles~="playback"]) .hk-playback-hot__no {
+ width: 28px;
+ height: auto;
+ margin-right: 0;
+ color: var(--text-dim);
+ font-family: Inter, var(--font);
+ font-size: 20px;
+ font-style: italic;
+ font-weight: 800;
+ background: none;
+}
+
+:where(html[data-hk-page-styles~="playback"]) .hk-playback-hot__no.hk-is-top {
+ color: transparent;
+ background: linear-gradient(135deg, var(--gold), var(--accent));
+ -webkit-background-clip: text;
+ background-clip: text;
+}
+
+@media (max-width: 1100px) {
+ :where(html[data-hk-page-styles~="playback"]) .hk-playback-body {
+ grid-template-columns: minmax(0, 1fr) 300px;
+ gap: 20px;
+ }
+
+ :where(html[data-hk-page-styles~="playback"]) .hk-playback-body__main .hk-playback-like__grid {
+ grid-template-columns: repeat(4, minmax(0, 1fr));
+ }
+}
+
+@media (max-width: 768px) {
+ :where(html[data-hk-page-styles~="playback"]) .hk-playback-body {
+ display: flex;
+ flex-direction: column;
+ align-items: stretch;
+ gap: 16px;
+ }
+
+ :where(html[data-hk-page-styles~="playback"]) .hk-playback-body__aside {
+ position: static;
+ }
+
+ :where(html[data-hk-page-styles~="playback"]) .hk-playback-body__aside .hk-playback-hot {
+ margin: 0 var(--h5-gutter);
+ }
+
+ :where(html[data-hk-page-styles~="playback"]) .hk-playback-body__main > .hk-playback-like {
+ padding: 0 var(--h5-gutter);
+ }
+
+ :where(html[data-hk-page-styles~="playback"]) .hk-playback-body__main .hk-playback-like__grid {
+ grid-template-columns: repeat(3, minmax(0, 1fr));
+ gap: 14px 8px;
+ }
+
+ :where(html[data-hk-page-styles~="playback"]) .hk-playback-meta__title {
+ font-size: 20px;
+ line-height: 28px;
+ }
+
+ :where(html[data-hk-page-styles~="playback"]) .hk-playback-facts__item {
+ flex-basis: 30%;
+ padding: 7px 10px;
+ }
+
+ :where(html[data-hk-page-styles~="playback"]) .hk-playback-facts__item--wide {
+ flex-basis: 60%;
+ }
+
+ :where(html[data-hk-page-styles~="playback"]) .hk-playback-facts dd {
+ font-size: 13px;
+ }
+
+ :where(html[data-hk-page-styles~="playback"]) .hk-playback-episodes__grid {
+ grid-template-columns: repeat(5, minmax(0, 1fr));
+ gap: 6px;
+ }
+
+ :where(html[data-hk-page-styles~="playback"]) .hk-playback-ep {
+ height: 46px;
+ }
+
+ :where(html[data-hk-page-styles~="playback"]) .hk-playback-ep__num {
+ font-size: 15px;
+ }
+
+ :where(html[data-hk-page-styles~="playback"]) :is(.hk-playback-synopsis__title, .hk-playback-episodes__title, .hk-playback-like__title, .hk-playback-hot__title, .hk-playback-related__title) {
+ font-size: 16px;
+ line-height: 24px;
+ }
+}
diff --git a/tests/catalog-react.test.tsx b/tests/catalog-react.test.tsx
index 9498f17..f8accaa 100644
--- a/tests/catalog-react.test.tsx
+++ b/tests/catalog-react.test.tsx
@@ -57,9 +57,14 @@ test("React card variants preserve watch URLs, episode gates, badges and linked
card,
/href="\/drama\/都市%20剧\/"|href="\/drama\/%E9%83%BD%E5%B8%82%20%E5%89%A7\/"/,
);
+ // Episode count and serial state sit in the cover corner; the line under the title lists genres.
assert.match(
card,
- /连载 · 8 集<\/span>/,
+ /8<\/b> 集 · 连更<\/span><\/a>/,
+ );
+ assert.match(
+ card,
+ /爱情<\/a>\/<\/span>/,
);
assert.doesNotMatch(card, /hk-drama-card__ep"/);
assert.match(card, /hk-badge hk-badge--hot/);
@@ -72,7 +77,7 @@ test("React card variants preserve watch URLs, episode gates, badges and linked
,
);
assert.match(recommendation, /hk-drama-card hk-drama-card--play/);
- assert.match(recommendation, /hk-drama-card__meta-ep" data-status="serial">连载 · 8 集);
+ assert.match(recommendation, /hk-drama-card__eps" data-status="serial">8<\/b> 集 · 连更);
assert.doesNotMatch(recommendation, /hk-badge--hot/);
const video = renderToStaticMarkup(
+ link.href.startsWith("/drama/") && coverBadge.test(link.text)
+ ? { ...link, text: "" }
+ : link,
+ ),
anchors(expected).map((link) =>
link.href.startsWith("/drama/") && coverEpisode.test(link.text)
? { ...link, text: "" }
@@ -112,7 +117,7 @@ test("React tags and list pages preserve the original Go catalog content and nav
name + " ad placement",
);
assert.match(actual, /花魁 & 第一部/);
- assert.match(actual, /完结 · 4 集<\/span>/);
+ assert.match(actual, /4<\/b> 集 · 完结<\/span>/);
}
});