diff --git a/assets/css/core/tokens.css b/assets/css/core/tokens.css
index 34964f6e..ab73d485 100644
--- a/assets/css/core/tokens.css
+++ b/assets/css/core/tokens.css
@@ -103,7 +103,7 @@
--container-wide: 1440px;
--container-read: 760px;
--container-page: 880px;
- --sidebar-width: 300px;
+ --sidebar-width: 311px;
--content-gap: 24px;
--section-gap: 24px;
--sidebar-bp: 992px;
diff --git a/assets/css/frontend/base.css b/assets/css/frontend/base.css
index ebc1807f..6c289d27 100644
--- a/assets/css/frontend/base.css
+++ b/assets/css/frontend/base.css
@@ -72,22 +72,83 @@ a[href] {
flex: 1;
}
-.container {
+/* Zibll dual-column float math expects a padding-free main.container.
+ * Bootstrap 5 also defines .container (max-width ladder + padding-x).
+ * Force Zibll geometry after Bootstrap so negative-margin sidebars land correctly. */
+.container,
+main.container,
+.site-main.container {
width: 100%;
- max-width: var(--container);
- margin: 0 auto;
- padding: 0 16px;
+ max-width: var(--container, var(--mian-max-width, 1200px));
+ margin-right: auto;
+ margin-left: auto;
+ padding-right: 0;
+ padding-left: 0;
+ /* Kill Bootstrap 5 --bs-gutter-x padding model on site shells */
+ --bs-gutter-x: 0;
+ --bs-gutter-y: 0;
+}
+
+@media (min-width: 576px) {
+ .container,
+ main.container {
+ max-width: var(--container, var(--mian-max-width, 1200px));
+ }
}
@media (min-width: 768px) {
- .container {
- padding: 0 24px;
+ .container,
+ main.container {
+ max-width: var(--container, var(--mian-max-width, 1200px));
+ }
+}
+
+@media (min-width: 992px) {
+ .container,
+ main.container {
+ max-width: var(--container, var(--mian-max-width, 1200px));
}
}
@media (min-width: 1200px) {
- .container {
- padding: 0 32px;
+ .container,
+ main.container {
+ max-width: var(--container, var(--mian-max-width, 1200px));
+ }
+}
+
+@media (min-width: 1240px) {
+ .container,
+ main.container,
+ .fluid-widget-wrap .widget-container {
+ width: auto;
+ max-width: var(--container, var(--mian-max-width, 1200px));
+ }
+}
+
+@media (min-width: 1400px) {
+ .container,
+ main.container {
+ max-width: var(--container, var(--mian-max-width, 1200px));
+ }
+}
+
+/* Soft pad only when the float dual-column is collapsed */
+@media (max-width: 991.98px) {
+ .container,
+ main.container {
+ padding-right: 10px;
+ padding-left: 10px;
+ }
+}
+
+@media (max-width: 767px) {
+ .container,
+ main.container {
+ width: 100%;
+ max-width: 100%;
+ padding-right: 10px;
+ padding-left: 10px;
}
}
diff --git a/assets/css/frontend/breadcrumb.css b/assets/css/frontend/breadcrumb.css
index f00800a9..43d855da 100644
--- a/assets/css/frontend/breadcrumb.css
+++ b/assets/css/frontend/breadcrumb.css
@@ -1,12 +1,17 @@
-/* ========== 面包屑导航 — 对齐 zibll breadcrumb ========== */
-.breadcrumb-nav,
+/* ========== 面包屑导航 — 对齐 zibll .breadcrumb (main.css) ========== */
+/* Single source for breadcrumb chrome. Do not re-define in layout.css. */
+
+.breadcrumb,
ul.breadcrumb,
+.breadcrumb-nav,
.breadcrumbs-wrap {
+ background: transparent;
font-size: 13px;
padding: 0 8px;
- margin-bottom: 12px;
+ margin: 0 0 12px;
opacity: 0.6;
line-height: 1.8;
+ list-style: none;
}
.breadcrumb-nav ol,
@@ -16,90 +21,98 @@ ul.breadcrumb,
list-style: none;
margin: 0;
padding: 0;
- display: flex;
- flex-wrap: wrap;
- align-items: center;
- gap: 0;
+ display: block;
}
-.breadcrumb-nav li,
+/* Zibll uses flat li + li:before separators (not flex-gap nodes) */
+.breadcrumb > li,
ul.breadcrumb > li,
+.breadcrumb-nav li,
.breadcrumbs.breadcrumb > li {
- display: inline-flex;
- align-items: center;
+ display: inline;
}
-/* Zibll flat ul.breadcrumb inserts parents with "
" — separators via content */
-.breadcrumb-nav li + li::before,
-ul.breadcrumb > li + li::before {
- content: '/';
- padding: 0 6px 0 6px;
+.breadcrumb > li + li:before,
+ul.breadcrumb > li + li:before,
+.breadcrumb-nav li + li:before {
+ content: "/";
+ padding: 0 0 0 6px;
opacity: 0.6;
}
+/* Archive/nav variant may still stamp sep nodes — keep neutral */
.breadcrumbs.breadcrumb .breadcrumbs__sep {
padding: 0 6px;
opacity: 0.6;
}
-.breadcrumb-nav a,
+.breadcrumb a,
ul.breadcrumb a,
+.breadcrumb-nav a,
.breadcrumbs a {
- color: var(--color-ink-4, #999);
+ color: var(--muted-2-color, var(--color-ink-4, #999));
text-decoration: none;
transition: color 0.2s;
}
-.breadcrumb-nav a:hover,
+.breadcrumb a:hover,
ul.breadcrumb a:hover,
+.breadcrumb-nav a:hover,
.breadcrumbs a:hover {
- color: var(--color-primary, #f04494);
+ color: var(--focus-color, var(--color-primary, #f04494));
}
-.breadcrumb-nav .current,
+.breadcrumb > li:last-child,
ul.breadcrumb > li:last-child,
+.breadcrumb-nav .current,
.breadcrumbs__item.is-current {
- color: var(--color-ink-2, #4e5358);
- font-weight: 500;
+ color: var(--main-color, var(--color-ink-2, #4e5358));
}
-.single-cover-con .breadcrumb-nav,
+/* Cover / video footer breadcrumb — Zibll single-cover-con / single-video */
.single-cover-con .breadcrumb,
.single-cover-con ul.breadcrumb,
-.post-breadcrumbs .breadcrumb {
+.single-cover-con .breadcrumb-nav,
+.post-breadcrumbs .breadcrumb,
+.single-video .breadcrumb {
font-size: 13px;
margin: 5px 0 0 -6px;
opacity: unset;
padding: 0;
+ background: transparent;
}
-/* 封面内面包屑 */
-.single-cover-con .breadcrumb-nav,
+.single-video .breadcrumb {
+ padding: 0;
+}
+
+.single-cover-con .breadcrumb,
.single-cover-con ul.breadcrumb,
-.single-cover-con .breadcrumb {
+.single-cover-con .breadcrumb-nav {
color: rgba(255, 255, 255, 0.85);
}
-.single-cover-con .breadcrumb-nav a,
+.single-cover-con .breadcrumb a,
.single-cover-con ul.breadcrumb a,
-.single-cover-con .breadcrumb a {
+.single-cover-con .breadcrumb-nav a {
color: rgba(255, 255, 255, 0.85);
}
-.single-cover-con .breadcrumb-nav a:hover,
-.single-cover-con ul.breadcrumb a:hover {
+.single-cover-con .breadcrumb a:hover,
+.single-cover-con ul.breadcrumb a:hover,
+.single-cover-con .breadcrumb-nav a:hover {
color: #fff;
}
-.single-cover-con .breadcrumb-nav .current,
+.single-cover-con .breadcrumb > li:last-child,
.single-cover-con ul.breadcrumb > li:last-child {
color: #fff;
}
-/* 移动端 */
@media (max-width: 767px) {
- .breadcrumb-nav,
+ .breadcrumb,
ul.breadcrumb,
+ .breadcrumb-nav,
.breadcrumbs-wrap {
font-size: 12px;
}
diff --git a/assets/css/frontend/card-primitives.css b/assets/css/frontend/card-primitives.css
index 351837a0..b7bc4c1d 100644
--- a/assets/css/frontend/card-primitives.css
+++ b/assets/css/frontend/card-primitives.css
@@ -73,22 +73,17 @@
/* ============================================================
* Zibll 兼容别名
* ============================================================ */
-.theme-box {
- background: var(--surface-1);
- border: none;
- border-radius: var(--radius, 8px);
- box-shadow: var(--shadow-sm);
+/* Zibll .theme-box is ONLY a spacing utility (margin-bottom: 20px).
+ * Background/shadow live on .main-bg / .main-shadow / .box-bg / .zib-widget.
+ * Do NOT turn every theme-box into a card — article-header also uses it. */
+.theme-box,
+.mb20 {
margin-bottom: 20px;
- transition: box-shadow 0.2s ease;
-}
-
-.theme-box:hover {
- box-shadow: var(--shadow);
}
.box-bg {
- background-color: var(--surface-1);
- box-shadow: var(--shadow-sm);
+ background-color: var(--main-bg-color, var(--surface-1));
+ box-shadow: 0 0 10px var(--main-shadow, rgba(116, 116, 116, 0.08));
}
.box-body {
@@ -109,7 +104,11 @@
}
.main-shadow {
- box-shadow: var(--shadow);
+ box-shadow: 0 0 10px var(--main-shadow, rgba(116, 116, 116, 0.08));
+}
+
+.main-bg {
+ background: var(--main-bg-color, var(--surface-1));
}
.muted-box {
@@ -123,26 +122,21 @@
* ============================================================ */
html.dark .aksrt-theme-box,
body.dark-theme .aksrt-theme-box,
-html.dark .theme-box,
-body.dark-theme .theme-box,
html.dark .box-bg,
body.dark-theme .box-bg {
border-color: transparent;
- box-shadow: var(--shadow-sm);
+ box-shadow: 0 0 10px var(--main-shadow, rgba(0, 0, 0, 0.2));
}
html.dark .aksrt-theme-box:hover,
-body.dark-theme .aksrt-theme-box:hover,
-html.dark .theme-box:hover,
-body.dark-theme .theme-box:hover {
- box-shadow: var(--shadow);
+body.dark-theme .aksrt-theme-box:hover {
+ box-shadow: 0 0 10px var(--main-shadow, rgba(0, 0, 0, 0.28));
}
/* ============================================================
* 卡片 hover 动效
* ============================================================ */
-.aksrt-theme-box,
-.theme-box {
+.aksrt-theme-box {
transition: box-shadow var(--dur) var(--ease), transform var(--dur) var(--ease);
}
diff --git a/assets/css/frontend/layout.css b/assets/css/frontend/layout.css
index fb94e5b7..730151d4 100644
--- a/assets/css/frontend/layout.css
+++ b/assets/css/frontend/layout.css
@@ -1,63 +1,4 @@
-/* ========== 面包屑 — 对齐 zibll .breadcrumb ========== */
-.breadcrumbs-wrap {
- margin-bottom: 18px;
-}
-
-.breadcrumbs {
- display: flex;
- align-items: center;
- flex-wrap: wrap;
- gap: 0;
- margin: 0;
- padding: 0;
- list-style: none;
- font-size: 13px;
- color: var(--muted-2-color, #999);
- opacity: 0.8;
-}
-
-.breadcrumbs__item {
- display: inline-flex;
- align-items: center;
- min-width: 0;
-}
-
-.breadcrumbs__item a,
-.breadcrumbs__item span {
- display: inline-flex;
- align-items: center;
- gap: 6px;
-}
-
-.breadcrumbs a {
- color: var(--muted-2-color, #999);
-}
-
-.breadcrumbs a:hover {
- color: var(--focus-color, #f04494);
-}
-
-.breadcrumbs__sep {
- margin: 0 0 0 6px;
- opacity: 0.6;
-}
-
-@media (max-width: 767px) {
- .breadcrumbs {
- font-size: 12px;
- }
-
- .breadcrumbs-wrap {
- margin-bottom: 14px;
- }
-}
-
-/* 封面内面包屑 */
-.single-cover-con .breadcrumbs {
- font-size: 13px;
- margin: 5px 0 0 -6px;
- opacity: unset;
-}
+/* Breadcrumb chrome lives in breadcrumb.css (single source). */
/* ========== 主布局 ========== */
.content-main {
@@ -149,8 +90,16 @@ main.content-shell::after,
max-width: 100%;
}
-.content-layout__aside,
+/* Base sidebar column (Zibll .sidebar defaults) — layout variants override below */
.sidebar {
+ float: left;
+ width: var(--sidebar-width, 311px);
+ min-width: 0;
+ position: relative;
+ box-sizing: border-box;
+}
+
+.content-layout__aside {
min-width: 0;
}
@@ -171,7 +120,7 @@ body.site-layout-1 .content-layout--no-sidebar {
margin-right: 0 !important;
}
-/* Sidebar RIGHT (layout 2) — Zibll default */
+/* Sidebar RIGHT (layout 2) — Zibll main.css 1:1 */
body.site-layout-2 .content-layout {
margin-right: calc(var(--sidebar-width, 311px) + 15px);
margin-left: 0;
@@ -181,10 +130,11 @@ body.site-layout-2 .sidebar {
float: left;
width: var(--sidebar-width, 311px);
margin-left: calc(0px - var(--sidebar-width, 311px));
- position: relative;
+ /* Zibll uses position:unset so sticky children aren't trapped */
+ position: unset;
}
-/* Sidebar LEFT (layout 3) */
+/* Sidebar LEFT (layout 3) — Zibll main.css 1:1 */
body.site-layout-3 .content-layout {
margin-left: calc(var(--sidebar-width, 311px) + 15px);
margin-right: unset;
@@ -194,7 +144,7 @@ body.site-layout-3 .sidebar {
float: left;
width: var(--sidebar-width, 311px);
margin-left: -100%;
- position: relative;
+ position: unset;
}
/* Sticky widgets inside sidebar */
diff --git a/assets/css/frontend/sidebar.css b/assets/css/frontend/sidebar.css
index 0fa51c46..bad458dd 100644
--- a/assets/css/frontend/sidebar.css
+++ b/assets/css/frontend/sidebar.css
@@ -156,13 +156,8 @@
margin-bottom: 12px;
}
-/* 侧边栏响应式 */
-@media (max-width: 1200px) {
- .sidebar {
- width: 280px;
- }
-}
-
+/* 侧边栏响应式 — width/float 由 layout.css 的 --sidebar-width + site-layout-* 拥有。
+ * 禁止在这里硬编码 280px(会与 content-layout gutter 失配导致叠层/空隙)。 */
@media (max-width: 991px) {
.sidebar {
display: none;
diff --git a/assets/css/frontend/single-post/author-actions.css b/assets/css/frontend/single-post/author-actions.css
index 5ee72529..f7f465ef 100644
--- a/assets/css/frontend/single-post/author-actions.css
+++ b/assets/css/frontend/single-post/author-actions.css
@@ -457,10 +457,14 @@ html.dark .post-drop-meta__item:hover {
width: 100%;
}
+.article-avatar .avatar-img {
+ --this-size: 42px;
+}
+
.article-avatar .avatar-img img,
.article-avatar .avatar {
- width: 42px;
- height: 42px;
+ width: 100%;
+ height: 100%;
border-radius: 50%;
object-fit: cover;
}
@@ -472,6 +476,8 @@ html.dark .post-drop-meta__item:hover {
.article-header .article-avatar .relative {
margin-top: 20px;
+ position: relative;
+ min-height: 1px;
}
.single-metabox {
@@ -514,11 +520,9 @@ html.dark .post-drop-meta__item:hover {
--body-bg-color: rgba(0, 0, 0, 0.3);
}
-.line-form-line {
+/* line-form-line owned by zibll-utilities.css — only context here */
+.article-avatar .line-form-line {
display: block;
- height: 1px;
- background: var(--main-border-color, rgba(50,50,50,.06));
- margin: 12px 0 0;
}
.post-actions {
diff --git a/assets/css/frontend/single-post/content.css b/assets/css/frontend/single-post/content.css
index 17ee09d5..bbf616d0 100644
--- a/assets/css/frontend/single-post/content.css
+++ b/assets/css/frontend/single-post/content.css
@@ -1,9 +1,34 @@
/* ========== Single Post ========== */
+
+/* Zibll .article — card body padding wins over .box-body (main.css order) */
+.article,
+article.article.box-body,
+.article.main-bg.box-body {
+ padding: 0 30px;
+ overflow: hidden;
+}
+
+@media (max-width: 767px) {
+ .article,
+ article.article.box-body,
+ .article.main-bg.box-body {
+ padding: 0 15px;
+ }
+
+ .article-header .article-title {
+ font-size: 18px;
+ }
+}
+
.entry-header,
.article-header {
margin-bottom: 10px;
padding-bottom: 0;
border-bottom: none;
+ /* theme-box is spacing only — never paint a nested card here */
+ background: transparent;
+ box-shadow: none;
+ border-radius: 0;
}
/* 标题 — 对齐 zibll: 22px, bold, line-height 1.4 */
@@ -17,6 +42,10 @@
color: var(--key-color, var(--color-ink));
}
+.article-title > a:hover {
+ color: inherit;
+}
+
.article-header .article-title {
font-size: 22px;
font-weight: bold;
diff --git a/assets/css/frontend/single-post/cover.css b/assets/css/frontend/single-post/cover.css
index f37a4a2f..eb863168 100644
--- a/assets/css/frontend/single-post/cover.css
+++ b/assets/css/frontend/single-post/cover.css
@@ -3,14 +3,20 @@
* The cover stays inside the content column with a fixed aspect ratio box.
* ============================================================ */
-/* ===== Cover (in-column ratio box) ===== */
+/* ===== Cover (in-column ratio box) — Zibll .single-cover ===== */
.single-cover {
position: relative;
overflow: hidden;
- border-radius: var(--radius-2xl, 16px);
- box-shadow: var(--shadow-sm);
+ border-radius: var(--main-radius, var(--radius, 8px));
+ box-shadow: 0 0 10px var(--main-shadow, rgba(116, 116, 116, 0.08));
margin-bottom: 20px;
- padding-bottom: var(--single-cover-scale, 35%);
+ /* Zibll: padding-bottom: calc(var(--single-cover-scale) + 50px) */
+ padding-bottom: calc(var(--single-cover-scale, 35%) + 50px);
+}
+
+.single-cover-slide {
+ padding-bottom: calc(var(--scale-height, var(--single-cover-scale, 35%)) + 50px);
+ border-radius: var(--main-radius, var(--radius, 8px));
}
.single-cover > .fit-cover,
@@ -22,6 +28,25 @@
object-fit: cover;
}
+.single-cover-con {
+ color: #fff;
+ padding: 15px 15px 10px 15px;
+ border-radius: 0 0 var(--main-radius, var(--radius, 8px)) var(--main-radius, var(--radius, 8px));
+ background-image: linear-gradient(0deg, rgba(29, 41, 49, 0.5), rgba(255, 255, 255, 0));
+ padding-top: 2em;
+}
+
+.single-cover-con a {
+ color: #fff;
+}
+
+.single-video .article-title,
+.single-cover-con .article-title {
+ font-size: 18px;
+ font-weight: 700;
+}
+
+/* Legacy overlay helpers (kept for non-zibll markup) */
.single-cover__overlay {
position: absolute;
inset: 0;
@@ -40,7 +65,7 @@
right: 0;
padding: 24px;
color: #fff;
- border-radius: 0 0 var(--radius-2xl, 16px) var(--radius-2xl, 16px);
+ border-radius: 0 0 var(--main-radius, var(--radius, 8px)) var(--main-radius, var(--radius, 8px));
}
.single-cover__title,
@@ -155,23 +180,13 @@
position: relative;
}
-.article-avatar .line-form-line,
-.article-avatar .line-form-line::before {
- position: absolute;
- top: 50%;
- left: calc(52px + 16px);
- right: 120px;
- height: 1px;
- transform: translateY(-50%);
- background: var(--color-line);
-}
-
-.article-avatar .line-form-line::before {
- content: "";
- right: auto;
- width: 42px;
- background: var(--color-primary, #f04494);
- opacity: 0.3;
+/* line-form-line geometry owned by zibll-utilities.css (absolute full-width bottom).
+ * Here only ensure the meta row has height so the rule sits correctly. */
+.article-header .article-avatar .relative {
+ margin-top: 20px;
+ position: relative;
+ min-height: 1px;
+ padding-bottom: 1px;
}
/* ===== Article Card ===== */
@@ -253,11 +268,11 @@
.single-cover-slide-wrap {
position: relative;
overflow: hidden;
- border-radius: var(--radius-2xl, 16px);
+ border-radius: var(--main-radius, var(--radius, 8px));
}
.single-cover-slide-wrap .abs-center.left-bottom {
z-index: 2;
- padding: 18px 20px;
+ padding: 15px 15px 10px 15px;
color: #fff;
}
.article-avatar name.flex {
@@ -277,11 +292,23 @@
/* Slide cover overlay (injected by aksrt_render_slider overlay_html) */
.aksrt-slider-wrapper--has-overlay,
-.aksrt-slider-wrapper--scale { position: relative; overflow: hidden; border-radius: var(--radius-2xl, 16px); }
+.aksrt-slider-wrapper--scale {
+ position: relative;
+ overflow: hidden;
+ border-radius: var(--main-radius, var(--radius, 8px));
+}
.aksrt-slider-wrapper--scale .new-swiper { position: absolute; inset: 0; width: 100%; height: 100%; }
.aksrt-slider-wrapper--scale .swiper-slide img.fit-cover { width: 100%; height: 100%; object-fit: cover; }
.aksrt-slider-overlay { position: absolute; inset: 0; z-index: 3; pointer-events: none; }
-.aksrt-slider-overlay .abs-center.left-bottom { pointer-events: none; padding: 18px 20px; color: #fff; }
+.aksrt-slider-overlay .abs-center.left-bottom {
+ pointer-events: none;
+ padding: 15px 15px 10px 15px;
+ color: #fff;
+ background-image: linear-gradient(0deg, rgba(29, 41, 49, 0.5), rgba(255, 255, 255, 0));
+ padding-top: 2em;
+ width: 100%;
+ box-sizing: border-box;
+}
.aksrt-slider-overlay .article-title,
.aksrt-slider-overlay .article-title.title-h-left { color: #fff; text-shadow: 0 1px 4px rgba(0,0,0,.45); }
.aksrt-slider-overlay .breadcrumb a,
diff --git a/assets/css/frontend/single-post/shell.css b/assets/css/frontend/single-post/shell.css
index 359b6e04..27349db9 100644
--- a/assets/css/frontend/single-post/shell.css
+++ b/assets/css/frontend/single-post/shell.css
@@ -25,7 +25,7 @@ body.single main.container .content-layout > .breadcrumbs-wrap {
padding-top: 2px;
}
-/* Sticky TOC widget in sidebar */
+/* Sticky TOC widget in sidebar — parent .sidebar is position:unset like Zibll */
body.single .sidebar .posts-nav-box.toc-widget {
position: sticky;
top: calc(var(--nav-height, 60px) + 16px);
@@ -35,3 +35,8 @@ body.single .sidebar .zib-widget,
body.single .sidebar .widget {
margin-bottom: 15px;
}
+
+/* Geometry owned by base/layout — keep single shell free of float overrides. */
+body.single main.container {
+ box-sizing: border-box;
+}
diff --git a/assets/css/frontend/zibll-utilities.css b/assets/css/frontend/zibll-utilities.css
index c913eff9..1bf25ea2 100644
--- a/assets/css/frontend/zibll-utilities.css
+++ b/assets/css/frontend/zibll-utilities.css
@@ -49,6 +49,132 @@
transform: translate(-50%, -50%);
}
+/* Zibll abs-center position variants (main.css) */
+.abs-center.left-bottom,
+.abs-center.right-bottom,
+.abs-center.conter-bottom {
+ top: auto;
+ transform: unset;
+ bottom: 0;
+}
+
+.abs-center.left-bottom {
+ left: 0;
+ right: auto;
+ text-align: left;
+}
+
+.abs-center.right-bottom,
+.abs-center.right-conter {
+ left: auto;
+ right: 0;
+ text-align: right;
+}
+
+/* Graphic ratio box (cover / related thumbs) — Zibll .graphic */
+.graphic,
+.page-cover {
+ text-shadow: 0 0 5px rgba(0, 0, 0, 0.2);
+ --main-color: #fff;
+ color: #fff;
+ position: relative;
+ overflow: hidden;
+ box-shadow: 0 0 10px var(--main-shadow, rgba(116, 116, 116, 0.08));
+ padding: 0;
+ padding-bottom: 70%;
+ border-radius: var(--main-radius, var(--radius, 8px));
+}
+
+.graphic > .fit-cover,
+.graphic > img.fit-cover {
+ position: absolute;
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+ inset: 0;
+}
+
+.fit-cover {
+ object-fit: cover;
+ max-width: 100%;
+}
+
+/* title-h-left underline bar (Zibll) */
+.title-h-left {
+ position: relative;
+ padding-bottom: 8px;
+}
+
+.title-h-left:before {
+ transition: 0.4s;
+ transform-origin: left;
+ position: absolute;
+ content: "";
+ width: 40px;
+ height: 3px;
+ background: var(--theme-color, var(--focus-color, #f04494));
+ left: 0;
+ bottom: 3px;
+ border-radius: 5px;
+ box-shadow: 1px 1px 3px -1px var(--theme-color, var(--focus-color, #f04494));
+}
+
+/* line-form-line — Zibll absolute bottom rule (author meta separator) */
+.line-form-line,
+.line-form-line:before {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ height: 1px;
+ width: 100%;
+ transition: 0.8s;
+ background: var(--main-border-color, rgba(50, 50, 50, 0.06));
+}
+
+.line-form-line:before {
+ content: "";
+ width: 0;
+ background: var(--focus-color, #f04494);
+}
+
+/* Avatar size primitive */
+.avatar-img {
+ position: relative;
+ display: inline-block;
+ flex-shrink: 0;
+ --this-size: 38px;
+ width: var(--this-size);
+ height: var(--this-size);
+}
+
+.avatar-img .avatar,
+.avatar-img img {
+ width: 100%;
+ height: 100%;
+ border-radius: 50%;
+ object-fit: cover;
+}
+
+.avatar-lg {
+ --this-size: 80px;
+}
+
+.avatar-md {
+ --this-size: 55px;
+}
+
+.avatar-mini {
+ --this-size: 20px;
+}
+
+.shrink0 {
+ flex-shrink: 0;
+}
+
+.opacity8 {
+ opacity: 0.8;
+}
+
/* Typography / color helpers */
.muted-color { color: var(--muted-color, var(--color-ink-3)); }
.muted-2-color { color: var(--muted-2-color, var(--color-ink-4)); }
diff --git a/inc/bootstrap.php b/inc/bootstrap.php
index 73278505..7571b587 100644
--- a/inc/bootstrap.php
+++ b/inc/bootstrap.php
@@ -29,6 +29,7 @@ require_once AKSRT_DIR . '/inc/helpers/aksrt-flow.php';
require_once AKSRT_DIR . '/inc/helpers/aksrt-homepage.php';
require_once AKSRT_DIR . '/inc/helpers/aksrt-single-components.php';
require_once AKSRT_DIR . '/inc/helpers/aksrt-single.php';
+require_once AKSRT_DIR . '/inc/helpers/aksrt-single-render.php';
require_once AKSRT_DIR . '/inc/helpers/aksrt-archive.php';
require_once AKSRT_DIR . '/inc/helpers/aksrt-archive-filters.php';
require_once AKSRT_DIR . '/inc/helpers/aksrt-comments.php';
diff --git a/inc/helpers/aksrt-single-render.php b/inc/helpers/aksrt-single-render.php
new file mode 100644
index 00000000..3de983cf
--- /dev/null
+++ b/inc/helpers/aksrt-single-render.php
@@ -0,0 +1,812 @@
+ $ctx Single context.
+ */
+ function aksrt_single_render_cover(array $ctx): void {
+ if (empty($ctx['show_cover']) || $ctx['cover_url'] === '') {
+ return;
+ }
+
+ $type = (string) $ctx['cover_type'];
+ $badge = (string) $ctx['status_badge'];
+ $crumbs = (string) $ctx['breadcrumbs_html'];
+ $meta_box = (string) ($ctx['meta_box_html'] ?? '');
+ $img_scale = max(10, min(100, (int) $ctx['img_scale']));
+ $video_scale = max(20, min(100, (int) $ctx['video_scale']));
+ $episode = (int) $ctx['episode_count'];
+ $slides = is_array($ctx['slide_images'] ?? null) ? $ctx['slide_images'] : [];
+ $poster = (string) ($ctx['video_poster'] ?? '');
+ $title_html = (string) ($ctx['title_html'] ?? esc_html(get_the_title()));
+
+ if ($type === 'video') :
+ ?>
+
+
+
+
style="position:absolute;inset:0;width:100%;height:100%;">
+
+
+
+
+ (string) $slide_url,
+ 'alt' => wp_strip_all_tags(get_the_title()),
+ ];
+ }
+ $overlay = ''
+ . '
' . $title_html . '
'
+ . ($crumbs !== '' ? $crumbs : '')
+ . $badge
+ . ''
+ . ($meta_box !== '' ? str_replace('abs-right', 'cover-meta abs-right', $meta_box) : '');
+ $slider_html = '';
+ if (function_exists('aksrt_render_slider')) {
+ $slider_html = aksrt_render_slider([
+ 'slides' => $slide_items,
+ 'scale_height' => true,
+ 'scale_ratio' => $img_scale / 100,
+ 'wrapper_class' => 'mb20 single-cover-slide imgbox-container',
+ 'slider_class' => 'single-cover single-cover--slide',
+ 'show_nav' => true,
+ 'show_pagination' => true,
+ 'loop' => count($slide_items) > 1,
+ 'autoplay' => count($slide_items) > 1,
+ 'overlay_html' => $overlay,
+ ]);
+ }
+ ?>
+
+
+
+
+
+ $slide_url) : ?>
+
; ?>)
+
+
+
+
+
+
+
+
+
![]()
alt="">
+
+
+
+
+
+
+
+
+
+
+
+
+ $ctx Single context.
+ */
+ function aksrt_single_render_box_header(array $ctx): void {
+ $settings = is_array($ctx['settings'] ?? null) ? $ctx['settings'] : [];
+ ?>
+
+
+
+
+
+
+ true,
+ 'show_time' => empty($settings['hide_time']),
+ 'meta_html' => empty($ctx['show_cover']) ? (string) ($ctx['meta_box_html'] ?? '') : '',
+ ]);
+ ?>
+
+ $ctx Single context.
+ */
+ function aksrt_single_render_actions(array $ctx): void {
+ $settings = is_array($ctx['settings'] ?? null) ? $ctx['settings'] : [];
+ $post_id = (int) $ctx['post_id'];
+ $like_count = (int) $ctx['like_count'];
+ $favorite_count = (int) $ctx['favorite_count'];
+ $is_liked = !empty($ctx['is_liked']);
+ $is_favorited = !empty($ctx['is_favorited']);
+ ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
 $settings['rewards_image']); ?>)
+
+
+
+
+
+ $ctx Single context.
+ */
+ function aksrt_single_render_content_footer(array $ctx): void {
+ $settings = is_array($ctx['settings'] ?? null) ? $ctx['settings'] : [];
+ $post_id = (int) $ctx['post_id'];
+ ?>
+
+
+
+
+
+
+
+
+ THE END
+
+ $ctx Single context.
+ */
+ function aksrt_single_render_author_card(array $ctx): void {
+ $author_id = (int) get_the_author_meta('ID');
+ if ($author_id <= 0) {
+ return;
+ }
+ $author_url = get_author_posts_url($author_id);
+ $author_name = get_the_author();
+ $bio = trim((string) get_the_author_meta('description'));
+ $vip_badge = function_exists('aksrt_render_vip_badge') ? aksrt_render_vip_badge($author_id, 'sm') : '';
+ $signals = [];
+ if (class_exists('AKSRT_User_Home')) {
+ $signals = AKSRT_User_Home::get_instance()->get_profile_signals($author_id);
+ }
+ $avatar = function_exists('aksrt_get_avatar_html')
+ ? aksrt_get_avatar_html($author_id, 80, ['class' => 'avatar avatar-lg'])
+ : get_avatar($author_id, 80, '', esc_attr($author_name), ['class' => 'avatar avatar-lg']);
+ $recent = get_posts([
+ 'author' => $author_id,
+ 'post_type' => 'post',
+ 'post_status' => 'publish',
+ 'posts_per_page' => 6,
+ 'orderby' => 'date',
+ 'order' => 'DESC',
+ 'no_found_rows' => true,
+ ]);
+ ?>
+
+ $ctx Single context.
+ */
+ function aksrt_single_render_prevnext(array $ctx = []): void {
+ $settings = is_array($ctx['settings'] ?? null) ? $ctx['settings'] : [];
+ $enabled = array_key_exists('prevnext', $settings)
+ ? !empty($settings['prevnext'])
+ : (!array_key_exists('prevnext_s', $settings) || !empty($settings['prevnext_s']));
+ if (!$enabled) {
+ return;
+ }
+
+ // Zibll: constrain to current category when available.
+ $in_same_term = !empty(get_the_category());
+ $prev = get_previous_post($in_same_term, '', 'category');
+ $next = get_next_post($in_same_term, '', 'category');
+ if (!$prev && !$next) {
+ // Fallback: any post.
+ $prev = get_previous_post();
+ $next = get_next_post();
+ }
+ if (!$prev && !$next) {
+ return;
+ }
+
+ $prev_title = $prev ? get_the_title($prev) : __('无更多文章', 'aksrt');
+ $next_title = $next ? get_the_title($next) : __('无更多文章', 'aksrt');
+ $prev_href = $prev ? get_permalink($prev) : 'javascript:;';
+ $next_href = $next ? get_permalink($next) : 'javascript:;';
+ ?>
+
+ $settings Single display settings.
+ * @return array
+ */
+ function aksrt_single_related_query_args(int $post_id, array $settings): array {
+ $count = max(1, min(12, (int) ($settings['related_count'] ?? 6)));
+ $type = sanitize_key((string) ($settings['related_source'] ?? ($settings['related_type'] ?? 'category')));
+ if (!in_array($type, ['category', 'tag', 'random'], true)) {
+ $type = 'category';
+ }
+ $orderby = sanitize_key((string) ($settings['related_orderby'] ?? 'views'));
+ if (!in_array($orderby, ['rand', 'relevance', 'date', 'views', 'modified'], true)) {
+ $orderby = 'views';
+ }
+
+ $args = [
+ 'post_type' => get_post_type($post_id) ?: 'post',
+ 'post_status' => 'publish',
+ 'post__not_in' => [$post_id],
+ 'posts_per_page' => $count,
+ 'ignore_sticky_posts' => true,
+ 'no_found_rows' => true,
+ 'order' => 'DESC',
+ ];
+
+ if ($type === 'random') {
+ $args['orderby'] = 'rand';
+ return $args;
+ }
+
+ $tax_query = ['relation' => 'OR'];
+ if ($type === 'tag') {
+ $tag_ids = wp_get_post_terms($post_id, 'post_tag', ['fields' => 'ids']);
+ if (!empty($tag_ids) && !is_wp_error($tag_ids)) {
+ $tax_query[] = [
+ 'taxonomy' => 'post_tag',
+ 'field' => 'term_id',
+ 'terms' => array_map('intval', $tag_ids),
+ ];
+ }
+ } else {
+ // category (default): OR across category + tags + topics like Zibll.
+ $cat_ids = wp_get_post_terms($post_id, 'category', ['fields' => 'ids']);
+ if (!empty($cat_ids) && !is_wp_error($cat_ids)) {
+ $tax_query[] = [
+ 'taxonomy' => 'category',
+ 'field' => 'term_id',
+ 'terms' => array_map('intval', $cat_ids),
+ ];
+ }
+ $tag_ids = wp_get_post_terms($post_id, 'post_tag', ['fields' => 'ids']);
+ if (!empty($tag_ids) && !is_wp_error($tag_ids)) {
+ $tax_query[] = [
+ 'taxonomy' => 'post_tag',
+ 'field' => 'term_id',
+ 'terms' => array_map('intval', $tag_ids),
+ ];
+ }
+ if (taxonomy_exists('topics')) {
+ $topic_ids = wp_get_post_terms($post_id, 'topics', ['fields' => 'ids']);
+ if (!empty($topic_ids) && !is_wp_error($topic_ids)) {
+ $tax_query[] = [
+ 'taxonomy' => 'topics',
+ 'field' => 'term_id',
+ 'terms' => array_map('intval', $topic_ids),
+ ];
+ }
+ }
+ }
+
+ if (count($tax_query) > 1) {
+ $args['tax_query'] = $tax_query;
+ }
+
+ switch ($orderby) {
+ case 'rand':
+ $args['orderby'] = 'rand';
+ break;
+ case 'date':
+ $args['orderby'] = 'date';
+ break;
+ case 'modified':
+ $args['orderby'] = 'modified';
+ break;
+ case 'views':
+ $args['meta_key'] = 'aksrt_post_views';
+ $args['orderby'] = 'meta_value_num';
+ break;
+ case 'relevance':
+ default:
+ // Prefer date when no search relevance context.
+ $args['orderby'] = 'date';
+ break;
+ }
+
+ return $args;
+ }
+endif;
+
+if (!function_exists('aksrt_single_render_related')) :
+ /**
+ * Related posts — Zibll-like list + optional shared mini renderer.
+ *
+ * @param array $ctx Single context.
+ */
+ function aksrt_single_render_related(array $ctx): void {
+ $settings = is_array($ctx['settings'] ?? null) ? $ctx['settings'] : [];
+ if (empty($settings['related_enabled'])) {
+ return;
+ }
+
+ $post_id = (int) $ctx['post_id'];
+ $title = (string) ($settings['related_title'] ?? '');
+ if ($title === '') {
+ $title = __('相关推荐', 'aksrt');
+ }
+ $style = sanitize_key((string) ($settings['related_style'] ?? 'img'));
+ if (!in_array($style, ['img', 'list', 'text'], true)) {
+ $style = 'img';
+ }
+
+ $args = function_exists('aksrt_single_related_query_args')
+ ? aksrt_single_related_query_args($post_id, $settings)
+ : [
+ 'post_type' => get_post_type($post_id) ?: 'post',
+ 'post_status' => 'publish',
+ 'post__not_in' => [$post_id],
+ 'posts_per_page' => max(1, min(12, (int) ($settings['related_count'] ?? 6))),
+ 'ignore_sticky_posts' => true,
+ ];
+
+ $query = new WP_Query($args);
+ if (!$query->have_posts()) {
+ wp_reset_postdata();
+ return;
+ }
+
+ $wrap_class = 'theme-box relates' . ($style === 'img' ? ' relates-thumb' : '');
+ ?>
+
+ $ctx Single context.
+ */
+ function aksrt_single_render_pay_box(array $ctx = []): void {
+ if ($ctx === []) {
+ $ctx = function_exists('aksrt_single_build_context') ? aksrt_single_build_context() : [];
+ }
+ if (empty($ctx['show_pay_box'])) {
+ return;
+ }
+ $allow = $ctx['allow_view'] ?? null;
+ if (is_array($allow) && empty($allow['allow'])) {
+ return;
+ }
+
+ $post_id = (int) ($ctx['post_id'] ?? get_the_ID());
+ $post = get_post($post_id);
+ if (!($post instanceof WP_Post)) {
+ return;
+ }
+
+ $pay_type = (string) ($ctx['pay_type'] ?? 'no');
+ if (!empty($ctx['has_download']) || $pay_type === 'download') {
+ echo '';
+ get_template_part('templates/parts/resource-download-box');
+ echo '
';
+ return;
+ }
+
+ if (!function_exists('aksrt_get_pay_meta')) {
+ return;
+ }
+
+ $has_access = function_exists('aksrt_has_paid_access') ? aksrt_has_paid_access($post) : false;
+ $paid_class = $has_access ? 'paid-box' : 'pay-box';
+ echo '';
+ if ($has_access) {
+ if ($pay_type === 'gallery' && function_exists('aksrt_render_paid_gallery')) {
+ echo aksrt_render_paid_gallery($post); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
+ } elseif ($pay_type === 'video' && function_exists('aksrt_render_paid_video')) {
+ echo aksrt_render_paid_video($post); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
+ } else {
+ echo '
' . esc_html__('已解锁', 'aksrt') . '' . esc_html(get_the_title($post)) . '
';
+ }
+ } elseif (function_exists('aksrt_get_paywall_html')) {
+ echo aksrt_get_paywall_html($post); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
+ }
+ echo '
';
+ }
+endif;
+
+if (!function_exists('aksrt_single_pay_box_matches')) :
+ /**
+ * @param array $ctx
+ */
+ function aksrt_single_pay_box_matches(array $ctx, string $slot): bool {
+ if (empty($ctx['show_pay_box'])) {
+ return false;
+ }
+ $allow = $ctx['allow_view'] ?? null;
+ if (is_array($allow) && empty($allow['allow'])) {
+ return false;
+ }
+ return (string) ($ctx['paid_box_position'] ?? 'top') === $slot;
+ }
+endif;
+
+if (!function_exists('aksrt_single_render_article')) :
+ /**
+ * Main article box (Zibll zib_single_content order).
+ *
+ * @param array $ctx Single context.
+ */
+ function aksrt_single_render_article(array $ctx): void {
+ $settings = is_array($ctx['settings'] ?? null) ? $ctx['settings'] : [];
+ $maxheight = (int) $ctx['content_maxheight'];
+ ?>
+ >
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
0 ? ' style="max-height:' . esc_attr((string) $maxheight) . 'px;"' : ''; ?>
+
+ data-maxheight=" 0 ? max(0, $maxheight - 80) : 0)); ?>"
+ data-aksrt-toc=""
+ data-aksrt-toc-depth=""
+ >
+
+ '
',
+ 'after' => '
',
+ ]);
+ ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $ctx Single context.
+ */
+ function aksrt_single_render_after_box(array $ctx): void {
+ $settings = is_array($ctx['settings'] ?? null) ? $ctx['settings'] : [];
+
+ if (!empty($settings['yiyan_box'])) {
+ ?>
+
+ $ctx Single context.
+ */
+ function aksrt_single_render_aside(array $ctx): void {
+ if (empty($ctx['show_aside']) || wp_is_mobile()) {
+ return;
+ }
+ ?>
+
+ $ctx Single context.
- */
- function aksrt_single_render_cover(array $ctx): void {
- if (empty($ctx['show_cover']) || $ctx['cover_url'] === '') {
- return;
- }
-
- $type = (string) $ctx['cover_type'];
- $badge = (string) $ctx['status_badge'];
- $crumbs = (string) $ctx['breadcrumbs_html'];
- $meta_box = (string) ($ctx['meta_box_html'] ?? '');
- $img_scale = max(10, min(100, (int) $ctx['img_scale']));
- $video_scale = max(20, min(100, (int) $ctx['video_scale']));
- $episode = (int) $ctx['episode_count'];
- $slides = is_array($ctx['slide_images'] ?? null) ? $ctx['slide_images'] : [];
- $poster = (string) ($ctx['video_poster'] ?? '');
- $title_html = (string) ($ctx['title_html'] ?? esc_html(get_the_title()));
-
- if ($type === 'video') :
- ?>
-
-
-
-
style="position:absolute;inset:0;width:100%;height:100%;">
-
-
-
-
- (string) $slide_url,
- 'alt' => wp_strip_all_tags(get_the_title()),
- ];
- }
- $overlay = ''
- . '
' . $title_html . '
'
- . ($crumbs !== '' ? $crumbs : '')
- . $badge
- . ''
- . ($meta_box !== '' ? str_replace('abs-right', 'cover-meta abs-right', $meta_box) : '');
- $slider_html = '';
- if (function_exists('aksrt_render_slider')) {
- $slider_html = aksrt_render_slider([
- 'slides' => $slide_items,
- 'scale_height' => true,
- 'scale_ratio' => $img_scale / 100,
- 'wrapper_class' => 'mb20 single-cover-slide imgbox-container',
- 'slider_class' => 'single-cover single-cover--slide',
- 'show_nav' => true,
- 'show_pagination' => true,
- 'loop' => count($slide_items) > 1,
- 'autoplay' => count($slide_items) > 1,
- 'overlay_html' => $overlay,
- ]);
- }
- ?>
-
-
-
-
-
- $slide_url) : ?>
-
; ?>)
-
-
-
-
-
-
-
-
-
![]()
alt="">
-
-
-
-
-
-
-
-
-
-
-
-
- $ctx Single context.
- */
- function aksrt_single_render_box_header(array $ctx): void {
- $settings = is_array($ctx['settings'] ?? null) ? $ctx['settings'] : [];
- ?>
-
-
-
-
-
-
- true,
- 'show_time' => empty($settings['hide_time']),
- 'meta_html' => empty($ctx['show_cover']) ? (string) ($ctx['meta_box_html'] ?? '') : '',
- ]);
- ?>
-
- $ctx Single context.
- */
- function aksrt_single_render_actions(array $ctx): void {
- $settings = is_array($ctx['settings'] ?? null) ? $ctx['settings'] : [];
- $post_id = (int) $ctx['post_id'];
- $like_count = (int) $ctx['like_count'];
- $favorite_count = (int) $ctx['favorite_count'];
- $is_liked = !empty($ctx['is_liked']);
- $is_favorited = !empty($ctx['is_favorited']);
- ?>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
 $settings['rewards_image']); ?>)
-
-
-
-
-
- $ctx Single context.
- */
- function aksrt_single_render_content_footer(array $ctx): void {
- $settings = is_array($ctx['settings'] ?? null) ? $ctx['settings'] : [];
- $post_id = (int) $ctx['post_id'];
- ?>
-
-
-
-
-
-
-
-
- THE END
-
- $ctx Single context.
- */
- function aksrt_single_render_author_card(array $ctx): void {
- $author_id = (int) get_the_author_meta('ID');
- if ($author_id <= 0) {
- return;
- }
- $author_url = get_author_posts_url($author_id);
- $author_name = get_the_author();
- $bio = trim((string) get_the_author_meta('description'));
- $vip_badge = function_exists('aksrt_render_vip_badge') ? aksrt_render_vip_badge($author_id, 'sm') : '';
- $signals = [];
- if (class_exists('AKSRT_User_Home')) {
- $signals = AKSRT_User_Home::get_instance()->get_profile_signals($author_id);
- }
- $avatar = function_exists('aksrt_get_avatar_html')
- ? aksrt_get_avatar_html($author_id, 80, ['class' => 'avatar avatar-lg'])
- : get_avatar($author_id, 80, '', esc_attr($author_name), ['class' => 'avatar avatar-lg']);
- $recent = get_posts([
- 'author' => $author_id,
- 'post_type' => 'post',
- 'post_status' => 'publish',
- 'posts_per_page' => 6,
- 'orderby' => 'date',
- 'order' => 'DESC',
- 'no_found_rows' => true,
- ]);
- ?>
-
- $ctx Single context.
- */
- function aksrt_single_render_prevnext(array $ctx = []): void {
- $settings = is_array($ctx['settings'] ?? null) ? $ctx['settings'] : [];
- $enabled = array_key_exists('prevnext', $settings)
- ? !empty($settings['prevnext'])
- : (!array_key_exists('prevnext_s', $settings) || !empty($settings['prevnext_s']));
- if (!$enabled) {
- return;
- }
-
- // Zibll: constrain to current category when available.
- $in_same_term = !empty(get_the_category());
- $prev = get_previous_post($in_same_term, '', 'category');
- $next = get_next_post($in_same_term, '', 'category');
- if (!$prev && !$next) {
- // Fallback: any post.
- $prev = get_previous_post();
- $next = get_next_post();
- }
- if (!$prev && !$next) {
- return;
- }
-
- $prev_title = $prev ? get_the_title($prev) : __('无更多文章', 'aksrt');
- $next_title = $next ? get_the_title($next) : __('无更多文章', 'aksrt');
- $prev_href = $prev ? get_permalink($prev) : 'javascript:;';
- $next_href = $next ? get_permalink($next) : 'javascript:;';
- ?>
-
- $settings Single display settings.
- * @return array
- */
- function aksrt_single_related_query_args(int $post_id, array $settings): array {
- $count = max(1, min(12, (int) ($settings['related_count'] ?? 6)));
- $type = sanitize_key((string) ($settings['related_source'] ?? ($settings['related_type'] ?? 'category')));
- if (!in_array($type, ['category', 'tag', 'random'], true)) {
- $type = 'category';
- }
- $orderby = sanitize_key((string) ($settings['related_orderby'] ?? 'views'));
- if (!in_array($orderby, ['rand', 'relevance', 'date', 'views', 'modified'], true)) {
- $orderby = 'views';
- }
-
- $args = [
- 'post_type' => get_post_type($post_id) ?: 'post',
- 'post_status' => 'publish',
- 'post__not_in' => [$post_id],
- 'posts_per_page' => $count,
- 'ignore_sticky_posts' => true,
- 'no_found_rows' => true,
- 'order' => 'DESC',
- ];
-
- if ($type === 'random') {
- $args['orderby'] = 'rand';
- return $args;
- }
-
- $tax_query = ['relation' => 'OR'];
- if ($type === 'tag') {
- $tag_ids = wp_get_post_terms($post_id, 'post_tag', ['fields' => 'ids']);
- if (!empty($tag_ids) && !is_wp_error($tag_ids)) {
- $tax_query[] = [
- 'taxonomy' => 'post_tag',
- 'field' => 'term_id',
- 'terms' => array_map('intval', $tag_ids),
- ];
- }
- } else {
- // category (default): OR across category + tags + topics like Zibll.
- $cat_ids = wp_get_post_terms($post_id, 'category', ['fields' => 'ids']);
- if (!empty($cat_ids) && !is_wp_error($cat_ids)) {
- $tax_query[] = [
- 'taxonomy' => 'category',
- 'field' => 'term_id',
- 'terms' => array_map('intval', $cat_ids),
- ];
- }
- $tag_ids = wp_get_post_terms($post_id, 'post_tag', ['fields' => 'ids']);
- if (!empty($tag_ids) && !is_wp_error($tag_ids)) {
- $tax_query[] = [
- 'taxonomy' => 'post_tag',
- 'field' => 'term_id',
- 'terms' => array_map('intval', $tag_ids),
- ];
- }
- if (taxonomy_exists('topics')) {
- $topic_ids = wp_get_post_terms($post_id, 'topics', ['fields' => 'ids']);
- if (!empty($topic_ids) && !is_wp_error($topic_ids)) {
- $tax_query[] = [
- 'taxonomy' => 'topics',
- 'field' => 'term_id',
- 'terms' => array_map('intval', $topic_ids),
- ];
- }
- }
- }
-
- if (count($tax_query) > 1) {
- $args['tax_query'] = $tax_query;
- }
-
- switch ($orderby) {
- case 'rand':
- $args['orderby'] = 'rand';
- break;
- case 'date':
- $args['orderby'] = 'date';
- break;
- case 'modified':
- $args['orderby'] = 'modified';
- break;
- case 'views':
- $args['meta_key'] = 'aksrt_post_views';
- $args['orderby'] = 'meta_value_num';
- break;
- case 'relevance':
- default:
- // Prefer date when no search relevance context.
- $args['orderby'] = 'date';
- break;
- }
-
- return $args;
- }
-endif;
-
-if (!function_exists('aksrt_single_render_related')) :
- /**
- * Related posts — Zibll-like list + optional shared mini renderer.
- *
- * @param array $ctx Single context.
- */
- function aksrt_single_render_related(array $ctx): void {
- $settings = is_array($ctx['settings'] ?? null) ? $ctx['settings'] : [];
- if (empty($settings['related_enabled'])) {
- return;
- }
-
- $post_id = (int) $ctx['post_id'];
- $title = (string) ($settings['related_title'] ?? '');
- if ($title === '') {
- $title = __('相关推荐', 'aksrt');
- }
- $style = sanitize_key((string) ($settings['related_style'] ?? 'img'));
- if (!in_array($style, ['img', 'list', 'text'], true)) {
- $style = 'img';
- }
-
- $args = function_exists('aksrt_single_related_query_args')
- ? aksrt_single_related_query_args($post_id, $settings)
- : [
- 'post_type' => get_post_type($post_id) ?: 'post',
- 'post_status' => 'publish',
- 'post__not_in' => [$post_id],
- 'posts_per_page' => max(1, min(12, (int) ($settings['related_count'] ?? 6))),
- 'ignore_sticky_posts' => true,
- ];
-
- $query = new WP_Query($args);
- if (!$query->have_posts()) {
- wp_reset_postdata();
- return;
- }
-
- $wrap_class = 'theme-box relates' . ($style === 'img' ? ' relates-thumb' : '');
- ?>
-
- $ctx Single context.
- */
- function aksrt_single_render_pay_box(array $ctx = []): void {
- if ($ctx === []) {
- $ctx = function_exists('aksrt_single_build_context') ? aksrt_single_build_context() : [];
- }
- if (empty($ctx['show_pay_box'])) {
- return;
- }
- $allow = $ctx['allow_view'] ?? null;
- if (is_array($allow) && empty($allow['allow'])) {
- return;
- }
-
- $post_id = (int) ($ctx['post_id'] ?? get_the_ID());
- $post = get_post($post_id);
- if (!($post instanceof WP_Post)) {
- return;
- }
-
- $pay_type = (string) ($ctx['pay_type'] ?? 'no');
- if (!empty($ctx['has_download']) || $pay_type === 'download') {
- echo '';
- get_template_part('templates/parts/resource-download-box');
- echo '
';
- return;
- }
-
- if (!function_exists('aksrt_get_pay_meta')) {
- return;
- }
-
- $has_access = function_exists('aksrt_has_paid_access') ? aksrt_has_paid_access($post) : false;
- $paid_class = $has_access ? 'paid-box' : 'pay-box';
- echo '';
- if ($has_access) {
- if ($pay_type === 'gallery' && function_exists('aksrt_render_paid_gallery')) {
- echo aksrt_render_paid_gallery($post); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
- } elseif ($pay_type === 'video' && function_exists('aksrt_render_paid_video')) {
- echo aksrt_render_paid_video($post); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
- } else {
- echo '
' . esc_html__('已解锁', 'aksrt') . '' . esc_html(get_the_title($post)) . '
';
- }
- } elseif (function_exists('aksrt_get_paywall_html')) {
- echo aksrt_get_paywall_html($post); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
- }
- echo '
';
- }
-endif;
-
-if (!function_exists('aksrt_single_pay_box_matches')) :
- /**
- * @param array $ctx
- */
- function aksrt_single_pay_box_matches(array $ctx, string $slot): bool {
- if (empty($ctx['show_pay_box'])) {
- return false;
- }
- $allow = $ctx['allow_view'] ?? null;
- if (is_array($allow) && empty($allow['allow'])) {
- return false;
- }
- return (string) ($ctx['paid_box_position'] ?? 'top') === $slot;
- }
-endif;
-
-if (!function_exists('aksrt_single_render_article')) :
- /**
- * Main article box (Zibll zib_single_content order).
- *
- * @param array $ctx Single context.
- */
- function aksrt_single_render_article(array $ctx): void {
- $settings = is_array($ctx['settings'] ?? null) ? $ctx['settings'] : [];
- $maxheight = (int) $ctx['content_maxheight'];
- ?>
- >
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
0 ? ' style="max-height:' . esc_attr((string) $maxheight) . 'px;"' : ''; ?>
-
- data-maxheight=" 0 ? max(0, $maxheight - 80) : 0)); ?>"
- data-aksrt-toc=""
- data-aksrt-toc-depth=""
- >
-
- '
',
- 'after' => '
',
- ]);
- ?>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- $ctx Single context.
- */
- function aksrt_single_render_after_box(array $ctx): void {
- $settings = is_array($ctx['settings'] ?? null) ? $ctx['settings'] : [];
-
- if (!empty($settings['yiyan_box'])) {
- ?>
-
- $ctx Single context.
- */
- function aksrt_single_render_aside(array $ctx): void {
- if (empty($ctx['show_aside']) || wp_is_mobile()) {
- return;
- }
- ?>
-
-
- 'avatar avatar-id-' . $author_id]); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
+ 'avatar avatar-id-' . $author_id]); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
- 'avatar avatar-id-' . $author_id]); ?>
+ 'avatar avatar-id-' . $author_id]); ?>