From 3247db7ed183dbed5b6993aa6463dbb76308abfd Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 3 Jul 2026 23:15:11 +0800 Subject: [PATCH] =?UTF-8?q?=E8=A1=A5=E5=85=85=E4=B8=BB=E9=A2=98=E9=9D=99?= =?UTF-8?q?=E6=80=81=E8=B5=84=E6=BA=90=E4=B8=8E=E5=BD=92=E6=A1=A3=E6=A8=A1?= =?UTF-8?q?=E6=9D=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 24 + assets/css/admin/admin-panel.css | 83 + assets/css/build/core.min.css.disabled | 1032 +++ .../css/build/frontend-base.min.css.disabled | 5701 +++++++++++++++++ assets/css/common/floating.css | 452 ++ assets/css/core/alerts.css | 53 + assets/css/core/animations.css | 323 + assets/css/core/buttons.css | 304 + assets/css/core/color-utilities.css | 272 + assets/css/core/components-ext.css | 555 ++ assets/css/core/forms.css | 142 + assets/css/core/reset.css | 128 + assets/css/core/tokens.css | 429 ++ assets/css/core/typography.css | 211 + assets/css/frontend/ajax-spinner.css | 114 + assets/css/frontend/base.css | 99 + assets/css/frontend/breadcrumb.css | 76 + assets/css/frontend/card-primitives.css | 163 + assets/css/frontend/comment-tools.css | 281 + assets/css/frontend/comments.css | 614 ++ assets/css/frontend/credits.css | 384 ++ assets/css/frontend/empty-state.css | 124 + assets/css/frontend/enhancements.css | 3 + .../css/frontend/enhancements/components.css | 3 + .../frontend/enhancements/components/base.css | 199 + .../enhancements/components/custom-amount.css | 571 ++ .../components/reward-amounts.css | 45 + assets/css/frontend/enhancements/core-ui.css | 483 ++ .../frontend/enhancements/modal-motion.css | 10 + .../enhancements/modal-motion/base.css | 95 + .../enhancements/modal-motion/dark-mode-2.css | 514 ++ .../enhancements/modal-motion/dark-mode.css | 19 + .../enhancements/modal-motion/divider.css | 18 + .../enhancements/modal-motion/footer.css | 22 + .../enhancements/modal-motion/form.css | 120 + .../enhancements/modal-motion/oauth.css | 27 + .../enhancements/modal-motion/panels.css | 9 + .../enhancements/modal-motion/responsive.css | 139 + .../enhancements/modal-motion/tabs.css | 34 + assets/css/frontend/floating-buttons.css | 350 + assets/css/frontend/footer.css | 4 + assets/css/frontend/footer/part-1.css | 300 + assets/css/frontend/footer/part-2.css | 300 + assets/css/frontend/footer/part-3.css | 300 + assets/css/frontend/footer/part-4.css | 52 + assets/css/frontend/forum.css | 4 + assets/css/frontend/forum/board.css | 402 ++ assets/css/frontend/forum/compose.css | 709 ++ assets/css/frontend/forum/extras.css | 7 + .../forum/extras/additional-role-badges.css | 52 + assets/css/frontend/forum/extras/base.css | 621 ++ .../css/frontend/forum/extras/like-button.css | 62 + .../css/frontend/forum/extras/load-more.css | 23 + .../frontend/forum/extras/quick-post-bar.css | 31 + .../forum/extras/reply-action-buttons.css | 239 + .../extras/reply-header-tabs-filters.css | 69 + assets/css/frontend/forum/topic.css | 331 + assets/css/frontend/header-components.css | 6 + .../frontend/header-components/admin-hint.css | 90 + .../css/frontend/header-components/base.css | 176 + .../card-device-visibility.css | 169 + .../frontend/header-components/dark-theme.css | 377 ++ .../header-components/search-keywords-row.css | 455 ++ .../widget-device-visibility.css | 198 + assets/css/frontend/home-modules.css | 16 + assets/css/frontend/home-modules/base.css | 89 + .../frontend/home-modules/button-group.css | 46 + .../css/frontend/home-modules/data-grid.css | 38 + assets/css/frontend/home-modules/faq.css | 48 + .../frontend/home-modules/friend-links.css | 55 + .../frontend/home-modules/highlight-cards.css | 57 + .../css/frontend/home-modules/html-module.css | 7 + .../frontend/home-modules/partner-marquee.css | 42 + .../home-modules/product-showcase.css | 58 + assets/css/frontend/home-modules/ranking.css | 60 + .../css/frontend/home-modules/responsive.css | 294 + assets/css/frontend/home-modules/spacing.css | 5 + assets/css/frontend/home-modules/tabs.css | 56 + .../css/frontend/home-modules/tag-cloud.css | 33 + .../css/frontend/home-modules/text-title.css | 17 + .../css/frontend/home-modules/user-cards.css | 180 + assets/css/frontend/homepage-fixed.css | 3 + .../homepage-fixed/ajax-tab-error-state.css | 197 + .../ajax-tab-skeleton-placeholder.css | 51 + assets/css/frontend/homepage-fixed/base-1.css | 401 ++ assets/css/frontend/homepage-fixed/base-2.css | 400 ++ assets/css/frontend/homepage-fixed/base-3.css | 245 + assets/css/frontend/homepage-fixed/base.css | 3 + assets/css/frontend/layout.css | 516 ++ assets/css/frontend/menu-decorations.css | 280 + assets/css/frontend/messages.css | 580 ++ assets/css/frontend/nav.css | 12 + assets/css/frontend/nav/base.css | 332 + assets/css/frontend/nav/cards-submenu.css | 128 + .../css/frontend/nav/dark-mode-mega-menu.css | 12 + assets/css/frontend/nav/dark-mode-submenu.css | 109 + assets/css/frontend/nav/hover-effects.css | 35 + assets/css/frontend/nav/mega-submenu.css | 28 + assets/css/frontend/nav/menu-item-badge.css | 41 + assets/css/frontend/nav/menu-item-icon.css | 20 + .../nav/mobile-theme-toggle-in-drawer.css | 18 + assets/css/frontend/nav/mobile-toggle.css | 604 ++ .../nav/nav-fixed-mobile-fallback.css | 10 + .../css/frontend/nav/responsive-mega-menu.css | 106 + assets/css/frontend/overlay-primitives.css | 78 + assets/css/frontend/pages.css | 5 + assets/css/frontend/pages/base-1.css | 400 ++ assets/css/frontend/pages/base-2.css | 400 ++ assets/css/frontend/pages/base-3.css | 193 + assets/css/frontend/pages/base.css | 3 + assets/css/frontend/pages/board-cards.css | 58 + assets/css/frontend/pages/empty-state.css | 292 + assets/css/frontend/pages/sidebar.css | 98 + assets/css/frontend/pages/topic-rows.css | 55 + assets/css/frontend/pagination.css | 230 + assets/css/frontend/post-card-cms.css | 60 + assets/css/frontend/post-card.css | 584 ++ assets/css/frontend/print.css | 105 + assets/css/frontend/product-archive.css | 711 ++ assets/css/frontend/resource-archive.css | 598 ++ assets/css/frontend/resource-meta.css | 5 + assets/css/frontend/resource-meta/part-1.css | 300 + assets/css/frontend/resource-meta/part-2.css | 300 + assets/css/frontend/resource-meta/part-3.css | 300 + assets/css/frontend/resource-meta/part-4.css | 300 + assets/css/frontend/resource-meta/part-5.css | 55 + assets/css/frontend/sidebar.css | 167 + assets/css/frontend/single-post.css | 7 + .../frontend/single-post/author-actions.css | 441 ++ .../css/frontend/single-post/code-blocks.css | 128 + assets/css/frontend/single-post/content.css | 290 + assets/css/frontend/single-post/cover.css | 192 + .../frontend/single-post/hidden-content.css | 121 + .../css/frontend/single-post/navigation.css | 79 + .../css/frontend/single-post/related-toc.css | 430 ++ assets/css/frontend/site-notice.css | 131 + assets/css/frontend/skeleton.css | 141 + assets/css/frontend/swiper-bundle.min.css | 13 + assets/css/frontend/theme-background.css | 72 + assets/css/frontend/widgets.css | 4 + assets/css/frontend/widgets/part-1.css | 300 + assets/css/frontend/widgets/part-2.css | 300 + assets/css/frontend/widgets/part-3.css | 300 + assets/css/frontend/widgets/part-4.css | 95 + assets/css/frontend/zibll-compat-vars.css | 98 + assets/css/gutenberg-blocks.css | 381 ++ assets/css/routes/auth.css | 354 + assets/css/routes/cart.css | 386 ++ assets/css/routes/categories.css | 224 + assets/css/routes/docs.css | 14 + assets/css/routes/friends.css | 74 + assets/css/routes/orders.css | 437 ++ assets/css/routes/product.css | 446 ++ assets/css/routes/profile.css | 3 + assets/css/routes/profile/layout.css | 567 ++ assets/css/routes/profile/lists.css | 660 ++ assets/css/routes/profile/modals.css | 604 ++ assets/css/routes/revenue.css | 227 + assets/css/routes/search.css | 350 + assets/css/routes/special.css | 237 + assets/css/routes/user-center.css | 5 + assets/css/routes/user-center/part-1.css | 300 + assets/css/routes/user-center/part-2.css | 300 + assets/css/routes/user-center/part-3.css | 300 + assets/css/routes/user-center/part-4.css | 300 + assets/css/routes/user-center/part-5.css | 51 + assets/css/routes/user-home.css | 646 ++ assets/css/shared/captcha.css | 22 + assets/img/default-favicon.svg | 10 + assets/img/default-logo.svg | 9 + assets/img/icons/bilibili.svg | 1 + assets/img/icons/discord.svg | 1 + assets/img/icons/email.svg | 1 + assets/img/icons/facebook.svg | 1 + assets/img/icons/gitee.svg | 1 + assets/img/icons/github.svg | 1 + assets/img/icons/google.svg | 1 + assets/img/icons/instagram.svg | 1 + assets/img/icons/linkedin.svg | 1 + assets/img/icons/qq.svg | 1 + assets/img/icons/telegram.svg | 1 + assets/img/icons/web.svg | 1 + assets/img/icons/wechat.svg | 1 + assets/img/icons/weibo.svg | 1 + assets/img/icons/x.svg | 1 + assets/img/icons/youtube.svg | 1 + assets/img/person_background.png | Bin 0 -> 59552 bytes assets/img/placeholder.svg | 10 + assets/img/widgets-original.png | Bin 0 -> 47376 bytes assets/js/aksrt-runtime.js | 965 +++ assets/js/author.js | 211 + assets/js/cart-checkout.js | 456 ++ assets/js/cms-download.js | 344 + assets/js/cms-home-modules.js | 52 + assets/js/color-extract.js | 147 + assets/js/comment-ajax.js | 241 + assets/js/comment-tools.js | 422 ++ assets/js/content-protect.js | 120 + assets/js/conversation.js | 125 + assets/js/core/archive.js | 213 + assets/js/core/article.js | 226 + assets/js/core/comments.js | 622 ++ assets/js/core/dropdown.js | 109 + assets/js/core/footer-tabbar.js | 140 + assets/js/core/misc.js | 144 + assets/js/core/nav.js | 54 + assets/js/core/pagination.js | 270 + assets/js/core/scroll.js | 180 + assets/js/core/search.js | 340 + assets/js/core/slider.js | 295 + assets/js/core/theme.js | 269 + assets/js/credits.js | 329 + assets/js/docs-navigation.js | 137 + assets/js/download-status.js | 61 + assets/js/effects.js | 214 + assets/js/enhancements.js | 588 ++ assets/js/enhancements2.js | 314 + assets/js/enlighter/enlighterjs.min.css | 1 + assets/js/enlighter/enlighterjs.min.js | 2 + assets/js/follow.js | 108 + assets/js/forum-edit.js | 47 + assets/js/forum-governance.js | 1375 ++++ assets/js/front-submit.js | 361 ++ assets/js/frontend-translate.js | 83 + assets/js/gutenberg-blocks.js | 737 +++ assets/js/homepage-fixed.js | 799 +++ assets/js/input-expand.js | 130 + assets/js/instant-page.js | 96 + assets/js/loader.js | 172 + assets/js/main.js | 27 + assets/js/messages.js | 168 + assets/js/mini-touch.js | 256 + assets/js/mini-upload.js | 332 + assets/js/modal-auth.js | 484 ++ assets/js/order-center.js | 306 + assets/js/page-edit.js | 255 + assets/js/page-navs.js | 454 ++ assets/js/page-template.js | 264 + assets/js/passive-events.js | 25 + assets/js/post-share.js | 309 + assets/js/poster-share.js | 410 ++ assets/js/precode.js | 226 + assets/js/product-archive.js | 44 + assets/js/product-purchase.js | 241 + assets/js/qrcode.min.js | 2 + assets/js/rehydrate.js | 81 + assets/js/report.js | 174 + assets/js/reward.js | 97 + assets/js/routes/user-center.js | 682 ++ assets/js/routes/user-home.js | 70 + assets/js/section-navs.js | 163 + assets/js/share-data-builder.js | 108 + assets/js/sign-register.js | 390 ++ assets/js/site-notice.js | 91 + assets/js/slider-captcha.js | 406 ++ assets/js/svg-icon-helper.js | 89 + assets/js/svg-icon.js | 138 + assets/js/swiper-bundle.min.js | 14 + assets/js/video-player.js | 263 + assets/js/waterfall.js | 178 + assets/js/weixin-share.js | 481 ++ assets/js/widget-set.js | 93 + assets/js/yiyan.js | 109 + category.php | 260 + tag.php | 179 + 265 files changed, 59174 insertions(+) create mode 100644 .gitignore create mode 100644 assets/css/admin/admin-panel.css create mode 100644 assets/css/build/core.min.css.disabled create mode 100644 assets/css/build/frontend-base.min.css.disabled create mode 100644 assets/css/common/floating.css create mode 100644 assets/css/core/alerts.css create mode 100644 assets/css/core/animations.css create mode 100644 assets/css/core/buttons.css create mode 100644 assets/css/core/color-utilities.css create mode 100644 assets/css/core/components-ext.css create mode 100644 assets/css/core/forms.css create mode 100644 assets/css/core/reset.css create mode 100644 assets/css/core/tokens.css create mode 100644 assets/css/core/typography.css create mode 100644 assets/css/frontend/ajax-spinner.css create mode 100644 assets/css/frontend/base.css create mode 100644 assets/css/frontend/breadcrumb.css create mode 100644 assets/css/frontend/card-primitives.css create mode 100644 assets/css/frontend/comment-tools.css create mode 100644 assets/css/frontend/comments.css create mode 100644 assets/css/frontend/credits.css create mode 100644 assets/css/frontend/empty-state.css create mode 100644 assets/css/frontend/enhancements.css create mode 100644 assets/css/frontend/enhancements/components.css create mode 100644 assets/css/frontend/enhancements/components/base.css create mode 100644 assets/css/frontend/enhancements/components/custom-amount.css create mode 100644 assets/css/frontend/enhancements/components/reward-amounts.css create mode 100644 assets/css/frontend/enhancements/core-ui.css create mode 100644 assets/css/frontend/enhancements/modal-motion.css create mode 100644 assets/css/frontend/enhancements/modal-motion/base.css create mode 100644 assets/css/frontend/enhancements/modal-motion/dark-mode-2.css create mode 100644 assets/css/frontend/enhancements/modal-motion/dark-mode.css create mode 100644 assets/css/frontend/enhancements/modal-motion/divider.css create mode 100644 assets/css/frontend/enhancements/modal-motion/footer.css create mode 100644 assets/css/frontend/enhancements/modal-motion/form.css create mode 100644 assets/css/frontend/enhancements/modal-motion/oauth.css create mode 100644 assets/css/frontend/enhancements/modal-motion/panels.css create mode 100644 assets/css/frontend/enhancements/modal-motion/responsive.css create mode 100644 assets/css/frontend/enhancements/modal-motion/tabs.css create mode 100644 assets/css/frontend/floating-buttons.css create mode 100644 assets/css/frontend/footer.css create mode 100644 assets/css/frontend/footer/part-1.css create mode 100644 assets/css/frontend/footer/part-2.css create mode 100644 assets/css/frontend/footer/part-3.css create mode 100644 assets/css/frontend/footer/part-4.css create mode 100644 assets/css/frontend/forum.css create mode 100644 assets/css/frontend/forum/board.css create mode 100644 assets/css/frontend/forum/compose.css create mode 100644 assets/css/frontend/forum/extras.css create mode 100644 assets/css/frontend/forum/extras/additional-role-badges.css create mode 100644 assets/css/frontend/forum/extras/base.css create mode 100644 assets/css/frontend/forum/extras/like-button.css create mode 100644 assets/css/frontend/forum/extras/load-more.css create mode 100644 assets/css/frontend/forum/extras/quick-post-bar.css create mode 100644 assets/css/frontend/forum/extras/reply-action-buttons.css create mode 100644 assets/css/frontend/forum/extras/reply-header-tabs-filters.css create mode 100644 assets/css/frontend/forum/topic.css create mode 100644 assets/css/frontend/header-components.css create mode 100644 assets/css/frontend/header-components/admin-hint.css create mode 100644 assets/css/frontend/header-components/base.css create mode 100644 assets/css/frontend/header-components/card-device-visibility.css create mode 100644 assets/css/frontend/header-components/dark-theme.css create mode 100644 assets/css/frontend/header-components/search-keywords-row.css create mode 100644 assets/css/frontend/header-components/widget-device-visibility.css create mode 100644 assets/css/frontend/home-modules.css create mode 100644 assets/css/frontend/home-modules/base.css create mode 100644 assets/css/frontend/home-modules/button-group.css create mode 100644 assets/css/frontend/home-modules/data-grid.css create mode 100644 assets/css/frontend/home-modules/faq.css create mode 100644 assets/css/frontend/home-modules/friend-links.css create mode 100644 assets/css/frontend/home-modules/highlight-cards.css create mode 100644 assets/css/frontend/home-modules/html-module.css create mode 100644 assets/css/frontend/home-modules/partner-marquee.css create mode 100644 assets/css/frontend/home-modules/product-showcase.css create mode 100644 assets/css/frontend/home-modules/ranking.css create mode 100644 assets/css/frontend/home-modules/responsive.css create mode 100644 assets/css/frontend/home-modules/spacing.css create mode 100644 assets/css/frontend/home-modules/tabs.css create mode 100644 assets/css/frontend/home-modules/tag-cloud.css create mode 100644 assets/css/frontend/home-modules/text-title.css create mode 100644 assets/css/frontend/home-modules/user-cards.css create mode 100644 assets/css/frontend/homepage-fixed.css create mode 100644 assets/css/frontend/homepage-fixed/ajax-tab-error-state.css create mode 100644 assets/css/frontend/homepage-fixed/ajax-tab-skeleton-placeholder.css create mode 100644 assets/css/frontend/homepage-fixed/base-1.css create mode 100644 assets/css/frontend/homepage-fixed/base-2.css create mode 100644 assets/css/frontend/homepage-fixed/base-3.css create mode 100644 assets/css/frontend/homepage-fixed/base.css create mode 100644 assets/css/frontend/layout.css create mode 100644 assets/css/frontend/menu-decorations.css create mode 100644 assets/css/frontend/messages.css create mode 100644 assets/css/frontend/nav.css create mode 100644 assets/css/frontend/nav/base.css create mode 100644 assets/css/frontend/nav/cards-submenu.css create mode 100644 assets/css/frontend/nav/dark-mode-mega-menu.css create mode 100644 assets/css/frontend/nav/dark-mode-submenu.css create mode 100644 assets/css/frontend/nav/hover-effects.css create mode 100644 assets/css/frontend/nav/mega-submenu.css create mode 100644 assets/css/frontend/nav/menu-item-badge.css create mode 100644 assets/css/frontend/nav/menu-item-icon.css create mode 100644 assets/css/frontend/nav/mobile-theme-toggle-in-drawer.css create mode 100644 assets/css/frontend/nav/mobile-toggle.css create mode 100644 assets/css/frontend/nav/nav-fixed-mobile-fallback.css create mode 100644 assets/css/frontend/nav/responsive-mega-menu.css create mode 100644 assets/css/frontend/overlay-primitives.css create mode 100644 assets/css/frontend/pages.css create mode 100644 assets/css/frontend/pages/base-1.css create mode 100644 assets/css/frontend/pages/base-2.css create mode 100644 assets/css/frontend/pages/base-3.css create mode 100644 assets/css/frontend/pages/base.css create mode 100644 assets/css/frontend/pages/board-cards.css create mode 100644 assets/css/frontend/pages/empty-state.css create mode 100644 assets/css/frontend/pages/sidebar.css create mode 100644 assets/css/frontend/pages/topic-rows.css create mode 100644 assets/css/frontend/pagination.css create mode 100644 assets/css/frontend/post-card-cms.css create mode 100644 assets/css/frontend/post-card.css create mode 100644 assets/css/frontend/print.css create mode 100644 assets/css/frontend/product-archive.css create mode 100644 assets/css/frontend/resource-archive.css create mode 100644 assets/css/frontend/resource-meta.css create mode 100644 assets/css/frontend/resource-meta/part-1.css create mode 100644 assets/css/frontend/resource-meta/part-2.css create mode 100644 assets/css/frontend/resource-meta/part-3.css create mode 100644 assets/css/frontend/resource-meta/part-4.css create mode 100644 assets/css/frontend/resource-meta/part-5.css create mode 100644 assets/css/frontend/sidebar.css create mode 100644 assets/css/frontend/single-post.css create mode 100644 assets/css/frontend/single-post/author-actions.css create mode 100644 assets/css/frontend/single-post/code-blocks.css create mode 100644 assets/css/frontend/single-post/content.css create mode 100644 assets/css/frontend/single-post/cover.css create mode 100644 assets/css/frontend/single-post/hidden-content.css create mode 100644 assets/css/frontend/single-post/navigation.css create mode 100644 assets/css/frontend/single-post/related-toc.css create mode 100644 assets/css/frontend/site-notice.css create mode 100644 assets/css/frontend/skeleton.css create mode 100644 assets/css/frontend/swiper-bundle.min.css create mode 100644 assets/css/frontend/theme-background.css create mode 100644 assets/css/frontend/widgets.css create mode 100644 assets/css/frontend/widgets/part-1.css create mode 100644 assets/css/frontend/widgets/part-2.css create mode 100644 assets/css/frontend/widgets/part-3.css create mode 100644 assets/css/frontend/widgets/part-4.css create mode 100644 assets/css/frontend/zibll-compat-vars.css create mode 100644 assets/css/gutenberg-blocks.css create mode 100644 assets/css/routes/auth.css create mode 100644 assets/css/routes/cart.css create mode 100644 assets/css/routes/categories.css create mode 100644 assets/css/routes/docs.css create mode 100644 assets/css/routes/friends.css create mode 100644 assets/css/routes/orders.css create mode 100644 assets/css/routes/product.css create mode 100644 assets/css/routes/profile.css create mode 100644 assets/css/routes/profile/layout.css create mode 100644 assets/css/routes/profile/lists.css create mode 100644 assets/css/routes/profile/modals.css create mode 100644 assets/css/routes/revenue.css create mode 100644 assets/css/routes/search.css create mode 100644 assets/css/routes/special.css create mode 100644 assets/css/routes/user-center.css create mode 100644 assets/css/routes/user-center/part-1.css create mode 100644 assets/css/routes/user-center/part-2.css create mode 100644 assets/css/routes/user-center/part-3.css create mode 100644 assets/css/routes/user-center/part-4.css create mode 100644 assets/css/routes/user-center/part-5.css create mode 100644 assets/css/routes/user-home.css create mode 100644 assets/css/shared/captcha.css create mode 100644 assets/img/default-favicon.svg create mode 100644 assets/img/default-logo.svg create mode 100644 assets/img/icons/bilibili.svg create mode 100644 assets/img/icons/discord.svg create mode 100644 assets/img/icons/email.svg create mode 100644 assets/img/icons/facebook.svg create mode 100644 assets/img/icons/gitee.svg create mode 100644 assets/img/icons/github.svg create mode 100644 assets/img/icons/google.svg create mode 100644 assets/img/icons/instagram.svg create mode 100644 assets/img/icons/linkedin.svg create mode 100644 assets/img/icons/qq.svg create mode 100644 assets/img/icons/telegram.svg create mode 100644 assets/img/icons/web.svg create mode 100644 assets/img/icons/wechat.svg create mode 100644 assets/img/icons/weibo.svg create mode 100644 assets/img/icons/x.svg create mode 100644 assets/img/icons/youtube.svg create mode 100644 assets/img/person_background.png create mode 100644 assets/img/placeholder.svg create mode 100644 assets/img/widgets-original.png create mode 100644 assets/js/aksrt-runtime.js create mode 100644 assets/js/author.js create mode 100644 assets/js/cart-checkout.js create mode 100644 assets/js/cms-download.js create mode 100644 assets/js/cms-home-modules.js create mode 100644 assets/js/color-extract.js create mode 100644 assets/js/comment-ajax.js create mode 100644 assets/js/comment-tools.js create mode 100644 assets/js/content-protect.js create mode 100644 assets/js/conversation.js create mode 100644 assets/js/core/archive.js create mode 100644 assets/js/core/article.js create mode 100644 assets/js/core/comments.js create mode 100644 assets/js/core/dropdown.js create mode 100644 assets/js/core/footer-tabbar.js create mode 100644 assets/js/core/misc.js create mode 100644 assets/js/core/nav.js create mode 100644 assets/js/core/pagination.js create mode 100644 assets/js/core/scroll.js create mode 100644 assets/js/core/search.js create mode 100644 assets/js/core/slider.js create mode 100644 assets/js/core/theme.js create mode 100644 assets/js/credits.js create mode 100644 assets/js/docs-navigation.js create mode 100644 assets/js/download-status.js create mode 100644 assets/js/effects.js create mode 100644 assets/js/enhancements.js create mode 100644 assets/js/enhancements2.js create mode 100644 assets/js/enlighter/enlighterjs.min.css create mode 100644 assets/js/enlighter/enlighterjs.min.js create mode 100644 assets/js/follow.js create mode 100644 assets/js/forum-edit.js create mode 100644 assets/js/forum-governance.js create mode 100644 assets/js/front-submit.js create mode 100644 assets/js/frontend-translate.js create mode 100644 assets/js/gutenberg-blocks.js create mode 100644 assets/js/homepage-fixed.js create mode 100644 assets/js/input-expand.js create mode 100644 assets/js/instant-page.js create mode 100644 assets/js/loader.js create mode 100644 assets/js/main.js create mode 100644 assets/js/messages.js create mode 100644 assets/js/mini-touch.js create mode 100644 assets/js/mini-upload.js create mode 100644 assets/js/modal-auth.js create mode 100644 assets/js/order-center.js create mode 100644 assets/js/page-edit.js create mode 100644 assets/js/page-navs.js create mode 100644 assets/js/page-template.js create mode 100644 assets/js/passive-events.js create mode 100644 assets/js/post-share.js create mode 100644 assets/js/poster-share.js create mode 100644 assets/js/precode.js create mode 100644 assets/js/product-archive.js create mode 100644 assets/js/product-purchase.js create mode 100644 assets/js/qrcode.min.js create mode 100644 assets/js/rehydrate.js create mode 100644 assets/js/report.js create mode 100644 assets/js/reward.js create mode 100644 assets/js/routes/user-center.js create mode 100644 assets/js/routes/user-home.js create mode 100644 assets/js/section-navs.js create mode 100644 assets/js/share-data-builder.js create mode 100644 assets/js/sign-register.js create mode 100644 assets/js/site-notice.js create mode 100644 assets/js/slider-captcha.js create mode 100644 assets/js/svg-icon-helper.js create mode 100644 assets/js/svg-icon.js create mode 100644 assets/js/swiper-bundle.min.js create mode 100644 assets/js/video-player.js create mode 100644 assets/js/waterfall.js create mode 100644 assets/js/weixin-share.js create mode 100644 assets/js/widget-set.js create mode 100644 assets/js/yiyan.js create mode 100644 category.php create mode 100644 tag.php diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..ba0b509c --- /dev/null +++ b/.gitignore @@ -0,0 +1,24 @@ +# Local tooling / agent workspace +.claude/ +.compare/ + +# Project planning / internal docs +CLAUDE.md +ask-*.md +docs/ + +# Frontend build output and installed dependencies +assets/admin/build/ +assets/admin/node_modules/ +assets/admin/.vite-temp/ + +# PHP installed dependencies +vendor/ + +# Temporary / recovery helpers +restore-helper-monoliths.php + +# OS / editor noise +.DS_Store +Thumbs.db +*.log \ No newline at end of file diff --git a/assets/css/admin/admin-panel.css b/assets/css/admin/admin-panel.css new file mode 100644 index 00000000..8d876934 --- /dev/null +++ b/assets/css/admin/admin-panel.css @@ -0,0 +1,83 @@ +body.toplevel_page_aksrt-settings { + background: #f5f7fb; +} + +body.toplevel_page_aksrt-settings #wpcontent { + padding-left: 0; +} + +body.toplevel_page_aksrt-settings #wpbody-content { + padding-bottom: 0; +} + +body.toplevel_page_aksrt-settings #wpbody-content .wrap { + margin: 0; + padding: 0; +} + +body.toplevel_page_aksrt-settings #wpbody-content .wrap > h1:first-child { + display: none !important; +} + +body.toplevel_page_aksrt-settings #wpbody-content .notice, +body.toplevel_page_aksrt-settings #wpbody-content .updated, +body.toplevel_page_aksrt-settings #wpbody-content .error { + position: relative; + z-index: 3; + margin: 18px 20px 0 0; +} + +body.toplevel_page_aksrt-settings #collapse-menu { + display: none !important; +} + +#aksrt-admin-app { + position: relative; + min-height: calc(100vh - 32px); + isolation: isolate; + background: transparent; +} + +#aksrt-admin-app:empty::before { + content: "AKSRT 管理台加载中..."; + display: flex; + align-items: center; + justify-content: center; + min-height: calc(100vh - 32px); + color: #64748b; + font-size: 14px; + letter-spacing: 0.04em; +} + +.n-modal-mask, +.n-modal, +.n-message-container, +.n-notification-container, +.n-dialog-mask, +.n-dialog, +.n-popover, +.n-drawer-mask, +.n-drawer { + z-index: 100000 !important; +} + +@media screen and (max-width: 782px) { + /* 隐藏 WP 后台默认顶栏的多余间距 */ + body.toplevel_page_aksrt-settings #wpbody { + padding-top: 0; + } + + body.toplevel_page_aksrt-settings #wpcontent { + margin-left: 0 !important; + } + + #aksrt-admin-app, + #aksrt-admin-app:empty::before { + min-height: calc(100vh - 46px); + } + + /* 移动端把 WP 折叠菜单按钮藏掉,避免与自定义菜单按钮重叠 */ + body.toplevel_page_aksrt-settings #wp-admin-bar-menu-toggle { + display: none; + } +} diff --git a/assets/css/build/core.min.css.disabled b/assets/css/build/core.min.css.disabled new file mode 100644 index 00000000..63489b6e --- /dev/null +++ b/assets/css/build/core.min.css.disabled @@ -0,0 +1,1032 @@ +/** + * AKSRT Design Tokens v7 — 1:1 Zibll Alignment + * ------------------------------------------------------------ + * 单一真理源(Single Source of Truth) + * 所有颜色、字体、间距、动效都从此处读取,禁止在组件内硬编码。 + * 严格对齐 zibll main.css 的视觉值。 + */ + +:root { + /* ===== Primary — Zibll theme-color (#f04494 pink) ===== */ + --color-primary: #f04494; + --color-primary-hover: #e0307e; + --color-primary-active: #c9206d; + --color-primary-soft: rgba(240, 68, 148, 0.10); + --color-primary-softer: rgba(240, 68, 148, 0.05); + --color-on-primary: #FFFFFF; + + /* ===== Ink (text) — 对齐 zibll --key-color / --main-color / --muted-color ===== */ + --color-ink: #333333; /* zibll --key-color */ + --color-ink-2: #4e5358; /* zibll --main-color */ + --color-ink-3: #777777; /* zibll --muted-color */ + --color-ink-4: #999999; /* zibll --muted-2-color */ + + /* ===== Surface — 对齐 zibll --body-bg-color / --main-bg-color / --muted-bg-color ===== */ + --surface-page: #f5f6f7; /* zibll --body-bg-color */ + --surface-1: #FFFFFF; /* zibll --main-bg-color */ + --surface-2: #eeeeee; /* zibll --muted-bg-color */ + --surface-3: #e8e8e8; /* 输入框 / code */ + + /* ===== Borders — 对齐 zibll --main-border-color ===== */ + --color-line: rgba(50, 50, 50, 0.06); + --color-line-soft: rgba(0, 0, 0, 0.03); + + /* ===== State colors ===== */ + --color-success: #10B981; + --color-warning: #F59E0B; + --color-error: #EF4444; + --color-info: #3B82F6; + + /* ===== Accent (action green — zibll tabbar/CTA) ===== */ + --color-accent: #18a058; + --color-accent-soft: rgba(24, 160, 88, 0.12); + --color-accent-shadow: rgba(24, 160, 88, 0.28); + + /* ===== Fonts — 对齐 zibll(系统默认字体栈)===== */ + --font-display: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans SC", "PingFang SC", "Microsoft YaHei", sans-serif; + --font-body: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans SC", "PingFang SC", "Microsoft YaHei", sans-serif; + --font-ui: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans SC", "PingFang SC", "Microsoft YaHei", sans-serif; + --font-mono: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace; + + /* ===== Type scale ===== */ + --text-xs: 0.75rem; /* 12 */ + --text-sm: 0.875rem; /* 14 */ + --text-base: 1rem; /* 16 */ + --text-md: 1.125rem; /* 18 */ + --text-lg: 1.25rem; /* 20 */ + --text-xl: 1.5rem; /* 24 */ + --text-2xl: 1.875rem; /* 30 */ + --text-3xl: 2.25rem; /* 36 */ + --text-4xl: 3rem; /* 48 */ + --text-5xl: 3.75rem; /* 60 */ + --leading-tight: 1.2; + --leading-snug: 1.4; + --leading-normal: 1.6; /* zibll body line-height */ + --leading-relaxed: 1.6; + + /* ===== Spacing (4px base) ===== */ + --space-1: 4px; + --space-2: 8px; + --space-3: 12px; + --space-4: 16px; + --space-5: 20px; + --space-6: 24px; + --space-7: 32px; + --space-8: 40px; + --space-9: 48px; + --space-10: 64px; + --space-11: 80px; + --space-12: 96px; + + /* ===== Radius — 对齐 zibll --main-radius: 8px ===== */ + --radius-sm: 4px; + --radius: 8px; + --radius-lg: 8px; + --radius-xl: 12px; + --radius-pill: 100px; + --radius-avatar: 50%; + + /* ===== Shadows — 对齐 zibll --main-shadow: rgba(116,116,116,0.08) ===== */ + --shadow-sm: 0 0 10px rgba(116, 116, 116, 0.08); + --shadow: 0 0 10px rgba(116, 116, 116, 0.08); + --shadow-lg: 0 0 10px rgba(116, 116, 116, 0.12); + --shadow-drawer: 0 8px 40px rgba(0, 0, 0, 0.20); + + /* ===== Layout — 对齐 zibll --mian-max-width: 1200px ===== */ + --nav-height: 60px; + --container: 1200px; + --container-wide: 1440px; + --container-read: 720px; + --container-page: 860px; + --sidebar-width: 300px; + --content-gap: 48px; + --sidebar-bp: 1024px; + + /* ===== Motion ===== */ + --ease: cubic-bezier(.4, 0, .2, 1); + --ease-out: cubic-bezier(.16, 1, .3, 1); + --ease-spring: cubic-bezier(.34, 1.56, .64, 1); + --dur-fast: 0.15s; + --dur: 0.25s; + --dur-slow: 0.4s; + + /* ===== Focus Ring — 对齐 zibll focus-shadow-color ===== */ + --focus-ring: 0 0 2px 3px rgba(253, 83, 161, 0.4); + + /* ===== Z-index layers ===== */ + --z-dropdown: 100; + --z-sticky: 200; + --z-fixed: 300; + --z-overlay: 400; + --z-modal: 500; + --z-popover: 600; + --z-toast: 700; + --z-tooltip: 800; + + /* ===== Button sizes — 对齐 zibll ===== */ + --radius-btn: 4px; + --btn-sm-h: 28px; + --btn-md-h: 34px; + --btn-lg-h: 44px; + + /* ===== Card density — 对齐 zibll .box-body { padding: 15px } ===== */ + --card-padding: 15px; + --card-padding-sm: 10px; + --card-gap: 16px; + + /* ===== Skeleton loader ===== */ + --skeleton-base: var(--surface-2); + --skeleton-shine: var(--surface-1); + + /* ===== Extended tokens (used by components) ===== */ + --color-primary-light: var(--color-primary-soft); + --color-surface: var(--surface-1); + --color-line-strong: var(--color-line); + --color-bg-hover: var(--surface-2); + --color-border-light: var(--color-line-soft); + --color-fill: var(--surface-2); + --color-warning-bg: #fffbe6; + --color-warning-text: #ad6800; + + --text-secondary: var(--color-ink-3); + --text-tertiary: var(--color-ink-4); + + --surface-active: var(--surface-2); + --surface-card: var(--surface-1); + --surface-hover: var(--surface-2); + --surface-secondary: var(--surface-2); + + --radius-code: var(--radius); + --radius-full: 100px; + --shadow-xl: 0 0 10px rgba(116, 116, 116, 0.12); + --space-16: 64px; + --z-floating: 900; + + --transition-fast: 0.15s ease; + --transition-base: 0.25s ease; + + /* ===== Composite / Context tokens — 对齐 zibll ===== */ + --header-bg: var(--blur-bg); + --header-color: var(--color-ink-2); + --footer-bg: var(--surface-1); + --footer-color: var(--color-ink-4); + --blur-bg: rgba(255, 255, 255, 0.80); + --float-btn-bg: rgba(200, 200, 200, 0.40); + + /* ===== AKSRT-to-AKSRT canonical aliases ===== */ + --content-max: var(--container); + --font-heading: var(--font-ui); + --radius-card: var(--radius); + --radius-md: var(--radius); + --color-primary-50: var(--color-primary-soft); + --color-primary-dark: var(--color-primary-active); + --shadow-md: var(--shadow); + --mini-radius: calc(var(--radius) / 1.4); + --single-cover-scale: 35%; + + /* ===== Avatar size system — Zibll --this-size 等价 ===== */ + --aksrt-avatar-size-xs: 24px; + --aksrt-avatar-size-sm: 32px; + --aksrt-avatar-size: 40px; + --aksrt-avatar-size-lg: 56px; + --aksrt-avatar-size-xl: 80px; + + /* ===== Post card thumbnail scale ===== */ + --aksrt-card-thumb-scale: 56.25%; /* 16:9 */ + + /* ===== Multi-color palette (for buttons / badges / gradients) ===== */ + --aksrt-rose: #f43f5e; + --aksrt-rose-soft: rgba(244, 63, 94, 0.12); + --aksrt-blue: #3b82f6; + --aksrt-blue-soft: rgba(59, 130, 246, 0.12); + --aksrt-green: #10b981; + --aksrt-green-soft: rgba(16, 185, 129, 0.12); + --aksrt-orange: #f97316; + --aksrt-orange-soft:rgba(249, 115, 22, 0.12); + --aksrt-purple: #8b5cf6; + --aksrt-purple-soft:rgba(139, 92, 246, 0.12); + --aksrt-cyan: #06b6d4; + --aksrt-cyan-soft: rgba(6, 182, 212, 0.12); + --aksrt-yellow: #eab308; + --aksrt-yellow-soft:rgba(234, 179, 8, 0.12); + --aksrt-red: #ef4444; + --aksrt-red-soft: rgba(239, 68, 68, 0.12); + --aksrt-teal: #14b8a6; + --aksrt-teal-soft: rgba(20, 184, 166, 0.12); + --aksrt-indigo: #6366f1; + --aksrt-indigo-soft:rgba(99, 102, 241, 0.12); + --aksrt-pink: #ec4899; + --aksrt-pink-soft: rgba(236, 72, 153, 0.12); + + /* ===== VIP / special gradients ===== */ + --aksrt-vip-gold-1: #f6d365; + --aksrt-vip-gold-2: #fda085; + --aksrt-grad-sunset-1: #f093fb; + --aksrt-grad-sunset-2: #f5576c; + --aksrt-grad-ocean-1: #4facfe; + --aksrt-grad-ocean-2: #00f2fe; + --aksrt-grad-forest-1: #43e97b; + --aksrt-grad-forest-2: #38f9d7; + --aksrt-grad-night-1: #a18cd1; + --aksrt-grad-night-2: #fbc2eb; + --aksrt-grad-fire-1: #f83600; + --aksrt-grad-fire-2: #f9d423; + + /* ===== Component sizing ===== */ + --aksrt-toggle-w: 44px; + --aksrt-toggle-h: 24px; + --aksrt-stepper-h: 36px; + --aksrt-badge-h: 22px; + + /* ===== Legacy name bridge ===== */ + --text-1: var(--color-ink); + --text-2: var(--color-ink-2); + --text-3: var(--color-ink-3); + --border: var(--color-line); + --color-text-1: var(--color-ink); + --color-text-2: var(--color-ink-2); + --color-text-3: var(--color-ink-3); + --color-primary-bg: var(--color-primary-softer); + --color-danger: var(--color-error); +} + +/* ============================================================ + * Blur-bg fallback cascade (mirrors zibll behaviour) + * ============================================================ */ +@supports not ((-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px))) { + :root { + --blur-bg: var(--surface-1); + --header-bg: var(--surface-1); + } +} + +body.modal-open, +body.dialog-open { + --blur-bg: var(--surface-1); + --header-bg: var(--surface-1); +} + +body.modal-open .site-nav, +body.modal-open .footer-tabbar, +body.modal-open .float-right .float-btn, +body.dialog-open .site-nav, +body.dialog-open .footer-tabbar, +body.dialog-open .float-right .float-btn { + backdrop-filter: none !important; + -webkit-backdrop-filter: none !important; +} + +/* ============================================================ + * Dark Theme — 对齐 zibll .dark-theme (#292a2d 范围) + * ============================================================ */ +html.dark { + --color-ink: #f8fafc; + --color-ink-2: #e5eef7; + --color-ink-3: #b4b6bb; + --color-ink-4: #888a8f; + + --surface-page: #292a2d; + --surface-1: #323335; + --surface-2: #2d2e31; + --surface-3: #3a3b3e; + + --color-line: rgba(114, 114, 114, 0.1); + --color-line-soft: rgba(184, 184, 184, 0.02); + + --color-primary-soft: rgba(240, 68, 148, 0.16); + --color-primary-softer: rgba(240, 68, 148, 0.08); + + --color-primary-light: var(--color-primary-soft); + --color-surface: var(--surface-1); + --color-line-strong: var(--color-line); + --color-bg-hover: var(--surface-2); + --color-border-light: var(--color-line-soft); + --color-fill: var(--surface-2); + + --text-secondary: var(--color-ink-3); + --text-tertiary: var(--color-ink-4); + + --surface-active: var(--surface-2); + --surface-card: var(--surface-1); + --surface-hover: var(--surface-2); + --surface-secondary: var(--surface-2); + + --shadow-xl: 0 0 10px rgba(24, 24, 24, 0.15); + + --shadow-sm: 0 0 10px rgba(24, 24, 24, 0.1); + --shadow: 0 0 10px rgba(24, 24, 24, 0.1); + --shadow-lg: 0 0 10px rgba(24, 24, 24, 0.15); + --shadow-drawer: 0 8px 40px rgba(0, 0, 0, 0.55); + + --blur-bg: rgba(50, 51, 53, 0.80); + --float-btn-bg: rgba(70, 70, 70, 0.40); + --header-bg: var(--blur-bg); + --footer-bg: var(--surface-1); + --footer-color: var(--color-ink-4); + --shadow-md: var(--shadow); + + --skeleton-base: #3a3b3e; + --skeleton-shine: #444548; + + /* Multi-color palette — dark mode: same hue, softer tint backgrounds */ + --aksrt-rose-soft: rgba(244, 63, 94, 0.18); + --aksrt-blue-soft: rgba(59, 130, 246, 0.18); + --aksrt-green-soft: rgba(16, 185, 129, 0.18); + --aksrt-orange-soft:rgba(249, 115, 22, 0.18); + --aksrt-purple-soft:rgba(139, 92, 246, 0.18); + --aksrt-cyan-soft: rgba(6, 182, 212, 0.18); + --aksrt-yellow-soft:rgba(234, 179, 8, 0.18); + --aksrt-red-soft: rgba(239, 68, 68, 0.18); + --aksrt-teal-soft: rgba(20, 184, 166, 0.18); + --aksrt-indigo-soft:rgba(99, 102, 241, 0.18); + --aksrt-pink-soft: rgba(236, 72, 153, 0.18); +} + +/* Dark mode component refinements */ +html.dark .site-nav { + border-bottom-color: var(--color-line); + box-shadow: none; +} + +html.dark .footer-tabbar { + background: rgba(50, 51, 53, 0.80); + box-shadow: 0 -1px 3px rgba(0, 0, 0, 0.20); +} + +html.dark .n-drawer, +html.dark .n-modal, +html.dark .n-dialog { + background: var(--surface-1); +} + +html.dark .post-card, +html.dark .widget, +html.dark .aksrt-theme-box, +html.dark .theme-box { + border-color: var(--color-line); +} +/** + * AKSRT Reset + * 现代精简 reset,结合 box-sizing 与 a11y 友好的默认值。 + */ + +*, +*::before, +*::after { + box-sizing: border-box; +} + +html { + font-size: 16px; + scroll-behavior: smooth; + -webkit-text-size-adjust: 100%; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + overflow-x: hidden; + text-rendering: optimizeLegibility; +} + +body { + margin: 0; + font-family: var(--font-body); + font-size: var(--text-base); + line-height: var(--leading-normal); + background-color: var(--surface-page); + color: var(--color-ink-2); + transition: background-color 0.25s ease, color 0.25s ease; + overflow-x: hidden; +} + +/* 媒体元素 */ +img, +picture, +video, +canvas, +svg { + display: block; + max-width: 100%; + height: auto; +} + +/* 表单元素继承字体 */ +input, +button, +textarea, +select { + font: inherit; + color: inherit; +} + +button { + background: none; + border: 0; + padding: 0; + cursor: pointer; +} + +/* 链接 */ +a { + color: inherit; + text-decoration: none; + transition: color var(--dur-fast) var(--ease); +} + +a:hover { + color: var(--color-primary); +} + +/* 焦点环:a11y 关键 */ +:focus { + outline: none; +} + +:focus-visible { + outline: none; + box-shadow: var(--focus-ring); + border-radius: 4px; +} + +/* 选区色 */ +::selection { + background: var(--color-primary-soft); + color: var(--color-ink); +} + +/* 屏幕阅读器隐藏 */ +.screen-reader-text, +.sr-only { + position: absolute !important; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border: 0; +} + +.screen-reader-text:focus, +.sr-only:focus { + position: fixed !important; + top: 16px; + left: 16px; + width: auto; + height: auto; + padding: 8px 16px; + background: var(--surface-1); + color: var(--color-ink); + z-index: 100000; + clip: auto; + box-shadow: var(--shadow-lg); + border-radius: var(--radius); +} + +/* 减少动效偏好 */ +@media (prefers-reduced-motion: reduce) { + *, + *::before, + *::after { + animation-duration: 0.01ms !important; + animation-iteration-count: 1 !important; + transition-duration: 0.01ms !important; + scroll-behavior: auto !important; + } +} +/** + * AKSRT Typography — 1:1 Zibll Alignment + * + * 对齐 zibll main.css 的排版系统 + */ + +/* ===== 全局标题 — 对齐 zibll line 8947 ===== */ +h1, h2, h3, h4, h5, h6 { + font-weight: 700; + margin: 20px 0 10px; + color: var(--key-color, #333); +} + +h1 { font-size: 22px; } +h2 { font-size: 20px; } +h3 { font-size: 18px; } +h4 { font-size: 16px; } +h5 { font-size: 15px; } +h6 { font-size: 14px; } + +/* ===== 文章正文 — 对齐 zibll line 8740 ===== */ +.wp-posts-content, +.entry-content, +.prose { + font-size: 16px; + line-height: 2; + color: var(--main-color, #4e5358); + min-height: 90px; +} + +/* ===== 文章内标题 — 对齐 zibll line 8947 ===== */ +.wp-posts-content h1, +.wp-posts-content h2, +.wp-posts-content h3, +.wp-posts-content h4, +.wp-posts-content h5, +.entry-content h1, +.entry-content h2, +.entry-content h3, +.entry-content h4, +.entry-content h5, +.prose h1, +.prose h2, +.prose h3, +.prose h4, +.prose h5 { + font-weight: 700; + margin: 20px 0 10px; + color: var(--key-color, #333); +} + +.wp-posts-content h1, +.entry-content h1, +.prose h1 { font-size: 22px; } + +.wp-posts-content h2, +.entry-content h2, +.prose h2 { font-size: 20px; } + +.wp-posts-content h3, +.entry-content h3, +.prose h3 { font-size: 18px; } + +.wp-posts-content h4, +.entry-content h4, +.prose h4 { font-size: 16px; } + +/* ===== 段落 — 对齐 zibll line 8999 ===== */ +.wp-posts-content p, +.entry-content p, +.prose p { + margin: 0 0 20px; + word-wrap: break-word; +} + +/* ===== 链接 — 对齐 zibll line 8836 ===== */ +.wp-posts-content a, +.entry-content a, +.prose a { + color: var(--focus-color, #f04494); + text-decoration: none; +} + +.wp-posts-content a:hover, +.entry-content a:hover, +.prose a:hover { + color: var(--focus-color, #f04494); +} + +/* ===== 图片 — 对齐 zibll line 8850 ===== */ +.wp-posts-content img, +.entry-content img, +.prose img { + max-width: 100%; + height: auto; + display: block; + margin: auto; +} + +/* ===== 内联代码 — 对齐 zibll line 8844 ===== */ +.wp-posts-content code:not(pre code), +.entry-content code:not(pre code), +.prose code:not(pre code) { + color: #ff3c98; + background: rgba(253, 153, 153, 0.2); + font-family: var(--font-mono, monospace); + font-size: 0.9em; +} + +/* ===== 代码块 — 对齐 zibll ===== */ +.wp-posts-content pre, +.entry-content pre, +.prose pre { + position: relative; + background: #282c34; + color: #abb2bf; + padding: 15px; + border-radius: var(--main-radius, 8px); + overflow-x: auto; + font-size: 14px; + line-height: 1.5; + margin: 0 0 20px; +} + +.wp-posts-content pre code, +.entry-content pre code, +.prose pre code { + color: inherit; + background: none; + padding: 0; + font-size: inherit; +} + +/* ===== 表格 — 对齐 zibll line 8897 ===== */ +.wp-posts-content table, +.entry-content table, +.prose table { + font-size: 14px; + width: 100%; + border-collapse: collapse; + margin: 0 0 20px; +} + +.wp-posts-content th, +.wp-posts-content td, +.entry-content th, +.entry-content td, +.prose th, +.prose td { + border: 1px solid var(--main-border-color, rgba(50, 50, 50, 0.06)); + padding: 8px; +} + +.wp-posts-content th, +.entry-content th, +.prose th { + background: var(--muted-border-color, rgba(0, 0, 0, 0.03)); + font-weight: 700; +} + +.wp-posts-content tr:hover, +.entry-content tr:hover, +.prose tr:hover { + background-color: rgba(240, 68, 148, 0.05); +} + +/* ===== 列表 — 对齐 zibll line 8977 ===== */ +.wp-posts-content ul, +.wp-posts-content ol, +.entry-content ul, +.entry-content ol, +.prose ul, +.prose ol { + margin: 10px 0 20px 15px; + padding-left: 15px; +} + +.wp-posts-content li, +.entry-content li, +.prose li { + margin-bottom: 10px; +} + +/* ===== 引用 — 对齐 zibll line 680 ===== */ +.wp-posts-content blockquote, +.entry-content blockquote, +.prose blockquote { + padding: 15px 20px; + margin: 0 0 20px; + border-left: 4px solid var(--main-border-color, rgba(50, 50, 50, 0.06)); + background: var(--muted-border-color, rgba(0, 0, 0, 0.03)); + font-size: 16px; + color: var(--muted-color, #777); + border-radius: 0; +} + +.wp-posts-content blockquote p:last-child, +.entry-content blockquote p:last-child, +.prose blockquote p:last-child { + margin-bottom: 0; +} + +/* ===== 水平分割线 — 对齐 zibll line 676 ===== */ +hr { + border-color: var(--main-border-color, rgba(50, 50, 50, 0.06)); +} + +/* ===== Strong / Bold ===== */ +strong, b { + font-weight: 700; +} +/** + * AKSRT Buttons — 1:1 Zibll Alignment + * + * 对齐 zibll .but 系统: + * - 正常字重 (normal) + * - 4px 圆角 + * - 灰色默认背景 + * - opacity hover + */ + +.btn, +.btn-primary, +.btn-outline, +.btn-ghost, +.btn-danger { + --btn-h: 34px; + --btn-px: 12px; + display: inline-flex; + align-items: center; + justify-content: center; + gap: 6px; + height: var(--btn-h); + padding: 0 var(--btn-px); + font-size: var(--text-sm); + font-weight: normal; + line-height: 1.44; + border: 1px solid transparent; + border-radius: var(--radius-btn); + cursor: pointer; + white-space: nowrap; + user-select: none; + text-decoration: none; + transition: opacity var(--dur-fast) var(--ease), + background var(--dur-fast) var(--ease), + border-color var(--dur-fast) var(--ease), + color var(--dur-fast) var(--ease); +} + +/* 尺寸变体 */ +.btn-sm { --btn-h: 28px; --btn-px: 8px; font-size: var(--text-xs); } +.btn-lg { --btn-h: 44px; --btn-px: 18px; font-size: var(--text-base); } + +/* === Default (gray background, like zibll .but default) === */ +.btn { + background: rgba(136, 136, 136, 0.1); + color: #888; +} + +.btn:hover { + opacity: 0.8; +} + +/* === Primary === */ +.btn-primary { + background: var(--color-primary); + color: var(--color-on-primary); + border-color: var(--color-primary); +} + +.btn-primary:hover { + opacity: 0.85; + color: var(--color-on-primary); +} + +.btn-primary:active { + opacity: 1; + box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15); +} + +/* === Outline === */ +.btn-outline { + background: transparent; + color: var(--color-ink-2); + border-color: var(--color-line); +} + +.btn-outline:hover { + border-color: var(--color-primary); + color: var(--color-primary); + opacity: 1; +} + +/* === Ghost === */ +.btn-ghost { + background: transparent; + color: var(--color-ink-2); + border-color: transparent; +} + +.btn-ghost:hover { + background: rgba(136, 136, 136, 0.1); + opacity: 1; +} + +/* === Danger === */ +.btn-danger { + background: var(--color-error); + color: #fff; + border-color: var(--color-error); +} + +.btn-danger:hover { + opacity: 0.85; + color: #fff; +} + +/* === Disabled === */ +.btn:disabled, +.btn-primary:disabled, +.btn-outline:disabled, +.btn-ghost:disabled, +.btn-danger:disabled { + opacity: 0.5; + cursor: not-allowed; + pointer-events: none; +} + +/* === Icon button === */ +.btn-icon { + width: var(--btn-h); + padding: 0; + justify-content: center; +} + +.btn-icon.btn-sm { width: 28px; } +.btn-icon.btn-lg { width: 44px; } + +/* === Full width === */ +.btn-block { + width: 100%; +} +/** + * AKSRT Forms — 1:1 Zibll Alignment + * + * 对齐 zibll .form-control: + * - 灰色背景 (#f5f6f7) + * - 透明边框 + * - 34px 高度 + * - 8px 圆角 + * - focus 时粉色边框 + 光晕 + */ + +/* ===== Field Wrapper ===== */ +.field { + display: flex; + flex-direction: column; + gap: 6px; + margin-bottom: var(--space-4); +} + +.field-label { + font-size: var(--text-sm); + font-weight: 600; + color: var(--color-ink); +} + +.field-help { + font-size: var(--text-xs); + color: var(--color-ink-3); +} + +.field-error { + font-size: var(--text-xs); + color: var(--color-error); +} + +/* ===== Input / Textarea / Select — 对齐 zibll .form-control ===== */ +.input, +.textarea, +.select, +input[type="text"].form-input, +input[type="email"].form-input, +input[type="password"].form-input, +input[type="search"].form-input, +input[type="url"].form-input, +input[type="tel"].form-input, +textarea.form-textarea, +select.form-select { + width: 100%; + height: 34px; + padding: 6px 12px; + font-size: 14px; + color: var(--color-ink); + background: var(--surface-page); + border: 1px solid transparent; + border-radius: var(--radius); + transition: border-color var(--dur-fast) var(--ease), + box-shadow var(--dur-fast) var(--ease); +} + +.textarea, +textarea.form-textarea { + height: auto; + min-height: 120px; + padding: 12px; + line-height: var(--leading-snug); + resize: vertical; +} + +.input:hover, +.textarea:hover, +.select:hover { + border-color: var(--color-primary); +} + +.input:focus, +.textarea:focus, +.select:focus { + outline: none; + border-color: var(--color-primary); + box-shadow: 0 0 2px 3px rgba(253, 83, 161, 0.4); +} + +.input::placeholder, +.textarea::placeholder { + color: var(--color-ink-4); +} + +/* ===== Select ===== */ +.select, +select.form-select { + appearance: none; + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%23777' d='M6 8L1 3h10z'/%3E%3C/svg%3E"); + background-repeat: no-repeat; + background-position: right 12px center; + padding-right: 32px; +} + +/* ===== Checkbox / Radio ===== */ +.checkbox, +.radio { + display: inline-flex; + align-items: center; + gap: 8px; + cursor: pointer; + font-size: var(--text-sm); + color: var(--color-ink-2); +} + +.checkbox input, +.radio input { + width: 16px; + height: 16px; + accent-color: var(--color-primary); + cursor: pointer; +} + +/* ===== Input Group ===== */ +.input-group { + display: flex; + align-items: stretch; +} + +.input-group .input { + border-radius: var(--radius) 0 0 var(--radius); +} + +.input-group .btn { + border-radius: 0 var(--radius) var(--radius) 0; +} + +/* ===== Form Layout ===== */ +.form-row { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); + gap: var(--space-4); +} + +.form-actions { + display: flex; + gap: var(--space-3); + margin-top: var(--space-5); +} +/** + * AKSRT Alerts + * 统一提示组件:error / warning / info / success + * 用于替代各页面 inline 的 .login-error / .bind-error 等 + */ + +.alert { + display: flex; + align-items: flex-start; + gap: 10px; + padding: 12px 14px; + margin-bottom: var(--space-4); + font-size: var(--text-sm); + line-height: var(--leading-snug); + border-radius: var(--radius); + border: 1px solid transparent; +} + +.alert > svg { + flex-shrink: 0; + width: 18px; + height: 18px; + margin-top: 1px; +} + +.alert--error { + color: #B91C1C; + background: rgba(239, 68, 68, 0.08); + border-color: rgba(239, 68, 68, 0.3); +} + +.alert--warning { + color: #B45309; + background: rgba(245, 158, 11, 0.08); + border-color: rgba(245, 158, 11, 0.3); +} + +.alert--success { + color: #047857; + background: rgba(16, 185, 129, 0.08); + border-color: rgba(16, 185, 129, 0.3); +} + +.alert--info { + color: #1D4ED8; + background: rgba(59, 130, 246, 0.08); + border-color: rgba(59, 130, 246, 0.3); +} + +html.dark .alert--error { color: #FCA5A5; } +html.dark .alert--warning { color: #FCD34D; } +html.dark .alert--success { color: #6EE7B7; } +html.dark .alert--info { color: #93C5FD; } diff --git a/assets/css/build/frontend-base.min.css.disabled b/assets/css/build/frontend-base.min.css.disabled new file mode 100644 index 00000000..0c121953 --- /dev/null +++ b/assets/css/build/frontend-base.min.css.disabled @@ -0,0 +1,5701 @@ +/** + * AKSRT Main v5 — 博客/个人站完整前端 + */ + +/* 防止 hero 等使用 100vw / full-bleed 时产生横向滚动条 */ +html, +body { + overflow-x: clip; +} + +@supports not (overflow-x: clip) { + html, + body { + overflow-x: hidden; + } +} + +/* ========== 阅读进度条(单篇文章顶 fixed)========== */ +.reading-progress-bar { + position: fixed; + top: 0; + left: 0; + height: 3px; + width: 0%; + z-index: 9999; + pointer-events: none; + background: linear-gradient(90deg, var(--color-primary), var(--color-primary-light)); + transition: width 0.1s ease-out; +} + +/* 折叠 body 内注入的 BOM / 空白文本节点,防止产生多余行高间距 */ +body { + font-size: 0; + line-height: 0; +} + +/* ========== 站点外壳 ========== */ +.site-wrapper { + min-height: 100vh; + display: flex; + flex-direction: column; + font-size: var(--text-base); + line-height: var(--leading-normal); +} + +.site-main { + flex: 1; +} + +.container { + width: 100%; + max-width: var(--container); + margin: 0 auto; + padding: 0 16px; +} + +@media (min-width: 768px) { + .container { + padding: 0 24px; + } +} + +@media (min-width: 1200px) { + .container { + padding: 0 32px; + } +} + +/* ========== 通用空状态 ========== */ +.no-results { + padding: 48px 20px; + text-align: center; + color: var(--color-ink-3); +}/** + * Zibll Variable Compatibility Layer — Global Bridge + * + * Maps Zibll CSS variable names to AKSRT design tokens. + * This file allows existing Zibll-style markup and third-party components + * that reference Zibll variables to work correctly in AKSRT. + * + * @package AKSRT + */ + +/* ============================================================ + * Global bridge (all pages) + * Maps Zibll variables → AKSRT tokens so any Zibll-style markup works. + * ============================================================ */ +:root { + /* Layout (zibll typo preserved for compat) */ + --mian-max-width: var(--container, 1200px); + + /* Theme color — now matches zibll #f04494 */ + --theme-color: var(--color-primary, #f04494); + --focus-color: var(--color-primary, #f04494); + --focus-shadow-color: var(--color-primary-soft, rgba(253, 83, 161, 0.4)); + + /* Text hierarchy */ + --key-color: var(--color-ink); + --main-color: var(--color-ink-2); + --muted-color: var(--color-ink-3); + --muted-2-color: var(--color-ink-4); + --muted-3-color: #b1b1b1; + --muted-4-color: #d2d2d2; + + /* Surfaces & borders */ + --body-bg-color: var(--surface-page); + --main-bg-color: var(--surface-1); + --muted-bg-color: var(--surface-2); + --main-border-color: var(--color-line); + --muted-border-color: var(--color-line-soft); + --main-shadow: rgba(116, 116, 116, 0.08); + --main-radius: var(--radius, 8px); + + /* Radius variants */ + --mini-radius: calc(var(--main-radius) / 1.4); + + /* Blur / glass */ + --blur-bg: rgba(255, 255, 255, 0.8); + --float-btn-bg: rgba(200, 200, 200, 0.4); + + /* Header / footer composites */ + --header-bg: var(--blur-bg); + --header-color: var(--color-ink-2); + --footer-bg: var(--surface-1); + --footer-color: var(--color-ink-4); + + /* Cards — 对齐 zibll 70% */ + --posts-card-scale: 70%; + --posts-list-scale: 70%; + --single-cover-scale: 35%; +} + +/* ============================================================ + * Dark mode bridge — 对齐 zibll dark theme + * ============================================================ */ +html.dark { + --theme-color: var(--color-primary); + --focus-color: var(--color-primary); + --focus-shadow-color: rgba(253, 83, 161, 0.25); + --key-color: var(--color-ink); + --main-color: var(--color-ink-2); + --muted-color: var(--color-ink-3); + --muted-2-color: var(--color-ink-4); + --muted-3-color: #666; + --muted-4-color: #555; + --body-bg-color: var(--surface-page); + --main-bg-color: var(--surface-1); + --muted-bg-color: var(--surface-2); + --main-border-color: var(--color-line); + --muted-border-color: var(--color-line-soft); + --main-shadow: rgba(24, 24, 24, 0.1); + --blur-bg: rgba(50, 51, 53, 0.8); + --float-btn-bg: rgba(70, 70, 70, 0.4); + --header-color: var(--color-ink-2); + --footer-color: var(--color-ink-4); +} +/** + * AKSRT Card Primitives — 1:1 Zibll Alignment + * + * 对齐 zibll 的 .theme-box / .box-bg / .box-body / .box-header: + * 阴影优先,无边框,8px 圆角,15px 内边距。 + * + * @package AKSRT + */ + +/* ============================================================ + * .aksrt-theme-box — 完整卡片原语(阴影 + 圆角 + 表面) + * 对齐 zibll .theme-box + .box-bg + * ============================================================ */ +.aksrt-theme-box { + border: none; + border-radius: var(--radius); + background: var(--surface-1); + box-shadow: var(--shadow-sm); + transition: box-shadow var(--dur) var(--ease); +} + +.aksrt-theme-box:hover { + box-shadow: var(--shadow); +} + +/* ============================================================ + * .aksrt-box-bg — 表面原语(仅背景 + 阴影) + * ============================================================ */ +.aksrt-box-bg { + background-color: var(--surface-1); + box-shadow: var(--shadow-sm); +} + +/* ============================================================ + * .aksrt-box-body / .aksrt-box-header — 内边距区段 + * 对齐 zibll .box-body / .box-header { padding: 15px } + * ============================================================ */ +.aksrt-box-body, +.aksrt-box-header { + padding: var(--card-padding); +} + +.aksrt-box-header { + border-bottom: 1px solid var(--color-line-soft); +} + +.aksrt-box-header + .aksrt-box-body { + padding-top: 0; +} + +.aksrt-box-body.notop, +.aksrt-box-header.notop { padding-top: 0; } +.aksrt-box-body.nobottom, +.aksrt-box-header.nobottom { padding-bottom: 0; } + +/* ============================================================ + * .aksrt-muted-box — 柔和背景嵌套 + * 对齐 zibll .muted-box + * ============================================================ */ +.aksrt-muted-box { + background-color: var(--surface-2); + border-radius: var(--radius); + padding: var(--card-padding); +} + +/* ============================================================ + * .aksrt-noshadow — 去除阴影 + * ============================================================ */ +.aksrt-noshadow { + box-shadow: none !important; +} + +/* ============================================================ + * Zibll 兼容别名 + * ============================================================ */ +.theme-box { + background: var(--surface-1); + border: none; + border-radius: var(--radius); + box-shadow: var(--shadow-sm); + margin-bottom: 20px; + transition: box-shadow var(--dur) var(--ease); +} + +.theme-box:hover { + box-shadow: var(--shadow); +} + +.box-bg { + background-color: var(--surface-1); + box-shadow: var(--shadow-sm); +} + +.box-body { + padding: var(--card-padding); +} + +.box-header { + padding: var(--card-padding); + border-bottom: 1px solid var(--color-line-soft); +} + +.box-header + .box-body { + padding-top: 0; +} + +.radius8 { + border-radius: var(--radius); +} + +.main-shadow { + box-shadow: var(--shadow); +} + +.muted-box { + background-color: var(--surface-2); + border-radius: var(--radius); + padding: var(--card-padding); +} + +/* ============================================================ + * 暗色模式 + * ============================================================ */ +html.dark .aksrt-theme-box, +html.dark .theme-box, +html.dark .box-bg { + box-shadow: var(--shadow-sm); +} + +html.dark .aksrt-theme-box:hover, +html.dark .theme-box:hover { + box-shadow: var(--shadow); +} + +/* ============================================================ + * 卡片 hover 动效 + * ============================================================ */ +.aksrt-theme-box, +.theme-box { + transition: box-shadow var(--dur) var(--ease), transform var(--dur) var(--ease); +} + +.aksrt-card-hover:hover, +.aksrt-card-hover:focus-within { + box-shadow: var(--shadow); + transform: translateY(-2px); +} + +.aksrt-card-hover-lg:hover, +.aksrt-card-hover-lg:focus-within { + box-shadow: var(--shadow-lg); + transform: translateY(-4px); +} + +.aksrt-noshadow:hover { + box-shadow: none !important; + transform: none !important; +} +/** + * AKSRT Overlay / Glass Primitives + * + * Provides backdrop-filter glass surfaces used by header, footer-tabbar, + * floating buttons and search overlays — matching zibll's blur system. + * + * @package AKSRT + */ + +/* ============================================================ + * .aksrt-blur-bg — generic glass surface + * Use on any element that needs a translucent blurred background. + * ============================================================ */ +.aksrt-blur-bg { + -webkit-backdrop-filter: saturate(5) blur(20px); + backdrop-filter: saturate(5) blur(20px); + background: var(--blur-bg); +} + +/* ============================================================ + * Glass on site-nav (when using fixed/sticky mode) + * Applied via .site-nav--blur already; this adds the zibll-grade + * saturate(5) blur(20px) instead of the lighter saturate(1.5) blur(18px). + * ============================================================ */ +.site-nav--glass { + -webkit-backdrop-filter: saturate(5) blur(20px); + backdrop-filter: saturate(5) blur(20px); + background: var(--blur-bg); + border-bottom-color: transparent; +} + +.site-nav--glass.is-scrolled { + box-shadow: 0 4px 10px rgba(20, 28, 48, 0.06); + border-bottom-color: var(--color-line-soft); +} + +html.dark .site-nav--glass.is-scrolled, +html.dark .site-nav--glass.is-scrolled { + box-shadow: 0 4px 10px rgba(0, 0, 0, 0.25); +} + +/* ============================================================ + * Glass on footer-tabbar (already uses backdrop-filter in footer.css; + * this class can be toggled to match zibll's exact blur spec) + * ============================================================ */ +.footer-tabbar--glass { + -webkit-backdrop-filter: saturate(5) blur(20px); + backdrop-filter: saturate(5) blur(20px); + background: var(--blur-bg); + box-shadow: 0 -4px 5px rgba(20, 28, 48, 0.06); +} + +html.dark .footer-tabbar--glass, +html.dark .footer-tabbar--glass { + box-shadow: 0 -4px 5px rgba(0, 0, 0, 0.25); +} + +/* ============================================================ + * Glass on floating buttons (lighter blur: saturate(2) blur(10px)) + * ============================================================ */ +.float-right--glass .float-btn { + -webkit-backdrop-filter: saturate(2) blur(10px); + backdrop-filter: saturate(2) blur(10px); + background: var(--float-btn-bg); + border-color: transparent; +} + +/* ============================================================ + * Scroll shadow on glass header (zibll: .body-scroll .header) + * ============================================================ */ +body.has-scrolled .site-nav--glass { + box-shadow: 0 4px 10px rgba(20, 28, 48, 0.06); +} + +html.dark body.has-scrolled .site-nav--glass, +html.dark body.has-scrolled .site-nav--glass { + box-shadow: 0 4px 10px rgba(0, 0, 0, 0.25); +} +/* ============================================================ + * AKSRT Navigation — Editorial v3.4 + * + * - 高度 60px (--nav-h) + * - 字体使用 --font-ui (Inter / 思源黑体) + * - 主色蓝调,hover 改为 primary-soft 浅底 + * - 永远实心:白底深字 + 1px 分隔线,滚动后追加 box-shadow + * - 移动端:≤768 显示汉堡菜单 + * ============================================================ */ + +.site-nav { + position: sticky; + top: 0; + z-index: 1000; + min-height: var(--nav-height, 60px); + border-bottom: 1px solid var(--color-line); + background-color: var(--blur-bg); + backdrop-filter: saturate(5) blur(20px); + -webkit-backdrop-filter: saturate(5) blur(20px); + transition: background-color 0.25s ease, + border-color 0.25s ease, + color 0.25s ease, + box-shadow 0.25s ease; +} + +.site-nav--static { + position: relative; +} + +.site-nav--transparent { + background: var(--blur-bg); + border-bottom-color: var(--color-line-soft); +} + +.site-nav--transparent.is-scrolled { + background: var(--blur-bg); +} + +.site-nav--blur { + background: var(--blur-bg); + backdrop-filter: saturate(5) blur(20px); + -webkit-backdrop-filter: saturate(5) blur(20px); + border-bottom-color: transparent; +} + +html.dark .site-nav--transparent, +html.dark .site-nav--blur, +html.dark .site-nav--transparent, +html.dark .site-nav--blur { + background: var(--blur-bg); + border-bottom-color: var(--color-line-soft); +} + +/* 滚动后追加轻阴影作为状态反馈(颜色不变) */ +.site-nav.is-scrolled { + box-shadow: var(--shadow-sm, 0 1px 6px rgba(0, 0, 0, 0.06)); +} + +/* WordPress Admin Bar 已全局禁用,无需偏移规则 */ + +/* ============================================================ + * Inner / Row layout + * ============================================================ */ +.site-nav__inner { + max-width: var(--nav-max-width, var(--container)); + margin: 0 auto; + padding: 0 15px; + display: flex; + flex-direction: column; + gap: 0; +} + +.site-nav__row { + display: flex; + align-items: center; + justify-content: flex-start; + gap: 12px; + width: 100%; + min-height: var(--nav-height, 60px); +} + +/* ============================================================ + * Brand + * ============================================================ */ +.site-brand { + display: inline-flex; + align-items: center; + gap: 10px; + min-width: 0; + max-width: min(48vw, 360px); + padding: 7px 10px; + color: var(--color-ink); + font-size: 1.0625rem; + font-weight: 700; + letter-spacing: -0.01em; + flex-shrink: 0; + text-decoration: none; +} + +.site-brand:hover { + color: var(--color-ink); + text-decoration: none; +} + +.site-brand--has-logo { + gap: 0; +} + +.site-brand__logo { + width: 36px; + height: 36px; + border-radius: 8px; + display: flex; + align-items: center; + justify-content: center; + font-weight: 800; + font-size: 13px; + color: var(--color-on-primary, #fff); + background: linear-gradient(135deg, var(--color-primary), var(--color-primary-active, var(--color-primary-dark))); + letter-spacing: 0.02em; + overflow: hidden; +} + +.site-brand__media { + display: block; + flex: 0 1 auto; + max-width: 100%; + padding: 0 30px; + line-height: 0; + box-sizing: border-box; + background: transparent !important; + border: 0; + border-radius: 0; + box-shadow: none; + filter: none !important; + opacity: 1; +} + +.site-brand__img { + display: block; + height: 36px; + width: auto; + max-width: 100%; + object-fit: contain; + object-position: left center; + background: transparent !important; + border-radius: 0; + box-shadow: none; + filter: none !important; + mix-blend-mode: normal !important; + opacity: 1; + transform: none !important; +} + +.site-brand__name { + font-weight: 700; + letter-spacing: -0.01em; + white-space: nowrap; +} + +/* ============================================================ + * Desktop menu + * ============================================================ */ +ul.nav-desktop { + display: none; + list-style: none; + margin: 0; + padding: 0; + align-items: center; + flex: 1 1 auto; + min-width: 0; +} + +.nav-desktop--fallback { + display: none; + align-items: center; + flex: 1 1 auto; + min-width: 0; +} + +ul.nav-desktop a, +.nav-desktop--fallback a { + color: var(--color-ink-3); + font-size: 15px; + font-weight: 500; + padding: 8px 10px; + border-radius: 4px; + transition: color var(--dur-fast, 0.15s) var(--ease), + background var(--dur-fast, 0.15s) var(--ease); +} + +/* Hover — 对齐 zibll: 仅变色,无背景 */ +ul.nav-desktop a:hover, +.nav-desktop--fallback a:hover { + color: var(--color-primary); + background: transparent; +} + +/* Active page — 对齐 zibll: 顶部彩色条指示器 */ +ul.nav-desktop .current-menu-item > a, +ul.nav-desktop .current_page_item > a { + color: var(--color-primary); + background: transparent; + position: relative; +} + +ul.nav-desktop .current-menu-item > a::before, +ul.nav-desktop .current_page_item > a::before { + content: ''; + position: absolute; + top: 0; + left: 0; + right: 0; + height: 3px; + background: var(--color-primary); + border-radius: 0 0 2px 2px; +} + +/* ============================================================ + * Desktop submenu (dropdown) + * ============================================================ */ +ul.nav-desktop .menu-item { + position: relative; +} + +ul.nav-desktop .sub-menu { + position: absolute; + top: 100%; + left: 0; + z-index: 998; + min-width: 200px; + list-style: none; + margin: 4px 0 0; + padding: 8px; + background: var(--main-bg-color, #fff); + border: 1px solid var(--main-border-color, rgba(50, 50, 50, 0.06)); + border-radius: var(--main-radius, 8px); + box-shadow: 0 6px 16px rgba(0, 0, 0, 0.08); + opacity: 0; + visibility: hidden; + transform: translateY(6px); + transition: opacity 0.2s ease, transform 0.2s ease, visibility 0.2s ease; +} + +ul.nav-desktop .menu-item:hover > .sub-menu { + opacity: 1; + visibility: visible; + transform: translateY(0); +} + +ul.nav-desktop .sub-menu .menu-item > a { + display: flex; + align-items: center; + gap: 8px; + padding: 8px 15px; + font-size: 14px; + border-radius: 4px; + white-space: nowrap; +} + +ul.nav-desktop .sub-menu .menu-item > a:hover { + background: var(--color-primary-soft, rgba(24, 144, 255, 0.08)); + color: var(--color-primary); +} + +/* Nested submenus fly out to the right */ +ul.nav-desktop .sub-menu .sub-menu { + top: -6px; + left: 100%; + margin: 0 0 0 4px; +} + +/* Dark mode submenu */ +html.dark ul.nav-desktop .sub-menu, +html.dark ul.nav-desktop .sub-menu { + background: var(--surface-page); + border-color: var(--color-line, #2d2d3f); +} + +/* ============================================================ + * Mega Menu (图文超级菜单) + * ============================================================ */ + +/* Mega Menu 容器:全宽定位 */ +ul.nav-desktop .mega-menu-item { + position: static; +} + +ul.nav-desktop .mega-menu-item > .mega-menu__panel { + position: absolute; + top: 100%; + left: 50%; + transform: translateX(-50%); + width: 100%; + max-width: var(--container); + min-width: auto; + padding: 16px; + margin-top: 4px; +} + +/* 列布局 */ +.mega-menu__columns-2 { + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: 8px; +} + +.mega-menu__columns-3 { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 8px; +} + +.mega-menu__columns-4 { + display: grid; + grid-template-columns: repeat(4, 1fr); + gap: 8px; +} + +.mega-menu__columns-5 { + display: grid; + grid-template-columns: repeat(5, 1fr); + gap: 8px; +} + +/* Mega Menu 子项(卡片样式) */ +.mega-menu__panel > .menu-item { + border-radius: 8px; + transition: background 0.15s; +} + +.mega-menu__panel > .menu-item:hover { + background: var(--surface-2, #F4F5F7); +} + +.mega-menu__panel > .menu-item > a { + display: flex; + align-items: center; + gap: 10px; + padding: 10px 12px; + font-size: 14px; + border-radius: 8px; + white-space: normal; + line-height: 1.4; +} + +.mega-menu__panel > .menu-item > a i { + width: 20px; + text-align: center; + color: var(--color-primary, var(--color-primary)); + flex-shrink: 0; +} + +/* 描述文字 */ +.mega-menu__item-desc { + display: block; + font-size: 12px; + color: var(--color-ink-4, #8A8F98); + margin-top: 2px; + line-height: 1.3; +} + +/* Mega Menu 标题分组 */ +.mega-menu__panel .mega-menu__group-title { + grid-column: 1 / -1; + padding: 8px 12px 4px; + font-size: 12px; + font-weight: 600; + color: var(--color-ink-3); + text-transform: uppercase; + letter-spacing: 0.05em; +} + +/* Mega Menu 底部区域(可放图片/CTA) */ +.mega-menu__panel .mega-menu__footer { + grid-column: 1 / -1; + padding: 12px 0 0; + margin-top: 8px; + border-top: 1px solid var(--color-line); +} + +/* Dark mode Mega Menu */ +html.dark ul.nav-desktop .mega-menu-item > .mega-menu__panel, +html.dark ul.nav-desktop .mega-menu-item > .mega-menu__panel { + background: var(--surface-page); + border-color: var(--color-line, #2d2d3f); +} + +html.dark .mega-menu__panel > .menu-item:hover, +html.dark .mega-menu__panel > .menu-item:hover { + background: var(--surface-2); +} + +/* Responsive Mega Menu */ +@media (max-width: 767px) { + ul.nav-desktop .mega-menu-item > .mega-menu__panel { + position: static; + transform: none; + width: 100%; + max-width: none; + } + + .mega-menu__columns-2, + .mega-menu__columns-3, + .mega-menu__columns-4, + .mega-menu__columns-5 { + grid-template-columns: 1fr; + } +} + +/* ============================================================ + * Right actions (icons + auth) + * ============================================================ */ +.nav-actions { + display: flex; + align-items: center; + gap: 4px; + flex-shrink: 0; + margin-left: auto; +} + +.nav-settings-link, +.nav-publish-btn { + flex-shrink: 0; +} + +.nav-settings-link svg { + width: 18px; + height: 18px; +} + +.nav-publish-btn { + display: inline-flex; + align-items: center; + gap: 8px; + height: 36px; + padding: 0 14px; + font-size: 0.875rem; + font-weight: 600; +} + +.nav-publish-btn i { + font-size: 0.8125rem; +} + +.theme-toggle.is-animating svg { + transform: rotate(360deg); +} + +/* ============================================================ + * Auth buttons (in nav, when logged out) + * ============================================================ */ +.nav-auth { + display: none; + align-items: center; + gap: 8px; +} + +/* btn-outline / btn-primary 复用 core/buttons.css 的定义, + * 这里仅做导航专用调整(高度对齐、字体) */ +.nav-auth .btn-outline, +.nav-auth .btn-primary { + height: 36px; + font-size: 0.875rem; + padding: 0 16px; +} + +/* Mobile toggle */ +.nav-toggle { + display: flex; +} + +@media (max-width: 991px) { + .site-brand { + max-width: min(46vw, 300px); + } + + .site-brand__media { + padding: 0 8px; + } + + .nav-publish-btn { + display: none; + } +} + +/* Desktop search icon: hide on mobile (use drawer search instead) */ +@media (max-width: 767px) { + .site-brand { + max-width: min(62vw, 260px); + padding: 7px 0; + } + + .site-brand__media { + padding: 0; + } + + #search-toggle { + display: none; + } + /* Search panel only makes sense alongside the desktop search icon */ + .nav-search-panel { + display: none !important; + } +} + +@media (min-width: 768px) { + ul.nav-desktop, + .nav-desktop--fallback { + display: flex; + } + + .nav-auth { + display: flex; + } + + .nav-toggle { + display: none; + } +} + +.nav-mobile-strip { + display: none; + width: calc(100% + 8px); + margin: 0 -4px; + padding: 0 0 12px; +} + +.nav-mobile-strip__menu, +.nav-mobile-strip__menu ul { + display: flex; + align-items: center; + gap: 8px; + overflow-x: auto; + margin: 0; + padding: 0; + list-style: none; + scrollbar-width: none; + -ms-overflow-style: none; +} + +.nav-mobile-strip__menu::-webkit-scrollbar, +.nav-mobile-strip__menu ul::-webkit-scrollbar { + display: none; +} + +.nav-mobile-strip__menu a { + display: inline-flex; + align-items: center; + min-height: 34px; + padding: 0 12px; + border-radius: var(--radius-pill, 999px); + background: var(--surface-2); + color: var(--color-ink-2); + white-space: nowrap; + text-decoration: none; + font-size: 0.875rem; + font-weight: 500; +} + +.nav-mobile-strip__menu .current-menu-item > a, +.nav-mobile-strip__menu .current_page_item > a { + background: var(--color-primary); + color: var(--color-on-primary, #fff); +} + +@media (max-width: 767px) { + .nav-mobile-strip { + display: block; + } +} + +/* ============================================================ + * User avatar + dropdown + * ============================================================ */ +.nav-user { + position: relative; +} + +.nav-user__toggle { + width: 40px; + height: 40px; + border-radius: var(--radius-avatar); + padding: 0; + border: 2px solid var(--color-line); + cursor: pointer; + overflow: hidden; + background: var(--surface-2); + transition: border-color var(--dur-fast, 0.15s) var(--ease); +} + +.nav-user__toggle:hover { + border-color: var(--color-primary); +} + +.nav-user__toggle img { + width: 100%; + height: 100%; + object-fit: cover; + display: block; +} + +.user-dropdown { + position: absolute; + top: calc(100% + 8px); + right: 0; + width: 260px; + max-width: calc(100vw - 32px); + padding: 12px 0; + background: var(--surface-1); + border: 1px solid var(--color-line); + border-radius: var(--radius-lg, 8px); + box-shadow: var(--shadow-lg); + z-index: 1100; + opacity: 0; + visibility: hidden; + transform: translateY(-6px); + transition: opacity 0.2s, transform 0.2s, visibility 0.2s; +} + +.user-dropdown.is-open { + opacity: 1; + visibility: visible; + transform: translateY(0); +} + +.user-dropdown__profile { + display: flex; + align-items: center; + gap: 12px; + padding: 8px 16px 14px; +} + +.user-dropdown__profile img { + width: 44px; + height: 44px; + border-radius: var(--radius-avatar); + object-fit: cover; + flex-shrink: 0; +} + +.user-dropdown__name { + font-weight: 700; + font-size: 0.9375rem; + color: var(--color-ink); +} + +.user-dropdown__email { + font-size: 0.75rem; + color: var(--color-ink-4); + word-break: break-all; + margin-top: 2px; +} + +.user-dropdown__sep { + height: 1px; + background: var(--color-line); + margin: 6px 0; +} + +.user-dropdown a, +.user-dropdown button { + display: flex; + align-items: center; + gap: 10px; + width: 100%; + padding: 0 16px; + height: 44px; + border: none; + background: none; + font-size: 0.875rem; + color: var(--color-ink); + text-align: left; + cursor: pointer; + transition: background var(--dur-fast, 0.15s) var(--ease), + color var(--dur-fast, 0.15s) var(--ease); +} + +.user-dropdown a:hover, +.user-dropdown button:hover { + background: var(--surface-3); + color: var(--color-primary-active); +} + +/* dropdown 项内的 SVG 图标 */ +.user-dropdown__item svg { + width: 16px; + height: 16px; + flex-shrink: 0; + opacity: 0.85; +} + +.user-dropdown__item span:first-of-type:not(.user-dropdown__pill) { + flex: 1; + min-width: 0; +} + +/* 未读消息数 badge */ +.user-dropdown__badge { + display: inline-flex; + align-items: center; + justify-content: center; + min-width: 18px; + height: 18px; + padding: 0 5px; + margin-left: auto; + font-size: 11px; + font-weight: 600; + color: #fff; + background: var(--color-error, #ef4444); + border-radius: 9px; + line-height: 1; +} + +.user-dropdown__credits { + display: flex; + align-items: center; + gap: 10px; + padding: 0 16px; + height: 44px; + font-size: 0.875rem; + color: var(--color-ink-2); +} + +.user-dropdown__credits i { + color: var(--color-warning); + flex-shrink: 0; +} + +.user-dropdown__credits-label { + flex: 1; +} + +.user-dropdown__credits-value { + font-weight: 600; + color: var(--color-primary); +} + +.user-dropdown__logout { + color: var(--color-error) !important; +} + +.user-dropdown__logout svg { + color: var(--color-error); +} + +.user-dropdown__logout:hover { + background: rgba(239, 68, 68, 0.08) !important; + color: var(--color-error) !important; +} + +.user-dropdown .badge-dot { + margin-left: auto; + min-width: 8px; + height: 8px; + border-radius: var(--radius-pill); + background: var(--color-error); +} + +/* ============================================================ + * Search panel + * ============================================================ */ +.nav-search-panel { + display: none; + padding: 12px 0 16px; + border-top: 1px solid var(--color-line); +} + +.nav-search-panel.is-open { + display: block; +} + +.nav-searchbox { + margin: 0; +} + +.nav-searchbox__field { + display: flex; + align-items: center; + gap: 10px; + min-height: 42px; + padding: 0 6px 0 14px; + border: 1px solid var(--color-line); + border-radius: var(--radius-pill, 999px); + background: var(--surface-3); + box-sizing: border-box; + transition: border-color var(--dur-fast, 0.15s) var(--ease), box-shadow var(--dur-fast, 0.15s) var(--ease), background var(--dur-fast, 0.15s) var(--ease); +} + +.nav-searchbox__icon { + order: 1; + flex: 0 0 16px; + width: 16px; + height: 16px; + color: var(--color-ink-4); + pointer-events: none; +} + +.nav-searchbox__input { + order: 2; + flex: 1; + min-width: 0; + width: auto; + height: 40px; + padding: 0; + border: 0; + background: transparent; + color: var(--color-ink); + font-size: 0.9rem; + line-height: 1.2; + box-sizing: border-box; +} + +.nav-searchbox__input:focus { + outline: none; +} + +.nav-searchbox__input::placeholder { + color: var(--color-ink-4); +} + +.nav-searchbox__submit { + order: 3; + flex: 0 0 auto; + height: 30px; + min-width: 64px; + padding: 0 14px; + border: 0; + border-radius: var(--radius-pill, 999px); + background: var(--color-primary); + color: #fff; + font-size: 0.8125rem; + font-weight: 600; + line-height: 1; + white-space: nowrap; + cursor: pointer; +} + +.nav-searchbox__field:focus-within { + border-color: var(--color-primary); + box-shadow: 0 0 0 3px var(--color-primary-soft); + background: var(--surface-1); +} + +.nav-searchbox__submit:hover { + background: var(--color-primary-active); +} + +/* ============================================================ + * Mobile drawer + * ============================================================ */ +.nav-drawer-backdrop { + position: fixed; + inset: 0; + background: rgba(0, 0, 0, 0.45); + z-index: 1200; + opacity: 0; + visibility: hidden; + transition: opacity 0.3s ease, visibility 0.3s; +} + +.nav-drawer-backdrop.is-open { + opacity: 1; + visibility: visible; +} + +.nav-drawer { + position: fixed; + top: 0; + right: 0; + width: min(100vw, 360px); + height: 100vh; + max-height: 100dvh; + background: var(--surface-page); + z-index: 1210; + box-shadow: var(--shadow-drawer); + transform: translateX(100%); + transition: transform 0.32s var(--ease-out, ease); + display: flex; + flex-direction: column; + overflow: auto; + pointer-events: none; + visibility: hidden; +} + +.nav-drawer.is-open { + transform: translateX(0); + pointer-events: auto; + visibility: visible; +} + +.nav-drawer__head { + display: flex; + align-items: center; + justify-content: space-between; + gap: 16px; + padding: 16px 20px; + border-bottom: 1px solid var(--color-line); + font-weight: 700; + font-size: 1rem; +} + +.site-brand--drawer { + max-width: calc(100% - 52px); + padding: 7px 0; +} + +.site-brand--drawer .site-brand__media { + padding: 0; +} + +.nav-drawer__search { + padding: 16px 20px 0; +} + +.nav-drawer__search .nav-searchbox__field { + min-height: 40px; +} + +.nav-drawer__search .nav-searchbox__input { + height: 38px; +} + +.nav-drawer__search .nav-searchbox__submit { + height: 28px; + min-width: 58px; + padding: 0 12px; + font-size: 0.75rem; +} + +.nav-drawer__menu { + flex: 1; + padding: 16px 20px 32px; +} + +.nav-drawer__menu a { + display: block; + padding: 14px 0; + font-size: 1rem; + font-weight: 500; + color: var(--color-ink); + border-bottom: 1px solid var(--color-line-soft); +} + +.nav-drawer__menu a:hover { + color: var(--color-primary-active); +} + +.nav-drawer__menu ul { + list-style: none; + margin: 0; + padding: 0; +} + +.nav-drawer__auth { + padding: 20px; + display: flex; + flex-direction: column; + gap: 12px; + border-top: 1px solid var(--color-line); +} + +.nav-drawer__auth .btn-outline, +.nav-drawer__auth .btn-primary { + width: 100%; + height: 44px; +} + +.nav-drawer__publish { + padding: 0 20px 20px; +} + +.nav-drawer__publish .btn-primary { + width: 100%; + min-height: 44px; + justify-content: center; + gap: 8px; +} + +/* ============================================================ + * Menu Decoration — Icons, Badges, Hover Effects + * ============================================================ */ + +/* Menu item icon */ +.aksrt-nav__icon { + font-size: 0.85em; + width: 1.2em; + text-align: center; + margin-right: 4px; + opacity: 0.7; + transition: opacity 0.2s; +} + +.aksrt-nav__item--has-icon > a { + display: inline-flex; + align-items: center; + gap: 4px; +} + +.aksrt-nav__item--has-icon:hover .aksrt-nav__icon { + opacity: 1; +} + +/* Menu item badge */ +.aksrt-nav__badge { + display: inline-flex; + align-items: center; + justify-content: center; + font-size: 10px; + font-weight: 600; + line-height: 1; + padding: 2px 5px; + border-radius: 3px; + margin-left: 4px; + white-space: nowrap; + vertical-align: middle; + transform: translateY(-1px); +} + +.aksrt-nav__badge--new { + color: #fff; + background: var(--color-error); +} + +.aksrt-nav__badge--hot { + color: #fff; + background: var(--color-warning); +} + +.aksrt-nav__badge--info { + color: #fff; + background: var(--color-info); +} + +.aksrt-nav__badge--success { + color: #fff; + background: var(--color-success); +} + +.aksrt-nav__badge--vip { + color: #fff; + background: linear-gradient(135deg, var(--color-warning), var(--color-error)); +} + +/* Hover effects */ +.aksrt-nav__item--hover-underline > a::after { + content: ''; + position: absolute; + bottom: 0; + left: 50%; + width: 0; + height: 2px; + background: var(--color-primary); + transition: width 0.2s ease, left 0.2s ease; + border-radius: 1px; +} + +.aksrt-nav__item--hover-underline:hover > a::after { + width: 60%; + left: 20%; +} + +.aksrt-nav__item--hover-background > a { + transition: background-color 0.2s; + border-radius: 4px; +} + +.aksrt-nav__item--hover-background:hover > a { + background-color: var(--color-primary-soft, rgba(24, 144, 255, 0.08)); +} + +.aksrt-nav__item--hover-color > a { + transition: color 0.2s; +} + +.aksrt-nav__item--hover-color:hover > a { + color: var(--color-primary); +} + +/* Mega submenu */ +.aksrt-nav__mega { + position: absolute; + top: 100%; + left: 0; + z-index: 1001; + background: var(--surface-1); + border: 1px solid var(--color-line); + border-radius: var(--radius); + box-shadow: var(--shadow-lg); + padding: 16px; + opacity: 0; + visibility: hidden; + transform: translateY(8px); + transition: opacity 0.2s ease, transform 0.2s ease, visibility 0.2s ease; +} + +.aksrt-nav__item:hover > .aksrt-nav__mega { + opacity: 1; + visibility: visible; + transform: translateY(0); +} + +.aksrt-nav__mega--columns { + display: grid; + gap: 16px; +} + +/* Cards submenu */ +.aksrt-nav__cards { + display: grid; + gap: 12px; + padding: 8px; +} + +.aksrt-nav__card { + display: flex; + align-items: center; + gap: 12px; + padding: 10px 12px; + border-radius: 6px; + text-decoration: none; + color: inherit; + transition: background 0.15s; +} + +.aksrt-nav__card:hover { + background: var(--color-primary-soft, rgba(24, 144, 255, 0.06)); +} + +.aksrt-nav__card-icon { + width: 36px; + height: 36px; + border-radius: 8px; + display: flex; + align-items: center; + justify-content: center; + background: var(--color-primary-soft, #e6f4ff); + color: var(--color-primary); + font-size: 16px; + flex-shrink: 0; +} + +.aksrt-nav__card-text { + flex: 1; + min-width: 0; +} + +.aksrt-nav__card-title { + font-size: 13px; + font-weight: 600; + color: var(--color-ink); + margin: 0; +} + +.aksrt-nav__card-desc { + font-size: 11px; + color: var(--color-ink-4); + margin: 2px 0 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +/* ============================================================ + * 导航溢出「更多」下拉 + * ============================================================ */ +.aksrt-nav-more { + position: relative; +} + +.aksrt-nav-more__btn { + display: inline-flex; + align-items: center; + gap: 4px; + padding: 6px 12px; + border: none; + background: none; + color: var(--color-ink-2); + font-size: 14px; + font-weight: 500; + cursor: pointer; + border-radius: var(--radius, 8px); + transition: background 0.15s, color 0.15s; +} + +.aksrt-nav-more__btn:hover { + background: var(--color-primary-soft, rgba(240, 68, 148, 0.08)); + color: var(--color-primary); +} + +.aksrt-nav-more__dropdown { + display: none; + position: absolute; + top: 100%; + right: 0; + min-width: 160px; + padding: 6px 0; + background: var(--surface-1, #fff); + border: 1px solid var(--color-line, rgba(50, 50, 50, 0.06)); + border-radius: var(--radius, 8px); + box-shadow: var(--shadow-lg, 0 0 10px rgba(116, 116, 116, 0.12)); + z-index: var(--z-dropdown, 100); + list-style: none; + margin: 4px 0 0; +} + +.aksrt-nav-more__dropdown.is-open { + display: block; +} + +.aksrt-nav-more__dropdown li { + display: block; +} + +.aksrt-nav-more__dropdown li a, +.aksrt-nav-more__dropdown li button { + display: block; + width: 100%; + padding: 8px 16px; + border: none; + background: none; + color: var(--color-ink-2); + font-size: 14px; + text-align: left; + text-decoration: none; + cursor: pointer; + transition: background 0.15s, color 0.15s; +} + +.aksrt-nav-more__dropdown li a:hover, +.aksrt-nav-more__dropdown li button:hover { + background: var(--color-primary-soft, rgba(240, 68, 148, 0.08)); + color: var(--color-primary); +} +/* ========== 面包屑 — 对齐 zibll .breadcrumb ========== */ +.breadcrumbs { + font-size: 13px; + color: var(--muted-2-color, #999); + margin-bottom: 12px; + opacity: 0.8; +} + +.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; + } +} + +/* 封面内面包屑 */ +.single-cover-con .breadcrumbs { + font-size: 13px; + margin: 5px 0 0 -6px; + opacity: unset; +} + +/* ========== 主布局 ========== */ +.content-shell { + width: 100%; + margin: 0 auto; + padding: 32px 16px 48px; + max-width: var(--container); +} + +@media (min-width: 768px) { + .content-shell { + padding: 40px 24px 56px; + } +} + +/* page.php 专用:阅读宽度收窄 */ +.content-shell--page { + max-width: var(--container-page, 860px); +} + +.content-shell--cms { + max-width: 100%; + padding: 0; +} + +/* page.php 内的元素 */ +.entry-page .entry-thumb { + margin: 0 0 var(--space-6, 24px); + border-radius: var(--radius-lg, 12px); + overflow: hidden; +} + +.entry-page .page-links { + margin-top: var(--space-6, 24px); + font-size: var(--text-sm, 0.875rem); + color: var(--color-ink-3, var(--color-ink-3)); +} + +.entry-page .page-links-title { + margin-right: 8px; + font-weight: 600; +} + +.content-layout { + display: grid; + grid-template-columns: 1fr; + gap: 20px; + align-items: start; +} + +@media (min-width: 992px) { + .content-layout { + grid-template-columns: minmax(0, 1fr) 300px; + gap: 20px; + } +} + +.content-layout__primary { + min-width: 0; +} + +.content-layout__aside { + min-width: 0; +} + +@media (min-width: 992px) { + .content-layout__aside { + position: sticky; + top: calc(var(--nav-height, 60px) + 16px); + align-self: start; + } + + /* WordPress Admin Bar 已全局禁用,无需偏移规则 */ +} + +@media (min-width: 992px) { + .has-static-nav .content-layout__aside { + top: 16px; + } +} + +.content-layout--no-sidebar { + grid-template-columns: 1fr; +} + +.content-layout--no-sidebar .content-layout__primary { + width: 100%; + max-width: var(--content-no-sidebar-max, 1080px); + margin: 0 auto; +} + +/* 三栏布局变体:侧边栏在左侧 */ +@media (min-width: 992px) { + .content-layout--sidebar-left { + grid-template-columns: 300px minmax(0, 1fr); + } + + .content-layout--sidebar-left .content-layout__aside { + order: -1; + } +} + +/* ========== 分页 ========== */ +.pagination, +.navigation.pagination .nav-links { + display: flex; + flex-wrap: wrap; + align-items: center; + justify-content: center; + gap: 8px; + margin: 40px 0 8px; +} + +.pagination a, +.pagination span, +.navigation.pagination a, +.navigation.pagination span { + min-width: 40px; + height: 40px; + display: inline-flex; + align-items: center; + justify-content: center; + border-radius: var(--radius-btn); + border: 1px solid var(--color-line); + color: var(--color-ink); + font-size: 14px; + font-weight: 500; + transition: border-color 0.2s, color 0.2s, background 0.2s; +} + +.pagination a:hover { + border-color: var(--color-primary); + color: var(--color-primary); +} + +.pagination .current, +.navigation.pagination span.current { + background: var(--color-primary); + border-color: var(--color-primary); + color: #fff; +} + +.pagination .dots, +.navigation.pagination .dots { + border: none; + color: var(--color-ink-4); + min-width: auto; + padding: 0 4px; +} + +.pagination .prev, +.pagination .next, +.navigation.pagination a.prev, +.navigation.pagination a.next { + min-width: 44px; +} + +.pagination .disabled, +.navigation.pagination span.disabled { + opacity: 0.4; + pointer-events: none; +} + +/* ========== 页面标题区 ========== */ +.page-header { + margin-bottom: 28px; +} + +.page-header .entry-title { + margin-bottom: 8px; +} + +.page-header p { + color: var(--color-ink-3); + margin: 0; + max-width: 720px; +} + +.term-page-header { + position: relative; + overflow: hidden; + border: 1px solid var(--color-line-soft, rgba(15, 23, 42, 0.08)); + border-radius: var(--radius-lg); + background: var(--surface-1); + box-shadow: var(--shadow-sm, 0 1px 6px rgba(15, 23, 42, 0.04)); +} + +.term-page-header__body { + position: relative; + z-index: 1; + display: flex; + align-items: flex-start; + justify-content: space-between; + gap: 16px; + padding: 24px; +} + +.term-page-header__eyebrow { + margin: 0 0 8px; + font-size: 0.8125rem; + font-weight: 700; + letter-spacing: 0.08em; + text-transform: uppercase; + color: var(--color-primary); +} + +.term-page-header__desc { + margin-top: 10px; +} + +.term-page-header__cover { + min-height: 140px; + background-position: center; + background-size: cover; + border-top: 1px solid var(--color-line-soft, rgba(15, 23, 42, 0.08)); +} + +.term-page-header--simple .term-page-header__cover { + display: none; +} + +.aksrt-admin-quicklink { + display: inline-flex; + align-items: center; + gap: 8px; + min-height: 36px; + padding: 0 14px; + border: 1px solid var(--color-line); + border-radius: var(--radius-pill, 999px); + background: var(--surface-2); + color: var(--color-ink-2); + text-decoration: none; + white-space: nowrap; + font-size: 0.875rem; + font-weight: 600; +} + +.aksrt-admin-quicklink:hover { + color: var(--color-primary); + border-color: var(--color-primary); + background: var(--color-primary-soft, rgba(59, 130, 246, 0.08)); +} + +.archive-filter-bar { + display: flex; + align-items: center; + justify-content: space-between; + gap: 16px; + flex-wrap: wrap; + margin: -8px 0 24px; + padding: 16px 18px; + border-radius: var(--radius-lg); + background: var(--surface-2); + border: 1px solid var(--color-line-soft, rgba(15, 23, 42, 0.06)); +} + +.archive-filter-bar__main { + display: flex; + align-items: center; + gap: 12px; + flex-wrap: wrap; +} + +.archive-filter-bar__label { + color: var(--color-ink-4); + font-size: 0.8125rem; + font-weight: 600; +} + +.archive-filter-bar__chips { + display: flex; + align-items: center; + flex-wrap: wrap; + gap: 8px; +} + +.archive-filter-bar__chip { + display: inline-flex; + align-items: center; + min-height: 34px; + padding: 0 12px; + border-radius: var(--radius-pill, 999px); + background: var(--surface-1); + color: var(--color-ink-2); + text-decoration: none; + font-size: 0.875rem; + font-weight: 500; +} + +.archive-filter-bar__chip.is-active, +.archive-filter-bar__chip:hover { + background: var(--color-primary); + color: var(--color-on-primary, #fff); +} + +.archive-filter-bar__meta { + color: var(--color-ink-4); + font-size: 0.8125rem; + font-weight: 600; +} + +@media (max-width: 767px) { + .term-page-header__body { + flex-direction: column; + align-items: stretch; + padding: 20px; + } + + .aksrt-admin-quicklink { + width: fit-content; + } +} + +/* ========== AJAX 分页(加载更多 / 无限滚动) ========== */ +.aksrt-pagination-ajax { + display: flex; + flex-direction: column; + align-items: center; + gap: 16px; + margin: 40px 0 8px; +} + +.aksrt-load-more-btn { + min-width: 180px; + height: 44px; + padding: 0 32px; + border-radius: var(--radius-btn); + border: 1px solid var(--color-line); + background: var(--surface-page); + color: var(--color-ink); + font-size: 14px; + font-weight: 600; + cursor: pointer; + transition: border-color 0.2s, color 0.2s, background 0.2s; + display: inline-flex; + align-items: center; + justify-content: center; + gap: 8px; +} + +.aksrt-load-more-btn:hover { + border-color: var(--color-primary); + color: var(--color-primary); +} + +.aksrt-load-more-btn:disabled { + opacity: 0.5; + pointer-events: none; +} + +.aksrt-loading-indicator { + display: none; + align-items: center; + gap: 8px; + font-size: 14px; + color: var(--color-ink-4); +} + +.aksrt-loading-indicator i { + font-size: 16px; +} + +.aksrt-scroll-sentinel { + width: 100%; + height: 1px; + pointer-events: none; +} + +/* ========== 移动端/平板隐藏侧栏(与 zibll 一致:991px 以下隐藏) ========== */ +@media (max-width: 991px) { + .content-layout__aside { + display: none; + } +} + +/* CMS 模块在侧栏布局中的适配 */ +.content-layout__primary--cms { + min-width: 0; +} + +.content-layout__primary--cms .home-modules { + gap: var(--space-7, 32px); +} + +.content-layout__primary--cms .home-modules > .home-module { + max-width: 100%; + padding-left: 0; + padding-right: 0; +} + +/* ============================================================ + * Phase 2 — 背景遮罩层级修正 + * body.aksrt-bg-overlay 的 ::before 需要 z-index: -1 让内容在其上方 + * ============================================================ */ +body.aksrt-bg-overlay { + position: relative; +} + +body.aksrt-bg-overlay::before { + z-index: -1; +} + +body.aksrt-bg-overlay .site-wrapper { + position: relative; + z-index: 0; +} + +/* ============================================================ + * Phase 2 — 侧栏 widget 内链接增强 + * ============================================================ */ +.content-layout__aside .widget a { + transition: color var(--dur-fast, 0.15s) var(--ease); +} + +.content-layout__aside .widget a:hover { + color: var(--color-primary); +} + +/* ============================================================ + * Phase 5 — 文章操作卡片增强 + * ============================================================ */ + +/* ============================================================ + * Phase 6 — 评论卡片容器 + * ============================================================ */ +.comments-card { + overflow: hidden; +} +/* ============================================================ + * AKSRT Footer — v4.0 Zibll-Inspired + * + * 包含: + * - 页脚主体(Bootstrap Grid) + * - 浮动右侧按钮组 + * - 移动端底部 Tab 栏 + * ============================================================ */ + +/* ============================================================ + * 页脚主体 + * ============================================================ */ +.site-footer { + margin-top: auto; + background: var(--surface-1); + border-top: 1px solid var(--color-line); + padding: 30px 0 0; +} + +.site-footer__inner { + max-width: var(--container); + margin: 0 auto; + padding: 0 16px; +} + +@media (min-width: 768px) { + .site-footer__inner { + padding: 0 24px; + } +} + +.site-footer__grid { + padding-bottom: 32px; +} + +.site-footer__brand { + margin-bottom: 24px; +} + +.site-footer__title { + font-size: 1rem; + font-weight: 700; + margin: 0 0 12px; + color: var(--color-ink); +} + +.site-footer__desc { + font-size: 0.875rem; + color: var(--color-ink-4); + line-height: 1.6; + margin: 0 0 16px; + max-width: 360px; +} + +.site-footer__col { + margin-bottom: 24px; +} + +.site-footer__col ul { + list-style: none; + margin: 0; + padding: 0; +} + +.site-footer__col li { + margin-bottom: 8px; +} + +.site-footer__col a { + font-size: 0.875rem; + color: var(--color-ink-3); + transition: color 0.15s ease; +} + +.site-footer__col a:hover { + color: var(--color-primary); +} + +/* 社交链接行 */ +.social-row { + display: flex; + flex-wrap: wrap; + gap: 8px; + margin-bottom: 16px; +} + +.social-row a { + display: inline-flex; + align-items: center; + justify-content: center; + width: 36px; + height: 36px; + border-radius: 50%; + background: var(--surface-3); + color: var(--color-ink-3); + transition: background 0.2s, color 0.2s, transform 0.2s; +} + +.social-row a:hover { + background: var(--color-primary); + color: #fff; + transform: translateY(-2px); +} + +.social-row .social-icon-link { + background: var(--surface-3); + color: var(--color-ink-3); +} + +.social-row .social-icon-link:hover { + background: var(--color-primary); + color: #fff; +} + +/* 友情链接 */ +.site-footer__friends { + margin-top: 16px; +} + +.site-footer__friends-title { + font-size: 0.8125rem; + font-weight: 600; + color: var(--color-ink-4); + margin: 0 0 8px; +} + +.site-footer__friends-list { + display: flex; + flex-wrap: wrap; + gap: 6px 12px; +} + +.site-footer__friends-list a { + font-size: 0.8125rem; + color: var(--color-ink-4); +} + +.site-footer__friends-list a:hover { + color: var(--color-primary); +} + +/* 底部栏 */ +.site-footer__bottom { + border-top: 1px solid var(--color-line); + padding: 20px 0; + text-align: center; +} + +.site-footer__filings { + display: flex; + justify-content: center; + gap: 16px; + margin-bottom: 8px; + flex-wrap: wrap; +} + +.site-footer__filings a { + font-size: 0.75rem; + color: var(--color-ink-4); +} + +.site-footer__filings a:hover { + color: var(--color-primary); +} + +.site-footer__copyright { + font-size: 0.75rem; + color: var(--color-ink-4); + margin: 0; +} + +/* ============================================================ + * 浮动右侧按钮组(模仿 zibll float-right) + * ============================================================ */ +/* 对齐 zibll: bottom 60px, z-index 1030 */ +.float-right-btns { + position: fixed; + right: 20px; + bottom: 60px; + z-index: 1030; + display: flex; + flex-direction: column; + gap: 8px; + transition: opacity 0.3s ease; +} + +/* 对齐 zibll: 40px, 1.4em icon */ +.float-btn { + display: flex; + align-items: center; + justify-content: center; + width: 40px; + min-height: 40px; + border-radius: 50%; + border: none; + background: var(--float-btn-bg); + color: var(--color-ink-3); + box-shadow: var(--shadow-sm); + cursor: pointer; + transition: transform var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease); + font-size: 1.4em; + text-decoration: none; +} + +.float-btn:hover { + transform: translateY(-2px); + box-shadow: var(--shadow); + color: var(--color-primary); + background: var(--surface-page); + text-decoration: none; +} + +.float-btn:active { + transform: scale(0.95); +} + +/* 回到顶部按钮 — 滚动后显示 */ +.float-btn--top { + opacity: 0; + visibility: hidden; + transition: opacity 0.3s ease, visibility 0.3s ease, transform 0.2s ease; +} + +.float-btn--top.is-visible { + opacity: 1; + visibility: visible; + display: flex; +} + +/* 主题切换按钮 */ +#float-theme-toggle .float-btn__icon-moon { + display: none !important; +} + +#float-theme-toggle .float-btn__icon-sun { + display: inline-block !important; +} + +#float-theme-toggle[aria-pressed="true"] .float-btn__icon-moon, +.theme-dark #float-theme-toggle .float-btn__icon-moon, +html.dark #float-theme-toggle .float-btn__icon-moon { + display: inline-block !important; +} + +#float-theme-toggle[aria-pressed="true"] .float-btn__icon-sun, +.theme-dark #float-theme-toggle .float-btn__icon-sun, +html.dark #float-theme-toggle .float-btn__icon-sun { + display: none !important; +} + +/* 移动端隐藏浮动按钮(用 tabbar 代替) */ +@media (max-width: 767px) { + .float-right-btns { + right: 12px; + bottom: 80px; + } + + .float-btn { + width: 38px; + height: 38px; + font-size: 14px; + } +} + +/* ============================================================ + * 移动端底部 Tab 栏(模仿 zibll footer-tabbar) + * ============================================================ */ +.footer-tabbar { + display: none; + position: fixed; + bottom: 0; + left: 0; + right: 0; + z-index: 1035; + min-height: 49px; + background: var(--blur-bg); + border-top: 1px solid var(--color-line-soft); + padding: 0 0 env(safe-area-inset-bottom, 0px); + justify-content: space-around; + align-items: center; + box-shadow: var(--shadow-sm); + -webkit-backdrop-filter: saturate(5) blur(20px); + backdrop-filter: saturate(5) blur(20px); +} + +.footer-tabbar-placeholder { + display: none; + height: calc(49px + env(safe-area-inset-bottom, 0px)); +} + +@media (max-width: 767px) { + .footer-tabbar { + display: flex; + } + + .footer-tabbar-placeholder { + display: block; + } + + /* 有 tabbar 时页脚需要额外底部间距 */ + .site-footer { + padding-bottom: calc(49px + env(safe-area-inset-bottom, 0px)); + } +} + +.tabbar-item { + display: flex; + flex: 1 1 0; + min-width: 0; + flex-direction: column; + align-items: center; + justify-content: center; + gap: 1px; + min-height: 49px; + padding: 4px 0 3px; + color: var(--color-ink-4); + font-size: 13px; + text-decoration: none; + border: none; + background: none; + cursor: pointer; + transition: color 0.15s ease; + -webkit-tap-highlight-color: transparent; + position: relative; +} + +/* 对齐 zibll: 24px 图标 */ +.tabbar-item i { + font-size: 24px; + line-height: 1; +} + +.tabbar-item span { + display: block; + font-weight: 500; + line-height: 1; + transform: scale(0.8); + transform-origin: center top; +} + +.tabbar-item:hover, +.tabbar-item.active { + color: var(--color-primary); + text-decoration: none; +} + +.tabbar-item.active i { + font-weight: 900; +} + +.tabbar-badge { + position: absolute; + top: 2px; + right: 8px; + min-width: 16px; + height: 16px; + padding: 0 4px; + border-radius: 999px; + background: var(--color-error); + color: #fff; + font-size: 10px; + line-height: 16px; + font-style: normal; + font-weight: 700; + text-align: center; + box-shadow: 0 2px 8px rgba(239, 68, 68, 0.20); +} + +.tabbar-item--add { + margin-top: -22px; + width: 62px; + height: 62px; + min-height: 62px; + border-radius: 50%; + background: var(--color-accent); + color: #fff; + box-shadow: 0 12px 24px var(--color-accent-shadow); + flex: 0 0 62px; + z-index: 1; +} + +.tabbar-item--add i { + font-size: 22px; +} + +.tabbar-item--add span { + font-size: 11px; +} + +.tabbar-item--add:hover, +.tabbar-item--add.active { + color: #fff; +} + +.tabbar-add-backdrop { + position: fixed; + inset: 0; + z-index: 951; + background: rgba(15, 23, 42, 0.38); +} + +.tabbar-add-panel { + position: fixed; + left: 0; + right: 0; + bottom: 0; + z-index: 952; + padding: 0 12px calc(84px + env(safe-area-inset-bottom, 0px)); +} + +.tabbar-add-panel__sheet { + border-radius: 20px; + background: var(--surface-page); + box-shadow: 0 18px 50px rgba(15, 23, 42, 0.18); + overflow: hidden; +} + +.tabbar-add-panel__head { + display: flex; + align-items: center; + justify-content: space-between; + padding: 16px 18px 12px; + border-bottom: 1px solid var(--color-line); +} + +.tabbar-add-panel__close { + width: 32px; + height: 32px; + border: 0; + border-radius: 50%; + background: var(--surface-2); + color: var(--color-ink-3); +} + +.tabbar-add-panel__list { + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 12px; + padding: 18px; +} + +.tabbar-add-panel__item { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + gap: 8px; + min-height: 88px; + border-radius: 18px; + background: var(--surface-2); + color: var(--color-ink-3); + text-decoration: none; +} + +.tabbar-add-panel__item i { + font-size: 22px; + color: var(--color-accent); +} + +.tabbar-add-panel__item span { + font-size: 13px; + font-weight: 600; +} + +.tabbar-search-overlay { + position: fixed; + inset: 0; + z-index: 953; + background: rgba(15, 23, 42, 0.58); + display: flex; + align-items: stretch; + justify-content: center; +} + +.tabbar-search-overlay__dialog { + width: 100%; + min-height: 100%; + background: var(--surface-page); + padding: 18px 16px calc(24px + env(safe-area-inset-bottom, 0px)); +} + +.tabbar-search-overlay__head { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 16px; +} + +.tabbar-search-overlay__close { + width: 36px; + height: 36px; + border: 0; + border-radius: 50%; + background: var(--surface-2); + color: var(--color-ink-3); +} + +.tabbar-search-overlay__form { + display: grid; + grid-template-columns: 20px 1fr auto; + gap: 10px; + align-items: center; + padding: 14px 14px 14px 12px; + border-radius: 18px; + background: var(--surface-2); +} + +.tabbar-search-overlay__icon { + color: var(--color-ink-4); +} + +.tabbar-search-overlay__form input { + min-width: 0; + border: 0; + background: transparent; + color: var(--color-ink); + font-size: 15px; + outline: none; +} + +.tabbar-search-overlay__submit { + border: 0; + border-radius: 12px; + padding: 10px 14px; + background: var(--color-accent); + color: #fff; + font-weight: 700; +} + +.tabbar-search-overlay__types { + display: flex; + gap: 8px; + margin-top: 14px; +} + +.tabbar-search-overlay__type { + border: 0; + border-radius: 999px; + padding: 9px 14px; + background: var(--surface-2); + color: var(--color-ink-3); + font-size: 13px; + font-weight: 600; +} + +.tabbar-search-overlay__type.is-active { + background: var(--color-accent-soft); + color: var(--color-accent); +} + +.tabbar-search-overlay__section { + margin-top: 20px; +} + +.tabbar-search-overlay__section-head { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 12px; +} + +.tabbar-search-overlay__label { + color: var(--color-ink-3); + font-size: 13px; + font-weight: 700; +} + +.tabbar-search-overlay__clear { + border: 0; + background: transparent; + color: var(--color-accent); + font-size: 12px; + font-weight: 700; +} + +.tabbar-search-overlay__history, +.tabbar-search-overlay__suggestions { + display: flex; + flex-direction: column; + gap: 10px; +} + +.tabbar-search-overlay__history-item, +.tabbar-search-overlay__suggestion-item { + display: flex; + align-items: center; + justify-content: space-between; + gap: 12px; + width: 100%; + border: 0; + border-radius: 16px; + padding: 12px 14px; + background: var(--surface-2); + color: var(--color-ink-3); + text-decoration: none; + text-align: left; +} + +.tabbar-search-overlay__history-item i { + color: var(--color-accent); +} + +.tabbar-search-overlay__history-item span, +.tabbar-search-overlay__suggestion-item span { + flex: 1; + min-width: 0; + font-size: 14px; + font-weight: 600; +} + +.tabbar-search-overlay__suggestion-item small { + color: var(--color-ink-4); + font-size: 12px; +} + +.tabbar-search-overlay__empty { + padding: 14px; + border-radius: 16px; + background: var(--surface-2); + color: var(--color-ink-4); + font-size: 13px; + text-align: center; +} + +.tabbar-search-overlay__tags { + display: flex; + flex-wrap: wrap; + gap: 10px; +} + +.tabbar-search-overlay__tag { + padding: 10px 14px; + border-radius: 999px; + background: var(--surface-2); + color: var(--color-ink-3); + text-decoration: none; + font-size: 13px; +} + +body.tabbar-search-open, +body.tabbar-add-open { + overflow: hidden; +} + +/* 滚动时隐藏 tabbar(可选,通过 JS 添加 class) */ +.footer-tabbar.scrolling-hide { + transform: translateY(100%); + transition: transform 0.3s ease; +} + +/* 向下滚动隐藏,向上滚动显示 */ +.footer-tabbar.scroll-down-hide { + transition: transform 0.3s ease; +} + +.footer-tabbar.scroll-down-hide.is-hidden { + transform: translateY(120%); +} + +/* 返回顶部包裹项(首页按钮 + 返回顶部切换) */ +.tabbar-ontop-wrap { + position: relative; +} + +.tabbar-ontop-wrap .tabbar-ontop-btn { + display: none; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + flex-direction: column; + align-items: center; + justify-content: center; + gap: 2px; + padding: 4px 12px; + color: var(--color-primary); + font-size: 13px; + text-decoration: none; + cursor: pointer; + -webkit-tap-highlight-color: transparent; +} + +.tabbar-ontop-wrap .tabbar-ontop-btn i { + font-size: 18px; + line-height: 1; +} + +.tabbar-ontop-wrap .tabbar-ontop-btn span { + font-weight: 500; + line-height: 1; + transform: scale(0.8); + transform-origin: center top; +} + +.tabbar-ontop-wrap.is-scrolled .tabbar-ontop-btn { + display: flex; +} + +.tabbar-ontop-wrap.is-scrolled > .tabbar-item:not(.tabbar-ontop-btn) { + opacity: 0; + pointer-events: none; +} + +/* ============================================================ + * 暗色模式适配 + * ============================================================ */ +.theme-dark .site-footer, +html.dark .site-footer { + background: var(--surface-1); +} + +.theme-dark .float-btn, +html.dark .float-btn { + background: var(--float-btn-bg); + box-shadow: var(--shadow-sm); +} + +.theme-dark .footer-tabbar, +html.dark .footer-tabbar { + background: var(--blur-bg); + box-shadow: 0 -1px 3px rgba(0, 0, 0, 0.20); +} + +/* ============================================================ + * 旧版 back-to-top 按钮兼容(隐藏,用浮动按钮代替) + * ============================================================ */ +.back-to-top { + display: none !important; +} + +/* ============================================================ + * 页脚布局模板变体 + * ============================================================ */ + +/* 紧凑模板:单行版权 + 链接 */ +.site-footer--compact .site-footer__grid { + display: flex; + flex-wrap: wrap; + align-items: center; + gap: 16px; +} + +.site-footer--compact .site-footer__brand { + flex: 1 1 100%; +} + +.site-footer--compact .site-footer__brand .site-footer__desc, +.site-footer--compact .site-footer__brand .social-row, +.site-footer--compact .site-footer__brand .site-footer__friends { + display: none; +} + +.site-footer--compact .site-footer__col { + flex: 0 0 auto; +} + +.site-footer--compact .site-footer__col ul { + display: flex; + flex-wrap: wrap; + gap: 12px; + list-style: none; + padding: 0; + margin: 0; +} + +.site-footer--compact .site-footer__bottom { + border-top: 1px solid var(--color-line); + padding-top: 12px; + margin-top: 12px; +} + +/* 中央模板:居中品牌 + 链接 */ +.site-footer--centered .site-footer__grid { + text-align: center; +} + +.site-footer--centered .site-footer__brand { + flex: 1 1 100%; + display: flex; + flex-direction: column; + align-items: center; +} + +.site-footer--centered .site-footer__col { + flex: 1 1 auto; +} + +.site-footer--centered .site-footer__col ul { + list-style: none; + padding: 0; + margin: 0; + display: flex; + flex-wrap: wrap; + justify-content: center; + gap: 16px; +} +/* ============================================================ + * Floating Buttons + * ============================================================ */ + +.float-right { + --float-btn-size: 42px; + --float-btn-color: var(--color-ink-3); + position: fixed; + right: 20px; + bottom: 96px; + z-index: 900; + display: flex; + flex-direction: column; + gap: 8px; + transition: transform var(--dur, 0.25s) var(--ease, ease), opacity var(--dur, 0.25s) var(--ease, ease); + padding-bottom: env(safe-area-inset-bottom, 0px); +} + +.float-right.position-center { + top: 50%; + bottom: auto; + transform: translateY(-50%); +} + +.float-right.square { + gap: 0; + overflow: hidden; + border-radius: var(--radius-lg, 8px); + box-shadow: var(--shadow-md, 0 10px 30px rgba(17, 24, 39, 0.12)); +} + +.float-right .float-btn { + width: var(--float-btn-size); + min-height: var(--float-btn-size); + display: inline-flex; + align-items: center; + justify-content: center; + position: relative; + color: var(--this-color, var(--float-btn-color)); + background: var(--this-bg, var(--float-btn-bg)); + border: 1px solid var(--color-line-soft, #f0f1f3); + text-decoration: none; + box-shadow: var(--shadow, 0 8px 24px rgba(17, 24, 39, 0.08)); + transition: transform var(--dur-fast, 0.15s) var(--ease, ease), box-shadow var(--dur-fast, 0.15s) var(--ease, ease), color var(--dur-fast, 0.15s) var(--ease, ease), background var(--dur-fast, 0.15s) var(--ease, ease); + cursor: pointer; + outline: none; + overflow: visible; +} + +.float-right.round .float-btn { + border-radius: 12px; +} + +.float-right.square .float-btn { + border-radius: 0; + box-shadow: none; + border-top-width: 0; +} + +.float-right.square .float-btn:first-child { + border-top-width: 1px; +} + +.float-right .float-btn:hover { + transform: translateY(-2px); + color: var(--color-primary, var(--color-primary)); + text-decoration: none; + box-shadow: var(--shadow-md, 0 10px 30px rgba(17, 24, 39, 0.12)); + z-index: 2; +} + +.float-right .float-btn:active { + transform: scale(0.96); +} + +.float-right .float-btn::after { + content: ""; + position: absolute; + inset: auto; + width: 6px; + height: 6px; + border-radius: 999px; + background: currentColor; + opacity: 0; + transform: scale(1); + pointer-events: none; +} + +.float-right .float-btn.is-rippling::after { + animation: float-btn-ripple 0.55s ease-out; +} + +.float-right .float-btn i { + font-size: 16px; + line-height: 1; +} + +.float-right .float-btn.ontop { + opacity: 0; + visibility: hidden; + pointer-events: none; +} + +.float-right .float-btn.ontop.is-visible { + opacity: 1; + visibility: visible; + pointer-events: auto; +} + +.float-right.has-blur-pc .float-btn { + backdrop-filter: saturate(1.5) blur(10px); + -webkit-backdrop-filter: saturate(1.5) blur(10px); +} + +.float-right .hover-show-con { + position: absolute; + display: block; + right: calc(100% + 12px); + top: 50%; + transform: translateY(-50%); + min-width: 180px; + max-width: 280px; + padding: 12px; + border-radius: var(--radius-lg, 8px); + background: var(--surface-1, #fff); + border: 1px solid var(--color-line); + box-shadow: var(--shadow-lg, 0 18px 40px rgba(17, 24, 39, 0.18)); + color: var(--color-ink-2); + opacity: 0; + visibility: hidden; + pointer-events: none; + transition: opacity var(--dur-fast, 0.15s) var(--ease, ease), transform var(--dur-fast, 0.15s) var(--ease, ease), visibility var(--dur-fast, 0.15s) var(--ease, ease); +} + +.float-right .hover-show-con::before { + content: ""; + position: absolute; + top: 50%; + right: -8px; + width: 16px; + height: 16px; + background: inherit; + border-top: 1px solid var(--color-line); + border-right: 1px solid var(--color-line); + transform: translateY(-50%) rotate(45deg); +} + +.float-right .hover-show-con img { + display: block; + width: 100%; + max-width: 160px; + height: auto; + margin: 0 auto 10px; + border-radius: var(--radius, 10px); +} + +.float-right .hover-show-con p { + margin: 0; + font-size: 13px; + line-height: 1.6; + color: var(--color-ink-3); +} + +.float-btn-qrcode { + display: flex; + align-items: center; + justify-content: center; + width: 100%; + min-height: 120px; + margin: 0 auto 10px; + background: #fff; + border-radius: var(--radius, 10px); +} + +.float-right .service-wechat .hover-show-con, +.float-right .service-qq .hover-show-con, +.float-right .qrcode-btn .hover-show-con { + padding: 14px; +} + +.float-right .service-wechat .hover-show-con img, +.float-right .service-qq .hover-show-con img { + margin: 0 auto; + box-shadow: 0 10px 24px rgba(17, 24, 39, 0.12); +} + +.float-right .service-wechat .hover-show-con p, +.float-right .service-qq .hover-show-con p { + display: none; +} + +.float-right .newadd-btns .hover-show-con { + min-width: 196px; + padding: 10px; +} + +.float-add-menu { + display: flex; + flex-direction: column; + gap: 6px; +} + +.float-add-menu__item { + display: flex; + align-items: center; + gap: 10px; + padding: 10px 12px; + border-radius: 10px; + color: var(--color-ink-2); + text-decoration: none; + transition: background var(--dur-fast, 0.15s) var(--ease, ease), color var(--dur-fast, 0.15s) var(--ease, ease), transform var(--dur-fast, 0.15s) var(--ease, ease); +} + +.float-add-menu__item i { + width: 18px; + text-align: center; + color: var(--color-primary, var(--color-primary)); +} + +.float-add-menu__item:hover { + background: var(--color-primary-soft, rgba(136, 171, 218, 0.1)); + color: var(--color-primary, var(--color-primary)); + transform: translateX(-2px); +} + +.float-btn-qrcode :deep(canvas), +.float-btn-qrcode :deep(img), +.float-btn-qrcode svg { + display: block; + margin: 0 auto; +} + +.float-right .float-btn:hover .hover-show-con, +.float-right .float-btn:focus-visible .hover-show-con { + opacity: 1; + visibility: visible; + pointer-events: auto; + transform: translateY(-50%) translateX(-4px); +} + +.float-right.scrolling-hide.is-hidden, +.float-right.scroll-down-hide.is-hidden { + transform: translateX(calc(100% + 24px)); +} + +.float-right.position-center.scrolling-hide.is-hidden, +.float-right.position-center.scroll-down-hide.is-hidden { + transform: translateX(calc(100% + 24px)) translateY(-50%); +} + +.float-right__html { + font-size: 13px; + line-height: 1.6; +} + +.float-right__html a { + color: var(--color-primary, var(--color-primary)); +} + +.float-right__html a:hover { + color: var(--color-primary-hover, #7099CC); +} + +@keyframes float-btn-ripple { + 0% { + opacity: 0.22; + transform: scale(1); + } + 100% { + opacity: 0; + transform: scale(14); + } +} + +.float-btn__icon-moon { + display: none; +} + +.float-btn__icon-sun { + display: inline-block; +} + +.theme-dark .float-btn__icon-moon, +html.dark .float-btn__icon-moon { + display: inline-block; +} + +.theme-dark .float-btn__icon-sun, +html.dark .float-btn__icon-sun { + display: none; +} + +.theme-dark .float-right, +html.dark .float-right { + --float-btn-color: var(--color-ink-4); +} + +.theme-dark .float-right .hover-show-con, +html.dark .float-right .hover-show-con { + background: var(--surface-2, #1f2430); + border-color: rgba(255, 255, 255, 0.08); +} + +@media (max-width: 767px) { + .float-right { + right: 12px; + bottom: 84px; + --float-btn-size: 40px; + } + + .float-right.has-blur-mobile .float-btn { + backdrop-filter: saturate(1.5) blur(10px); + -webkit-backdrop-filter: saturate(1.5) blur(10px); + } + + .float-right .hover-show-con { + max-width: min(240px, calc(100vw - 84px)); + } +} +/** + * AKSRT Theme Background System + * + * 全局背景图、夜间背景图、页面背景色/背景图。 + * 所有选择器均带 aksrt- 命名空间。 + */ + +/* ========== 全局背景 ========== */ +.aksrt-bg-body { + background-color: var(--aksrt-bg-color, transparent); + background-image: var(--aksrt-bg-image, none); + background-size: var(--aksrt-bg-size, cover); + background-position: var(--aksrt-bg-position, center center); + background-repeat: var(--aksrt-bg-repeat, no-repeat); + background-attachment: var(--aksrt-bg-attachment, fixed); +} + +/* ========== 夜间模式背景 ========== */ +.aksrt-bg-dark { + background-color: var(--aksrt-bg-dark-color, transparent); + background-image: var(--aksrt-bg-dark-image, none); +} + +/* ========== 页面级背景 ========== */ +.aksrt-bg-page { + background-color: var(--aksrt-page-bg-color, transparent); + background-image: var(--aksrt-page-bg-image, none); + background-size: cover; + background-position: center center; + background-repeat: no-repeat; +} + +/* ========== 模块级背景 ========== */ +.aksrt-bg-module { + background-color: var(--aksrt-module-bg-color, transparent); + background-image: var(--aksrt-module-bg-image, none); + background-size: cover; + background-position: center center; + background-repeat: no-repeat; +} + +/* ========== 背景遮罩层(提升文字可读性)========== */ +.aksrt-bg-overlay { + position: relative; +} + +.aksrt-bg-overlay::before { + content: ''; + position: absolute; + inset: 0; + background: var(--aksrt-bg-overlay-color, rgba(0, 0, 0, 0.3)); + pointer-events: none; + z-index: 0; +} + +.aksrt-bg-overlay > * { + position: relative; + z-index: 1; +} + +/* ========== 暗色模式自动切换 ========== */ +@media (prefers-color-scheme: dark) { + :root:not(.aksrt-light-mode) .aksrt-bg-body { + background-color: var(--aksrt-bg-dark-color, var(--aksrt-bg-color, transparent)); + background-image: var(--aksrt-bg-dark-image, var(--aksrt-bg-image, none)); + } +} + +html.aksrt-dark-mode .aksrt-bg-body { + background-color: var(--aksrt-bg-dark-color, var(--aksrt-bg-color, transparent)); + background-image: var(--aksrt-bg-dark-image, var(--aksrt-bg-image, none)); +} +/** + * AKSRT Menu Decorations + * + * 菜单图标、徽章、多列下拉、图文卡片子菜单样式。 + * 所有选择器均带 aksrt- 或 .site-nav 命名空间。 + */ + +/* ========== 菜单图标 ========== */ +.nav-desktop .menu-item > a .menu-icon, +.nav-desktop .menu-item > a > i:first-child { + display: inline-flex; + align-items: center; + margin-right: 6px; + font-size: 14px; + opacity: 0.75; + transition: opacity 0.2s ease; +} + +.nav-desktop .menu-item:hover > a .menu-icon, +.nav-desktop .menu-item:hover > a > i:first-child { + opacity: 1; +} + +/* ========== 菜单徽章 ========== */ +.nav-desktop .menu-item > a .menu-badge, +.nav-desktop .menu-item > a .aksrt-menu-badge { + display: inline-flex; + align-items: center; + justify-content: center; + margin-left: 6px; + padding: 1px 6px; + font-size: 10px; + font-weight: 700; + line-height: 1.4; + letter-spacing: 0.02em; + border-radius: 8px; + white-space: nowrap; + vertical-align: middle; + transform: translateY(-1px); +} + +.aksrt-menu-badge--new { + background: var(--color-primary); + color: #fff; +} + +.aksrt-menu-badge--hot { + background: #ff4d4f; + color: #fff; +} + +.aksrt-menu-badge--info { + background: var(--color-info, #1890ff); + color: #fff; +} + +.aksrt-menu-badge--success { + background: var(--color-success, #52c41a); + color: #fff; +} + +.aksrt-menu-badge--warning { + background: var(--color-warning, #faad14); + color: #fff; +} + +/* ========== Hover 效果 ========== */ +/* 下划线效果 */ +.aksrt-menu-hover--underline .nav-desktop .menu-item > a { + position: relative; +} + +.aksrt-menu-hover--underline .nav-desktop .menu-item > a::after { + content: ''; + position: absolute; + bottom: 0; + left: 50%; + width: 0; + height: 2px; + background: var(--color-primary); + border-radius: 1px; + transform: translateX(-50%); + transition: width 0.25s ease; +} + +.aksrt-menu-hover--underline .nav-desktop .menu-item:hover > a::after, +.aksrt-menu-hover--underline .nav-desktop .menu-item.current-menu-item > a::after, +.aksrt-menu-hover--underline .nav-desktop .menu-item.current_page_item > a::after { + width: 70%; +} + +/* 背景色效果 */ +.aksrt-menu-hover--background .nav-desktop .menu-item > a { + border-radius: 6px; + transition: background-color 0.2s ease; +} + +.aksrt-menu-hover--background .nav-desktop .menu-item:hover > a { + background-color: var(--color-primary-soft, rgba(24, 144, 255, 0.08)); +} + +/* 文字变色效果 */ +.aksrt-menu-hover--color .nav-desktop .menu-item > a { + transition: color 0.2s ease; +} + +.aksrt-menu-hover--color .nav-desktop .menu-item:hover > a { + color: var(--color-primary); +} + +/* ========== 多列 Mega 下拉 ========== */ +.nav-desktop .menu-item .aksrt-mega-submenu { + position: absolute; + top: 100%; + left: 50%; + z-index: 999; + min-width: var(--aksrt-mega-width, 480px); + padding: 16px 20px; + background: var(--surface-page, #fff); + border: 1px solid var(--color-line, #e8e8e8); + border-radius: 8px; + box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12); + opacity: 0; + visibility: hidden; + transform: translateX(-50%) translateY(8px); + transition: opacity 0.2s ease, transform 0.2s ease, visibility 0.2s ease; +} + +.nav-desktop .menu-item:hover .aksrt-mega-submenu { + opacity: 1; + visibility: visible; + transform: translateX(-50%) translateY(0); +} + +.aksrt-mega-submenu__grid { + display: grid; + gap: 12px; +} + +.aksrt-mega-submenu__grid--cols-2 { grid-template-columns: repeat(2, 1fr); } +.aksrt-mega-submenu__grid--cols-3 { grid-template-columns: repeat(3, 1fr); } +.aksrt-mega-submenu__grid--cols-4 { grid-template-columns: repeat(4, 1fr); } +.aksrt-mega-submenu__grid--cols-5 { grid-template-columns: repeat(5, 1fr); } + +.aksrt-mega-submenu__item { + display: flex; + align-items: flex-start; + gap: 10px; + padding: 10px 12px; + border-radius: 6px; + text-decoration: none; + color: var(--color-ink); + transition: background-color 0.15s ease; +} + +.aksrt-mega-submenu__item:hover { + background-color: var(--color-primary-soft, rgba(24, 144, 255, 0.08)); +} + +.aksrt-mega-submenu__item-icon { + flex-shrink: 0; + display: flex; + align-items: center; + justify-content: center; + width: 32px; + height: 32px; + border-radius: 6px; + background: var(--color-primary-soft, rgba(24, 144, 255, 0.08)); + color: var(--color-primary); + font-size: 14px; +} + +.aksrt-mega-submenu__item-content { + flex: 1; + min-width: 0; +} + +.aksrt-mega-submenu__item-title { + font-size: 13px; + font-weight: 500; + line-height: 1.4; + color: var(--color-ink); +} + +.aksrt-mega-submenu__item-desc { + margin-top: 2px; + font-size: 12px; + line-height: 1.4; + color: var(--text-tertiary, #8a909c); + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +/* ========== 图文卡片子菜单 ========== */ +.nav-desktop .menu-item .aksrt-card-submenu { + position: absolute; + top: 100%; + left: 50%; + z-index: 999; + display: flex; + gap: 12px; + padding: 16px; + background: var(--surface-page, #fff); + border: 1px solid var(--color-line, #e8e8e8); + border-radius: 8px; + box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12); + opacity: 0; + visibility: hidden; + transform: translateX(-50%) translateY(8px); + transition: opacity 0.2s ease, transform 0.2s ease, visibility 0.2s ease; +} + +.nav-desktop .menu-item:hover .aksrt-card-submenu { + opacity: 1; + visibility: visible; + transform: translateX(-50%) translateY(0); +} + +.aksrt-card-submenu__item { + display: flex; + flex-direction: column; + width: var(--aksrt-card-width, 160px); + text-decoration: none; + border-radius: 8px; + overflow: hidden; + transition: transform 0.2s ease, box-shadow 0.2s ease; +} + +.aksrt-card-submenu__item:hover { + transform: translateY(-2px); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); +} + +.aksrt-card-submenu__thumb { + width: 100%; + aspect-ratio: 16 / 10; + object-fit: cover; + background: var(--color-fill, #f5f5f5); +} + +.aksrt-card-submenu__body { + padding: 8px 10px; +} + +.aksrt-card-submenu__title { + font-size: 13px; + font-weight: 500; + line-height: 1.4; + color: var(--color-ink); + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.aksrt-card-submenu__desc { + margin-top: 2px; + font-size: 11px; + line-height: 1.4; + color: var(--text-tertiary, #8a909c); + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +/* ========== 暗色模式适配 ========== */ +html.dark .aksrt-mega-submenu, +html.dark .aksrt-card-submenu, +html.dark .aksrt-mega-submenu, +html.dark .aksrt-card-submenu { + background: var(--surface-page); + border-color: var(--color-line, #2d2d3f); +} + +html.dark .aksrt-mega-submenu__item-title, +html.dark .aksrt-card-submenu__title, +html.dark .aksrt-mega-submenu__item-title, +html.dark .aksrt-card-submenu__title { + color: var(--color-ink); +} +/** + * AKSRT Enhancements — 全局 UI 增强 + * + * 包含:Toast 通知、骨架屏、悬停动效、暗色过渡、滚动感知 + * 所有选择器使用 aksrt- 前缀避免冲突 + */ + +/* ============================================================ + * 1. Toast 通知系统 + * ============================================================ */ +.aksrt-toast-container { + position: fixed; + bottom: 80px; + right: 16px; + max-width: 360px; + z-index: 10000; + display: flex; + flex-direction: column-reverse; + gap: 8px; + pointer-events: none; +} + +.aksrt-toast { + pointer-events: auto; + display: flex; + align-items: center; + gap: 10px; + padding: 12px 16px; + border-radius: var(--main-radius, 8px); + color: #fff; + font-size: 14px; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12); + backdrop-filter: saturate(5) blur(20px); + -webkit-backdrop-filter: saturate(5) blur(20px); + transform: translateX(120%); + opacity: 0; + animation: aksrt-toast-in 0.35s cubic-bezier(0.35, 0.71, 0.46, 1.08) forwards; + cursor: pointer; + transition: transform 0.3s, opacity 0.3s; +} + +.aksrt-toast.is-dismissing { + transform: translateX(120%); + opacity: 0; + transition: transform 0.3s ease-in, opacity 0.3s ease-in; +} + +.aksrt-toast__icon { + font-size: 18px; + flex-shrink: 0; +} + +.aksrt-toast__text { + flex: 1; + min-width: 0; + line-height: 1.4; +} + +/* Toast 类型 — 对齐 zibll 纯色 */ +.aksrt-toast--success { + background: rgba(16, 185, 129, 0.9); +} + +.aksrt-toast--info { + background: rgba(59, 130, 246, 0.9); +} + +.aksrt-toast--warning { + background: rgba(245, 158, 11, 0.9); +} + +.aksrt-toast--danger, +.aksrt-toast--error { + background: rgba(239, 68, 68, 0.9); +} + +.aksrt-toast--loading { + background: rgba(107, 114, 128, 0.9); +} + +.aksrt-toast--loading .aksrt-toast__icon { + animation: aksrt-spin 1s linear infinite; +} + +@keyframes aksrt-toast-in { + from { + transform: translateX(120%); + opacity: 0; + } + to { + transform: translateX(0); + opacity: 1; + } +} + +@keyframes aksrt-spin { + from { transform: rotate(0deg); } + to { transform: rotate(360deg); } +} + +/* ============================================================ + * 2. 骨架屏加载动画 + * ============================================================ */ +.aksrt-skeleton { + background: linear-gradient( + 90deg, + rgba(121, 121, 121, 0.08) 25%, + rgba(121, 121, 121, 0.15) 37%, + rgba(121, 121, 121, 0.08) 63% + ); + background-size: 400% 100%; + animation: aksrt-skeleton-shimmer 1.5s ease infinite; + border-radius: 4px; +} + +.aksrt-skeleton--image { + height: 0; + padding-bottom: 66.67%; /* 3:2 aspect ratio */ +} + +.aksrt-skeleton--avatar { + width: 40px; + height: 40px; + border-radius: 50%; +} + +.aksrt-skeleton--title { + height: 22px; + width: 80%; +} + +.aksrt-skeleton--text { + height: 16px; + width: 100%; +} + +.aksrt-skeleton--text-short { + height: 16px; + width: 60%; +} + +.aksrt-skeleton--button { + height: 36px; + width: 100px; + border-radius: 8px; +} + +@keyframes aksrt-skeleton-shimmer { + 0% { background-position: 100% 50%; } + 100% { background-position: 0 50%; } +} + +/* 骨架屏组合:文章卡片骨架 */ +.aksrt-skeleton-card { + background: var(--surface-1, #fff); + border: 1px solid var(--color-line); + border-radius: 12px; + overflow: hidden; + padding: 0; +} + +.aksrt-skeleton-card .aksrt-skeleton--image { + border-radius: 0; +} + +.aksrt-skeleton-card__body { + padding: 16px; + display: flex; + flex-direction: column; + gap: 10px; +} + +/* ============================================================ + * 3. 悬停交互动效 + * ============================================================ */ + +/* 卡片放大 */ +.aksrt-hover-zoom { + transition: transform 0.3s ease; +} + +.aksrt-hover-zoom:hover { + transform: scale(1.02); +} + +/* 卡片轻微放大 */ +.aksrt-hover-zoom-sm { + transition: transform 0.3s ease; +} + +.aksrt-hover-zoom-sm:hover { + transform: scale(1.02); +} + +/* 悬停显示内容 */ +.aksrt-hover-show { + position: relative; +} + +.aksrt-hover-show__content { + position: absolute; + opacity: 0; + visibility: hidden; + transform: translateY(6px); + transition: opacity 0.3s, transform 0.3s, visibility 0.3s; + z-index: 10; +} + +.aksrt-hover-show:hover .aksrt-hover-show__content { + opacity: 1; + visibility: visible; + transform: translateY(0); +} + +/* 关闭按钮旋转 */ +.aksrt-ic-close { + transition: transform 0.3s; + cursor: pointer; +} + +.aksrt-ic-close:hover { + transform: rotate(270deg); +} + +/* 图片悬停缩放(缩略图容器) */ +.aksrt-hover-zoom-img img { + transition: transform 0.3s ease; +} + +.aksrt-hover-zoom-img:hover img { + transform: scale(1.02); +} + +.aksrt-hover-zoom-img-sm img { + transition: transform 0.3s ease; +} + +.aksrt-hover-zoom-img-sm:hover img { + transform: scale(1.02); +} + +/* 按钮悬停上浮 */ +.aksrt-hover-lift { + transition: transform 0.2s ease, box-shadow 0.2s ease; +} + +.aksrt-hover-lift:hover { + transform: translateY(-2px); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); +} + +/* ============================================================ + * 4. 暗色模式过渡 (View Transitions API) + * ============================================================ */ +::view-transition-old(root), +::view-transition-new(root) { + animation: none; + mix-blend-mode: normal; +} + +.dark::view-transition-old(root) { + z-index: 1; +} + +.dark::view-transition-new(root) { + z-index: 2147483646; +} + +::view-transition-old(root) { + z-index: 2147483646; +} + +::view-transition-new(root) { + z-index: 1; +} + +/* backdrop-filter 不支持时的降级 */ +@supports not ((-webkit-backdrop-filter: blur(20px)) or (backdrop-filter: blur(20px))) { + :root { + --aksrt-blur-bg: #ffffff; + } + + .dark { + --aksrt-blur-bg: var(--surface-1); + } + + .aksrt-toast { + backdrop-filter: none; + -webkit-backdrop-filter: none; + } +} + +/* ============================================================ + * 5. 滚动方向感知 + * ============================================================ */ + +/* 向下滚动时隐藏导航栏 */ +body.aksrt-scroll-down .site-nav.nav-scroll-hide { + transform: translateY(-100%); + transition: transform 0.3s ease; +} + +body.aksrt-scroll-up .site-nav.nav-scroll-hide { + transform: translateY(0); + transition: transform 0.3s ease; +} + +/* 滚动时隐藏浮动按钮 */ +body.aksrt-scrolling .aksrt-floating-right.scrolling-hide { + opacity: 0; + pointer-events: none; + transition: opacity 0.2s; +} + +/* body-scroll 状态类 */ +body.aksrt-body-scroll .aksrt-show-on-scroll { + opacity: 1; + visibility: visible; +} + +.aksrt-show-on-scroll { + opacity: 0; + visibility: hidden; + transition: opacity 0.3s, visibility 0.3s; +} + +/* ============================================================ + * 6. 图片灯箱 + * ============================================================ */ +.aksrt-lightbox { + position: fixed; + inset: 0; + z-index: 9999; + background: rgba(0, 0, 0, 0.85); + display: flex; + align-items: center; + justify-content: center; + opacity: 0; + visibility: hidden; + transition: opacity 0.3s, visibility 0.3s; + cursor: zoom-out; +} + +.aksrt-lightbox.is-open { + opacity: 1; + visibility: visible; +} + +.aksrt-lightbox__img { + max-width: 90vw; + max-height: 85vh; + object-fit: contain; + border-radius: 4px; + transform: scale(0.9); + transition: transform 0.3s; + cursor: default; +} + +.aksrt-lightbox.is-open .aksrt-lightbox__img { + transform: scale(1); +} + +.aksrt-lightbox__close { + position: absolute; + top: 16px; + right: 16px; + width: 36px; + height: 36px; + border: none; + border-radius: 50%; + background: rgba(255, 255, 255, 0.15); + color: #fff; + font-size: 20px; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + transition: background 0.2s; +} + +.aksrt-lightbox__close:hover { + background: rgba(255, 255, 255, 0.3); +} + +.aksrt-lightbox__caption { + position: absolute; + bottom: 16px; + left: 50%; + transform: translateX(-50%); + color: rgba(255, 255, 255, 0.8); + font-size: 14px; + text-align: center; + max-width: 80%; +} + +.aksrt-lightbox__nav { + position: absolute; + top: 50%; + transform: translateY(-50%); + width: 48px; + height: 48px; + border: none; + border-radius: 50%; + background: rgba(255, 255, 255, 0.1); + color: #fff; + font-size: 24px; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + transition: background 0.2s; +} + +.aksrt-lightbox__nav:hover { + background: rgba(255, 255, 255, 0.25); +} + +.aksrt-lightbox__nav--prev { + left: 16px; +} + +.aksrt-lightbox__nav--next { + right: 16px; +} + +.aksrt-lightbox__counter { + position: absolute; + top: 16px; + left: 16px; + color: rgba(255, 255, 255, 0.7); + font-size: 14px; +} + +.aksrt-lightbox__download { + position: absolute; + top: 16px; + right: 64px; + width: 40px; + height: 40px; + border: none; + border-radius: 50%; + background: rgba(255, 255, 255, 0.15); + color: #fff; + font-size: 18px; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + transition: background 0.2s; +} + +.aksrt-lightbox__download:hover { + background: rgba(255, 255, 255, 0.3); +} + +/* 可缩放图片的光标 */ +.aksrt-cursor-zoom-in { + cursor: zoom-in; +} + +/* ============================================================ + * 7. 文章封面轮播 + * ============================================================ */ +.single-cover-slider { + position: relative; + width: 100%; + overflow: hidden; + border-radius: var(--radius-lg, 8px); +} + +.single-cover-slider .swiper-slide { + position: relative; + overflow: hidden; +} + +.single-cover-slider__img { + width: 100%; + height: 400px; + object-fit: cover; + display: block; +} + +.single-cover-slider__overlay { + position: absolute; + inset: 0; + background: linear-gradient(180deg, rgba(0,0,0,0) 40%, rgba(0,0,0,0.6) 100%); + pointer-events: none; +} + +.single-cover-slider__content { + position: absolute; + bottom: 0; + left: 0; + right: 0; + padding: 24px; + color: #fff; + z-index: 2; +} + +.single-cover-slider__title { + margin: 0 0 8px; + font-size: 24px; + font-weight: 700; + text-shadow: 0 1px 3px rgba(0,0,0,0.3); +} + +.single-cover-slider__meta { + display: flex; + gap: 16px; + font-size: 13px; + opacity: 0.9; +} + +.single-cover-slider__pagination { + position: absolute; + bottom: 12px; + right: 16px; + z-index: 3; +} + +.single-cover-slider__pagination .swiper-pagination-bullet { + background: rgba(255,255,255,0.6); + opacity: 1; +} + +.single-cover-slider__pagination .swiper-pagination-bullet-active { + background: #fff; +} + +.single-cover-slider__prev, +.single-cover-slider__next { + position: absolute; + top: 50%; + transform: translateY(-50%); + z-index: 3; + width: 40px; + height: 40px; + border: none; + border-radius: 50%; + background: rgba(0,0,0,0.3); + color: #fff; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + transition: background 0.2s; +} + +.single-cover-slider__prev:hover, +.single-cover-slider__next:hover { + background: rgba(0,0,0,0.5); +} + +.single-cover-slider__prev { left: 12px; } +.single-cover-slider__next { right: 12px; } + +@media (max-width: 640px) { + .single-cover-slider__img { + height: 240px; + } + .single-cover-slider__title { + font-size: 18px; + } +} + +/* ============================================================ + * 8. 打赏按钮 + * ============================================================ */ +.action-btn--reward { + position: relative; +} + +.action-btn--reward.is-active { + color: var(--color-warning, #F59E0B); +} + +.reward-modal { + position: fixed; + inset: 0; + z-index: 99999; + display: flex; + align-items: center; + justify-content: center; + opacity: 0; + visibility: hidden; + transition: opacity 0.3s, visibility 0.3s; +} + +.reward-modal.is-open { + opacity: 1; + visibility: visible; +} + +.reward-modal__overlay { + position: absolute; + inset: 0; + background: rgba(0,0,0,0.5); +} + +.reward-modal__card { + position: relative; + background: var(--surface-1, #fff); + border-radius: var(--radius-lg, 8px); + padding: 32px; + max-width: 360px; + width: 90%; + text-align: center; + box-shadow: 0 8px 32px rgba(0,0,0,0.15); + z-index: 1; +} + +.reward-modal__title { + margin: 0 0 8px; + font-size: 18px; + font-weight: 600; + color: var(--color-ink); +} + +.reward-modal__desc { + margin: 0 0 20px; + font-size: 14px; + color: var(--color-ink-3); +} + +.reward-modal__qr { + width: 200px; + height: 200px; + margin: 0 auto 16px; + border-radius: var(--radius, 10px); + overflow: hidden; +} + +.reward-modal__qr img { + width: 100%; + height: 100%; + object-fit: contain; +} + +.reward-modal__close { + position: absolute; + top: 12px; + right: 12px; + width: 32px; + height: 32px; + border: none; + border-radius: 50%; + background: var(--surface-2, #F4F5F7); + color: var(--color-ink-3); + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + transition: background 0.2s; +} + +.reward-modal__close:hover { + background: var(--surface-3, #ECEEF1); +} + +/* ============================================================ + * 9. 公告跑马灯 Widget + * ============================================================ */ +.aksrt-announcement { + position: relative; + overflow: hidden; + padding: 10px 12px; + background: var(--surface-2, #F4F5F7); + border-radius: var(--radius, 10px); +} + +.aksrt-announcement__icon { + position: absolute; + left: 12px; + top: 50%; + transform: translateY(-50%); + color: var(--color-primary, var(--color-primary)); + font-size: 14px; + z-index: 1; +} + +.aksrt-announcement__track { + margin-left: 24px; + overflow: hidden; + height: 20px; +} + +.aksrt-announcement__list { + margin: 0; + padding: 0; + list-style: none; + animation: aksrt-marquee 10s linear infinite; +} + +.aksrt-announcement__item { + height: 20px; + line-height: 20px; + font-size: 13px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.aksrt-announcement__item a { + color: var(--color-ink-2); + text-decoration: none; +} + +.aksrt-announcement__item a:hover { + color: var(--color-primary, var(--color-primary)); +} + +@keyframes aksrt-marquee { + 0% { transform: translateY(0); } + 100% { transform: translateY(-100%); } +} + +.aksrt-announcement:hover .aksrt-announcement__list { + animation-play-state: paused; +} + +/* ============================================================ + * 10. 用户卡片 Widget + * ============================================================ */ +.aksrt-user-card { + text-align: center; + padding: 20px; +} + +.aksrt-user-card__avatar { + width: 72px; + height: 72px; + border-radius: 50%; + margin: 0 auto 12px; + overflow: hidden; + border: 3px solid var(--color-primary-soft, rgba(136,171,218,0.1)); +} + +.aksrt-user-card__avatar img { + width: 100%; + height: 100%; + object-fit: cover; +} + +.aksrt-user-card__name { + margin: 0 0 4px; + font-size: 16px; + font-weight: 600; + color: var(--color-ink); +} + +.aksrt-user-card__name a { + color: inherit; + text-decoration: none; +} + +.aksrt-user-card__name a:hover { + color: var(--color-primary, var(--color-primary)); +} + +.aksrt-user-card__bio { + margin: 0 0 12px; + font-size: 13px; + color: var(--color-ink-3); + line-height: 1.5; + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + overflow: hidden; +} + +.aksrt-user-card__stats { + display: flex; + justify-content: center; + gap: 20px; + margin-bottom: 16px; +} + +.aksrt-user-card__stat { + text-align: center; +} + +.aksrt-user-card__stat-value { + display: block; + font-size: 18px; + font-weight: 600; + color: var(--color-ink); +} + +.aksrt-user-card__stat-label { + font-size: 12px; + color: var(--color-ink-4, #8A8F98); +} + +.aksrt-user-card__actions { + display: flex; + gap: 8px; + justify-content: center; +} + +.aksrt-user-card__btn { + display: inline-flex; + align-items: center; + gap: 4px; + padding: 6px 16px; + border-radius: var(--radius, 10px); + font-size: 13px; + text-decoration: none; + transition: all 0.15s; +} + +.aksrt-user-card__btn--primary { + background: var(--color-primary, var(--color-primary)); + color: #fff; +} + +.aksrt-user-card__btn--primary:hover { + opacity: 0.85; + color: #fff; +} + +.aksrt-user-card__btn--ghost { + border: 1px solid var(--color-line); + color: var(--color-ink-2); +} + +.aksrt-user-card__btn--ghost:hover { + border-color: var(--color-primary, var(--color-primary)); + color: var(--color-primary, var(--color-primary)); +} + +/* ============================================================ + * 11. 滚动触发动画初始状态 + * ============================================================ */ +[data-aksrt-animate] { + will-change: opacity, transform; +} + +/* ============================================================ + * 12. 粘性侧栏 + * ============================================================ */ +[data-aksrt-sticky] { + will-change: transform; +} + +/* ============================================================ + * 13. 用户排行榜 Widget + * ============================================================ */ +.aksrt-user-ranking { + margin: 0; + padding: 0; + list-style: none; +} + +.aksrt-user-ranking__item { + display: flex; + align-items: center; + gap: 10px; + padding: 10px 0; + border-bottom: 1px solid var(--color-line-soft, #F0F1F3); +} + +.aksrt-user-ranking__item:last-child { + border-bottom: none; +} + +.aksrt-user-ranking__rank { + display: flex; + align-items: center; + justify-content: center; + width: 24px; + height: 24px; + border-radius: 6px; + background: var(--surface-2, #F4F5F7); + color: var(--color-ink-3); + font-size: 12px; + font-weight: 600; + flex-shrink: 0; +} + +.aksrt-user-ranking__item--top:nth-child(1) .aksrt-user-ranking__rank { + background: #FFD700; + color: #fff; +} + +.aksrt-user-ranking__item--top:nth-child(2) .aksrt-user-ranking__rank { + background: #C0C0C0; + color: #fff; +} + +.aksrt-user-ranking__item--top:nth-child(3) .aksrt-user-ranking__rank { + background: #CD7F32; + color: #fff; +} + +.aksrt-user-ranking__avatar { + flex-shrink: 0; +} + +.aksrt-user-ranking__avatar img { + width: 36px; + height: 36px; + border-radius: 50%; + object-fit: cover; +} + +.aksrt-user-ranking__name { + flex: 1; + min-width: 0; + font-size: 14px; + color: var(--color-ink); + text-decoration: none; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.aksrt-user-ranking__name:hover { + color: var(--color-primary, var(--color-primary)); +} + +.aksrt-user-ranking__value { + font-size: 12px; + color: var(--color-ink-4, #8A8F98); + white-space: nowrap; +} + +/* ============================================================ + * 14. 图文封面卡片 Widget + * ============================================================ */ +.aksrt-cover-cards { + display: grid; + grid-template-columns: repeat(var(--cols, 2), 1fr); + gap: 12px; +} + +.aksrt-cover-card { + position: relative; + border-radius: var(--radius-lg, 8px); + overflow: hidden; + min-height: 160px; + display: flex; + align-items: flex-end; + transition: transform 0.3s, box-shadow 0.3s; +} + +.aksrt-cover-card:hover { + transform: translateY(-3px); + box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15); +} + +.aksrt-cover-card__bg { + position: absolute; + inset: 0; +} + +.aksrt-cover-card__bg img { + width: 100%; + height: 100%; + object-fit: cover; + transition: transform 0.5s; +} + +.aksrt-cover-card:hover .aksrt-cover-card__bg img { + transform: scale(1.02); +} + +.aksrt-cover-card__overlay { + position: absolute; + inset: 0; + background: linear-gradient(180deg, rgba(0,0,0,0) 30%, rgba(0,0,0,0.6) 100%); +} + +.aksrt-cover-card__content { + position: relative; + z-index: 1; + padding: 16px; + width: 100%; +} + +.aksrt-cover-card__link { + text-decoration: none; + color: inherit; + display: block; +} + +.aksrt-cover-card__title { + margin: 0 0 4px; + font-size: 16px; + font-weight: 600; + color: #fff; + text-shadow: 0 1px 3px rgba(0, 0, 0, 0.4); +} + +.aksrt-cover-card__desc { + margin: 0; + font-size: 13px; + color: rgba(255, 255, 255, 0.85); + text-shadow: 0 1px 2px rgba(0, 0, 0, 0.3); + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + overflow: hidden; +} + +/* ============================================================ + * 15. 视频播放器 Widget + * ============================================================ */ +.aksrt-video-widget { + position: relative; + width: 100%; + overflow: hidden; + border-radius: var(--radius, 10px); + background: #000; +} + +.aksrt-video-widget iframe, +.aksrt-video-widget video { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + border: none; +} + +/* ============================================================ + * 16. 表单输入浮动标签 + * ============================================================ */ +.aksrt-float-label { + position: relative; +} + +.aksrt-float-label__input { + width: 100%; + padding: 14px 12px 6px; + font-size: 14px; + border: 1px solid var(--color-line); + border-radius: var(--radius, 10px); + background: var(--surface-1, #fff); + color: var(--color-ink); + transition: border-color 0.2s; +} + +.aksrt-float-label__input:focus { + outline: none; + border-color: var(--color-primary, var(--color-primary)); +} + +.aksrt-float-label__label { + position: absolute; + left: 12px; + top: 50%; + transform: translateY(-50%); + font-size: 14px; + color: var(--color-ink-4, #8A8F98); + pointer-events: none; + transition: all 0.2s ease; +} + +.aksrt-float-label__input:focus + .aksrt-float-label__label, +.aksrt-float-label__input:not(:placeholder-shown) + .aksrt-float-label__label { + top: 8px; + transform: translateY(0); + font-size: 11px; + color: var(--color-primary, var(--color-primary)); +} + +/* ============================================================ + * 17. 视差滚动层 + * ============================================================ */ +[data-aksrt-parallax] { + will-change: transform; + transition: transform 0.1s linear; +} + +/* ============================================================ + * 18. 签到日历可视化 + * ============================================================ */ +.aksrt-signin-calendar__grid { + display: grid; + grid-template-columns: repeat(7, 1fr); + gap: 4px; +} + +.aksrt-signin-calendar__day { + aspect-ratio: 1; + display: flex; + align-items: center; + justify-content: center; + border-radius: 6px; + background: var(--surface-2, #F4F5F7); + font-size: 12px; + color: var(--color-ink-3); + transition: all 0.2s; +} + +.aksrt-signin-calendar__day.is-signed { + background: var(--color-success, #10B981); + color: #fff; +} + +.aksrt-signin-calendar__day.is-today { + border: 2px solid var(--color-primary, var(--color-primary)); +} + +.aksrt-signin-calendar__day.is-signed.is-today { + background: var(--color-primary, var(--color-primary)); + border-color: var(--color-primary, var(--color-primary)); +} + +.uc-signin-calendar__title { + display: flex; + align-items: center; + gap: 6px; + margin: 0 0 10px; + font-size: 14px; + font-weight: 600; + color: var(--color-ink-2); +} + +.uc-signin-calendar__title i { + color: var(--color-primary, var(--color-primary)); +} + +/* ============================================================ + * 19. VIP 等级标识 + * ============================================================ */ +.aksrt-vip-badge { + display: inline-flex; + align-items: center; + gap: 4px; + padding: 2px 8px; + border-radius: var(--radius-pill, 999px); + font-size: 11px; + font-weight: 600; +} + +.aksrt-vip-badge--gold { + background: linear-gradient(135deg, #FFD700, #FFA500); + color: #fff; +} + +.aksrt-vip-badge--silver { + background: linear-gradient(135deg, #C0C0C0, #A8A8A8); + color: #fff; +} + +.aksrt-vip-badge--bronze { + background: linear-gradient(135deg, #CD7F32, #A0522D); + color: #fff; +} + +/* ============================================================ + * 20. 用户等级进度条 + * ============================================================ */ +.aksrt-level-bar { + position: relative; + height: 8px; + background: var(--surface-2, #F4F5F7); + border-radius: 4px; + overflow: hidden; +} + +.aksrt-level-bar__fill { + height: 100%; + background: linear-gradient(90deg, var(--color-primary, var(--color-primary)), var(--color-primary-active, #5A85BD)); + border-radius: 4px; + transition: width 0.5s ease; +} + +.aksrt-level-bar__label { + position: absolute; + right: 0; + top: -18px; + font-size: 11px; + color: var(--color-ink-4, #8A8F98); +} + +/* ============================================================ + * 21. 弹窗登录/注册 + * ============================================================ */ +.aksrt-modal-auth { + position: fixed; + inset: 0; + z-index: 99999; + display: flex; + align-items: center; + justify-content: center; + opacity: 0; + visibility: hidden; + transition: opacity 0.3s, visibility 0.3s; +} + +.aksrt-modal-auth.is-open { + opacity: 1; + visibility: visible; +} + +.aksrt-modal-auth__overlay { + position: absolute; + inset: 0; + background: rgba(0, 0, 0, 0.5); + backdrop-filter: blur(4px); + -webkit-backdrop-filter: blur(4px); +} + +.aksrt-modal-auth__card { + position: relative; + background: var(--main-bg-color, #fff); + border-radius: var(--main-radius, 8px); + padding: 32px; + max-width: 400px; + width: 90%; + max-height: 90vh; + overflow-y: auto; + box-shadow: 0 0 10px var(--main-shadow, rgba(116, 116, 116, 0.08)); + z-index: 1; + transform: scale(0.9); + transition: transform 0.5s cubic-bezier(0.32, 0.85, 0.45, 1.18); +} + +.aksrt-modal-auth.is-open .aksrt-modal-auth__card { + transform: scale(1); +} + +.aksrt-modal-auth__close { + position: absolute; + top: 12px; + right: 12px; + width: 36px; + height: 36px; + border: none; + border-radius: 50%; + background: var(--surface-2, #F4F5F7); + color: var(--color-ink-3); + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + transition: background 0.2s; + font-size: 16px; +} + +.aksrt-modal-auth__close:hover { + background: var(--surface-3, #ECEEF1); +} + +.aksrt-modal-auth__header { + text-align: center; + margin-bottom: 24px; +} + +.aksrt-modal-auth__logo { + width: 56px; + height: 56px; + border-radius: var(--radius); + background: linear-gradient(135deg, var(--color-primary, var(--color-primary)), var(--color-primary-active, #5A85BD)); + color: #fff; + font-size: 22px; + font-weight: 700; + display: flex; + align-items: center; + justify-content: center; + margin: 0 auto 12px; +} + +.aksrt-modal-auth__title { + margin: 0; + font-size: 20px; + font-weight: 600; + color: var(--color-ink); +} + +/* Tabs */ +.aksrt-modal-auth__tabs { + display: flex; + border-bottom: 1px solid var(--color-line); + margin-bottom: 20px; +} + +.aksrt-modal-auth__tab { + flex: 1; + padding: 10px; + border: none; + background: none; + font-size: 15px; + font-weight: 500; + color: var(--color-ink-3); + cursor: pointer; + position: relative; + transition: color 0.2s; +} + +.aksrt-modal-auth__tab.is-active { + color: var(--color-primary, var(--color-primary)); +} + +.aksrt-modal-auth__tab.is-active::after { + content: ''; + position: absolute; + bottom: -1px; + left: 0; + right: 0; + height: 2px; + background: var(--color-primary, var(--color-primary)); +} + +/* Panels */ +.aksrt-modal-auth__panel { + display: none; +} + +.aksrt-modal-auth__panel.is-active { + display: block; +} + +/* Form */ +.aksrt-modal-auth__form { + display: flex; + flex-direction: column; + gap: 16px; +} + +.aksrt-modal-auth__error { + padding: 10px 14px; + border-radius: 8px; + background: rgba(239, 68, 68, 0.08); + color: var(--color-error, #EF4444); + font-size: 13px; + line-height: 1.5; +} + +.aksrt-modal-auth__error a { + color: var(--color-primary, var(--color-primary)); + text-decoration: underline; +} + +.aksrt-modal-auth__field label { + display: block; + font-size: 13px; + font-weight: 500; + color: var(--color-ink-2); + margin-bottom: 6px; +} + +.aksrt-modal-auth__field input { + width: 100%; + padding: 10px 14px; + border: 1px solid var(--color-line); + border-radius: 10px; + font-size: 14px; + color: var(--color-ink); + background: var(--surface-1, #fff); + transition: border-color 0.2s; + box-sizing: border-box; +} + +.aksrt-modal-auth__field input:focus { + outline: none; + border-color: var(--color-primary, var(--color-primary)); +} + +.aksrt-modal-auth__field input::placeholder { + color: var(--color-ink-4, #8A8F98); +} + +.aksrt-modal-auth__pass-wrap { + position: relative; +} + +.aksrt-modal-auth__pass-wrap input { + padding-right: 44px; +} + +.aksrt-modal-auth__pass-toggle { + position: absolute; + right: 8px; + top: 50%; + transform: translateY(-50%); + width: 32px; + height: 32px; + border: none; + background: none; + color: var(--color-ink-4, #8A8F98); + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + border-radius: 6px; +} + +.aksrt-modal-auth__pass-toggle:hover { + background: var(--surface-2, #F4F5F7); +} + +.aksrt-modal-auth__actions { + display: flex; + justify-content: flex-end; +} + +.aksrt-modal-auth__link { + font-size: 13px; + color: var(--color-primary, var(--color-primary)); + text-decoration: none; +} + +.aksrt-modal-auth__link:hover { + text-decoration: underline; +} + +.aksrt-modal-auth__submit { + width: 100%; + padding: 12px; + border: none; + border-radius: 10px; + background: var(--color-primary, var(--color-primary)); + color: #fff; + font-size: 15px; + font-weight: 600; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + gap: 8px; + transition: opacity 0.2s; +} + +.aksrt-modal-auth__submit:hover { + opacity: 0.85; +} + +.aksrt-modal-auth__submit:disabled { + opacity: 0.6; + cursor: not-allowed; +} + +/* Divider */ +.aksrt-modal-auth__divider { + display: flex; + align-items: center; + gap: 12px; + margin: 20px 0; + color: var(--color-ink-4, #8A8F98); + font-size: 12px; +} + +.aksrt-modal-auth__divider::before, +.aksrt-modal-auth__divider::after { + content: ''; + flex: 1; + height: 1px; + background: var(--color-line); +} + +/* OAuth */ +.aksrt-modal-auth__oauth { + display: flex; + justify-content: center; + gap: 12px; +} + +.aksrt-modal-auth__oauth-btn { + width: 44px; + height: 44px; + border: 1px solid var(--color-line); + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + color: var(--color-ink-2); + font-size: 18px; + text-decoration: none; + transition: all 0.2s; +} + +.aksrt-modal-auth__oauth-btn:hover { + border-color: var(--color-primary, var(--color-primary)); + color: var(--color-primary, var(--color-primary)); + background: var(--color-primary-soft, rgba(136, 171, 218, 0.1)); +} + +/* Footer */ +.aksrt-modal-auth__footer { + text-align: center; + margin-top: 20px; + font-size: 13px; + color: var(--color-ink-3); +} + +.aksrt-modal-auth__switch { + border: none; + background: none; + color: var(--color-primary, var(--color-primary)); + cursor: pointer; + font-size: 13px; + font-weight: 500; + padding: 0; +} + +.aksrt-modal-auth__switch:hover { + text-decoration: underline; +} + +/* Dark mode */ +.theme-dark .aksrt-modal-auth__card, +html.dark .aksrt-modal-auth__card { + background: #1e1e2e; + border: 1px solid rgba(255, 255, 255, 0.1); +} + +.theme-dark .aksrt-modal-auth__field input, +html.dark .aksrt-modal-auth__field input { + background: #2a2a3a; + border-color: rgba(255, 255, 255, 0.15); + color: #e0e0e0; +} + +.theme-dark .aksrt-modal-auth__close, +html.dark .aksrt-modal-auth__close { + background: #2a2a3a; +} + +/* Responsive */ +@media (max-width: 480px) { + .aksrt-modal-auth__card { + padding: 24px 20px; + border-radius: 12px; + } + + .aksrt-modal-auth__logo { + width: 48px; + height: 48px; + font-size: 18px; + } + + .aksrt-modal-auth__title { + font-size: 18px; + } +} + +/* ============================================================ + * 22. 语言切换器 + * ============================================================ */ +.aksrt-lang-switch { + position: relative; +} + +.aksrt-lang-switch__toggle { + display: flex; + align-items: center; + gap: 6px; + padding: 8px 12px; + border: 1px solid var(--color-line); + border-radius: var(--radius, 10px); + background: var(--surface-1, #fff); + color: var(--color-ink-2); + font-size: 13px; + cursor: pointer; + transition: border-color 0.2s; + width: 100%; +} + +.aksrt-lang-switch__toggle:hover { + border-color: var(--color-primary, var(--color-primary)); +} + +.aksrt-lang-switch__toggle img { + border-radius: 2px; +} + +.aksrt-lang-switch__dropdown { + position: absolute; + top: 100%; + left: 0; + right: 0; + margin: 4px 0 0; + padding: 4px; + list-style: none; + background: var(--surface-1, #fff); + border: 1px solid var(--color-line); + border-radius: var(--radius, 10px); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08); + z-index: 100; + opacity: 0; + visibility: hidden; + transform: translateY(4px); + transition: all 0.2s; +} + +.aksrt-lang-switch:hover .aksrt-lang-switch__dropdown, +.aksrt-lang-switch__toggle:focus + .aksrt-lang-switch__dropdown { + opacity: 1; + visibility: visible; + transform: translateY(0); +} + +.aksrt-lang-switch__item { + display: flex; + align-items: center; + gap: 8px; + padding: 8px 10px; + border-radius: 6px; + font-size: 13px; + color: var(--color-ink-2); + text-decoration: none; + transition: background 0.15s; +} + +.aksrt-lang-switch__item:hover { + background: var(--surface-2, #F4F5F7); +} + +.aksrt-lang-switch__item.is-active { + color: var(--color-primary, var(--color-primary)); + font-weight: 600; +} + +.aksrt-lang-switch__item img { + border-radius: 2px; +} + +/* 国旗模式 */ +.aksrt-lang-switch--flags { + display: flex; + flex-wrap: wrap; + gap: 8px; +} + +.aksrt-lang-switch__flag { + display: inline-flex; + align-items: center; + justify-content: center; + width: 32px; + height: 24px; + border: 2px solid transparent; + border-radius: 4px; + overflow: hidden; + transition: border-color 0.2s; + text-decoration: none; +} + +.aksrt-lang-switch__flag:hover { + border-color: var(--color-primary, var(--color-primary)); +} + +.aksrt-lang-switch__flag.is-active { + border-color: var(--color-primary, var(--color-primary)); +} + +.aksrt-lang-switch__flag img { + width: 100%; + height: 100%; + object-fit: cover; +} + +.aksrt-lang-switch__flag span { + font-size: 10px; + font-weight: 600; + color: var(--color-ink-3); +} + +/* Dark mode */ +.theme-dark .aksrt-lang-switch__toggle, +html.dark .aksrt-lang-switch__toggle { + background: #2a2a3a; + border-color: rgba(255, 255, 255, 0.15); +} + +.theme-dark .aksrt-lang-switch__dropdown, +html.dark .aksrt-lang-switch__dropdown { + background: #2a2a3a; + border-color: rgba(255, 255, 255, 0.15); +} + +/* ============================================================ + * 响应式 + * ============================================================ */ +@media (max-width: 640px) { + .aksrt-toast-container { + right: 8px; + left: 8px; + max-width: none; + } + + .aksrt-lightbox__nav { + width: 36px; + height: 36px; + font-size: 18px; + } + + .single-cover-slider__img { + height: 240px; + } + + .single-cover-slider__title { + font-size: 18px; + } + + .reward-modal__card { + padding: 24px; + } + + .reward-modal__qr { + width: 160px; + height: 160px; + } + + .aksrt-cover-cards { + grid-template-columns: 1fr; + } + + .aksrt-cover-card { + min-height: 140px; + } +} + +/* ============================================================ + * 13. 无障碍:prefers-reduced-motion + * 用户系统设置"减少动画"时,禁用所有非必要动效 + * ============================================================ */ +@media (prefers-reduced-motion: reduce) { + *, + *::before, + *::after { + animation-duration: 0.01ms !important; + animation-iteration-count: 1 !important; + transition-duration: 0.01ms !important; + scroll-behavior: auto !important; + } + + .aksrt-skeleton { + animation: none !important; + } + + .aksrt-toast { + animation: none !important; + } + + [data-aksrt-animate] { + opacity: 1 !important; + transform: none !important; + } +} + +/* ============================================================ + * 14. 图片懒加载 blur-to-sharp 过渡 + * 模仿 zibll 的 lazy_blur 效果 + * ============================================================ */ +img.lazyload, +img.lazyloaded, +img[data-src] { + transition: filter 0.6s var(--ease), opacity 0.4s var(--ease); +} + +img.lazyload, +img[data-src] { + filter: blur(5px); + opacity: 0.7; +} + +img.lazyloaded { + filter: blur(0); + opacity: 1; +} + +/* ============================================================ + * 15. 错误反馈 shake 动画 + * 表单验证失败时的水平抖动效果 + * ============================================================ */ +@keyframes aksrtShake { + 0%, 100% { transform: translateX(0); } + 10%, 30%, 50%, 70%, 90% { transform: translateX(-4px); } + 20%, 40%, 60%, 80% { transform: translateX(4px); } +} + +.aksrt-shake { + animation: aksrtShake 0.4s ease-in-out; +} + +/* 应用于 Naive UI 表单验证 */ +.n-form-item--error .n-input, +.n-form-item--error .n-select, +.n-form-item--error .n-input-number { + animation: aksrtShake 0.3s ease-in-out; +} + +/* ============================================================ + * 16. FPS 加速模式:低端设备禁用 backdrop-filter + * 模仿 zibll 的 body.fps-accelerat 模式 + * ============================================================ */ +body.fps-accelerat .site-nav, +body.fps-accelerat .footer-tabbar, +body.fps-accelerat .float-right .float-btn, +body.fps-accelerat .aksrt-blur-bg { + backdrop-filter: none !important; + -webkit-backdrop-filter: none !important; +} + +/* 模态框内禁用 backdrop-filter 避免渲染冲突 */ +body.modal-open .site-nav, +body.dialog-open .site-nav { + backdrop-filter: none !important; + -webkit-backdrop-filter: none !important; +} + +/* ============================================================ + * 17. .blur-bg 通用工具类 + * 模仿 zibll 的 .blur-bg,可在任意元素上应用毛玻璃效果 + * ============================================================ */ +.aksrt-blur-bg { + background: var(--blur-bg); + backdrop-filter: saturate(5) blur(20px); + -webkit-backdrop-filter: saturate(5) blur(20px); +} + +/* ============================================================ + * 18. 滚动触发动画延迟支持 + * data-aksrt-delay 属性控制入场延迟 + * ============================================================ */ +[data-aksrt-animate][data-aksrt-delay="1"] { transition-delay: 0.1s; } +[data-aksrt-animate][data-aksrt-delay="2"] { transition-delay: 0.2s; } +[data-aksrt-animate][data-aksrt-delay="3"] { transition-delay: 0.3s; } +[data-aksrt-animate][data-aksrt-delay="4"] { transition-delay: 0.4s; } +[data-aksrt-animate][data-aksrt-delay="5"] { transition-delay: 0.5s; } + +/* ============================================================ + * 19. 全站动效节奏统一 + * 模仿 zibll 的统一 hover / slide / blur / drawer 语言 + * ============================================================ */ + +/* --- 全局过渡基线 --- */ +a, button, input, select, textarea { + transition: border-color var(--dur-fast) var(--ease), + box-shadow var(--dur-fast) var(--ease), + background-color var(--dur-fast) var(--ease), + color var(--dur-fast) var(--ease); +} + +/* --- 卡片 hover 统一 --- */ +.post-card, .widget, .aksrt-theme-box, .theme-box, +.comment-body, .friend-card, .special-card, +.resource-download-box, .resource-meta-box { + transition: box-shadow var(--dur) var(--ease), + border-color var(--dur) var(--ease), + transform var(--dur) var(--ease); +} + +.post-card:hover, .widget:hover, .friend-card:hover, .special-card:hover { + box-shadow: var(--shadow); + transform: translateY(-2px); +} + +/* --- 按钮 hover 统一 --- */ +.btn-primary, .btn-outline, .btn-lg, .btn-sm, +.n-button, .aksrt-button { + transition: all var(--dur-fast) var(--ease); +} + +.btn-primary:hover, .n-button--primary-type:hover { + opacity: 0.85; +} + +.btn-primary:active, .n-button--primary-type:active { + opacity: 1; +} + +/* --- 输入框 focus 统一 --- */ +input:focus, textarea:focus, select:focus, +.n-input--focus, .n-select--focus { + box-shadow: var(--focus-ring); + transition: box-shadow var(--dur-fast) var(--ease); +} + +/* --- 抽屉/模态框动效统一 --- */ +.n-drawer, .n-modal, .n-dialog { + transition: all var(--dur) var(--ease-out); +} + +.n-drawer-mask, .n-modal-mask, .n-dialog-mask { + transition: opacity var(--dur) var(--ease); +} + +/* --- Tab 切换动效 --- */ +.n-tabs-tab, .nav-tab, .aksrt-tab { + transition: color var(--dur-fast) var(--ease), + border-color var(--dur-fast) var(--ease), + background-color var(--dur-fast) var(--ease); +} + +/* --- 下拉菜单动效 --- */ +.n-dropdown-menu, .aksrt-dropdown { + transition: opacity var(--dur-fast) var(--ease), + transform var(--dur-fast) var(--ease-out); + transform-origin: top; +} + +/* --- Toast 通知动效 --- */ +.aksrt-toast { + animation: aksrtToastIn 0.35s var(--ease-out) forwards; +} + +.aksrt-toast--out { + animation: aksrtToastOut 0.3s var(--ease) forwards; +} + +/* --- 骨架屏动效 --- */ +.aksrt-skeleton { + animation: aksrtSkeletonShimmer 1.5s infinite linear; + background: linear-gradient(90deg, var(--skeleton-base) 25%, var(--skeleton-shine) 50%, var(--skeleton-base) 75%); + background-size: 200% 100%; +} + +/* --- 页面切换动效 --- */ +.fade-slide-enter-active, +.fade-slide-leave-active { + transition: opacity var(--dur) var(--ease), + transform var(--dur) var(--ease); +} + +.fade-slide-enter-from { + opacity: 0; + transform: translateY(8px); +} + +.fade-slide-leave-to { + opacity: 0; + transform: translateY(-8px); +} + +/* --- 导航栏滚动动效 --- */ +.site-nav { + transition: transform var(--dur) var(--ease), + background-color var(--dur) var(--ease), + box-shadow var(--dur) var(--ease); +} + +.site-nav.aksrt-nav--hidden { + transform: translateY(-100%); +} + +/* --- 浮层弹出动效 --- */ +@keyframes aksrtPopIn { + 0% { opacity: 0; transform: scale(0.95) translateY(-4px); } + 100% { opacity: 1; transform: scale(1) translateY(0); } +} + +@keyframes aksrtPopOut { + 0% { opacity: 1; transform: scale(1) translateY(0); } + 100% { opacity: 0; transform: scale(0.95) translateY(-4px); } +} + +.aksrt-popover, .aksrt-tooltip, .aksrt-dropdown-panel { + animation: aksrtPopIn var(--dur-fast) var(--ease-out) forwards; +} + +/* --- 图片懒加载过渡 --- */ +img.lazyload, img.lazyloaded, img[data-src] { + transition: filter 0.6s var(--ease), opacity 0.4s var(--ease); +} + +img.lazyload, img[data-src] { + filter: blur(5px); + opacity: 0.7; +} + +img.lazyloaded { + filter: blur(0); + opacity: 1; +} + +/* --- 滚动进度条动效 --- */ +.reading-progress-bar { + transition: width 0.1s linear; +} + +/* --- 移动端抽屉动效 --- */ +@media (max-width: 767px) { + .n-drawer { + transition: transform var(--dur) var(--ease-out); + } + + .site-nav .n-drawer-body { + transition: transform var(--dur) var(--ease-out); + } +} + +/* --- 暗色模式切换动效 --- */ +html.dark { + transition: background-color 0.3s var(--ease), + color 0.3s var(--ease); +} + +html.dark * { + transition: background-color 0.3s var(--ease), + border-color 0.3s var(--ease), + color 0.3s var(--ease), + box-shadow 0.3s var(--ease); +} + +/* ============================================================ + * 18. 合作伙伴无缝滚动 (marquee) + * ============================================================ */ +.aksrt-marquee { + position: relative; + overflow: hidden; + width: 100%; +} + +.aksrt-marquee__inner { + display: flex; + gap: 24px; + white-space: nowrap; + will-change: transform; +} + +.aksrt-marquee__inner > * { + flex-shrink: 0; +} + +@media (prefers-reduced-motion: reduce) { + .aksrt-marquee__inner { + animation: none !important; + transform: none !important; + } +} + +/* ============================================================ + * 19. 视频剧集切换按钮 + * ============================================================ */ +.switch-video, +.switch-iframe { + display: inline-flex; + align-items: center; + gap: 4px; + padding: 6px 14px; + border: 1px solid var(--color-line, rgba(50, 50, 50, 0.1)); + border-radius: var(--radius, 8px); + background: var(--surface-1, #fff); + color: var(--color-ink-2, #4e5358); + font-size: 13px; + font-weight: 500; + cursor: pointer; + transition: all 0.15s ease; + text-decoration: none; +} + +.switch-video:hover, +.switch-iframe:hover { + border-color: var(--color-primary); + color: var(--color-primary); +} + +.switch-video.is-active, +.switch-iframe.is-active { + background: var(--color-primary); + border-color: var(--color-primary); + color: #fff; +} + +/* ============================================================ + * 20. 一言轮播组件 + * ============================================================ */ +.aksrt-yiyan { + padding: 16px; + text-align: center; +} + +.aksrt-yiyan__content { + min-height: 60px; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + gap: 8px; +} + +.aksrt-yiyan__icon { + font-size: 20px; + color: var(--color-primary); + opacity: 0.6; +} + +.aksrt-yiyan__text { + font-size: 14px; + line-height: 1.8; + color: var(--color-ink-2, #4e5358); + margin: 0; + transition: opacity 0.2s ease; + font-style: italic; +} + +.aksrt-yiyan__from { + font-size: 12px; + color: var(--color-ink-4, #999); + margin: 0; +} + +.aksrt-yiyan__dots { + display: flex; + align-items: center; + justify-content: center; + gap: 6px; + margin-top: 12px; +} + +.aksrt-yiyan__dot { + width: 6px; + height: 6px; + border-radius: 50%; + background: var(--color-line, rgba(50, 50, 50, 0.1)); + transition: background 0.2s; +} + +.aksrt-yiyan__dot.is-active { + background: var(--color-primary); + width: 16px; + border-radius: 3px; +} + +/* ============================================================ + * 底部弹出 Sheet — 对齐 zibll .modal.bottom + * ============================================================ */ +.aksrt-modal--bottom .aksrt-modal-auth__card, +.modal.bottom .modal-dialog { + position: fixed; + bottom: 0; + left: 0; + right: 0; + max-width: 100%; + width: 100%; + border-radius: var(--main-radius, 8px) var(--main-radius, 8px) 0 0; + transform: translateY(110%); + transition: transform 0.4s; + margin-bottom: 0; + padding-bottom: env(safe-area-inset-bottom); +} + +.aksrt-modal--bottom.is-open .aksrt-modal-auth__card, +.modal.bottom.in .modal-dialog { + transform: translateY(0); +} + +.aksrt-modal--bottom .aksrt-modal-auth__card, +.modal.bottom .modal-dialog .modal-content { + box-shadow: 0 -10px 50px rgba(0, 0, 0, 0.15); +} diff --git a/assets/css/common/floating.css b/assets/css/common/floating.css new file mode 100644 index 00000000..561ca3a8 --- /dev/null +++ b/assets/css/common/floating.css @@ -0,0 +1,452 @@ +/* ============================================================ + AKSRT – Floating UI & Site Footer + ============================================================ + Covers: + • .floating-toolbar – fixed action buttons (scroll-top, + font-size, sidebar toggle) + • .mobile-nav-overlay – full-screen drawer nav (mobile) + • .site-footer – footer grid + bottom bar + ============================================================ */ + + +/* ═══════════════════════════════════════════════════════════ + FLOATING TOOLBAR + ═══════════════════════════════════════════════════════════ */ + +.floating-toolbar { + position: fixed; + right: var(--space-5); + bottom: var(--space-8); + z-index: var(--z-floating); + display: flex; + flex-direction: column; + gap: var(--space-2); +} + +/* ── Individual button ────────────────────────────────────── */ +.floating-btn { + display: flex; + align-items: center; + justify-content: center; + width: 40px; + height: 40px; + background: var(--color-surface); + border: 1px solid var(--color-line); + border-radius: var(--radius-full); + box-shadow: var(--shadow-md); + cursor: pointer; + color: var(--color-ink-4); + transition: + background var(--transition-fast), + color var(--transition-fast), + box-shadow var(--transition-fast), + transform var(--transition-fast); + padding: 0; +} + +.floating-btn svg { + width: 18px; + height: 18px; + flex-shrink: 0; +} + +.floating-btn:hover, +.floating-btn:focus-visible { + background: var(--color-primary); + color: #fff; + border-color: var(--color-primary); + box-shadow: var(--shadow-lg); + transform: translateY(-2px); +} + +.floating-btn:active { + transform: translateY(0); + box-shadow: var(--shadow-sm); +} + +.floating-btn:focus-visible { + outline: 2px solid var(--color-primary); + outline-offset: 2px; +} + +/* ── Scroll-to-top: hide until page is scrolled ───────────── */ +.floating-btn--top { + opacity: 0; + pointer-events: none; + transition: + opacity var(--transition-base), + background var(--transition-fast), + color var(--transition-fast), + box-shadow var(--transition-fast), + transform var(--transition-fast); +} + +.floating-btn--top.is-visible { + opacity: 1; + pointer-events: auto; +} + +/* ── Mobile: smaller toolbar, stacked horizontally ───────── */ +@media (max-width: 767px) { + .floating-toolbar { + right: var(--space-4); + bottom: var(--space-6); + flex-direction: row; /* horizontal row on mobile */ + } + + .floating-btn { + width: 36px; + height: 36px; + } + + .floating-btn svg { + width: 16px; + height: 16px; + } +} + + +/* ═══════════════════════════════════════════════════════════ + MOBILE NAV OVERLAY + ═══════════════════════════════════════════════════════════ */ + +.mobile-nav-overlay { + position: fixed; + inset: 0; + z-index: var(--z-overlay); + background: rgba(0, 0, 0, 0.45); + opacity: 0; + visibility: hidden; + transition: + opacity var(--transition-base), + visibility var(--transition-base); + /* backdrop blur on supporting browsers */ + backdrop-filter: blur(2px); + -webkit-backdrop-filter: blur(2px); +} + +.mobile-nav-overlay.is-open { + opacity: 1; + visibility: visible; +} + +/* ── Drawer panel ─────────────────────────────────────────── */ +.mobile-nav-drawer { + position: absolute; + top: 0; + left: 0; + width: min(320px, 85vw); + height: 100%; + background: var(--color-surface); + box-shadow: var(--shadow-xl); + display: flex; + flex-direction: column; + gap: var(--space-4); + padding: var(--space-6); + overflow-y: auto; + overscroll-behavior: contain; + transform: translateX(-100%); + transition: transform var(--transition-base); +} + +.mobile-nav-overlay.is-open .mobile-nav-drawer { + transform: translateX(0); +} + +/* ── Close button ─────────────────────────────────────────── */ +.mobile-nav-close { + align-self: flex-end; + display: flex; + align-items: center; + justify-content: center; + width: 36px; + height: 36px; + background: var(--surface-page); + border: 1px solid var(--color-line); + border-radius: var(--radius-full); + cursor: pointer; + color: var(--color-ink-4); + transition: background var(--transition-fast), color var(--transition-fast); + flex-shrink: 0; +} + +.mobile-nav-close:hover { + background: var(--color-danger); + color: #fff; + border-color: var(--color-danger); +} + +.mobile-nav-close svg { + width: 18px; + height: 18px; +} + +/* ── Brand ────────────────────────────────────────────────── */ +.mobile-nav-brand { + padding-bottom: var(--space-4); + border-bottom: 1px solid var(--color-line); +} + +.mobile-nav-brand a { + font-size: 1.125rem; + font-weight: 700; + color: var(--color-ink); + text-decoration: none; +} + +.mobile-nav-brand a:hover { + color: var(--color-primary); +} + +/* ── Nav menu (WordPress-generated ul) ────────────────────── */ +.mobile-nav-menu { + display: flex; + flex-direction: column; + gap: var(--space-1); +} + +.mobile-nav-menu li { + list-style: none; +} + +.mobile-nav-menu a { + display: block; + padding: var(--space-2) var(--space-3); + font-size: 0.9375rem; + font-weight: 500; + color: var(--color-ink-4); + border-radius: var(--radius-md); + text-decoration: none; + transition: background var(--transition-fast), color var(--transition-fast); +} + +.mobile-nav-menu a:hover, +.mobile-nav-menu .current-menu-item > a, +.mobile-nav-menu .current-page-item > a { + background: var(--color-primary-light); + color: var(--color-primary); +} + +/* sub-menu indented */ +.mobile-nav-menu .sub-menu { + padding-left: var(--space-4); + margin-top: var(--space-1); +} + +/* ── Search form ──────────────────────────────────────────── */ +.mobile-nav-search { + margin-top: auto; + padding-top: var(--space-4); + border-top: 1px solid var(--color-line); +} + +.mobile-nav-search form { + display: flex; + gap: var(--space-2); +} + +.mobile-nav-search input[type="search"] { + flex: 1; + padding: var(--space-2) var(--space-3); + border: 1px solid var(--color-line); + border-radius: var(--radius-md); + font-size: 0.875rem; + background: var(--surface-page); + color: var(--color-ink); +} + +.mobile-nav-search input[type="search"]:focus { + outline: none; + border-color: var(--color-primary); +} + +.mobile-nav-search button[type="submit"] { + display: inline-flex; + align-items: center; + justify-content: center; + padding: var(--space-2) var(--space-3); + background: var(--color-primary); + color: #fff; + border: none; + border-radius: var(--radius-md); + cursor: pointer; + font-size: 0.875rem; + transition: background var(--transition-fast); +} + +.mobile-nav-search button[type="submit"]:hover { + background: var(--color-primary-dark); +} + +/* ── Only mount overlay on mobile ─────────────────────────── */ +@media (min-width: 769px) { + .mobile-nav-overlay { + display: none !important; + } +} + + +/* ═══════════════════════════════════════════════════════════ + SITE FOOTER + ═══════════════════════════════════════════════════════════ */ + +.site-footer { + margin-top: var(--space-16); + background: var(--color-surface); + border-top: 1px solid var(--color-line); +} + +.site-footer__inner { + padding-top: var(--space-12); + padding-bottom: var(--space-10); +} + +/* ── Grid of columns ──────────────────────────────────────── */ +.site-footer__grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); + gap: var(--space-8); + align-items: start; +} + +/* Give the about column a bit more real estate when there's room */ +.site-footer__about { + grid-column: span 2; +} + +@media (max-width: 900px) { + .site-footer__about { + grid-column: span 1; + } +} + +@media (max-width: 600px) { + .site-footer__grid { + grid-template-columns: 1fr 1fr; + } + + .site-footer__about { + grid-column: 1 / -1; + } +} + +/* ── Column headings ──────────────────────────────────────── */ +.site-footer__heading { + font-size: 0.8125rem; + font-weight: 700; + text-transform: uppercase; + letter-spacing: 0.06em; + color: var(--color-ink-4); + margin-bottom: var(--space-4); +} + +/* ── About description ────────────────────────────────────── */ +.site-footer__desc { + font-size: 0.875rem; + color: var(--color-ink-4); + line-height: 1.65; + margin-bottom: var(--space-4); +} + +/* ── Contact icon row ─────────────────────────────────────── */ +.site-footer__contacts { + display: flex; + flex-wrap: wrap; + gap: var(--space-2); +} + +.site-footer__contacts a { + display: flex; + align-items: center; + justify-content: center; + width: 32px; + height: 32px; + border-radius: var(--radius-full); + border: 1px solid var(--color-line); + color: var(--color-ink-4); + transition: background var(--transition-fast), color var(--transition-fast), border-color var(--transition-fast); +} + +.site-footer__contacts a:hover { + background: var(--color-primary); + color: #fff; + border-color: var(--color-primary); +} + +.site-footer__contacts .dashicons { + font-size: 16px; + width: 16px; + height: 16px; +} + +/* ── Link lists ───────────────────────────────────────────── */ +.site-footer__links { + display: flex; + flex-direction: column; + gap: var(--space-2); +} + +.site-footer__links li { + list-style: none; +} + +.site-footer__links a { + font-size: 0.875rem; + color: var(--color-ink-4); + text-decoration: none; + transition: color var(--transition-fast); +} + +.site-footer__links a:hover { + color: var(--color-primary); +} + +/* ── Friend links: wrap horizontally ─────────────────────── */ +.site-footer__links--friends { + flex-direction: row; + flex-wrap: wrap; + gap: var(--space-2) var(--space-4); +} + +/* ── Bottom copyright bar ─────────────────────────────────── */ +.site-footer__bottom { + border-top: 1px solid var(--color-border-light); + background: var(--surface-page); + padding: var(--space-4) 0; +} + +.site-footer__bottom .container { + display: flex; + align-items: center; + justify-content: space-between; + flex-wrap: wrap; + gap: var(--space-2); +} + +.site-footer__copy, +.site-footer__icp { + font-size: 0.8125rem; + color: var(--color-ink-4); +} + +.site-footer__icp { + display: flex; + align-items: center; + gap: var(--space-3); +} + +.site-footer__icp a { + color: var(--color-ink-4); + transition: color var(--transition-fast); +} + +.site-footer__icp a:hover { + color: var(--color-primary); +} + +@media (max-width: 600px) { + .site-footer__bottom .container { + flex-direction: column; + text-align: center; + } +} diff --git a/assets/css/core/alerts.css b/assets/css/core/alerts.css new file mode 100644 index 00000000..b0c9b2c4 --- /dev/null +++ b/assets/css/core/alerts.css @@ -0,0 +1,53 @@ +/** + * AKSRT Alerts + * 统一提示组件:error / warning / info / success + * 用于替代各页面 inline 的 .login-error / .bind-error 等 + */ + +.alert { + display: flex; + align-items: flex-start; + gap: 10px; + padding: 12px 14px; + margin-bottom: var(--space-4); + font-size: var(--text-sm); + line-height: var(--leading-snug); + border-radius: var(--radius); + border: 1px solid transparent; +} + +.alert > svg { + flex-shrink: 0; + width: 18px; + height: 18px; + margin-top: 1px; +} + +.alert--error { + color: #B91C1C; + background: rgba(239, 68, 68, 0.08); + border-color: rgba(239, 68, 68, 0.3); +} + +.alert--warning { + color: #B45309; + background: rgba(245, 158, 11, 0.08); + border-color: rgba(245, 158, 11, 0.3); +} + +.alert--success { + color: #047857; + background: rgba(16, 185, 129, 0.08); + border-color: rgba(16, 185, 129, 0.3); +} + +.alert--info { + color: #1D4ED8; + background: rgba(59, 130, 246, 0.08); + border-color: rgba(59, 130, 246, 0.3); +} + +html.dark .alert--error { color: #FCA5A5; } +html.dark .alert--warning { color: #FCD34D; } +html.dark .alert--success { color: #6EE7B7; } +html.dark .alert--info { color: #93C5FD; } diff --git a/assets/css/core/animations.css b/assets/css/core/animations.css new file mode 100644 index 00000000..cba303f3 --- /dev/null +++ b/assets/css/core/animations.css @@ -0,0 +1,323 @@ +/** + * AKSRT Animations — animate.css 等价(独立重写) + * ------------------------------------------------------------ + * 关键帧 + 工具类 + IntersectionObserver 触发配合 + * 触发 JS 已在 enhancements2.js([data-aksrt-animate] 属性) + * 本文件仅定义 @keyframes 和 .aksrt-anim-* 工具类 + */ + +/* ============================================================ + * Keyframes + * ============================================================ */ + +/* Fade 系列 */ +@keyframes aksrtFadeIn { + from { opacity: 0; } + to { opacity: 1; } +} + +@keyframes aksrtFadeInUp { + from { opacity: 0; transform: translateY(20px); } + to { opacity: 1; transform: none; } +} + +@keyframes aksrtFadeInDown { + from { opacity: 0; transform: translateY(-20px); } + to { opacity: 1; transform: none; } +} + +@keyframes aksrtFadeInLeft { + from { opacity: 0; transform: translateX(-20px); } + to { opacity: 1; transform: none; } +} + +@keyframes aksrtFadeInRight { + from { opacity: 0; transform: translateX(20px); } + to { opacity: 1; transform: none; } +} + +/* Zoom 系列 */ +@keyframes aksrtZoomIn { + from { opacity: 0; transform: scale(.85); } + to { opacity: 1; transform: none; } +} + +@keyframes aksrtZoomInUp { + from { opacity: 0; transform: scale(.85) translateY(20px); } + to { opacity: 1; transform: none; } +} + +/* Bounce 系列 */ +@keyframes aksrtBounceIn { + 0% { opacity: 0; transform: scale(.3); } + 50% { opacity: 1; transform: scale(1.08); } + 70% { transform: scale(.95); } + 100% { opacity: 1; transform: none; } +} + +@keyframes aksrtBounce { + 0%, 20%, 50%, 80%, 100% { transform: translateY(0); } + 40% { transform: translateY(-12px); } + 60% { transform: translateY(-6px); } +} + +/* Pulse */ +@keyframes aksrtPulse { + 0% { transform: scale(1); } + 50% { transform: scale(1.06); } + 100% { transform: scale(1); } +} + +/* Flash */ +@keyframes aksrtFlash { + 0%, 50%, 100% { opacity: 1; } + 25%, 75% { opacity: 0; } +} + +/* RubberBand */ +@keyframes aksrtRubberBand { + 0% { transform: scale(1); } + 30% { transform: scaleX(1.25) scaleY(0.75); } + 40% { transform: scaleX(0.75) scaleY(1.25); } + 50% { transform: scaleX(1.15) scaleY(0.85); } + 65% { transform: scaleX(0.95) scaleY(1.05); } + 75% { transform: scaleX(1.05) scaleY(0.95); } + 100% { transform: scale(1); } +} + +/* Shake */ +@keyframes aksrtShake { + 0%, 100% { transform: translateX(0); } + 10%, 30%, 50%, 70%, 90% { transform: translateX(-4px); } + 20%, 40%, 60%, 80% { transform: translateX(4px); } +} + +/* Swing */ +@keyframes aksrtSwing { + 20% { transform: rotate(15deg); } + 40% { transform: rotate(-10deg); } + 60% { transform: rotate(5deg); } + 80% { transform: rotate(-5deg); } + 100% { transform: none; } +} + +/* Tada */ +@keyframes aksrtTada { + 0% { transform: scale(1); } + 10%, 20% { transform: scale(0.9) rotate(-3deg); } + 30%, 50%, 70%, 90% { transform: scale(1.1) rotate(3deg); } + 40%, 60%, 80% { transform: scale(1.1) rotate(-3deg); } + 100% { transform: scale(1) rotate(0); } +} + +/* Wobble */ +@keyframes aksrtWobble { + 0% { transform: none; } + 15% { transform: translateX(-25%) rotate(-5deg); } + 30% { transform: translateX(20%) rotate(3deg); } + 45% { transform: translateX(-15%) rotate(-3deg); } + 60% { transform: translateX(10%) rotate(2deg); } + 75% { transform: translateX(-5%) rotate(-1deg); } + 100% { transform: none; } +} + +/* Slide 系列 */ +@keyframes aksrtSlideInUp { + from { opacity: 0; transform: translateY(100%); } + to { opacity: 1; transform: none; } +} + +@keyframes aksrtSlideInDown { + from { opacity: 0; transform: translateY(-100%); } + to { opacity: 1; transform: none; } +} + +@keyframes aksrtSlideInLeft { + from { opacity: 0; transform: translateX(-100%); } + to { opacity: 1; transform: none; } +} + +@keyframes aksrtSlideInRight { + from { opacity: 0; transform: translateX(100%); } + to { opacity: 1; transform: none; } +} + +/* HeartBeat */ +@keyframes aksrtHeartBeat { + 0% { transform: scale(1); } + 14% { transform: scale(1.3); } + 28% { transform: scale(1); } + 42% { transform: scale(1.3); } + 70% { transform: scale(1); } + 100% { transform: scale(1); } +} + +/* Jello */ +@keyframes aksrtJello { + 0%, 100% { transform: none; } + 11% { transform: skewX(-12.5deg) skewY(-12.5deg); } + 22% { transform: skewX(6.25deg) skewY(6.25deg); } + 33% { transform: skewX(-6.25deg) skewY(-6.25deg); } + 44% { transform: skewX(3.125deg) skewY(3.125deg); } + 55% { transform: skewX(-3.125deg) skewY(-3.125deg); } + 66% { transform: skewX(1.5625deg) skewY(1.5625deg); } + 77% { transform: skewX(-1.5625deg) skewY(-1.5625deg); } + 88% { transform: skewX(0.78125deg) skewY(0.78125deg); } +} + +/* HeadShake */ +@keyframes aksrtHeadShake { + 0% { transform: translateX(0); } + 6.5% { transform: translateX(-6px) rotateY(-9deg); } + 18.5% { transform: translateX(5px) rotateY(7deg); } + 31.5% { transform: translateX(-3px) rotateY(-5deg); } + 43.5% { transform: translateX(2px) rotateY(3deg); } + 50% { transform: translateX(0); } + 100% { transform: translateX(0); } +} + +/* BounceOut — 退出动画 */ +@keyframes aksrtBounceOut { + 0% { transform: scale(1); } + 25% { transform: scale(0.95); } + 50% { transform: scale(1.1); } + 75% { transform: scale(0.97); } + 100% { transform: scale(1); opacity: 0; } +} + +/* ZoomOut — 退出动画 */ +@keyframes aksrtZoomOut { + 0% { opacity: 1; transform: none; } + 100% { opacity: 0; transform: scale(0.85); } +} + +/* BackIn/BackOut */ +@keyframes aksrtBackInUp { + 0% { opacity: 0; transform: translateY(30px) scale(0.7); } + 80% { opacity: 0.8; transform: translateY(-5px) scale(1.02); } + 100% { opacity: 1; transform: none; } +} + +@keyframes aksrtBackInDown { + 0% { opacity: 0; transform: translateY(-30px) scale(0.7); } + 80% { opacity: 0.8; transform: translateY(5px) scale(1.02); } + 100% { opacity: 1; transform: none; } +} + +/* Flip */ +@keyframes aksrtFlip { + 0% { transform: perspective(400px) rotateY(90deg); opacity: 0; } + 40% { transform: perspective(400px) rotateY(-10deg); } + 70% { transform: perspective(400px) rotateY(10deg); } + 100% { transform: perspective(400px) rotateY(0deg); opacity: 1; } +} + +@keyframes aksrtFlipInX { + 0% { transform: perspective(400px) rotateX(90deg); opacity: 0; } + 40% { transform: perspective(400px) rotateX(-10deg); } + 70% { transform: perspective(400px) rotateX(10deg); } + 100% { transform: perspective(400px) rotateX(0deg); opacity: 1; } +} + +/* ============================================================ + * Animation utility classes + * ============================================================ */ +.aksrt-anim-fade-in { animation: aksrtFadeIn var(--dur-base, .4s) var(--ease-out, ease) both; } +.aksrt-anim-fade-up { animation: aksrtFadeInUp var(--dur-base, .4s) var(--ease-out, ease) both; } +.aksrt-anim-fade-down { animation: aksrtFadeInDown var(--dur-base, .4s) var(--ease-out, ease) both; } +.aksrt-anim-fade-left { animation: aksrtFadeInLeft var(--dur-base, .4s) var(--ease-out, ease) both; } +.aksrt-anim-fade-right { animation: aksrtFadeInRight var(--dur-base, .4s) var(--ease-out, ease) both; } + +.aksrt-anim-zoom-in { animation: aksrtZoomIn var(--dur-base, .4s) var(--ease-out, ease) both; } +.aksrt-anim-zoom-in-up { animation: aksrtZoomInUp var(--dur-base, .4s) var(--ease-out, ease) both; } + +.aksrt-anim-bounce-in { animation: aksrtBounceIn .6s var(--ease-out, ease) both; } +.aksrt-anim-bounce { animation: aksrtBounce 1s ease both; } + +.aksrt-anim-pulse { animation: aksrtPulse 1s ease infinite; } +.aksrt-anim-flash { animation: aksrtFlash 1s ease both; } +.aksrt-anim-rubber-band { animation: aksrtRubberBand .8s ease both; } +.aksrt-anim-shake { animation: aksrtShake .5s ease both; } +.aksrt-anim-swing { animation: aksrtSwing .6s var(--ease-out, ease) both; } +.aksrt-anim-tada { animation: aksrtTada 1s ease both; } +.aksrt-anim-wobble { animation: aksrtWobble .8s ease both; } +.aksrt-anim-heart-beat { animation: aksrtHeartBeat 1.3s ease both; } +.aksrt-anim-jello { animation: aksrtJello .8s ease both; } +.aksrt-anim-head-shake { animation: aksrtHeadShake .8s ease both; } + +/* 退出动画 */ +.aksrt-anim-bounce-out { animation: aksrtBounceOut .5s ease both; } +.aksrt-anim-zoom-out { animation: aksrtZoomOut .3s ease both; } + +/* BackIn 动画 */ +.aksrt-anim-back-in-up { animation: aksrtBackInUp .5s var(--ease-out, ease) both; } +.aksrt-anim-back-in-down { animation: aksrtBackInDown .5s var(--ease-out, ease) both; } + +.aksrt-anim-slide-up { animation: aksrtSlideInUp .5s var(--ease-out, ease) both; } +.aksrt-anim-slide-down { animation: aksrtSlideInDown .5s var(--ease-out, ease) both; } +.aksrt-anim-slide-left { animation: aksrtSlideInLeft .5s var(--ease-out, ease) both; } +.aksrt-anim-slide-right { animation: aksrtSlideInRight .5s var(--ease-out, ease) both; } + +.aksrt-anim-flip { animation: aksrtFlip .6s var(--ease-out, ease) both; } +.aksrt-anim-flip-x { animation: aksrtFlipInX .6s var(--ease-out, ease) both; } + +/* ============================================================ + * Duration modifiers + * ============================================================ */ +.aksrt-anim-fast { --dur-base: .2s; } +.aksrt-anim-slow { --dur-base: .6s; } + +/* ============================================================ + * Delay modifiers (配合 data-aksrt-delay 使用时为 inline, + * 也可用 class 方式独立设置) + * ============================================================ */ +.aksrt-anim-delay-1 { animation-delay: .1s; } +.aksrt-anim-delay-2 { animation-delay: .2s; } +.aksrt-anim-delay-3 { animation-delay: .3s; } +.aksrt-anim-delay-4 { animation-delay: .4s; } +.aksrt-anim-delay-5 { animation-delay: .5s; } +.aksrt-anim-delay-6 { animation-delay: .6s; } +.aksrt-anim-delay-7 { animation-delay: .7s; } +.aksrt-anim-delay-8 { animation-delay: .8s; } + +/* ============================================================ + * Infinite modifier + * ============================================================ */ +.aksrt-anim-infinite { animation-iteration-count: infinite; } + +/* ============================================================ + * Reduced-motion — 尊重用户偏好 + * ============================================================ */ +@media (prefers-reduced-motion: reduce) { + .aksrt-anim-fade-in, + .aksrt-anim-fade-up, + .aksrt-anim-fade-down, + .aksrt-anim-fade-left, + .aksrt-anim-fade-right, + .aksrt-anim-zoom-in, + .aksrt-anim-zoom-in-up, + .aksrt-anim-bounce-in, + .aksrt-anim-bounce, + .aksrt-anim-pulse, + .aksrt-anim-flash, + .aksrt-anim-rubber-band, + .aksrt-anim-shake, + .aksrt-anim-swing, + .aksrt-anim-tada, + .aksrt-anim-wobble, + .aksrt-anim-heart-beat, + .aksrt-anim-jello, + .aksrt-anim-head-shake, + .aksrt-anim-bounce-out, + .aksrt-anim-zoom-out, + .aksrt-anim-back-in-up, + .aksrt-anim-back-in-down, + .aksrt-anim-slide-up, + .aksrt-anim-slide-down, + .aksrt-anim-slide-left, + .aksrt-anim-slide-right, + .aksrt-anim-flip, + .aksrt-anim-flip-x { + animation: none !important; + } +} diff --git a/assets/css/core/buttons.css b/assets/css/core/buttons.css new file mode 100644 index 00000000..4a3182f0 --- /dev/null +++ b/assets/css/core/buttons.css @@ -0,0 +1,304 @@ +/** + * AKSRT Buttons — 1:1 Zibll Alignment + * + * 对齐 zibll .but 系统: + * - 正常字重 (normal) + * - 4px 圆角 + * - 灰色默认背景 + * - opacity hover + */ + +.btn, +.btn-primary, +.btn-outline, +.btn-ghost, +.btn-danger { + --btn-h: 34px; + --btn-px: 12px; + display: inline-flex; + align-items: center; + justify-content: center; + gap: 6px; + height: var(--btn-h); + padding: 0 var(--btn-px); + font-size: var(--text-sm); + font-weight: normal; + line-height: 1.44; + border: 1px solid transparent; + border-radius: var(--radius-btn); + cursor: pointer; + white-space: nowrap; + user-select: none; + text-decoration: none; + transition: opacity var(--dur-fast) var(--ease), + background var(--dur-fast) var(--ease), + border-color var(--dur-fast) var(--ease), + color var(--dur-fast) var(--ease); +} + +/* 尺寸变体 */ +.btn-sm { --btn-h: 28px; --btn-px: 8px; font-size: var(--text-xs); } +.btn-lg { --btn-h: 44px; --btn-px: 18px; font-size: var(--text-base); } + +/* === Default (gray background, like zibll .but default) === */ +.btn { + background: rgba(136, 136, 136, 0.1); + color: #888; +} + +.btn:hover { + opacity: 0.8; +} + +/* === Primary === */ +.btn-primary { + background: var(--color-primary); + color: var(--color-on-primary); + border-color: var(--color-primary); +} + +.btn-primary:hover { + opacity: 0.8; + color: var(--color-on-primary); +} + +.btn-primary:active { + opacity: 1; + box-shadow: inset 0 2px 3px rgba(0, 0, 0, 0.08); +} + +/* === Outline === */ +.btn-outline { + background: transparent; + color: var(--color-ink-2); + border-color: var(--color-line); +} + +.btn-outline:hover { + background: var(--color-primary-soft); + border-color: var(--color-primary); + color: var(--color-primary); + opacity: 1; +} + +/* === Ghost === */ +.btn-ghost { + background: transparent; + color: var(--color-ink-2); + border-color: transparent; +} + +.btn-ghost:hover { + background: rgba(136, 136, 136, 0.1); + opacity: 1; +} + +/* === Danger === */ +.btn-danger { + background: var(--color-error); + color: #fff; + border-color: var(--color-error); +} + +.btn-danger:hover { + opacity: 0.8; + color: #fff; +} + +/* === Disabled === */ +.btn:disabled, +.btn-primary:disabled, +.btn-outline:disabled, +.btn-ghost:disabled, +.btn-danger:disabled { + opacity: 0.5; + cursor: not-allowed; + pointer-events: none; +} + +/* === Icon button === */ +.btn-icon { + width: var(--btn-h); + padding: 0; + justify-content: center; +} + +.btn-icon.btn-sm { width: 28px; } +.btn-icon.btn-lg { width: 44px; } + +/* === Full width === */ +.btn-block { + width: 100%; +} + +/* ============================================================ + * Zibll .but / .badg compat layer — 1:1 zibll main.css (.but system) + * ------------------------------------------------------------ + * Additive: does NOT alter the AKSRT .btn system above. Lets reused + * zibll-style markup (.but / .badg / .b-* / .jb-* / .c-* / .but-group / + * .but-average / .toggle-radius) render via the --this-* context-coloring vars. + * The --this-* DEFAULTS are set on the base rule here (BEFORE the .b-*/.jb-* + * modifiers) so the cascade resolves colored variants correctly; scoped to + * .but/.badg (never :root) so .float-btn's own var(--this-*, fallback) stays intact. + * Consumes --focus-color-opacity* from zibll-compat-vars.css. + * ============================================================ */ + +/* Base (zibll .but / .badg) */ +.but, +.badg { + display: inline-block; + vertical-align: middle; + padding: 0.3em 0.6em; + text-align: center; + font-weight: normal; + line-height: 1.44; + border-radius: 4px; + border: 1px solid var(--this-border); + box-shadow: var(--this-shadow); + background: var(--this-bg); + color: var(--this-color); + --main-color: var(--this-color); + --this-bg: rgba(136, 136, 136, 0.1); + --this-border: transparent; + --this-shadow: none; + --this-color: #888; + text-shadow: 0 0 0; + transition: 0.15s; + cursor: pointer; +} + +.but a { color: inherit; } + +.but .icon, +.but > .fa:not(.fa-angle-right) { margin-right: 0.25em; } + +/* hover / active */ +.but:focus, +.but:hover { opacity: 0.8; color: var(--this-color); } +.but:active { --this-shadow: inset 0 2px 3px rgba(0, 0, 0, 0.08); } + +/* radius variants */ +.but.radius, +.badg.radius, +.radius > .but { border-radius: 50px; padding: 0.3em 1em; } +.but.main-radius, +.badg.main-radius { border-radius: var(--main-radius); } +.but.mini-radius, +.badg.mini-radius { border-radius: var(--mini-radius); } + +/* hollow (outline) */ +.but.hollow, +.badg.hollow { background: transparent; --this-border: var(--this-color); } +.but.hollow:hover { background: var(--this-bg); } +.badg.hollow[class*='b-'], +.but.hollow[class*='b-'] { background: 0 0; --this-border: var(--this-bg); --this-color: var(--this-bg); } +.but.hollow[class*='b-']:hover { color: #fff; } +.but.hollow.c-white:hover { background: 0 0; --this-color: var(--focus-color); color: var(--focus-color); } + +/* circular icon button */ +.circular, +.badg.cir, +.but.cir { + padding: 0; + border-radius: 5em; + --this-size: 1.8em; + display: inline-flex; + justify-content: center; + align-items: center; + height: var(--this-size); + min-width: var(--this-size); +} +.circular.radius4, +.badg.cir.radius4, +.but.cir.radius4 { border-radius: 4px; } +.but.cir svg.icon, +.but.cir > .fa { margin: 0; } + +/* button group (joined) */ +.but-group { display: inline-flex; } +.but-group > .but { border-radius: 0; margin: 0; } +.but-group > .but:first-of-type { border-radius: 4px 0 0 4px; } +.but-group > .but:last-of-type { border-radius: 0 4px 4px 0; } + +/* segmented control (equal-width) */ +.but-average { display: flex; border-radius: 4px; overflow: hidden; } +.but-average.inline { display: inline-flex; } +.but-average.radius { border-radius: 100px; } +.but-average.main-radius { border-radius: var(--main-radius); } +.but-average.mini-radius { border-radius: var(--mini-radius); } +.but-average > .but { margin: 0 !important; border-radius: 0; flex: auto; } +.but-average > .but.active { --this-bg: var(--focus-color-opacity1); --this-color: var(--focus-color); } + +/* size variants */ +.but.but-sm { font-size: 0.9em; padding: 0.1em 0.4em; vertical-align: 0.05em; } +.but.badg-sm, +.badg.badg-sm { font-size: 0.8em; padding: 0 0.2em; vertical-align: 0.1em; min-width: 1.6em; } +.badg.badg-sm.cir { --this-size: 1.6em; } +.padding-lg, +.badg.badg-lg, +.but.padding-lg { padding: 0.5em 2em; } + +/* active badge state */ +.active.badg, +.active > .badg:not(.vip-tag) { --this-bg: var(--focus-color); --this-color: #fff; } +.active.badg.hollow, +.active > .hollow:not(.vip-tag) { --this-color: var(--focus-color); } + +/* toggle-radius (round 29px toggle) */ +.toggle-radius { + background: var(--this-bg); + width: 29px; + height: 29px; + display: inline-block; + text-align: center; + border-radius: 100%; + position: relative; + vertical-align: text-top; + --this-bg: var(--main-border-color); +} +.toggle-radius .fa, +.toggle-radius .icon { right: 0 !important; left: 0 !important; margin: auto; } + +/* solid color modifiers — set --this-bg; default --this-color white */ +.b-gray, .b-theme, .b-red, .b-yellow, .b-blue, .b-blue-2, .b-black, +.b-cyan, .b-green, .b-purple, +.jb-red, .jb-pink, .jb-yellow, .jb-blue, .jb-green, .jb-purple, +.jb-vip1, .jb-vip2 { + color: var(--this-color); + background: var(--this-bg); + --this-color: #fff; +} +.jb-red, .jb-pink, .jb-yellow, .jb-blue, .jb-green, .jb-purple, +.jb-vip1, .jb-vip2 { border: none; } + +.b-theme { --this-bg: var(--focus-color); } +.b-gray { --this-bg: #818b95; } +.b-red { --this-bg: #ff5473; } +.b-yellow { --this-bg: #ff6f06; } +.b-cyan { --this-bg: #08c4c1; } +.b-blue { --this-bg: #2997f7; } +.b-blue-2 { --this-bg: #5c7cff; } +.b-green { --this-bg: #12b928; } +.b-purple { --this-bg: #d448f5; } +.b-black { --this-bg: #121517; } + +/* gradient modifiers (zibll .jb-*) */ +.jb-red { --this-bg: linear-gradient(135deg, #fd7a64 10%, #fb2d2d 100%); } +.jb-yellow { --this-bg: linear-gradient(135deg, #f99d4d 10%, #f7631d 100%); } +.jb-blue { --this-bg: linear-gradient(135deg, #59c3fb 10%, #268df7 100%); } +.jb-green { --this-bg: linear-gradient(135deg, #60e464 10%, #5cb85b 100%); } +.jb-purple { --this-bg: linear-gradient(135deg, #f98dfb 10%, #ea00f9 100%); } +.jb-pink { --this-bg: linear-gradient(135deg, #ff5e7f 30%, #ff967e 100%); } +.jb-vip1 { --this-bg: linear-gradient(25deg, #eabe7b 10%, #f5e3c7 70%, #edc788 100%); --this-color: #866127; } +.jb-vip2 { --this-bg: linear-gradient(317deg, #4d4c4c 30%, #7b7b7b 70%, #5f5c5c 100%); --this-color: #ddd; } + +/* text-color modifiers (zibll .c-*) — set --this-color + light --this-bg */ +.c-theme, .c-gray, .c-white, .c-red, .c-red-2, .c-yellow, .c-blue, .c-blue-2, +.c-green, .c-cyan, .c-purple { color: var(--this-color); } +.c-theme { --this-color: var(--focus-color); --this-bg: var(--focus-color-opacity1); } +.c-gray { --this-color: #888; --this-bg: rgba(136, 136, 136, 0.1); } +.c-white { --this-color: #fff; --this-bg: rgba(255, 255, 255, 0.1); } +.c-red { --this-color: #ff5473; --this-bg: rgba(255, 84, 115, 0.1); } +.c-red-2 { --this-color: #d6064c; --this-bg: rgba(194, 41, 46, 0.1); } +.c-yellow { --this-color: #ff6f06; --this-bg: rgba(255, 111, 6, 0.1); } +.c-blue { --this-color: #2997f7; --this-bg: rgba(41, 151, 247, 0.1); } diff --git a/assets/css/core/color-utilities.css b/assets/css/core/color-utilities.css new file mode 100644 index 00000000..091522c0 --- /dev/null +++ b/assets/css/core/color-utilities.css @@ -0,0 +1,272 @@ +/** + * AKSRT Color Utilities — 多色按钮 / 渐变按钮 / 文字渐变 / Badge + * ------------------------------------------------------------ + * 所有颜色走 CSS 变量(定义在 tokens.css),不硬编码十六进制。 + */ + +/* ============================================================ + * 1. 多色按钮 — .aksrt-btn--{color} + * ============================================================ */ +.aksrt-btn--rose { background: var(--aksrt-rose); color: #fff; } +.aksrt-btn--rose:hover, +.aksrt-btn--rose:focus-visible { background: #e11d48; } + +.aksrt-btn--blue { background: var(--aksrt-blue); color: #fff; } +.aksrt-btn--blue:hover, +.aksrt-btn--blue:focus-visible { background: #2563eb; } + +.aksrt-btn--green { background: var(--aksrt-green); color: #fff; } +.aksrt-btn--green:hover, +.aksrt-btn--green:focus-visible { background: #059669; } + +.aksrt-btn--orange { background: var(--aksrt-orange); color: #fff; } +.aksrt-btn--orange:hover, +.aksrt-btn--orange:focus-visible { background: #ea580c; } + +.aksrt-btn--purple { background: var(--aksrt-purple); color: #fff; } +.aksrt-btn--purple:hover, +.aksrt-btn--purple:focus-visible { background: #7c3aed; } + +.aksrt-btn--cyan { background: var(--aksrt-cyan); color: #fff; } +.aksrt-btn--cyan:hover, +.aksrt-btn--cyan:focus-visible { background: #0891b2; } + +.aksrt-btn--yellow { background: var(--aksrt-yellow); color: #422006; } +.aksrt-btn--yellow:hover, +.aksrt-btn--yellow:focus-visible { background: #ca8a04; color: #fff; } + +.aksrt-btn--red { background: var(--aksrt-red); color: #fff; } +.aksrt-btn--red:hover, +.aksrt-btn--red:focus-visible { background: #dc2626; } + +.aksrt-btn--teal { background: var(--aksrt-teal); color: #fff; } +.aksrt-btn--teal:hover, +.aksrt-btn--teal:focus-visible { background: #0d9488; } + +.aksrt-btn--indigo { background: var(--aksrt-indigo); color: #fff; } +.aksrt-btn--indigo:hover, +.aksrt-btn--indigo:focus-visible { background: #4f46e5; } + +.aksrt-btn--pink { background: var(--aksrt-pink); color: #fff; } +.aksrt-btn--pink:hover, +.aksrt-btn--pink:focus-visible { background: #db2777; } + +/* Soft variant — 浅色背景 + 深色文字 */ +.aksrt-btn--rose-soft { background: var(--aksrt-rose-soft); color: var(--aksrt-rose); } +.aksrt-btn--blue-soft { background: var(--aksrt-blue-soft); color: var(--aksrt-blue); } +.aksrt-btn--green-soft { background: var(--aksrt-green-soft); color: var(--aksrt-green); } +.aksrt-btn--orange-soft { background: var(--aksrt-orange-soft); color: var(--aksrt-orange); } +.aksrt-btn--purple-soft { background: var(--aksrt-purple-soft); color: var(--aksrt-purple); } +.aksrt-btn--cyan-soft { background: var(--aksrt-cyan-soft); color: var(--aksrt-cyan); } +.aksrt-btn--yellow-soft { background: var(--aksrt-yellow-soft); color: #92400e; } +.aksrt-btn--red-soft { background: var(--aksrt-red-soft); color: var(--aksrt-red); } +.aksrt-btn--teal-soft { background: var(--aksrt-teal-soft); color: var(--aksrt-teal); } +.aksrt-btn--indigo-soft { background: var(--aksrt-indigo-soft); color: var(--aksrt-indigo); } +.aksrt-btn--pink-soft { background: var(--aksrt-pink-soft); color: var(--aksrt-pink); } + +/* ============================================================ + * 2. 渐变按钮 — .aksrt-btn--grad-{name} + * ============================================================ */ +.aksrt-btn--grad-vip { + background: linear-gradient(135deg, var(--aksrt-vip-gold-1), var(--aksrt-vip-gold-2)); + color: #5a3d00; + border: none; +} + +.aksrt-btn--grad-sunset { + background: linear-gradient(135deg, var(--aksrt-grad-sunset-1), var(--aksrt-grad-sunset-2)); + color: #fff; + border: none; +} + +.aksrt-btn--grad-ocean { + background: linear-gradient(135deg, var(--aksrt-grad-ocean-1), var(--aksrt-grad-ocean-2)); + color: #fff; + border: none; +} + +.aksrt-btn--grad-forest { + background: linear-gradient(135deg, var(--aksrt-grad-forest-1), var(--aksrt-grad-forest-2)); + color: #064e3b; + border: none; +} + +.aksrt-btn--grad-night { + background: linear-gradient(135deg, var(--aksrt-grad-night-1), var(--aksrt-grad-night-2)); + color: #4c1d95; + border: none; +} + +.aksrt-btn--grad-fire { + background: linear-gradient(135deg, var(--aksrt-grad-fire-1), var(--aksrt-grad-fire-2)); + color: #fff; + border: none; +} + +.aksrt-btn--grad-primary { + background: linear-gradient(135deg, var(--color-primary), var(--color-primary-active)); + color: var(--color-on-primary); + border: none; +} + +/* 渐变按钮 hover — 亮度微调 */ +.aksrt-btn--grad-vip:hover, +.aksrt-btn--grad-sunset:hover, +.aksrt-btn--grad-ocean:hover, +.aksrt-btn--grad-forest:hover, +.aksrt-btn--grad-night:hover, +.aksrt-btn--grad-fire:hover, +.aksrt-btn--grad-primary:hover { + filter: brightness(1.08); + box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15); +} + +/* ============================================================ + * 3. 文字渐变 — .aksrt-text-grad-{name} + * ============================================================ */ +.aksrt-text-grad-primary { + background: linear-gradient(135deg, var(--color-primary), var(--color-primary-active)); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; +} + +.aksrt-text-grad-vip { + background: linear-gradient(135deg, var(--aksrt-vip-gold-1), var(--aksrt-vip-gold-2)); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; +} + +.aksrt-text-grad-sunset { + background: linear-gradient(135deg, var(--aksrt-grad-sunset-1), var(--aksrt-grad-sunset-2)); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; +} + +.aksrt-text-grad-ocean { + background: linear-gradient(135deg, var(--aksrt-grad-ocean-1), var(--aksrt-grad-ocean-2)); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; +} + +.aksrt-text-grad-forest { + background: linear-gradient(135deg, var(--aksrt-grad-forest-1), var(--aksrt-grad-forest-2)); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; +} + +.aksrt-text-grad-night { + background: linear-gradient(135deg, var(--aksrt-grad-night-1), var(--aksrt-grad-night-2)); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; +} + +.aksrt-text-grad-fire { + background: linear-gradient(135deg, var(--aksrt-grad-fire-1), var(--aksrt-grad-fire-2)); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; +} + +/* ============================================================ + * 4. Badge 系统 — .aksrt-badge / .aksrt-badge--{color} + * ============================================================ */ +.aksrt-badge { + display: inline-flex; + align-items: center; + justify-content: center; + height: var(--aksrt-badge-h, 22px); + padding: 0 8px; + border-radius: var(--radius-pill, 100px); + font-size: 12px; + font-weight: 600; + line-height: 1; + white-space: nowrap; + vertical-align: middle; +} + +.aksrt-badge--primary { background: var(--color-primary-soft); color: var(--color-primary); } +.aksrt-badge--success { background: rgba(16, 185, 129, 0.12); color: var(--color-success); } +.aksrt-badge--warning { background: rgba(245, 158, 11, 0.12); color: var(--color-warning); } +.aksrt-badge--error { background: rgba(239, 68, 68, 0.12); color: var(--color-error); } +.aksrt-badge--info { background: rgba(59, 130, 246, 0.12); color: var(--color-info); } + +.aksrt-badge--rose { background: var(--aksrt-rose-soft); color: var(--aksrt-rose); } +.aksrt-badge--blue { background: var(--aksrt-blue-soft); color: var(--aksrt-blue); } +.aksrt-badge--green { background: var(--aksrt-green-soft); color: var(--aksrt-green); } +.aksrt-badge--orange { background: var(--aksrt-orange-soft); color: var(--aksrt-orange); } +.aksrt-badge--purple { background: var(--aksrt-purple-soft); color: var(--aksrt-purple); } +.aksrt-badge--cyan { background: var(--aksrt-cyan-soft); color: var(--aksrt-cyan); } +.aksrt-badge--yellow { background: var(--aksrt-yellow-soft); color: #92400e; } +.aksrt-badge--red { background: var(--aksrt-red-soft); color: var(--aksrt-red); } +.aksrt-badge--teal { background: var(--aksrt-teal-soft); color: var(--aksrt-teal); } +.aksrt-badge--indigo { background: var(--aksrt-indigo-soft); color: var(--aksrt-indigo); } +.aksrt-badge--pink { background: var(--aksrt-pink-soft); color: var(--aksrt-pink); } + +/* 渐变 Badge */ +.aksrt-badge--grad-vip { + background: linear-gradient(135deg, var(--aksrt-vip-gold-1), var(--aksrt-vip-gold-2)); + color: #5a3d00; +} + +.aksrt-badge--grad-primary { + background: linear-gradient(135deg, var(--color-primary), var(--color-primary-active)); + color: var(--color-on-primary); +} + +/* Solid badge variant — 纯色背景 + 白色文字 */ +.aksrt-badge--solid-primary { background: var(--color-primary); color: #fff; } +.aksrt-badge--solid-success { background: var(--color-success); color: #fff; } +.aksrt-badge--solid-warning { background: var(--color-warning); color: #fff; } +.aksrt-badge--solid-error { background: var(--color-error); color: #fff; } +.aksrt-badge--solid-info { background: var(--color-info); color: #fff; } +.aksrt-badge--solid-rose { background: var(--aksrt-rose); color: #fff; } +.aksrt-badge--solid-blue { background: var(--aksrt-blue); color: #fff; } +.aksrt-badge--solid-green { background: var(--aksrt-green); color: #fff; } +.aksrt-badge--solid-orange { background: var(--aksrt-orange); color: #fff; } +.aksrt-badge--solid-purple { background: var(--aksrt-purple); color: #fff; } +.aksrt-badge--solid-cyan { background: var(--aksrt-cyan); color: #fff; } +.aksrt-badge--solid-yellow { background: var(--aksrt-yellow); color: #422006; } +.aksrt-badge--solid-red { background: var(--aksrt-red); color: #fff; } +.aksrt-badge--solid-teal { background: var(--aksrt-teal); color: #fff; } +.aksrt-badge--solid-indigo { background: var(--aksrt-indigo); color: #fff; } +.aksrt-badge--solid-pink { background: var(--aksrt-pink); color: #fff; } + +/* Badge sizes */ +.aksrt-badge--sm { height: 18px; padding: 0 6px; font-size: 11px; } +.aksrt-badge--lg { height: 28px; padding: 0 12px; font-size: 13px; } + +/* ============================================================ + * 5. 背景色工具类 — .aksrt-bg-{color} + * ============================================================ */ +.aksrt-bg-rose { background-color: var(--aksrt-rose-soft); } +.aksrt-bg-blue { background-color: var(--aksrt-blue-soft); } +.aksrt-bg-green { background-color: var(--aksrt-green-soft); } +.aksrt-bg-orange { background-color: var(--aksrt-orange-soft); } +.aksrt-bg-purple { background-color: var(--aksrt-purple-soft); } +.aksrt-bg-cyan { background-color: var(--aksrt-cyan-soft); } +.aksrt-bg-yellow { background-color: var(--aksrt-yellow-soft); } +.aksrt-bg-red { background-color: var(--aksrt-red-soft); } +.aksrt-bg-teal { background-color: var(--aksrt-teal-soft); } +.aksrt-bg-indigo { background-color: var(--aksrt-indigo-soft); } +.aksrt-bg-pink { background-color: var(--aksrt-pink-soft); } + +/* ============================================================ + * 6. 文字色工具类 — .aksrt-text-{color} + * ============================================================ */ +.aksrt-text-rose { color: var(--aksrt-rose); } +.aksrt-text-blue { color: var(--aksrt-blue); } +.aksrt-text-green { color: var(--aksrt-green); } +.aksrt-text-orange { color: var(--aksrt-orange); } +.aksrt-text-purple { color: var(--aksrt-purple); } +.aksrt-text-cyan { color: var(--aksrt-cyan); } +.aksrt-text-yellow { color: var(--aksrt-yellow); } +.aksrt-text-red { color: var(--aksrt-red); } +.aksrt-text-teal { color: var(--aksrt-teal); } +.aksrt-text-indigo { color: var(--aksrt-indigo); } +.aksrt-text-pink { color: var(--aksrt-pink); } diff --git a/assets/css/core/components-ext.css b/assets/css/core/components-ext.css new file mode 100644 index 00000000..5e72e3fd --- /dev/null +++ b/assets/css/core/components-ext.css @@ -0,0 +1,555 @@ +/** + * AKSRT Extended Components — 时间轴 / 步骤向导 / 九宫格 / 定价卡片 / + * Toggle 开关 / 自定义复选框 / 数字步进器 + * ------------------------------------------------------------ + * 全部使用 aksrt- 前缀,保持原生语义可访问性。 + */ + +/* ============================================================ + * 1. 时间轴 — .aksrt-timeline + * ============================================================ */ +.aksrt-timeline { + position: relative; + padding-left: 28px; + margin: 0; + list-style: none; +} + +/* 竖线 */ +.aksrt-timeline::before { + content: ''; + position: absolute; + left: 8px; + top: 4px; + bottom: 4px; + width: 2px; + background: var(--color-line, rgba(50, 50, 50, 0.1)); + border-radius: 1px; +} + +.aksrt-timeline__item { + position: relative; + padding-bottom: 24px; +} + +.aksrt-timeline__item:last-child { + padding-bottom: 0; +} + +/* 圆点 */ +.aksrt-timeline__dot { + position: absolute; + left: -24px; + top: 4px; + width: 12px; + height: 12px; + border-radius: 50%; + background: var(--color-primary); + border: 2px solid var(--surface-1, #fff); + box-shadow: 0 0 0 2px var(--color-primary-soft, rgba(240, 68, 148, 0.12)); + z-index: 1; +} + +/* 空心圆点变体 */ +.aksrt-timeline__dot--outline { + background: var(--surface-1, #fff); + border: 2px solid var(--color-primary); + box-shadow: none; +} + +/* 灰色圆点 — 已完成/已过去 */ +.aksrt-timeline__dot--muted { + background: var(--color-ink-4, #999); + box-shadow: 0 0 0 2px var(--surface-2, #eee); +} + +.aksrt-timeline__time { + display: block; + font-size: 12px; + color: var(--color-ink-4, #999); + margin-bottom: 4px; +} + +.aksrt-timeline__title { + font-weight: 600; + color: var(--color-ink, #333); + margin-bottom: 4px; +} + +.aksrt-timeline__content { + font-size: 14px; + color: var(--color-ink-3, #777); + line-height: 1.6; +} + +/* ============================================================ + * 2. 步骤向导 — .aksrt-steps + * ============================================================ */ +.aksrt-steps { + display: flex; + align-items: flex-start; + gap: 0; + margin: 0; + padding: 0; + list-style: none; + counter-reset: aksrt-step; +} + +.aksrt-steps__item { + flex: 1; + position: relative; + text-align: center; + counter-increment: aksrt-step; +} + +/* 连接线 */ +.aksrt-steps__item:not(:last-child)::after { + content: ''; + position: absolute; + top: 16px; + left: calc(50% + 20px); + right: calc(-50% + 20px); + height: 2px; + background: var(--color-line, rgba(50, 50, 50, 0.1)); +} + +.aksrt-steps__icon { + display: inline-flex; + align-items: center; + justify-content: center; + width: 34px; + height: 34px; + border-radius: 50%; + background: var(--surface-2, #eee); + color: var(--color-ink-3, #777); + font-size: 14px; + font-weight: 700; + margin: 0 auto 8px; + position: relative; + z-index: 1; +} + +.aksrt-steps__item--active .aksrt-steps__icon { + background: var(--color-primary); + color: var(--color-on-primary, #fff); +} + +.aksrt-steps__item--done .aksrt-steps__icon { + background: var(--color-success); + color: #fff; +} + +.aksrt-steps__item--done:not(:last-child)::after { + background: var(--color-success); +} + +.aksrt-steps__label { + font-size: 13px; + font-weight: 600; + color: var(--color-ink-3, #777); +} + +.aksrt-steps__item--active .aksrt-steps__label { + color: var(--color-primary); +} + +.aksrt-steps__item--done .aksrt-steps__label { + color: var(--color-success); +} + +/* 垂直模式 */ +.aksrt-steps--vertical { + flex-direction: column; + gap: 0; + padding-left: 20px; +} + +.aksrt-steps--vertical .aksrt-steps__item { + text-align: left; + padding-left: 28px; + padding-bottom: 20px; +} + +.aksrt-steps--vertical .aksrt-steps__item:not(:last-child)::after { + top: 34px; + left: 36px; + right: auto; + width: 2px; + height: calc(100% - 34px); +} + +.aksrt-steps--vertical .aksrt-steps__icon { + position: absolute; + left: 0; + margin: 0; +} + +/* ============================================================ + * 3. 九宫格 — .aksrt-img-grid + * ============================================================ */ +.aksrt-img-grid { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 4px; + border-radius: var(--radius, 8px); + overflow: hidden; +} + +.aksrt-img-grid img { + width: 100%; + aspect-ratio: 1; + object-fit: cover; + display: block; + cursor: pointer; + transition: transform .2s ease; +} + +.aksrt-img-grid img:hover { + transform: scale(1.03); +} + +/* 自适应列数 */ +.aksrt-img-grid--2 { grid-template-columns: repeat(2, 1fr); } +.aksrt-img-grid--4 { grid-template-columns: repeat(4, 1fr); } + +@media (max-width: 480px) { + .aksrt-img-grid--4 { grid-template-columns: repeat(3, 1fr); } +} + +/* ============================================================ + * 4. 定价卡片 — .aksrt-pricing-card + * ============================================================ */ +.aksrt-pricing-card { + position: relative; + background: var(--surface-1, #fff); + border: 1px solid var(--color-line, rgba(50, 50, 50, 0.06)); + border-radius: var(--radius-lg, 8px); + padding: 28px 24px; + text-align: center; + transition: box-shadow .25s ease, transform .25s ease; +} + +.aksrt-pricing-card:hover { + box-shadow: var(--shadow-lg, 0 0 10px rgba(116, 116, 116, 0.12)); + transform: translateY(-2px); +} + +/* 推荐/高亮卡片 */ +.aksrt-pricing-card--featured { + border-color: var(--color-primary); + box-shadow: 0 0 0 1px var(--color-primary), var(--shadow-lg); +} + +.aksrt-pricing-card__badge { + position: absolute; + top: -1px; + left: 50%; + transform: translateX(-50%); + background: var(--color-primary); + color: #fff; + padding: 2px 16px; + border-radius: 0 0 var(--radius, 8px) var(--radius, 8px); + font-size: 12px; + font-weight: 700; +} + +.aksrt-pricing-card__title { + font-size: 18px; + font-weight: 700; + color: var(--color-ink, #333); + margin-bottom: 8px; +} + +.aksrt-pricing-card__price { + font-size: 36px; + font-weight: 800; + color: var(--color-primary); + line-height: 1.2; + margin: 12px 0 4px; +} + +.aksrt-pricing-card__price small { + font-size: 14px; + font-weight: 500; + color: var(--color-ink-3, #777); +} + +.aksrt-pricing-card__desc { + font-size: 14px; + color: var(--color-ink-3, #777); + margin-bottom: 20px; +} + +.aksrt-pricing-card__features { + list-style: none; + padding: 0; + margin: 0 0 24px; + text-align: left; +} + +.aksrt-pricing-card__features li { + padding: 6px 0; + font-size: 14px; + color: var(--color-ink-2, #4e5358); + display: flex; + align-items: center; + gap: 8px; +} + +.aksrt-pricing-card__features li::before { + content: '✓'; + color: var(--color-success); + font-weight: 700; + font-size: 13px; +} + +.aksrt-pricing-card__cta { + display: block; + width: 100%; +} + +/* ============================================================ + * 5. Toggle 开关 — .aksrt-toggle (纯 CSS + :checked) + * 保持原生 可访问性 + * ============================================================ */ +.aksrt-toggle { + position: relative; + display: inline-flex; + align-items: center; + cursor: pointer; + user-select: none; + gap: 8px; +} + +.aksrt-toggle__input { + position: absolute; + opacity: 0; + width: 0; + height: 0; + pointer-events: none; +} + +.aksrt-toggle__track { + position: relative; + width: var(--aksrt-toggle-w, 44px); + height: var(--aksrt-toggle-h, 24px); + background: var(--surface-3, #e8e8e8); + border-radius: var(--aksrt-toggle-h, 24px); + transition: background .2s ease; + flex-shrink: 0; +} + +.aksrt-toggle__track::after { + content: ''; + position: absolute; + top: 2px; + left: 2px; + width: calc(var(--aksrt-toggle-h, 24px) - 4px); + height: calc(var(--aksrt-toggle-h, 24px) - 4px); + background: #fff; + border-radius: 50%; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.15); + transition: transform .2s ease; +} + +/* Checked */ +.aksrt-toggle__input:checked + .aksrt-toggle__track { + background: var(--color-primary); +} + +.aksrt-toggle__input:checked + .aksrt-toggle__track::after { + transform: translateX(calc(var(--aksrt-toggle-w, 44px) - var(--aksrt-toggle-h, 24px))); +} + +/* Focus-visible */ +.aksrt-toggle__input:focus-visible + .aksrt-toggle__track { + box-shadow: var(--focus-ring, 0 0 2px 3px rgba(253, 83, 161, 0.4)); +} + +/* Disabled */ +.aksrt-toggle__input:disabled + .aksrt-toggle__track { + opacity: 0.5; + cursor: not-allowed; +} + +.aksrt-toggle__label { + font-size: 14px; + color: var(--color-ink-2, #4e5358); +} + +/* ============================================================ + * 6. 自定义复选框 — .aksrt-checkbox (纯 CSS + :checked) + * 保持原生 可访问性 + * ============================================================ */ +.aksrt-checkbox { + display: inline-flex; + align-items: center; + gap: 8px; + cursor: pointer; + user-select: none; +} + +.aksrt-checkbox__input { + position: absolute; + opacity: 0; + width: 0; + height: 0; + pointer-events: none; +} + +.aksrt-checkbox__box { + position: relative; + width: 18px; + height: 18px; + border: 2px solid var(--color-line, rgba(50, 50, 50, 0.15)); + border-radius: 4px; + background: var(--surface-1, #fff); + transition: background .15s ease, border-color .15s ease; + flex-shrink: 0; +} + +/* 打勾 SVG */ +.aksrt-checkbox__box::after { + content: ''; + position: absolute; + top: 2px; + left: 5px; + width: 5px; + height: 9px; + border: 2px solid #fff; + border-top: none; + border-left: none; + transform: rotate(45deg) scale(0); + transition: transform .15s ease; +} + +.aksrt-checkbox__input:checked + .aksrt-checkbox__box { + background: var(--color-primary); + border-color: var(--color-primary); +} + +.aksrt-checkbox__input:checked + .aksrt-checkbox__box::after { + transform: rotate(45deg) scale(1); +} + +.aksrt-checkbox__input:focus-visible + .aksrt-checkbox__box { + box-shadow: var(--focus-ring, 0 0 2px 3px rgba(253, 83, 161, 0.4)); +} + +.aksrt-checkbox__input:disabled + .aksrt-checkbox__box { + opacity: 0.5; + cursor: not-allowed; +} + +.aksrt-checkbox__label { + font-size: 14px; + color: var(--color-ink-2, #4e5358); +} + +/* ============================================================ + * 7. 数字步进器 — .aksrt-stepper + * ============================================================ */ +.aksrt-stepper { + display: inline-flex; + align-items: center; + border: 1px solid var(--color-line, rgba(50, 50, 50, 0.1)); + border-radius: var(--radius, 8px); + overflow: hidden; + height: var(--aksrt-stepper-h, 36px); +} + +.aksrt-stepper__btn { + display: flex; + align-items: center; + justify-content: center; + width: var(--aksrt-stepper-h, 36px); + height: 100%; + background: var(--surface-2, #eee); + color: var(--color-ink-2, #4e5358); + border: none; + cursor: pointer; + font-size: 16px; + font-weight: 600; + transition: background .15s ease, color .15s ease; + user-select: none; +} + +.aksrt-stepper__btn:hover { + background: var(--surface-3, #e8e8e8); + color: var(--color-ink, #333); +} + +.aksrt-stepper__btn:disabled { + opacity: 0.4; + cursor: not-allowed; +} + +.aksrt-stepper__input { + width: 48px; + height: 100%; + border: none; + text-align: center; + font-size: 14px; + font-weight: 600; + color: var(--color-ink, #333); + background: var(--surface-1, #fff); + -moz-appearance: textfield; +} + +.aksrt-stepper__input::-webkit-outer-spin-button, +.aksrt-stepper__input::-webkit-inner-spin-button { + -webkit-appearance: none; + margin: 0; +} + +.aksrt-stepper__input:focus { + outline: none; + background: var(--color-primary-softer, rgba(240, 68, 148, 0.05)); +} + +/* ============================================================ + * 8. 头像尺寸变量系统 — .aksrt-avatar--{size} + * ============================================================ */ +.aksrt-avatar--xs { width: var(--aksrt-avatar-size-xs); height: var(--aksrt-avatar-size-xs); } +.aksrt-avatar--sm { width: var(--aksrt-avatar-size-sm); height: var(--aksrt-avatar-size-sm); } +.aksrt-avatar { width: var(--aksrt-avatar-size); height: var(--aksrt-avatar-size); } +.aksrt-avatar--lg { width: var(--aksrt-avatar-size-lg); height: var(--aksrt-avatar-size-lg); } +.aksrt-avatar--xl { width: var(--aksrt-avatar-size-xl); height: var(--aksrt-avatar-size-xl); } + +/* ============================================================ + * 9. 涟漪点击效果 — .aksrt-ripple + * 容器加此类,点击时 JS 注入 span.aksrt-ripple__wave + * ============================================================ */ +.aksrt-ripple { + position: relative; + overflow: hidden; +} + +.aksrt-ripple__wave { + position: absolute; + border-radius: 50%; + background: rgba(255, 255, 255, 0.35); + transform: scale(0); + animation: aksrtRippleWave .6s ease-out forwards; + pointer-events: none; +} + +@keyframes aksrtRippleWave { + to { + transform: scale(4); + opacity: 0; + } +} + +/* ============================================================ + * 10. 模态框堆叠动画 — 父模态缩小 + * ============================================================ */ +.modal-stacked .modal-dialog { + transition: transform .25s var(--ease, ease), filter .25s ease; +} + +.modal-stacked .modal-dialog.modal-behind { + transform: scale(0.92); + filter: brightness(0.85); + pointer-events: none; +} diff --git a/assets/css/core/forms.css b/assets/css/core/forms.css new file mode 100644 index 00000000..eef12925 --- /dev/null +++ b/assets/css/core/forms.css @@ -0,0 +1,142 @@ +/** + * AKSRT Forms — 1:1 Zibll Alignment + * + * 对齐 zibll .form-control: + * - 灰色背景 (#f5f6f7) + * - 透明边框 + * - 34px 高度 + * - 8px 圆角 + * - focus 时粉色边框 + 光晕 + */ + +/* ===== Field Wrapper ===== */ +.field { + display: flex; + flex-direction: column; + gap: 6px; + margin-bottom: var(--space-4); +} + +.field-label { + font-size: var(--text-sm); + font-weight: 600; + color: var(--color-ink); +} + +.field-help { + font-size: var(--text-xs); + color: var(--color-ink-3); +} + +.field-error { + font-size: var(--text-xs); + color: var(--color-error); +} + +/* ===== Input / Textarea / Select — 对齐 zibll .form-control ===== */ +.input, +.textarea, +.select, +input[type="text"].form-input, +input[type="email"].form-input, +input[type="password"].form-input, +input[type="search"].form-input, +input[type="url"].form-input, +input[type="tel"].form-input, +textarea.form-textarea, +select.form-select { + width: 100%; + height: 34px; + padding: 6px 12px; + font-size: 14px; + color: var(--color-ink); + background: var(--surface-page); + border: 1px solid transparent; + border-radius: var(--radius); + transition: border-color var(--dur-fast) var(--ease), + box-shadow var(--dur-fast) var(--ease); +} + +.textarea, +textarea.form-textarea { + height: auto; + min-height: 120px; + padding: 12px; + line-height: var(--leading-snug); + resize: vertical; +} + +.input:hover, +.textarea:hover, +.select:hover { + border-color: var(--color-primary); +} + +.input:focus, +.textarea:focus, +.select:focus { + outline: none; + border-color: var(--color-primary); + box-shadow: 0 0 2px 3px rgba(253, 83, 161, 0.4); +} + +.input::placeholder, +.textarea::placeholder { + color: var(--color-ink-4); +} + +/* ===== Select ===== */ +.select, +select.form-select { + appearance: none; + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%23777' d='M6 8L1 3h10z'/%3E%3C/svg%3E"); + background-repeat: no-repeat; + background-position: right 12px center; + padding-right: 32px; +} + +/* ===== Checkbox / Radio ===== */ +.checkbox, +.radio { + display: inline-flex; + align-items: center; + gap: 8px; + cursor: pointer; + font-size: var(--text-sm); + color: var(--color-ink-2); +} + +.checkbox input, +.radio input { + width: 16px; + height: 16px; + accent-color: var(--color-primary); + cursor: pointer; +} + +/* ===== Input Group ===== */ +.input-group { + display: flex; + align-items: stretch; +} + +.input-group .input { + border-radius: var(--radius) 0 0 var(--radius); +} + +.input-group .btn { + border-radius: 0 var(--radius) var(--radius) 0; +} + +/* ===== Form Layout ===== */ +.form-row { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); + gap: var(--space-4); +} + +.form-actions { + display: flex; + gap: var(--space-3); + margin-top: var(--space-5); +} diff --git a/assets/css/core/reset.css b/assets/css/core/reset.css new file mode 100644 index 00000000..0a381dab --- /dev/null +++ b/assets/css/core/reset.css @@ -0,0 +1,128 @@ +/** + * AKSRT Reset + * 现代精简 reset,结合 box-sizing 与 a11y 友好的默认值。 + */ + +*, +*::before, +*::after { + box-sizing: border-box; +} + +html { + font-size: 16px; + scroll-behavior: smooth; + -webkit-text-size-adjust: 100%; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + overflow-x: hidden; + text-rendering: optimizeLegibility; +} + +body { + margin: 0; + font-family: var(--font-body); + font-size: var(--text-base); + line-height: var(--leading-normal); + background-color: var(--surface-page); + color: var(--color-ink-2); + transition: background-color 0.25s ease, color 0.25s ease; + overflow-x: hidden; +} + +/* 媒体元素 */ +img, +picture, +video, +canvas, +svg { + display: block; + max-width: 100%; + height: auto; +} + +/* 表单元素继承字体 */ +input, +button, +textarea, +select { + font: inherit; + color: inherit; +} + +button { + background: none; + border: 0; + padding: 0; + cursor: pointer; +} + +/* 链接 */ +a { + color: inherit; + text-decoration: none; + transition: color var(--dur-fast) var(--ease); +} + +a:hover { + color: var(--color-primary); +} + +/* 焦点环:a11y 关键 */ +:focus { + outline: none; +} + +:focus-visible { + outline: none; + box-shadow: var(--focus-ring); + border-radius: 4px; +} + +/* 选区色 */ +::selection { + background: var(--color-primary-soft); + color: var(--color-ink); +} + +/* 屏幕阅读器隐藏 */ +.screen-reader-text, +.sr-only { + position: absolute !important; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border: 0; +} + +.screen-reader-text:focus, +.sr-only:focus { + position: fixed !important; + top: 16px; + left: 16px; + width: auto; + height: auto; + padding: 8px 16px; + background: var(--surface-1); + color: var(--color-ink); + z-index: 100000; + clip: auto; + box-shadow: var(--shadow-lg); + border-radius: var(--radius); +} + +/* 减少动效偏好 */ +@media (prefers-reduced-motion: reduce) { + *, + *::before, + *::after { + animation-duration: 0.01ms !important; + animation-iteration-count: 1 !important; + transition-duration: 0.01ms !important; + scroll-behavior: auto !important; + } +} diff --git a/assets/css/core/tokens.css b/assets/css/core/tokens.css new file mode 100644 index 00000000..065f8b86 --- /dev/null +++ b/assets/css/core/tokens.css @@ -0,0 +1,429 @@ +/** + * AKSRT Design Tokens v7 — 1:1 Zibll Alignment + * ------------------------------------------------------------ + * 单一真理源(Single Source of Truth) + * 所有颜色、字体、间距、动效都从此处读取,禁止在组件内硬编码。 + * 严格对齐 zibll main.css 的视觉值。 + */ + +:root { + /* ===== Primary — Zibll theme-color (#f04494 pink) ===== */ + --color-primary: #f04494; + --color-primary-hover: #e0307e; + --color-primary-active: #c9206d; + --color-primary-soft: rgba(240, 68, 148, 0.10); + --color-primary-softer: rgba(240, 68, 148, 0.05); + --color-on-primary: #FFFFFF; + + /* ===== Ink (text) — 对齐 zibll --key-color / --main-color / --muted-color ===== */ + --color-ink: #333333; /* zibll --key-color */ + --color-ink-2: #4e5358; /* zibll --main-color */ + --color-ink-3: #777777; /* zibll --muted-color */ + --color-ink-4: #999999; /* zibll --muted-2-color */ + + /* ===== Surface — 对齐 zibll --body-bg-color / --main-bg-color / --muted-bg-color ===== */ + --surface-page: #f5f6f7; /* zibll --body-bg-color */ + --surface-1: #FFFFFF; /* zibll --main-bg-color */ + --surface-2: #eeeeee; /* zibll --muted-bg-color */ + --surface-3: #e8e8e8; /* 输入框 / code */ + + /* ===== Borders — 对齐 zibll --main-border-color ===== */ + --color-line: rgba(50, 50, 50, 0.06); + --color-line-soft: rgba(0, 0, 0, 0.03); + + /* ===== State colors ===== */ + --color-success: #10B981; + --color-warning: #F59E0B; + --color-error: #EF4444; + --color-info: #3B82F6; + + /* ===== Accent (action green — zibll tabbar/CTA) ===== */ + --color-accent: #18a058; + --color-accent-soft: rgba(24, 160, 88, 0.12); + --color-accent-shadow: rgba(24, 160, 88, 0.28); + + /* ===== Fonts — 对齐 zibll(系统默认字体栈)===== */ + --font-display: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans SC", "PingFang SC", "Microsoft YaHei", sans-serif; + --font-body: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans SC", "PingFang SC", "Microsoft YaHei", sans-serif; + --font-ui: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans SC", "PingFang SC", "Microsoft YaHei", sans-serif; + --font-mono: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace; + + /* ===== Type scale ===== */ + --text-xs: 0.75rem; /* 12 */ + --text-sm: 0.875rem; /* 14 */ + --text-base: 1rem; /* 16 */ + --text-md: 1.125rem; /* 18 */ + --text-lg: 1.25rem; /* 20 */ + --text-xl: 1.5rem; /* 24 */ + --text-2xl: 1.875rem; /* 30 */ + --text-3xl: 2.25rem; /* 36 */ + --text-4xl: 3rem; /* 48 */ + --text-5xl: 3.75rem; /* 60 */ + --leading-tight: 1.2; + --leading-snug: 1.4; + --leading-normal: 1.6; /* zibll body line-height */ + --leading-relaxed: 1.6; + + /* ===== Spacing (4px base) ===== */ + --space-1: 4px; + --space-2: 8px; + --space-3: 12px; + --space-4: 16px; + --space-5: 20px; + --space-6: 24px; + --space-7: 32px; + --space-8: 40px; + --space-9: 48px; + --space-10: 64px; + --space-11: 80px; + --space-12: 96px; + + /* ===== Radius — 对齐 zibll --main-radius: 8px ===== */ + --radius-sm: 4px; + --radius: 8px; + --radius-lg: 8px; + --radius-xl: 12px; + --radius-pill: 100px; + --radius-avatar: 50%; + + /* ===== Shadows — 对齐 zibll --main-shadow: rgba(116,116,116,0.08) ===== */ + --shadow-sm: 0 0 10px rgba(116, 116, 116, 0.08); + --shadow: 0 0 10px rgba(116, 116, 116, 0.08); + --shadow-lg: 0 0 10px rgba(116, 116, 116, 0.12); + --shadow-drawer: 0 8px 40px rgba(0, 0, 0, 0.20); + + /* ===== Layout — 对齐 zibll --mian-max-width: 1200px ===== */ + --nav-height: 60px; + --container: 1200px; + --container-wide: 1440px; + --container-read: 720px; + --container-page: 860px; + --sidebar-width: 311px; + --content-gap: 48px; + --sidebar-bp: 992px; + + /* ===== Motion ===== */ + --ease: cubic-bezier(.4, 0, .2, 1); + --ease-out: cubic-bezier(.16, 1, .3, 1); + --ease-spring: cubic-bezier(.34, 1.56, .64, 1); + --dur-fast: 0.15s; + --dur: 0.25s; + --dur-slow: 0.4s; + + /* ===== Focus Ring — 对齐 zibll focus-shadow-color ===== */ + --focus-ring: 0 0 2px 3px rgba(253, 83, 161, 0.4); + + /* ===== Z-index layers ===== */ + --z-dropdown: 100; + --z-sticky: 200; + --z-fixed: 300; + --z-overlay: 400; + --z-modal: 500; + --z-popover: 600; + --z-toast: 700; + --z-tooltip: 800; + + /* ===== Button sizes — 对齐 zibll ===== */ + --radius-btn: 4px; + --btn-sm-h: 28px; + --btn-md-h: 34px; + --btn-lg-h: 44px; + + /* ===== Card density — 对齐 zibll .box-body { padding: 15px } ===== */ + --card-padding: 15px; + --card-padding-sm: 10px; + --card-gap: 16px; + + /* ===== Skeleton loader ===== */ + --skeleton-base: var(--surface-2); + --skeleton-shine: var(--surface-1); + + /* ===== Extended tokens (used by components) ===== */ + --color-primary-light: var(--color-primary-soft); + --color-surface: var(--surface-1); + --color-line-strong: var(--color-line); + --color-bg-hover: var(--surface-2); + --color-border-light: var(--color-line-soft); + --color-fill: var(--surface-2); + --color-warning-bg: #fffbe6; + --color-warning-text: #ad6800; + + --text-secondary: var(--color-ink-3); + --text-tertiary: var(--color-ink-4); + + --surface-active: var(--surface-2); + --surface-card: var(--surface-1); + --surface-hover: var(--surface-2); + --surface-secondary: var(--surface-2); + + --radius-code: var(--radius); + --radius-full: 100px; + --shadow-xl: 0 0 10px rgba(116, 116, 116, 0.12); + --space-16: 64px; + --z-floating: 900; + + --transition-fast: 0.15s ease; + --transition-base: 0.25s ease; + + /* ===== Composite / Context tokens — 对齐 zibll ===== */ + --header-bg: var(--blur-bg); + --header-color: var(--color-ink-2); + --footer-bg: var(--surface-1); + --footer-color: var(--color-ink-4); + --blur-bg: rgba(255, 255, 255, 0.80); + --float-btn-bg: rgba(200, 200, 200, 0.40); + + /* ===== AKSRT-to-AKSRT canonical aliases ===== */ + --content-max: var(--container); + --font-heading: var(--font-ui); + --radius-card: var(--radius); + --radius-md: var(--radius); + --color-primary-50: var(--color-primary-soft); + --color-primary-dark: var(--color-primary-active); + --shadow-md: var(--shadow); + --mini-radius: calc(var(--radius) / 1.4); + --single-cover-scale: 35%; + + /* ===== Avatar size system — Zibll --this-size 等价 ===== */ + --aksrt-avatar-size-xs: 24px; + --aksrt-avatar-size-sm: 32px; + --aksrt-avatar-size: 40px; + --aksrt-avatar-size-lg: 56px; + --aksrt-avatar-size-xl: 80px; + + /* ===== Post card thumbnail scale ===== */ + --aksrt-card-thumb-scale: 56.25%; /* 16:9 */ + + /* ===== Multi-color palette (for buttons / badges / gradients) ===== */ + --aksrt-rose: #f43f5e; + --aksrt-rose-soft: rgba(244, 63, 94, 0.12); + --aksrt-blue: #3b82f6; + --aksrt-blue-soft: rgba(59, 130, 246, 0.12); + --aksrt-green: #10b981; + --aksrt-green-soft: rgba(16, 185, 129, 0.12); + --aksrt-orange: #f97316; + --aksrt-orange-soft:rgba(249, 115, 22, 0.12); + --aksrt-purple: #8b5cf6; + --aksrt-purple-soft:rgba(139, 92, 246, 0.12); + --aksrt-cyan: #06b6d4; + --aksrt-cyan-soft: rgba(6, 182, 212, 0.12); + --aksrt-yellow: #eab308; + --aksrt-yellow-soft:rgba(234, 179, 8, 0.12); + --aksrt-red: #ef4444; + --aksrt-red-soft: rgba(239, 68, 68, 0.12); + --aksrt-teal: #14b8a6; + --aksrt-teal-soft: rgba(20, 184, 166, 0.12); + --aksrt-indigo: #6366f1; + --aksrt-indigo-soft:rgba(99, 102, 241, 0.12); + --aksrt-pink: #ec4899; + --aksrt-pink-soft: rgba(236, 72, 153, 0.12); + + /* ===== VIP / special gradients ===== */ + --aksrt-vip-gold-1: #f6d365; + --aksrt-vip-gold-2: #fda085; + --aksrt-grad-sunset-1: #f093fb; + --aksrt-grad-sunset-2: #f5576c; + --aksrt-grad-ocean-1: #4facfe; + --aksrt-grad-ocean-2: #00f2fe; + --aksrt-grad-forest-1: #43e97b; + --aksrt-grad-forest-2: #38f9d7; + --aksrt-grad-night-1: #a18cd1; + --aksrt-grad-night-2: #fbc2eb; + --aksrt-grad-fire-1: #f83600; + --aksrt-grad-fire-2: #f9d423; + + /* ===== Component sizing ===== */ + --aksrt-toggle-w: 44px; + --aksrt-toggle-h: 24px; + --aksrt-stepper-h: 36px; + --aksrt-badge-h: 22px; + + /* ===== Legacy name bridge ===== */ + --text-1: var(--color-ink); + --text-2: var(--color-ink-2); + --text-3: var(--color-ink-3); + --border: var(--color-line); + --color-text-1: var(--color-ink); + --color-text-2: var(--color-ink-2); + --color-text-3: var(--color-ink-3); + --color-primary-bg: var(--color-primary-softer); + --color-danger: var(--color-error); +} + +/* ============================================================ + * Blur-bg fallback cascade (mirrors zibll behaviour) + * ============================================================ */ +@supports not ((-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px))) { + :root { + --blur-bg: var(--surface-1); + --header-bg: var(--surface-1); + } +} + +@supports not ((-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px))) { + html.dark, + body.dark-theme { + --blur-bg: #37383a; + --header-bg: #37383a; + } +} + +body.modal-open, +body.dialog-open { + --blur-bg: var(--surface-1); + --header-bg: var(--surface-1); +} + +body.modal-open .site-nav, +body.modal-open .footer-tabbar, +body.modal-open .float-right .float-btn, +body.dialog-open .site-nav, +body.dialog-open .footer-tabbar, +body.dialog-open .float-right .float-btn { + backdrop-filter: none !important; + -webkit-backdrop-filter: none !important; +} + +html.dark body.modal-open, +html.dark body.dialog-open, +body.dark-theme body.modal-open, +body.dark-theme body.dialog-open { + --blur-bg: #37383a; + --header-bg: #37383a; +} + +/* ============================================================ + * Multi-level container responsive — 对齐 zibll --mian-max-width + * 不同视口宽度下容器自动调整 + * ============================================================ */ +@media (min-width: 992px) { + :root { + --container: 960px; + } +} + +@media (min-width: 1200px) { + :root { + --container: 1140px; + } +} + +@media (min-width: 1400px) { + :root { + --container: 1200px; + } +} + +/* ============================================================ + * Dark Theme — 对齐 zibll .dark-theme (#292a2d 范围) + * ============================================================ */ +html.dark { + --color-ink: #f8fafc; + --color-ink-2: #e5eef7; + --color-ink-3: #b4b6bb; + --color-ink-4: #888a8f; + + --surface-page: #292a2d; + --surface-1: #323335; + --surface-2: #2d2e31; + --surface-3: #3a3b3e; + + --color-line: rgba(114, 114, 114, 0.1); + --color-line-soft: rgba(184, 184, 184, 0.02); + + --color-primary-soft: rgba(240, 68, 148, 0.16); + --color-primary-softer: rgba(240, 68, 148, 0.08); + + --color-primary-light: var(--color-primary-soft); + --color-surface: var(--surface-1); + --color-line-strong: var(--color-line); + --color-bg-hover: var(--surface-2); + --color-border-light: var(--color-line-soft); + --color-fill: var(--surface-2); + + --text-secondary: var(--color-ink-3); + --text-tertiary: var(--color-ink-4); + + --surface-active: var(--surface-2); + --surface-card: var(--surface-1); + --surface-hover: var(--surface-2); + --surface-secondary: var(--surface-2); + + --shadow-xl: 0 0 10px rgba(24, 24, 24, 0.15); + + --shadow-sm: 0 0 10px rgba(24, 24, 24, 0.1); + --shadow: 0 0 10px rgba(24, 24, 24, 0.1); + --shadow-lg: 0 0 10px rgba(24, 24, 24, 0.15); + --shadow-drawer: 0 8px 40px rgba(0, 0, 0, 0.55); + + --blur-bg: rgba(50, 51, 53, 0.80); + --float-btn-bg: rgba(70, 70, 70, 0.40); + --header-bg: var(--blur-bg); + --footer-bg: var(--surface-1); + --footer-color: var(--color-ink-4); + --shadow-md: var(--shadow); + + --skeleton-base: #3a3b3e; + --skeleton-shine: #444548; + + /* Multi-color palette — dark mode: same hue, softer tint backgrounds */ + --aksrt-rose-soft: rgba(244, 63, 94, 0.18); + --aksrt-blue-soft: rgba(59, 130, 246, 0.18); + --aksrt-green-soft: rgba(16, 185, 129, 0.18); + --aksrt-orange-soft:rgba(249, 115, 22, 0.18); + --aksrt-purple-soft:rgba(139, 92, 246, 0.18); + --aksrt-cyan-soft: rgba(6, 182, 212, 0.18); + --aksrt-yellow-soft:rgba(234, 179, 8, 0.18); + --aksrt-red-soft: rgba(239, 68, 68, 0.18); + --aksrt-teal-soft: rgba(20, 184, 166, 0.18); + --aksrt-indigo-soft:rgba(99, 102, 241, 0.18); + --aksrt-pink-soft: rgba(236, 72, 153, 0.18); +} + +/* Dark mode component refinements */ +html.dark .site-nav { + border-bottom-color: var(--color-line); + box-shadow: none; +} + +html.dark .footer-tabbar { + background: rgba(50, 51, 53, 0.80); + box-shadow: 0 -1px 3px rgba(0, 0, 0, 0.20); +} + +html.dark .n-drawer, +html.dark .n-modal, +html.dark .n-dialog { + background: var(--surface-1); +} + +html.dark .post-card, +html.dark .widget, +html.dark .aksrt-theme-box, +html.dark .theme-box { + border-color: var(--color-line); +} + +/* body.dark-theme — zibll compatibility alias for html.dark */ +body.dark-theme .site-nav { + border-bottom-color: var(--color-line); + box-shadow: none; +} + +body.dark-theme .footer-tabbar { + background: rgba(50, 51, 53, 0.80); + box-shadow: 0 -1px 3px rgba(0, 0, 0, 0.20); +} + +body.dark-theme .n-drawer, +body.dark-theme .n-modal, +body.dark-theme .n-dialog { + background: var(--surface-1); +} + +body.dark-theme .post-card, +body.dark-theme .widget, +body.dark-theme .aksrt-theme-box, +body.dark-theme .theme-box { + border-color: var(--color-line); +} diff --git a/assets/css/core/typography.css b/assets/css/core/typography.css new file mode 100644 index 00000000..44425457 --- /dev/null +++ b/assets/css/core/typography.css @@ -0,0 +1,211 @@ +/** + * AKSRT Typography — 1:1 Zibll Alignment + * + * 对齐 zibll main.css 的排版系统 + */ + +/* ===== 全局标题 — 对齐 zibll line 8947 ===== */ +h1, h2, h3, h4, h5, h6 { + font-weight: 700; + margin: 20px 0 10px; + color: var(--key-color, #333); +} + +h1 { font-size: 22px; } +h2 { font-size: 20px; } +h3 { font-size: 18px; } +h4 { font-size: 16px; } +h5 { font-size: 15px; } +h6 { font-size: 14px; } + +/* ===== 文章正文 — 对齐 zibll line 8740 ===== */ +.wp-posts-content, +.entry-content, +.prose { + font-size: 16px; + line-height: 2; + color: var(--main-color, #4e5358); + min-height: 90px; +} + +/* ===== 文章内标题 — 对齐 zibll line 8947 ===== */ +.wp-posts-content h1, +.wp-posts-content h2, +.wp-posts-content h3, +.wp-posts-content h4, +.wp-posts-content h5, +.entry-content h1, +.entry-content h2, +.entry-content h3, +.entry-content h4, +.entry-content h5, +.prose h1, +.prose h2, +.prose h3, +.prose h4, +.prose h5 { + font-weight: 700; + margin: 20px 0 10px; + color: var(--key-color, #333); +} + +.wp-posts-content h1, +.entry-content h1, +.prose h1 { font-size: 22px; } + +.wp-posts-content h2, +.entry-content h2, +.prose h2 { font-size: 20px; } + +.wp-posts-content h3, +.entry-content h3, +.prose h3 { font-size: 18px; } + +.wp-posts-content h4, +.entry-content h4, +.prose h4 { font-size: 16px; } + +/* ===== 段落 — 对齐 zibll line 8999 ===== */ +.wp-posts-content p, +.entry-content p, +.prose p { + margin: 0 0 20px; + word-wrap: break-word; +} + +/* ===== 链接 — 对齐 zibll line 8836 ===== */ +.wp-posts-content a, +.entry-content a, +.prose a { + color: var(--focus-color, #f04494); + text-decoration: none; +} + +.wp-posts-content a:hover, +.entry-content a:hover, +.prose a:hover { + color: var(--focus-color, #f04494); +} + +/* ===== 图片 — 对齐 zibll line 8850 ===== */ +.wp-posts-content img, +.entry-content img, +.prose img { + max-width: 100%; + height: auto; + display: block; + margin: auto; +} + +/* ===== 内联代码 — 对齐 zibll line 8844 ===== */ +.wp-posts-content code:not(pre code), +.entry-content code:not(pre code), +.prose code:not(pre code) { + color: #ff3c98; + background: rgba(253, 153, 153, 0.2); + font-family: var(--font-mono, monospace); + font-size: 0.9em; +} + +/* ===== 代码块 — 对齐 zibll ===== */ +.wp-posts-content pre, +.entry-content pre, +.prose pre { + position: relative; + background: #282c34; + color: #abb2bf; + padding: 15px; + border-radius: var(--main-radius, 8px); + overflow-x: auto; + font-size: 14px; + line-height: 1.5; + margin: 0 0 20px; +} + +.wp-posts-content pre code, +.entry-content pre code, +.prose pre code { + color: inherit; + background: none; + padding: 0; + font-size: inherit; +} + +/* ===== 表格 — 对齐 zibll line 8897 ===== */ +.wp-posts-content table, +.entry-content table, +.prose table { + font-size: 14px; + width: 100%; + border-collapse: collapse; + margin: 0 0 20px; +} + +.wp-posts-content th, +.wp-posts-content td, +.entry-content th, +.entry-content td, +.prose th, +.prose td { + border: 1px solid var(--main-border-color, rgba(50, 50, 50, 0.06)); + padding: 8px; +} + +.wp-posts-content th, +.entry-content th, +.prose th { + background: var(--muted-border-color, rgba(0, 0, 0, 0.03)); + font-weight: 700; +} + +.wp-posts-content tr:hover, +.entry-content tr:hover, +.prose tr:hover { + background-color: rgba(240, 68, 148, 0.05); +} + +/* ===== 列表 — 对齐 zibll line 8977 ===== */ +.wp-posts-content ul, +.wp-posts-content ol, +.entry-content ul, +.entry-content ol, +.prose ul, +.prose ol { + margin: 10px 0 20px 15px; + padding-left: 15px; +} + +.wp-posts-content li, +.entry-content li, +.prose li { + margin-bottom: 10px; +} + +/* ===== 引用 — 对齐 zibll line 680 ===== */ +.wp-posts-content blockquote, +.entry-content blockquote, +.prose blockquote { + padding: 15px 20px; + margin: 0 0 20px; + border-left: 4px solid var(--main-border-color, rgba(50, 50, 50, 0.06)); + background: var(--muted-border-color, rgba(0, 0, 0, 0.03)); + font-size: 16px; + color: var(--muted-color, #777); + border-radius: 0; +} + +.wp-posts-content blockquote p:last-child, +.entry-content blockquote p:last-child, +.prose blockquote p:last-child { + margin-bottom: 0; +} + +/* ===== 水平分割线 — 对齐 zibll line 676 ===== */ +hr { + border-color: var(--main-border-color, rgba(50, 50, 50, 0.06)); +} + +/* ===== Strong / Bold ===== */ +strong, b { + font-weight: 700; +} diff --git a/assets/css/frontend/ajax-spinner.css b/assets/css/frontend/ajax-spinner.css new file mode 100644 index 00000000..0b72a476 --- /dev/null +++ b/assets/css/frontend/ajax-spinner.css @@ -0,0 +1,114 @@ +/* ========== AJAX 加载指示器 — 对齐 zibll loading spinner ========== */ +.aksrt-loading { + display: flex; + align-items: center; + justify-content: center; + padding: 40px 20px; + color: var(--color-ink-4, #999); + font-size: 13px; + gap: 8px; +} + +.aksrt-loading__spinner { + display: inline-block; + width: 20px; + height: 20px; + border: 2px solid var(--surface-3, #e8e8e8); + border-top-color: var(--color-primary, #f04494); + border-radius: 50%; + animation: aksrt-spin 0.6s linear infinite; +} + +@keyframes aksrt-spin { + to { transform: rotate(360deg); } +} + +/* 全屏加载遮罩 */ +.aksrt-loading-overlay { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: rgba(255, 255, 255, 0.8); + display: flex; + align-items: center; + justify-content: center; + z-index: 9999; + backdrop-filter: blur(2px); +} + +.aksrt-loading-overlay__content { + text-align: center; +} + +.aksrt-loading-overlay__spinner { + width: 36px; + height: 36px; + border: 3px solid var(--surface-3, #e8e8e8); + border-top-color: var(--color-primary, #f04494); + border-radius: 50%; + animation: aksrt-spin 0.6s linear infinite; + margin: 0 auto 12px; +} + +.aksrt-loading-overlay__text { + font-size: 13px; + color: var(--color-ink-3, #777); +} + +/* 行内加载(替换内容时) */ +.aksrt-loading-inline { + display: flex; + align-items: center; + justify-content: center; + padding: 20px; + color: var(--color-ink-4, #999); + font-size: 12px; + gap: 6px; +} + +.aksrt-loading-inline__dot { + width: 6px; + height: 6px; + background: var(--color-primary, #f04494); + border-radius: 50%; + animation: aksrt-dot-pulse 1.2s ease-in-out infinite; +} + +.aksrt-loading-inline__dot:nth-child(2) { + animation-delay: 0.2s; +} + +.aksrt-loading-inline__dot:nth-child(3) { + animation-delay: 0.4s; +} + +@keyframes aksrt-dot-pulse { + 0%, 80%, 100% { opacity: 0.3; transform: scale(0.8); } + 40% { opacity: 1; transform: scale(1); } +} + +/* 页面加载进度条 */ +.aksrt-progress-bar { + position: fixed; + top: 0; + left: 0; + height: 2px; + background: var(--color-primary, #f04494); + z-index: 10000; + transition: width 0.3s ease; +} + +/* 减弱动画偏好 */ +@media (prefers-reduced-motion: reduce) { + .aksrt-loading__spinner, + .aksrt-loading-overlay__spinner { + animation-duration: 1.5s; + } + + .aksrt-loading-inline__dot { + animation: none; + opacity: 0.6; + } +} diff --git a/assets/css/frontend/base.css b/assets/css/frontend/base.css new file mode 100644 index 00000000..ebc1807f --- /dev/null +++ b/assets/css/frontend/base.css @@ -0,0 +1,99 @@ +/** + * AKSRT Main v5 — 博客/个人站完整前端 + */ + +/* 防止 hero 等使用 100vw / full-bleed 时产生横向滚动条 */ +html, +body { + overflow-x: clip; +} + +@supports not (overflow-x: clip) { + html, + body { + overflow-x: hidden; + } +} + +/* ========== 阅读进度条(单篇文章顶 fixed)========== */ +.reading-progress-bar { + position: fixed; + top: 0; + left: 0; + height: 3px; + width: 0%; + z-index: 9999; + pointer-events: none; + background: linear-gradient(90deg, var(--color-primary), var(--color-primary-light)); + transition: width 0.1s ease-out; +} + +/* 折叠 body 内注入的 BOM / 空白文本节点,防止产生多余行高间距 */ +body { + font-family: var(--font-body); + font-size: var(--text-base); + line-height: var(--leading-normal); + color: var(--color-ink-2); + background-color: var(--surface-page); +} + +/* zibll compat: global link composite transition */ +a[href] { + transition: color 0.2s, background 0.3s, opacity 0.3s, box-shadow 0.3s, transform 0.3s; +} + +.skip-link { + position: absolute; + left: 16px; + top: 12px; + z-index: 1100; + padding: 10px 14px; + border-radius: 999px; + background: var(--color-primary); + color: #fff; + transform: translateY(-140%); + transition: transform 0.2s ease; +} + +.skip-link:focus { + transform: translateY(0); +} + +/* ========== 站点外壳 ========== */ +.site-wrapper { + min-height: 100vh; + display: flex; + flex-direction: column; + font-size: var(--text-base); + line-height: var(--leading-normal); +} + +.site-main { + flex: 1; +} + +.container { + width: 100%; + max-width: var(--container); + margin: 0 auto; + padding: 0 16px; +} + +@media (min-width: 768px) { + .container { + padding: 0 24px; + } +} + +@media (min-width: 1200px) { + .container { + padding: 0 32px; + } +} + +/* ========== 通用空状态 ========== */ +.no-results { + padding: 48px 20px; + text-align: center; + color: var(--color-ink-3); +} diff --git a/assets/css/frontend/breadcrumb.css b/assets/css/frontend/breadcrumb.css new file mode 100644 index 00000000..a5603001 --- /dev/null +++ b/assets/css/frontend/breadcrumb.css @@ -0,0 +1,76 @@ +/* ========== 面包屑导航 — 对齐 zibll breadcrumb ========== */ +.breadcrumb-nav { + font-size: 13px; + padding: 0 8px; + margin-bottom: 12px; + opacity: 0.6; + line-height: 1.8; +} + +.breadcrumb-nav ol, +.breadcrumb-nav ul { + list-style: none; + margin: 0; + padding: 0; + display: flex; + flex-wrap: wrap; + align-items: center; + gap: 0; +} + +.breadcrumb-nav li { + display: inline-flex; + align-items: center; +} + +.breadcrumb-nav li + li::before { + content: '/'; + padding: 0 0 0 6px; + opacity: 0.6; +} + +.breadcrumb-nav a { + color: var(--color-ink-4, #999); + text-decoration: none; + transition: color 0.2s; +} + +.breadcrumb-nav a:hover { + color: var(--color-primary, #f04494); +} + +.breadcrumb-nav .current { + color: var(--color-ink-2, #4e5358); + font-weight: 500; +} + +.single-cover-con .breadcrumb-nav, +.single-cover-con .breadcrumb { + font-size: 13px; + margin: 5px 0 0 -6px; + opacity: unset; +} + +/* 封面内面包屑 */ +.single-cover-con .breadcrumb-nav { + color: rgba(255, 255, 255, 0.7); +} + +.single-cover-con .breadcrumb-nav a { + color: rgba(255, 255, 255, 0.7); +} + +.single-cover-con .breadcrumb-nav a:hover { + color: #fff; +} + +.single-cover-con .breadcrumb-nav .current { + color: #fff; +} + +/* 移动端 */ +@media (max-width: 767px) { + .breadcrumb-nav { + font-size: 12px; + } +} diff --git a/assets/css/frontend/card-primitives.css b/assets/css/frontend/card-primitives.css new file mode 100644 index 00000000..92cb32c1 --- /dev/null +++ b/assets/css/frontend/card-primitives.css @@ -0,0 +1,163 @@ +/** + * AKSRT Card Primitives — 1:1 Zibll Alignment + * + * 对齐 zibll 的 .theme-box / .box-bg / .box-body / .box-header: + * 阴影优先,无边框,8px 圆角,15px 内边距。 + * + * @package AKSRT + */ + +/* ============================================================ + * .aksrt-theme-box — 完整卡片原语(阴影 + 圆角 + 表面) + * 对齐 zibll .theme-box + .box-bg + * ============================================================ */ +.aksrt-theme-box { + border: none; + border-radius: var(--radius); + background: var(--surface-1); + box-shadow: var(--shadow-sm); + transition: box-shadow var(--dur) var(--ease); +} + +.aksrt-theme-box:hover { + box-shadow: var(--shadow); +} + +/* ============================================================ + * .aksrt-box-bg — 表面原语(仅背景 + 阴影) + * ============================================================ */ +.aksrt-box-bg { + background-color: var(--surface-1); + box-shadow: var(--shadow-sm); +} + +/* ============================================================ + * .aksrt-box-body / .aksrt-box-header — 内边距区段 + * 对齐 zibll .box-body / .box-header { padding: 15px } + * ============================================================ */ +.aksrt-box-body, +.aksrt-box-header { + padding: var(--card-padding); +} + +.aksrt-box-header { + border-bottom: 1px solid var(--color-line-soft); +} + +.aksrt-box-header + .aksrt-box-body { + padding-top: 0; +} + +.aksrt-box-body.notop, +.aksrt-box-header.notop { padding-top: 0; } +.aksrt-box-body.nobottom, +.aksrt-box-header.nobottom { padding-bottom: 0; } + +/* ============================================================ + * .aksrt-muted-box — 柔和背景嵌套 + * 对齐 zibll .muted-box + * ============================================================ */ +.aksrt-muted-box { + background-color: var(--surface-2); + border-radius: var(--radius); + padding: var(--card-padding); +} + +/* ============================================================ + * .aksrt-noshadow — 去除阴影 + * ============================================================ */ +.aksrt-noshadow { + box-shadow: none !important; +} + +/* ============================================================ + * Zibll 兼容别名 + * ============================================================ */ +.theme-box { + background: var(--surface-1); + border: none; + border-radius: var(--radius); + box-shadow: var(--shadow-sm); + margin-bottom: 20px; + transition: box-shadow var(--dur) var(--ease); +} + +.theme-box:hover { + box-shadow: var(--shadow); +} + +.box-bg { + background-color: var(--surface-1); + box-shadow: var(--shadow-sm); +} + +.box-body { + padding: var(--card-padding); +} + +.box-header { + padding: var(--card-padding); + border-bottom: 1px solid var(--color-line-soft); +} + +.box-header + .box-body { + padding-top: 0; +} + +.radius8 { + border-radius: var(--radius); +} + +.main-shadow { + box-shadow: var(--shadow); +} + +.muted-box { + background-color: var(--surface-2); + border-radius: var(--radius); + padding: var(--card-padding); +} + +/* ============================================================ + * 暗色模式 + * ============================================================ */ +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 { + box-shadow: var(--shadow-sm); +} + +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); +} + +/* ============================================================ + * 卡片 hover 动效 + * ============================================================ */ +.aksrt-theme-box, +.theme-box { + transition: box-shadow var(--dur) var(--ease), transform var(--dur) var(--ease); +} + +.aksrt-card-hover:hover, +.aksrt-card-hover:focus-within { + box-shadow: none; + transform: none; +} + +.aksrt-card-hover-lg:hover, +.aksrt-card-hover-lg:focus-within { + box-shadow: var(--shadow-lg); + transform: translateY(-4px); +} + +.aksrt-noshadow:hover { + box-shadow: none !important; + transform: none !important; +} diff --git a/assets/css/frontend/comment-tools.css b/assets/css/frontend/comment-tools.css new file mode 100644 index 00000000..e46ff0b3 --- /dev/null +++ b/assets/css/frontend/comment-tools.css @@ -0,0 +1,281 @@ +/** + * AKSRT Comment Tools + * + * 评论工具栏样式:表情、代码、图片上传、快捷回复。 + * 所有选择器均带 .comment- 或 .aksrt-comment- 命名空间。 + */ + +/* ========== 评论工具栏 ========== */ +.comment-toolbar { + display: flex; + align-items: center; + gap: 4px; + padding: 6px 8px; + margin-bottom: 8px; + background: var(--surface-secondary, #f8f9fa); + border: 1px solid var(--color-line, #e8e8e8); + border-radius: 8px; +} + +.comment-toolbar__btn { + display: inline-flex; + align-items: center; + justify-content: center; + width: 32px; + height: 32px; + border: none; + border-radius: 6px; + background: transparent; + color: var(--text-secondary, #666); + font-size: 14px; + cursor: pointer; + transition: background-color 0.15s ease, color 0.15s ease; +} + +.comment-toolbar__btn:hover { + background: var(--color-primary-soft, rgba(240, 68, 148, 0.08)); + color: var(--color-primary); +} + +.comment-toolbar__btn:disabled { + opacity: 0.4; + cursor: not-allowed; +} + +.comment-toolbar__separator { + width: 1px; + height: 20px; + margin: 0 4px; + background: var(--color-line, #e8e8e8); +} + +/* Server-side toolbar gating (comment_smilie / comment_code / comment_img): + the .comment-toolbar__btn display rule outranks the UA [hidden] rule, so an + attribute-qualified selector is needed to honor the rendered hidden state. */ +.comment-toolbar__btn[hidden], +.comment-toolbar__separator[hidden] { + display: none; +} + +/* ========== 表情选择器 ========== */ +.comment-emoji-picker { + position: absolute; + bottom: 100%; + left: 0; + z-index: 100; + width: 320px; + max-height: 240px; + padding: 12px; + background: var(--surface-page, #fff); + border: 1px solid var(--color-line, #e8e8e8); + border-radius: 8px; + box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12); + overflow-y: auto; +} + +.comment-emoji-picker__grid { + display: grid; + grid-template-columns: repeat(8, 1fr); + gap: 4px; +} + +.comment-emoji-picker__item { + display: flex; + align-items: center; + justify-content: center; + width: 32px; + height: 32px; + border: none; + border-radius: 4px; + background: transparent; + font-size: 18px; + cursor: pointer; + transition: background-color 0.1s ease; +} + +.comment-emoji-picker__item:hover { + background: var(--color-primary-soft, rgba(240, 68, 148, 0.08)); +} + +/* ========== 快捷回复 ========== */ +.comment-quick-reply { + padding: 8px 12px; + margin-top: 8px; + background: var(--surface-secondary, #f8f9fa); + border: 1px solid var(--color-line, #e8e8e8); + border-radius: 8px; +} + +.comment-quick-reply__title { + font-size: 12px; + font-weight: 600; + color: var(--text-secondary, #666); +} + +.comment-quick-reply__templates { + display: flex; + flex-wrap: wrap; + gap: 6px; + margin-top: 6px; +} + +.comment-quick-reply__template { + padding: 4px 10px; + border: 1px solid var(--color-line, #e8e8e8); + border-radius: 16px; + background: var(--surface-page, #fff); + font-size: 12px; + color: var(--text-secondary, #666); + cursor: pointer; + transition: border-color 0.15s ease, color 0.15s ease; +} + +.comment-quick-reply__template:hover { + border-color: var(--color-primary); + color: var(--color-primary); +} + +/* ========== 评论代码块 ========== */ +.comment-form textarea code, +.comment-content code { + padding: 2px 6px; + background: var(--surface-secondary, #f5f5f5); + border-radius: 4px; + font-family: var(--font-mono, 'Fira Code', monospace); + font-size: 0.875em; +} + +.comment-form textarea pre, +.comment-content pre { + padding: 12px; + background: var(--surface-secondary, #f5f5f5); + border-radius: 8px; + overflow-x: auto; + font-family: var(--font-mono, 'Fira Code', monospace); + font-size: 0.875em; + line-height: 1.6; +} + +/* ========== 投稿页面增强 ========== */ +.aksrt-submit-form__cover-preview { + width: 100%; + max-width: 400px; + aspect-ratio: 16 / 9; + margin-top: 8px; + border-radius: 8px; + overflow: hidden; + background: var(--surface-secondary, #f5f5f5); + display: flex; + align-items: center; + justify-content: center; +} + +.aksrt-submit-form__cover-preview img { + width: 100%; + height: 100%; + object-fit: cover; +} + +.aksrt-submit-form__cover-placeholder { + color: var(--text-tertiary, #8a909c); + font-size: 13px; +} + +.aksrt-submit-form__field-toggle { + display: flex; + align-items: center; + gap: 8px; + padding: 8px 0; + font-size: 13px; + color: var(--text-secondary, #666); +} + +.aksrt-submit-form__word-count { + margin-top: 4px; + font-size: 12px; + color: var(--text-tertiary, #8a909c); + text-align: right; +} + +.aksrt-submit-form__leave-warning { + position: fixed; + bottom: 20px; + left: 50%; + transform: translateX(-50%); + z-index: 9999; + padding: 12px 20px; + background: var(--color-warning-bg, #fffbe6); + border: 1px solid var(--color-warning, #faad14); + border-radius: 8px; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); + font-size: 13px; + color: var(--color-warning-text, #ad6800); +} + +/* ========== Post Share Buttons ========== */ +.aksrt-share-bar { + display: flex; + align-items: center; + gap: 8px; + flex-wrap: wrap; +} + +.aksrt-share-btn { + display: inline-flex; + align-items: center; + gap: 6px; + padding: 6px 14px; + border: 1px solid var(--color-line, #e8e8e8); + border-radius: 20px; + background: var(--surface-page, #fff); + color: var(--text-secondary, #666); + font-size: 13px; + text-decoration: none; + cursor: pointer; + transition: all 0.2s; +} + +.aksrt-share-btn:hover { + border-color: var(--color-primary); + color: var(--color-primary); + background: var(--color-primary-soft, rgba(240, 68, 148, 0.06)); +} + +.aksrt-share-btn.is-copied { + border-color: #52c41a; + color: #52c41a; + background: #f6ffed; +} + +.aksrt-share-btn--weibo:hover { border-color: #e6162d; color: #e6162d; } +.aksrt-share-btn--qq:hover { border-color: #12b7f5; color: #12b7f5; } +.aksrt-share-btn--wechat:hover { border-color: #07c160; color: #07c160; } +.aksrt-share-btn--telegram:hover { border-color: #26a5e4; color: #26a5e4; } +.aksrt-share-btn--twitter:hover { border-color: #1da1f2; color: #1da1f2; } + +/* Quick quote button */ +.aksrt-quick-quote { + position: fixed; + padding: 4px 12px; + background: var(--color-primary); + color: #fff; + border: none; + border-radius: 4px; + font-size: 12px; + cursor: pointer; + z-index: 9999; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15); + transition: background 0.2s; +} + +.aksrt-quick-quote:hover { + background: var(--color-primary-hover, #40a9ff); +} + +/* TOC active state */ +.aksrt-doc-toc__item.is-active > a, +.aksrt-doc-toc__item a.is-active { + color: var(--color-primary); + font-weight: 600; + border-left-color: var(--color-primary); +} diff --git a/assets/css/frontend/comments.css b/assets/css/frontend/comments.css new file mode 100644 index 00000000..a99081e4 --- /dev/null +++ b/assets/css/frontend/comments.css @@ -0,0 +1,614 @@ +/* ============================================================ + * AKSRT Comments — v4.0 Zibll-Inspired + * + * 功能: + * - 评论表单(头像 + 输入框 + 操作栏) + * - 评论列表(嵌套回复 + 头像 + 时间) + * - 排序/过滤栏 + * - 空状态 + * - 移动端固定底部输入框(可选) + * ============================================================ */ + +/* ============================================================ + * 评论区容器 + * ============================================================ */ +.comments-area { + margin: 0; + padding: 0; + /* 对齐 zibll: 45px */ + --aksrt-comment-avatar: 45px; + --aksrt-comment-avatar-form: 45px; + --aksrt-comment-indent: 48px; +} + +/* 评论标题 */ +.comments-header { + margin-bottom: 16px; +} + +.comments-title { + font-size: 1rem; + font-weight: 700; + margin: 0; + display: flex; + align-items: center; + gap: 8px; + color: var(--color-ink); +} + +.comments-title i { + color: var(--color-primary); + font-size: 16px; +} + +.comments-count { + font-size: 0.8125rem; + font-weight: 400; + color: var(--color-ink-4); +} + +/* ============================================================ + * 登录提示 + * ============================================================ */ +.comment-login-prompt { + margin-bottom: 20px; +} + +.comment-login-prompt__inner { + display: flex; + align-items: center; + gap: 12px; + padding: 16px; + border-radius: 8px; + background: var(--surface-3); + font-size: 14px; + color: var(--color-ink-4); +} + +.comment-login-prompt__inner i { + font-size: 16px; + color: var(--color-ink-4); +} + +.comment-login-prompt__btns { + margin-left: auto; + display: flex; + gap: 8px; +} + +/* ============================================================ + * 评论表单 + * ============================================================ */ +.comment-respond { + margin-bottom: 20px; +} + +.comment-form__inner { + display: flex; + gap: 12px; + align-items: flex-start; +} + +.comment-form__avatar { + flex-shrink: 0; +} + +.comment-form__avatar img { + width: var(--aksrt-comment-avatar-form); + height: var(--aksrt-comment-avatar-form); + border-radius: 50%; + object-fit: cover; +} + +.comment-form__avatar-placeholder { + width: var(--aksrt-comment-avatar-form); + height: var(--aksrt-comment-avatar-form); + border-radius: 50%; + background: var(--surface-3); + display: flex; + align-items: center; + justify-content: center; + color: var(--color-ink-4); +} + +.comment-form__body { + flex: 1; + min-width: 0; +} + +.comment-form__reply-info { + font-size: 0.8125rem; + color: var(--color-ink-4); + margin-bottom: 8px; + display: flex; + align-items: center; + gap: 8px; +} + +.comment-form__cancel-reply { + color: var(--color-error, #ef4444); + font-size: 12px; +} + +.comment-form__textarea { + width: 100%; + min-height: 80px; + resize: vertical; + border-radius: 8px; + border: 1px solid var(--color-line); + padding: 5px 5px 4px 5px; + font-size: 14px; + background: var(--main-bg-color, var(--surface-1)); + color: var(--color-ink); + transition: border-color 0.2s ease, box-shadow 0.2s ease; +} + +.comment-form__textarea:focus { + outline: none; + border-color: var(--color-primary); + box-shadow: none; +} + +.comment-form__actions { + display: flex; + align-items: center; + justify-content: space-between; + margin-top: 10px; + gap: 8px; +} + +.comment-form__tools { + display: flex; + gap: 8px; +} + +.comment-form__submit-area { + display: flex; + align-items: center; + gap: 8px; + margin-left: auto; +} + +.comment-form__guest-field { + width: 120px; + height: 32px; + font-size: 13px; +} + +.comment-form__submit { + display: inline-flex; + align-items: center; + gap: 6px; +} + +/* ============================================================ + * 排序/过滤栏 + * ============================================================ */ +.comment-filter { + display: flex; + align-items: center; + justify-content: space-between; + padding: 10px 0; + margin-bottom: 12px; + border-bottom: 1px solid var(--color-line); +} + +.comment-filter__tabs { + display: flex; + list-style: none; + margin: 0; + padding: 0; + gap: 4px; +} + +.comment-filter__tabs li a { + display: inline-block; + padding: 4px 12px; + border-radius: 4px; + font-size: 13px; + font-weight: 500; + color: var(--color-ink-4); + text-decoration: none; + transition: background 0.15s ease, color 0.15s ease; +} + +.comment-filter__tabs li a:hover { + background: var(--surface-3); + color: var(--color-ink); +} + +.comment-filter__tabs li.active a { + background: var(--color-primary-soft, rgba(240, 68, 148, 0.12)); + color: var(--color-primary); + font-weight: 600; +} + +/* ============================================================ + * 评论列表 + * ============================================================ */ +.comment-list { + list-style: none; + margin: 0; + padding: 0; +} + +.comment-list .comment { + padding: 16px 0; + border-bottom: 1px solid var(--color-line); +} + +.comment-list .comment:last-child { + border-bottom: none; +} + +/* 嵌套回复 — 对齐 zibll: 86px 缩进 + 灰色背景 */ +.comment-list .children { + list-style: none; + margin: 0; + margin-left: 86px; +} + +.comment-list .children .comment { + padding: 10px; + background: var(--main-shadow, rgba(0, 0, 0, 0.03)); + border-radius: var(--radius); +} + +/* 深层嵌套缩进递减 */ +.comment-list .children .children { + margin-left: 13px; +} + +/* 评论项内部结构(由 aksrt_comment_callback 渲染) */ +.aksrt-comment__body { + display: flex; + gap: 12px; +} + +.aksrt-comment__avatar { + flex-shrink: 0; +} + +.aksrt-comment__avatar img { + width: var(--aksrt-comment-avatar); + height: var(--aksrt-comment-avatar); + border-radius: 50%; + object-fit: cover; + margin-right: 20px; +} + +.aksrt-comment__content { + flex: 1; + min-width: 0; +} + +.aksrt-comment__header { + display: flex; + align-items: center; + gap: 8px; + margin-bottom: 6px; + flex-wrap: wrap; +} + +.aksrt-comment__author { + font-weight: 600; + font-size: 14px; + color: var(--color-ink); +} + +.aksrt-comment__author a { + color: inherit; +} + +.aksrt-comment__author a:hover { + color: var(--color-primary); +} + +.aksrt-comment__badge { + font-size: 10px; + padding: 1px 6px; + border-radius: 3px; + background: var(--color-primary-soft, rgba(240, 68, 148, 0.12)); + color: var(--color-primary); + font-weight: 500; +} + +.aksrt-comment__time { + font-size: 12px; + color: var(--color-ink-4); +} + +.aksrt-comment__text { + font-size: 14px; + line-height: 1.6; + color: var(--color-ink); + margin: 0 0 8px; + word-wrap: break-word; + white-space: pre-wrap; +} + +/* 对齐 zibll: 评论内图片限制 */ +.aksrt-comment__text img:not(.smilie-icon) { + max-width: 260px; + max-height: 350px; +} + +.aksrt-comment__text p { + margin: 0 0 8px; +} + +.aksrt-comment__text p:last-child { + margin-bottom: 0; +} + +.aksrt-comment__actions { + display: flex; + gap: 12px; + font-size: 12px; +} + +.aksrt-comment__actions a, +.aksrt-comment__actions button { + color: var(--color-ink-4); + background: none; + border: none; + padding: 0; + cursor: pointer; + font-size: 12px; + display: inline-flex; + align-items: center; + gap: 4px; + transition: color 0.15s ease; +} + +.aksrt-comment__actions a:hover, +.aksrt-comment__actions button:hover { + color: var(--color-primary); +} + +/* 嵌套回复中的头像更小 */ +/* 对齐 zibll: 嵌套头像 26px */ +.children .aksrt-comment__avatar img { + width: 26px; + height: 26px; + margin-right: 6px; + vertical-align: 2px; +} + +/* ============================================================ + * 空状态 + * ============================================================ */ +.comments-empty { + text-align: center; + padding: 40px 20px; +} + +.comments-empty__icon { + font-size: 48px; + color: var(--color-ink-4); + opacity: 0.4; + margin-bottom: 12px; +} + +.comments-empty__text { + font-size: 1rem; + font-weight: 600; + color: var(--color-ink-4); + margin: 0 0 4px; +} + +.comments-empty__hint { + font-size: 0.8125rem; + color: var(--color-ink-4); + margin: 0; +} + +.comments-closed { + text-align: center; + font-size: 14px; + color: var(--color-ink-4); + padding: 20px; +} + +/* ============================================================ + * 评论分页 + * ============================================================ */ +.comment-pagination { + text-align: center; + padding: 16px 0; +} + +/* ============================================================ + * 移动端适配 + * ============================================================ */ +@media (max-width: 767px) { + .comment-form__inner { + flex-direction: column; + gap: 8px; + } + + .comment-form__avatar { + display: none; + } + + .comment-form__submit-area { + flex-wrap: wrap; + } + + .comment-form__guest-field { + width: 100%; + } + + .comment-list .children { + margin-left: 0; + } + + .children .aksrt-comment__avatar img { + width: 36px; + height: 36px; + } + + /* 移动端评论输入吸底 — 模仿 zibll mobile-fixed */ + .comment-respond.comment-form--mobile-fixed { + position: fixed; + bottom: 0; + left: 0; + right: 0; + z-index: var(--z-sticky, 200); + background: var(--surface-1); + border-top: 1px solid var(--color-line); + box-shadow: 0 -2px 12px rgba(0, 0, 0, 0.08); + padding: 12px 16px; + padding-bottom: max(12px, env(safe-area-inset-bottom)); + } + + .comment-respond.comment-form--mobile-fixed .comment-form__textarea { + min-height: 44px; + max-height: 120px; + } + + .comment-respond.comment-form--mobile-fixed .comment-form__submit-area { + margin-top: 8px; + } + + /* 当评论区可见时隐藏吸底输入框 */ + .comment-respond.comment-form--mobile-fixed.is-visible { + display: none; + } +} + +/* ============================================================ + * 暗色模式 + * ============================================================ */ +html.dark .comment-form__textarea, +body.dark-theme .comment-form__textarea { + background: var(--surface-2); + border-color: var(--color-line); +} + +.theme-dark .comment-login-prompt__inner, +html.dark .comment-login-prompt__inner, +body.dark-theme .comment-login-prompt__inner { + background: var(--surface-1); +} + +/* ============================================================ + * 评论操作按钮(编辑/删除/审核) + * ============================================================ */ +.aksrt-comment-actions { + display: flex; + align-items: center; + gap: 8px; + margin-top: 8px; +} + +.aksrt-comment-action-btn { + display: inline-flex; + align-items: center; + gap: 4px; + padding: 3px 10px; + border: 1px solid var(--color-line, rgba(50, 50, 50, 0.1)); + border-radius: var(--radius, 8px); + background: var(--surface-1, #fff); + color: var(--color-ink-3, #777); + font-size: 12px; + font-weight: 500; + cursor: pointer; + transition: all 0.15s ease; +} + +.aksrt-comment-action-btn:hover { + border-color: var(--color-primary); + color: var(--color-primary); + background: var(--color-primary-soft, rgba(240, 68, 148, 0.08)); +} + +.aksrt-comment-action-btn--danger:hover { + border-color: var(--color-error); + color: var(--color-error); + background: rgba(239, 68, 68, 0.08); +} + +.aksrt-comment-action-btn--success:hover { + border-color: var(--color-success); + color: var(--color-success); + background: rgba(16, 185, 129, 0.08); +} + +.aksrt-comment-edit-form { + margin: 8px 0; +} + +.aksrt-comment-edit-textarea { + width: 100%; + min-height: 80px; + padding: 8px 12px; + border: 1px solid var(--color-line, #ddd); + border-radius: var(--radius, 8px); + font-size: 14px; + font-family: var(--font-body); + color: var(--color-ink); + background: var(--surface-1, #fff); + resize: vertical; + transition: border-color 0.15s; +} + +.aksrt-comment-edit-textarea:focus { + outline: none; + border-color: var(--color-primary); +} + +/* ============================================================ + * 评论互动:点赞 / 置顶 / 内联管理动作(统一合同) + * 这些动作均渲染在 .aksrt-comment__actions 内,复用其文字链按钮样式, + * 仅补充点赞激活态、置顶徽章与危险/成功色提示。 + * ============================================================ */ +.aksrt-comment__like.is-active, +.aksrt-comment__like.is-active i { + color: var(--color-primary); +} + +.aksrt-comment__like-count { + font-variant-numeric: tabular-nums; +} + +.aksrt-comment__action--danger:hover { + color: var(--color-error, #ef4444); +} + +.aksrt-comment__action--success:hover { + color: var(--color-success, #10b981); +} + +/* 置顶徽章 */ +.aksrt-comment__badge--pinned { + background: var(--color-warning-soft, rgba(245, 158, 11, 0.14)); + color: var(--color-warning, #d97706); + display: inline-flex; + align-items: center; + gap: 3px; +} + +/* 置顶评论容器高亮 */ +.aksrt-comment--pinned > .aksrt-comment__body { + position: relative; +} + +.comment-list .comment.aksrt-comment--pinned { + background: var(--color-warning-soft, rgba(245, 158, 11, 0.06)); + border-radius: var(--radius, 8px); + padding-left: 12px; + padding-right: 12px; +} + +/* zibll compat: emoji icon forced 30px */ +.comment-content .smilie-icon, +.comment-form .smilie-icon { + width: 30px !important; +} + +/* zibll compat: code block in comments */ +.comment-content .enlighter-default { + margin-bottom: 0; + opacity: 0.9; +} diff --git a/assets/css/frontend/credits.css b/assets/css/frontend/credits.css new file mode 100644 index 00000000..68c8ae29 --- /dev/null +++ b/assets/css/frontend/credits.css @@ -0,0 +1,384 @@ +/** + * Credits · 顶部余额徽章 / 积分明细 / 签到 / 邀请共用样式 + * + * 仅在已登录 + cms_features.download_credit 启用时加载。 + */ + +/* ============ 用户下拉中的余额块 ============ */ +.user-dropdown__credits { + display: flex; + align-items: center; + gap: 8px; + padding: 10px 16px; + color: var(--color-ink); + font: 500 13px/1 var(--font-ui); + background: linear-gradient(135deg, rgba(240, 68, 148, 0.08) 0%, rgba(240, 68, 148, 0.02) 100%); +} + +.user-dropdown__credits i { + color: #f59e0b; + font-size: 14px; +} + +.user-dropdown__credits-label { + color: var(--color-ink-2); +} + +.user-dropdown__credits-value { + margin-left: auto; + font-weight: 700; + color: var(--color-primary); +} + +/* ============ 积分明细列表(profile 用) ============ */ +.credits-log { + display: flex; + flex-direction: column; + gap: 8px; +} + +.credits-log__row { + display: grid; + grid-template-columns: auto 1fr auto auto; + gap: var(--space-3, 12px); + align-items: center; + padding: 12px 16px; + background: var(--surface-1); + border: 1px solid var(--color-line); + border-radius: var(--radius); + font-size: 13px; +} + +.credits-log__icon { + display: inline-flex; + align-items: center; + justify-content: center; + width: 32px; + height: 32px; + border-radius: 50%; + background: var(--surface-2); + color: var(--color-ink-2); +} + +.credits-log__icon.is-positive { + background: rgba(22, 163, 74, .1); + color: #16a34a; +} + +.credits-log__icon.is-negative { + background: rgba(239, 68, 68, .1); + color: #ef4444; +} + +.credits-log__reason { + color: var(--color-ink); + font-weight: 500; +} + +.credits-log__remark { + font-weight: 400; + color: var(--color-ink-2); + font-size: 12px; +} + +.credits-log__date { + color: var(--color-ink-3); + font-size: 12px; +} + +.credits-log__delta { + font-weight: 700; + font-variant-numeric: tabular-nums; +} + +.credits-log__delta.is-positive { + color: #16a34a; +} + +.credits-log__delta.is-negative { + color: #ef4444; +} + +/* ============ 余额卡片(profile 头部) ============ */ +.credits-card { + display: flex; + flex-wrap: wrap; + align-items: center; + justify-content: space-between; + gap: 16px; + padding: 20px 24px; + border-radius: var(--radius-lg); + background: linear-gradient(135deg, var(--color-primary) 0%, var(--color-primary-active) 100%); + color: var(--color-on-primary); + margin-bottom: 20px; +} + +.credits-card__info { + display: flex; + flex-direction: column; + gap: 6px; +} + +.credits-card__label { + font: 500 13px/1 var(--font-ui); + opacity: .85; +} + +.credits-card__value { + font: 700 32px/1 var(--font-ui); + display: flex; + align-items: baseline; + gap: 6px; +} + +.credits-card__unit { + font: 500 14px/1 var(--font-ui); + opacity: .85; +} + +.credits-card__sign { + display: flex; + align-items: center; + gap: 12px; + flex-shrink: 0; +} + +.credits-card__sign-status { + font: 500 13px/1.4 var(--font-ui); + opacity: .9; + max-width: 160px; + text-align: right; +} + +.credits-card__sign .btn-primary { + background: rgba(255, 255, 255, .2); + border: 1px solid rgba(255, 255, 255, .3); + backdrop-filter: blur(4px); +} + +.credits-card__sign .btn-primary:hover:not(:disabled) { + background: rgba(255, 255, 255, .35); +} + +.credits-card__sign .btn-primary:disabled { + opacity: .5; + cursor: default; +} + +/* ============ 签到 panel ============ */ +.aksrt-signin-status { + margin: 0 0 16px; + color: var(--color-ink-2); + font-size: 14px; + line-height: 1.6; +} + +.aksrt-signin-status strong { + color: var(--color-primary); + font-weight: 700; +} + +.aksrt-signin-tip { + margin: 0; + width: 100%; + color: var(--color-on-primary); + opacity: .85; + font-size: 13px; +} + +/* ============ 邀请 panel ============ */ +.aksrt-invite-desc { + margin: 0 0 16px; + color: var(--color-ink-2); + font-size: 14px; +} + +.aksrt-invite-link-row { + display: flex; + gap: 8px; + margin-bottom: 16px; +} + +.aksrt-invite-link { + flex: 1 1 auto; + height: 36px; + padding: 0 12px; + border: 1px solid var(--color-line); + border-radius: var(--radius); + background: var(--surface-2); + color: var(--color-ink); + font: 500 13px/1 var(--font-mono, monospace); +} + +.aksrt-invite-stats { + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 12px; +} + +.aksrt-invite-stats > div { + display: flex; + flex-direction: column; + gap: 4px; + padding: 12px; + background: var(--surface-2); + border-radius: var(--radius); + text-align: center; +} + +.aksrt-invite-stats span { + color: var(--color-ink-3); + font: 500 12px/1 var(--font-ui); +} + +.aksrt-invite-stats strong { + color: var(--color-primary); + font: 700 22px/1 var(--font-ui); + font-variant-numeric: tabular-nums; +} + +/* ============ VIP 会员卡片 ============ */ +.uc-vip-card { + position: relative; + border-radius: var(--radius-lg, 12px); + overflow: hidden; + margin-bottom: 16px; + background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%); + color: #fff; +} + +.uc-vip-card--active { + background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%); +} + +.uc-vip-card__bg { + position: absolute; + top: 0; + right: 0; + width: 120px; + height: 120px; + background: radial-gradient(circle, rgba(255, 255, 255, .1) 0%, transparent 70%); + pointer-events: none; +} + +.uc-vip-card__content { + position: relative; + padding: 20px; +} + +.uc-vip-card__header { + display: flex; + align-items: center; + gap: 12px; + margin-bottom: 12px; +} + +.uc-vip-card__icon { + display: flex; + align-items: center; + justify-content: center; + width: 40px; + height: 40px; + border-radius: 50%; + background: rgba(255, 255, 255, .15); + font-size: 18px; +} + +.uc-vip-card--active .uc-vip-card__icon { + background: rgba(255, 255, 255, .25); +} + +.uc-vip-card__info { + display: flex; + flex-direction: column; + gap: 4px; +} + +.uc-vip-card__label { + font: 700 16px/1 var(--font-ui); +} + +.uc-vip-card__status { + font: 500 12px/1 var(--font-ui); + opacity: .8; +} + +.uc-vip-card__status--active { + color: #4ade80; + opacity: 1; +} + +.uc-vip-card__benefits { + display: flex; + flex-wrap: wrap; + gap: 8px; + margin-bottom: 16px; +} + +.uc-vip-card__benefit { + display: inline-flex; + align-items: center; + gap: 6px; + padding: 6px 10px; + border-radius: var(--radius, 8px); + background: rgba(255, 255, 255, .1); + font: 500 12px/1 var(--font-ui); +} + +.uc-vip-card__benefit i { + font-size: 12px; +} + +.uc-vip-card__btn { + display: inline-flex; + align-items: center; + justify-content: center; + padding: 10px 24px; + border-radius: var(--radius, 8px); + background: rgba(255, 255, 255, .2); + border: 1px solid rgba(255, 255, 255, .3); + color: #fff; + font: 600 14px/1 var(--font-ui); + text-decoration: none; + transition: all .2s ease; +} + +.uc-vip-card__btn:hover { + background: rgba(255, 255, 255, .3); + color: #fff; +} + +/* ============ VIP 徽标 ============ */ +.aksrt-vip-badge { + display: inline-flex; + align-items: center; + gap: 4px; + padding: 2px 8px; + border-radius: 4px; + font: 600 11px/1 var(--font-ui); + background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%); + color: #fff; + vertical-align: middle; +} + +.aksrt-vip-badge i { + font-size: 10px; +} + +.aksrt-vip-badge--sm { + padding: 2px 6px; + font-size: 10px; +} + +.aksrt-vip-badge--sm i { + font-size: 9px; +} + +.aksrt-vip-badge--lg { + padding: 4px 12px; + font-size: 13px; +} + +.aksrt-vip-badge--lg i { + font-size: 12px; +} diff --git a/assets/css/frontend/empty-state.css b/assets/css/frontend/empty-state.css new file mode 100644 index 00000000..09622f5a --- /dev/null +++ b/assets/css/frontend/empty-state.css @@ -0,0 +1,124 @@ +/* ========== 空状态 — 对齐 zibll empty state ========== */ +.empty-state { + text-align: center; + padding: 60px 20px; + color: var(--color-ink-3, #777); +} + +.empty-state__icon { + font-size: 56px; + color: var(--surface-3, #e8e8e8); + margin-bottom: 16px; + line-height: 1; +} + +.empty-state__icon i { + display: inline-block; +} + +.empty-state__title { + font-size: 16px; + font-weight: 500; + color: var(--color-ink-2, #4e5358); + margin-bottom: 8px; +} + +.empty-state__desc { + font-size: 13px; + color: var(--color-ink-4, #999); + margin-bottom: 20px; + max-width: 320px; + margin-left: auto; + margin-right: auto; + line-height: 1.6; +} + +.empty-state__action { + display: inline-flex; + align-items: center; + gap: 6px; +} + +/* 空状态变体 */ +.empty-state--sm { + padding: 30px 16px; +} + +.empty-state--sm .empty-state__icon { + font-size: 40px; +} + +.empty-state--sm .empty-state__title { + font-size: 14px; +} + +.empty-state--sm .empty-state__desc { + font-size: 12px; +} + +/* 评论空状态 */ +.comments-empty { + text-align: center; + padding: 40px 20px; +} + +.comments-empty__icon { + font-size: 48px; + color: var(--surface-3, #e8e8e8); + margin-bottom: 12px; +} + +.comments-empty__text { + font-size: 14px; + color: var(--color-ink-3, #777); + margin-bottom: 4px; +} + +.comments-empty__hint { + font-size: 12px; + color: var(--color-ink-4, #999); +} + +/* 搜索空状态 */ +.search-empty { + text-align: center; + padding: 80px 20px; +} + +.search-empty__icon { + font-size: 64px; + color: var(--surface-3, #e8e8e8); + margin-bottom: 16px; +} + +.search-empty__title { + font-size: 18px; + font-weight: 500; + color: var(--color-ink-2, #4e5358); + margin-bottom: 8px; +} + +.search-empty__suggestions { + font-size: 13px; + color: var(--color-ink-4, #999); +} + +.search-empty__suggestions a { + color: var(--color-primary, #f04494); + text-decoration: none; +} + +.search-empty__suggestions a:hover { + text-decoration: underline; +} + +/* 移动端 */ +@media (max-width: 767px) { + .empty-state { + padding: 40px 16px; + } + + .empty-state__icon { + font-size: 44px; + } +} diff --git a/assets/css/frontend/enhancements.css b/assets/css/frontend/enhancements.css new file mode 100644 index 00000000..2d06f0ec --- /dev/null +++ b/assets/css/frontend/enhancements.css @@ -0,0 +1,3 @@ +@import url("enhancements/core-ui.css"); +@import url("enhancements/components.css"); +@import url("enhancements/modal-motion.css"); diff --git a/assets/css/frontend/enhancements/components.css b/assets/css/frontend/enhancements/components.css new file mode 100644 index 00000000..5be1dd16 --- /dev/null +++ b/assets/css/frontend/enhancements/components.css @@ -0,0 +1,3 @@ +@import url("components/base.css"); +@import url("components/reward-amounts.css"); +@import url("components/custom-amount.css"); diff --git a/assets/css/frontend/enhancements/components/base.css b/assets/css/frontend/enhancements/components/base.css new file mode 100644 index 00000000..9206b0cc --- /dev/null +++ b/assets/css/frontend/enhancements/components/base.css @@ -0,0 +1,199 @@ +/* ============================================================ + * 7. 文章封面轮播 + * ============================================================ */ +.single-cover-slider { + position: relative; + width: 100%; + overflow: hidden; + border-radius: var(--radius-lg, 8px); +} + +.single-cover-slider .swiper-slide { + position: relative; + overflow: hidden; +} + +.single-cover-slider__img { + width: 100%; + height: 400px; + object-fit: cover; + display: block; +} + +.single-cover-slider__overlay { + position: absolute; + inset: 0; + background: linear-gradient(180deg, rgba(0,0,0,0) 40%, rgba(0,0,0,0.6) 100%); + pointer-events: none; +} + +.single-cover-slider__content { + position: absolute; + bottom: 0; + left: 0; + right: 0; + padding: 24px; + color: #fff; + z-index: 2; +} + +.single-cover-slider__title { + margin: 0 0 8px; + font-size: 24px; + font-weight: 700; + text-shadow: 0 1px 3px rgba(0,0,0,0.3); +} + +.single-cover-slider__meta { + display: flex; + gap: 16px; + font-size: 13px; + opacity: 0.9; +} + +.single-cover-slider__pagination { + position: absolute; + bottom: 12px; + right: 16px; + z-index: 3; +} + +.single-cover-slider__pagination .swiper-pagination-bullet { + background: rgba(255,255,255,0.6); + opacity: 1; +} + +.single-cover-slider__pagination .swiper-pagination-bullet-active { + background: #fff; +} + +.single-cover-slider__prev, +.single-cover-slider__next { + position: absolute; + top: 50%; + transform: translateY(-50%); + z-index: 3; + width: 40px; + height: 40px; + border: none; + border-radius: 50%; + background: rgba(0,0,0,0.3); + color: #fff; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + transition: background 0.2s; +} + +.single-cover-slider__prev:hover, +.single-cover-slider__next:hover { + background: rgba(0,0,0,0.5); +} + +.single-cover-slider__prev { left: 12px; } +.single-cover-slider__next { right: 12px; } + +@media (max-width: 640px) { + .single-cover-slider__img { + height: 240px; + } + .single-cover-slider__title { + font-size: 18px; + } +} + +/* ============================================================ + * 8. 打赏按钮 + * ============================================================ */ +.action-btn--reward { + position: relative; +} + +.action-btn--reward.is-active { + color: var(--color-warning, #F59E0B); +} + +.reward-modal { + position: fixed; + inset: 0; + z-index: 99999; + display: flex; + align-items: center; + justify-content: center; + opacity: 0; + visibility: hidden; + transition: opacity 0.3s, visibility 0.3s; +} + +.reward-modal.is-open { + opacity: 1; + visibility: visible; +} + +.reward-modal__overlay { + position: absolute; + inset: 0; + background: rgba(0,0,0,0.5); +} + +.reward-modal__card { + position: relative; + background: var(--surface-1, #fff); + border-radius: var(--radius-lg, 8px); + padding: 32px; + max-width: 360px; + width: 90%; + text-align: center; + box-shadow: 0 8px 32px rgba(0,0,0,0.15); + z-index: 1; +} + +.reward-modal__title { + margin: 0 0 8px; + font-size: 18px; + font-weight: 600; + color: var(--color-ink); +} + +.reward-modal__desc { + margin: 0 0 20px; + font-size: 14px; + color: var(--color-ink-3); +} + +.reward-modal__qr { + width: 200px; + height: 200px; + margin: 0 auto 16px; + border-radius: var(--radius, 10px); + overflow: hidden; +} + +.reward-modal__qr img { + width: 100%; + height: 100%; + object-fit: contain; +} + +.reward-modal__close { + position: absolute; + top: 12px; + right: 12px; + width: 32px; + height: 32px; + border: none; + border-radius: 50%; + background: var(--surface-2, #F4F5F7); + color: var(--color-ink-3); + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + transition: background 0.2s; +} + +.reward-modal__close:hover { + background: var(--surface-3, #ECEEF1); +} + diff --git a/assets/css/frontend/enhancements/components/custom-amount.css b/assets/css/frontend/enhancements/components/custom-amount.css new file mode 100644 index 00000000..478687e2 --- /dev/null +++ b/assets/css/frontend/enhancements/components/custom-amount.css @@ -0,0 +1,571 @@ +/* ---- custom amount ---- */ +.reward-custom { + display: flex; + align-items: center; + gap: 8px; + margin-bottom: 16px; +} + +.reward-custom__input { + flex: 1; + height: 40px; + padding: 0 12px; + border: 1px solid var(--color-line, #e5e7eb); + border-radius: var(--radius, 10px); + background: var(--surface-2, #F4F5F7); + color: var(--color-ink); + font-size: 14px; + text-align: center; + outline: none; + transition: border-color 0.2s; + -moz-appearance: textfield; +} + +.reward-custom__input::-webkit-inner-spin-button, +.reward-custom__input::-webkit-outer-spin-button { + -webkit-appearance: none; + margin: 0; +} + +.reward-custom__input:focus { + border-color: var(--color-primary, #f04494); +} + +.reward-custom__confirm { + flex-shrink: 0; + height: 40px; + padding: 0 20px; + border: none; + border-radius: var(--radius, 10px); + background: var(--color-primary, #f04494); + color: #fff; + font-size: 14px; + font-weight: 500; + cursor: pointer; + transition: opacity 0.2s; +} + +.reward-custom__confirm:hover { + opacity: 0.85; +} + +/* ============================================================ + * 9. 公告跑马灯 Widget + * ============================================================ */ +.aksrt-announcement { + position: relative; + overflow: hidden; + padding: 10px 12px; + background: var(--surface-2, #F4F5F7); + border-radius: var(--radius, 10px); +} + +.aksrt-announcement__icon { + position: absolute; + left: 12px; + top: 50%; + transform: translateY(-50%); + color: var(--color-primary, var(--color-primary)); + font-size: 14px; + z-index: 1; +} + +.aksrt-announcement__track { + margin-left: 24px; + overflow: hidden; + height: 20px; +} + +.aksrt-announcement__list { + margin: 0; + padding: 0; + list-style: none; + animation: aksrt-marquee 10s linear infinite; +} + +.aksrt-announcement__item { + height: 20px; + line-height: 20px; + font-size: 13px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.aksrt-announcement__item a { + color: var(--color-ink-2); + text-decoration: none; +} + +.aksrt-announcement__item a:hover { + color: var(--color-primary, var(--color-primary)); +} + +@keyframes aksrt-marquee { + 0% { transform: translateY(0); } + 100% { transform: translateY(-100%); } +} + +.aksrt-announcement:hover .aksrt-announcement__list { + animation-play-state: paused; +} + +/* ============================================================ + * 10. 用户卡片 Widget + * ============================================================ */ +.aksrt-user-card { + text-align: center; + padding: 20px; +} + +.aksrt-user-card__avatar { + width: 72px; + height: 72px; + border-radius: 50%; + margin: 0 auto 12px; + overflow: hidden; + border: 3px solid var(--color-primary-soft, rgba(136,171,218,0.1)); +} + +.aksrt-user-card__avatar img { + width: 100%; + height: 100%; + object-fit: cover; +} + +.aksrt-user-card__name { + margin: 0 0 4px; + font-size: 16px; + font-weight: 600; + color: var(--color-ink); +} + +.aksrt-user-card__name a { + color: inherit; + text-decoration: none; +} + +.aksrt-user-card__name a:hover { + color: var(--color-primary, var(--color-primary)); +} + +.aksrt-user-card__bio { + margin: 0 0 12px; + font-size: 13px; + color: var(--color-ink-3); + line-height: 1.5; + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + overflow: hidden; +} + +.aksrt-user-card__stats { + display: flex; + justify-content: center; + gap: 20px; + margin-bottom: 16px; +} + +.aksrt-user-card__stat { + text-align: center; +} + +.aksrt-user-card__stat-value { + display: block; + font-size: 18px; + font-weight: 600; + color: var(--color-ink); +} + +.aksrt-user-card__stat-label { + font-size: 12px; + color: var(--color-ink-4, #8A8F98); +} + +.aksrt-user-card__actions { + display: flex; + gap: 8px; + justify-content: center; +} + +.aksrt-user-card__btn { + display: inline-flex; + align-items: center; + gap: 4px; + padding: 6px 16px; + border-radius: var(--radius, 10px); + font-size: 13px; + text-decoration: none; + transition: all 0.15s; +} + +.aksrt-user-card__btn--primary { + background: var(--color-primary, var(--color-primary)); + color: #fff; +} + +.aksrt-user-card__btn--primary:hover { + opacity: 0.85; + color: #fff; +} + +.aksrt-user-card__btn--ghost { + border: 1px solid var(--color-line); + color: var(--color-ink-2); +} + +.aksrt-user-card__btn--ghost:hover { + border-color: var(--color-primary, var(--color-primary)); + color: var(--color-primary, var(--color-primary)); +} + +/* ============================================================ + * 11. 滚动触发动画初始状态 + * ============================================================ */ +[data-aksrt-animate] { + will-change: opacity, transform; +} + +/* ============================================================ + * 12. 粘性侧栏 + * ============================================================ */ +[data-aksrt-sticky] { + will-change: transform; +} + +/* ============================================================ + * 13. 用户排行榜 Widget + * ============================================================ */ +.aksrt-user-ranking { + margin: 0; + padding: 0; + list-style: none; +} + +.aksrt-user-ranking__item { + display: flex; + align-items: center; + gap: 10px; + padding: 10px 0; + border-bottom: 1px solid var(--color-line-soft, #F0F1F3); +} + +.aksrt-user-ranking__item:last-child { + border-bottom: none; +} + +.aksrt-user-ranking__rank { + display: flex; + align-items: center; + justify-content: center; + width: 24px; + height: 24px; + border-radius: 6px; + background: var(--surface-2, #F4F5F7); + color: var(--color-ink-3); + font-size: 12px; + font-weight: 600; + flex-shrink: 0; +} + +.aksrt-user-ranking__item--top:nth-child(1) .aksrt-user-ranking__rank { + background: #FFD700; + color: #fff; +} + +.aksrt-user-ranking__item--top:nth-child(2) .aksrt-user-ranking__rank { + background: #C0C0C0; + color: #fff; +} + +.aksrt-user-ranking__item--top:nth-child(3) .aksrt-user-ranking__rank { + background: #CD7F32; + color: #fff; +} + +.aksrt-user-ranking__avatar { + flex-shrink: 0; +} + +.aksrt-user-ranking__avatar img { + width: 36px; + height: 36px; + border-radius: 50%; + object-fit: cover; +} + +.aksrt-user-ranking__name { + flex: 1; + min-width: 0; + font-size: 14px; + color: var(--color-ink); + text-decoration: none; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.aksrt-user-ranking__name:hover { + color: var(--color-primary, var(--color-primary)); +} + +.aksrt-user-ranking__value { + font-size: 12px; + color: var(--color-ink-4, #8A8F98); + white-space: nowrap; +} + +/* ============================================================ + * 14. 图文封面卡片 Widget + * ============================================================ */ +.aksrt-cover-cards { + display: grid; + grid-template-columns: repeat(var(--cols, 2), 1fr); + gap: 12px; +} + +.aksrt-cover-card { + position: relative; + border-radius: var(--radius-lg, 8px); + overflow: hidden; + min-height: 160px; + display: flex; + align-items: flex-end; + transition: transform 0.3s, box-shadow 0.3s; +} + +.aksrt-cover-card:hover { + transform: translateY(-3px); + box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15); +} + +.aksrt-cover-card__bg { + position: absolute; + inset: 0; +} + +.aksrt-cover-card__bg img { + width: 100%; + height: 100%; + object-fit: cover; + transition: transform 0.5s; +} + +.aksrt-cover-card:hover .aksrt-cover-card__bg img { + transform: scale(1.02); +} + +.aksrt-cover-card__overlay { + position: absolute; + inset: 0; + background: linear-gradient(180deg, rgba(0,0,0,0) 30%, rgba(0,0,0,0.6) 100%); +} + +.aksrt-cover-card__content { + position: relative; + z-index: 1; + padding: 16px; + width: 100%; +} + +.aksrt-cover-card__link { + text-decoration: none; + color: inherit; + display: block; +} + +.aksrt-cover-card__title { + margin: 0 0 4px; + font-size: 16px; + font-weight: 600; + color: #fff; + text-shadow: 0 1px 3px rgba(0, 0, 0, 0.4); +} + +.aksrt-cover-card__desc { + margin: 0; + font-size: 13px; + color: rgba(255, 255, 255, 0.85); + text-shadow: 0 1px 2px rgba(0, 0, 0, 0.3); + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + overflow: hidden; +} + +/* ============================================================ + * 15. 视频播放器 Widget + * ============================================================ */ +.aksrt-video-widget { + position: relative; + width: 100%; + overflow: hidden; + border-radius: var(--radius, 10px); + background: #000; +} + +.aksrt-video-widget iframe, +.aksrt-video-widget video { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + border: none; +} + +/* ============================================================ + * 16. 表单输入浮动标签 + * ============================================================ */ +.aksrt-float-label { + position: relative; +} + +.aksrt-float-label__input { + width: 100%; + padding: 14px 12px 6px; + font-size: 14px; + border: 1px solid var(--color-line); + border-radius: var(--radius, 10px); + background: var(--surface-1, #fff); + color: var(--color-ink); + transition: border-color 0.2s; +} + +.aksrt-float-label__input:focus { + outline: none; + border-color: var(--color-primary, var(--color-primary)); +} + +.aksrt-float-label__label { + position: absolute; + left: 12px; + top: 50%; + transform: translateY(-50%); + font-size: 14px; + color: var(--color-ink-4, #8A8F98); + pointer-events: none; + transition: all 0.2s ease; +} + +.aksrt-float-label__input:focus + .aksrt-float-label__label, +.aksrt-float-label__input:not(:placeholder-shown) + .aksrt-float-label__label { + top: 8px; + transform: translateY(0); + font-size: 11px; + color: var(--color-primary, var(--color-primary)); +} + +/* ============================================================ + * 17. 视差滚动层 + * ============================================================ */ +[data-aksrt-parallax] { + will-change: transform; + transition: transform 0.1s linear; +} + +/* ============================================================ + * 18. 签到日历可视化 + * ============================================================ */ +.aksrt-signin-calendar__grid { + display: grid; + grid-template-columns: repeat(7, 1fr); + gap: 4px; +} + +.aksrt-signin-calendar__day { + aspect-ratio: 1; + display: flex; + align-items: center; + justify-content: center; + border-radius: 6px; + background: var(--surface-2, #F4F5F7); + font-size: 12px; + color: var(--color-ink-3); + transition: all 0.2s; +} + +.aksrt-signin-calendar__day.is-signed { + background: var(--color-success, #10B981); + color: #fff; +} + +.aksrt-signin-calendar__day.is-today { + border: 2px solid var(--color-primary, var(--color-primary)); +} + +.aksrt-signin-calendar__day.is-signed.is-today { + background: var(--color-primary, var(--color-primary)); + border-color: var(--color-primary, var(--color-primary)); +} + +.uc-signin-calendar__title { + display: flex; + align-items: center; + gap: 6px; + margin: 0 0 10px; + font-size: 14px; + font-weight: 600; + color: var(--color-ink-2); +} + +.uc-signin-calendar__title i { + color: var(--color-primary, var(--color-primary)); +} + +/* ============================================================ + * 19. VIP 等级标识 + * ============================================================ */ +.aksrt-vip-badge { + display: inline-flex; + align-items: center; + gap: 4px; + padding: 2px 8px; + border-radius: var(--radius-pill, 999px); + font-size: 11px; + font-weight: 600; +} + +.aksrt-vip-badge--gold { + background: linear-gradient(135deg, #FFD700, #FFA500); + color: #fff; +} + +.aksrt-vip-badge--silver { + background: linear-gradient(135deg, #C0C0C0, #A8A8A8); + color: #fff; +} + +.aksrt-vip-badge--bronze { + background: linear-gradient(135deg, #CD7F32, #A0522D); + color: #fff; +} + +/* ============================================================ + * 20. 用户等级进度条 + * ============================================================ */ +.aksrt-level-bar { + position: relative; + height: 8px; + background: var(--surface-2, #F4F5F7); + border-radius: 4px; + overflow: hidden; +} + +.aksrt-level-bar__fill { + height: 100%; + background: linear-gradient(90deg, var(--color-primary, var(--color-primary)), var(--color-primary-active, #5A85BD)); + border-radius: 4px; + transition: width 0.5s ease; +} + +.aksrt-level-bar__label { + position: absolute; + right: 0; + top: -18px; + font-size: 11px; + color: var(--color-ink-4, #8A8F98); +} + + diff --git a/assets/css/frontend/enhancements/components/reward-amounts.css b/assets/css/frontend/enhancements/components/reward-amounts.css new file mode 100644 index 00000000..e974ae27 --- /dev/null +++ b/assets/css/frontend/enhancements/components/reward-amounts.css @@ -0,0 +1,45 @@ +/* ---- reward amounts ---- */ +.reward-amounts { + display: flex; + flex-wrap: wrap; + gap: 8px; + justify-content: center; + margin-bottom: 16px; +} + +.reward-amounts__btn { + display: inline-flex; + align-items: baseline; + gap: 2px; + padding: 8px 16px; + border: 1px solid var(--color-line, #e5e7eb); + border-radius: var(--radius, 10px); + background: var(--surface-2, #F4F5F7); + color: var(--color-ink); + font-size: 15px; + font-weight: 600; + cursor: pointer; + transition: all 0.2s ease; + user-select: none; +} + +.reward-amounts__btn:hover { + border-color: var(--color-primary, #f04494); + background: rgba(240, 68, 148, 0.06); +} + +.reward-amounts__btn.is-active { + border-color: var(--color-primary, #f04494); + background: var(--color-primary, #f04494); + color: #fff; +} + +.reward-amounts__currency { + font-size: 13px; + font-weight: 400; +} + +.reward-amounts__value { + font-size: 15px; +} + diff --git a/assets/css/frontend/enhancements/core-ui.css b/assets/css/frontend/enhancements/core-ui.css new file mode 100644 index 00000000..e5e5691c --- /dev/null +++ b/assets/css/frontend/enhancements/core-ui.css @@ -0,0 +1,483 @@ +/** + * AKSRT Enhancements — 全局 UI 增强 + * + * 包含:Toast 通知、骨架屏、悬停动效、暗色过渡、滚动感知 + * 所有选择器使用 aksrt- 前缀避免冲突 + */ + +/* ============================================================ + * 1. Toast 通知系统 + * ============================================================ */ +.aksrt-toast-container { + position: fixed; + bottom: 80px; + right: 16px; + max-width: 360px; + z-index: 10000; + display: flex; + flex-direction: column-reverse; + gap: 8px; + pointer-events: none; +} + +.aksrt-toast { + pointer-events: auto; + display: flex; + align-items: center; + gap: 10px; + padding: 12px 16px; + border-radius: var(--main-radius, 8px); + color: #fff; + font-size: 14px; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12); + backdrop-filter: saturate(5) blur(20px); + -webkit-backdrop-filter: saturate(5) blur(20px); + transform: translateX(120%); + opacity: 0; + animation: aksrt-toast-in 0.35s cubic-bezier(0.35, 0.71, 0.46, 1.08) forwards; + cursor: pointer; + transition: transform 0.3s, opacity 0.3s; +} + +.aksrt-toast.is-dismissing { + transform: translateX(120%); + opacity: 0; + transition: transform 0.3s ease-in, opacity 0.3s ease-in; +} + +.aksrt-toast__icon { + font-size: 18px; + flex-shrink: 0; +} + +.aksrt-toast__text { + flex: 1; + min-width: 0; + line-height: 1.4; +} + +/* Toast 类型 — 对齐 zibll 纯色 */ +.aksrt-toast--success { + background: rgba(16, 185, 129, 0.9); +} + +.aksrt-toast--info { + background: rgba(59, 130, 246, 0.9); +} + +.aksrt-toast--warning { + background: rgba(245, 158, 11, 0.9); +} + +.aksrt-toast--danger, +.aksrt-toast--error { + background: rgba(239, 68, 68, 0.9); +} + +.aksrt-toast--loading { + background: rgba(107, 114, 128, 0.9); +} + +.aksrt-toast--loading .aksrt-toast__icon { + animation: aksrt-spin 1s linear infinite; +} + +.aksrt-modal-auth__error.is-success { + background: rgba(16, 185, 129, 0.08); + border-color: rgba(16, 185, 129, 0.22); + color: #047857; +} + +.aksrt-modal-auth__checkbox { + display: flex; + align-items: flex-start; + gap: 8px; + font-size: 13px; + color: var(--muted-color, #777); +} + +.aksrt-modal-auth__hint { + margin: -4px 0 0; + font-size: 13px; + color: var(--muted-color, #777); + line-height: 1.6; +} + +@keyframes aksrt-toast-in { + from { + transform: translateX(120%); + opacity: 0; + } + to { + transform: translateX(0); + opacity: 1; + } +} + +@keyframes aksrt-spin { + from { transform: rotate(0deg); } + to { transform: rotate(360deg); } +} + +/* ============================================================ + * 2. 骨架屏加载动画 + * ============================================================ */ +.aksrt-skeleton { + background: linear-gradient( + 90deg, + rgba(121, 121, 121, 0.08) 25%, + rgba(121, 121, 121, 0.15) 37%, + rgba(121, 121, 121, 0.08) 63% + ); + background-size: 400% 100%; + animation: aksrt-skeleton-shimmer 1.5s ease infinite; + border-radius: 4px; +} + +.aksrt-skeleton--image { + height: 0; + padding-bottom: 66.67%; /* 3:2 aspect ratio */ +} + +.aksrt-skeleton--avatar { + width: 40px; + height: 40px; + border-radius: 50%; +} + +.aksrt-skeleton--title { + height: 22px; + width: 80%; +} + +.aksrt-skeleton--text { + height: 16px; + width: 100%; +} + +.aksrt-skeleton--text-short { + height: 16px; + width: 60%; +} + +.aksrt-skeleton--button { + height: 36px; + width: 100px; + border-radius: 8px; +} + +@keyframes aksrt-skeleton-shimmer { + 0% { background-position: 100% 50%; } + 100% { background-position: 0 50%; } +} + +/* 骨架屏组合:文章卡片骨架 */ +.aksrt-skeleton-card { + background: var(--surface-1, #fff); + border: 1px solid var(--color-line); + border-radius: 12px; + overflow: hidden; + padding: 0; +} + +.aksrt-skeleton-card .aksrt-skeleton--image { + border-radius: 0; +} + +.aksrt-skeleton-card__body { + padding: 16px; + display: flex; + flex-direction: column; + gap: 10px; +} + +/* ============================================================ + * 3. 悬停交互动效 + * ============================================================ */ + +/* 卡片放大 */ +.aksrt-hover-zoom { + transition: transform 0.3s ease; +} + +.aksrt-hover-zoom:hover { + transform: scale(1.02); +} + +/* 卡片轻微放大 */ +.aksrt-hover-zoom-sm { + transition: transform 0.3s ease; +} + +.aksrt-hover-zoom-sm:hover { + transform: scale(1.02); +} + +/* 悬停显示内容 */ +.aksrt-hover-show { + position: relative; +} + +.aksrt-hover-show__content { + position: absolute; + opacity: 0; + visibility: hidden; + transform: translateY(6px); + transition: opacity 0.3s, transform 0.3s, visibility 0.3s; + z-index: 10; +} + +.aksrt-hover-show:hover .aksrt-hover-show__content { + opacity: 1; + visibility: visible; + transform: translateY(0); +} + +/* 关闭按钮旋转 */ +.aksrt-ic-close { + transition: transform 0.3s; + cursor: pointer; +} + +.aksrt-ic-close:hover { + transform: rotate(270deg); +} + +/* 图片悬停缩放(缩略图容器) */ +.aksrt-hover-zoom-img img { + transition: transform 0.3s ease; +} + +.aksrt-hover-zoom-img:hover img { + transform: scale(1.02); +} + +.aksrt-hover-zoom-img-sm img { + transition: transform 0.3s ease; +} + +.aksrt-hover-zoom-img-sm:hover img { + transform: scale(1.02); +} + +/* 按钮悬停上浮 */ +.aksrt-hover-lift { + transition: transform 0.2s ease, box-shadow 0.2s ease; +} + +.aksrt-hover-lift:hover { + transform: translateY(-2px); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); +} + +/* ============================================================ + * 4. 暗色模式过渡 (View Transitions API) + * ============================================================ */ +::view-transition-old(root), +::view-transition-new(root) { + animation: none; + mix-blend-mode: normal; +} + +.dark::view-transition-old(root), +body.dark-theme::view-transition-old(root) { + z-index: 1; +} + +.dark::view-transition-new(root), +body.dark-theme::view-transition-new(root) { + z-index: 2147483646; +} + +::view-transition-old(root) { + z-index: 2147483646; +} + +::view-transition-new(root) { + z-index: 1; +} + +/* backdrop-filter 不支持时的降级 */ +@supports not ((-webkit-backdrop-filter: blur(20px)) or (backdrop-filter: blur(20px))) { + :root { + --aksrt-blur-bg: #ffffff; + } + + .dark { + --aksrt-blur-bg: var(--surface-1); + } + + .aksrt-toast { + backdrop-filter: none; + -webkit-backdrop-filter: none; + } +} + +/* ============================================================ + * 5. 滚动方向感知 + * ============================================================ */ + +/* 向下滚动时隐藏导航栏 */ +body.aksrt-scroll-down .site-nav.nav-scroll-hide { + transform: translateY(-100%); + transition: transform 0.3s ease; +} + +body.aksrt-scroll-up .site-nav.nav-scroll-hide { + transform: translateY(0); + transition: transform 0.3s ease; +} + +/* 滚动时隐藏浮动按钮 */ +body.aksrt-scrolling .aksrt-floating-right.scrolling-hide { + opacity: 0; + pointer-events: none; + transition: opacity 0.2s; +} + +/* body-scroll 状态类 */ +body.aksrt-body-scroll .aksrt-show-on-scroll { + opacity: 1; + visibility: visible; +} + +.aksrt-show-on-scroll { + opacity: 0; + visibility: hidden; + transition: opacity 0.3s, visibility 0.3s; +} + +/* ============================================================ + * 6. 图片灯箱 + * ============================================================ */ +.aksrt-lightbox { + position: fixed; + inset: 0; + z-index: 9999; + background: rgba(0, 0, 0, 0.85); + display: flex; + align-items: center; + justify-content: center; + opacity: 0; + visibility: hidden; + transition: opacity 0.3s, visibility 0.3s; + cursor: zoom-out; +} + +.aksrt-lightbox.is-open { + opacity: 1; + visibility: visible; +} + +.aksrt-lightbox__img { + max-width: 90vw; + max-height: 85vh; + object-fit: contain; + border-radius: 4px; + transform: scale(0.9); + transition: transform 0.3s; + cursor: default; +} + +.aksrt-lightbox.is-open .aksrt-lightbox__img { + transform: scale(1); +} + +.aksrt-lightbox__close { + position: absolute; + top: 16px; + right: 16px; + width: 36px; + height: 36px; + border: none; + border-radius: 50%; + background: rgba(255, 255, 255, 0.15); + color: #fff; + font-size: 20px; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + transition: background 0.2s; +} + +.aksrt-lightbox__close:hover { + background: rgba(255, 255, 255, 0.3); +} + +.aksrt-lightbox__caption { + position: absolute; + bottom: 16px; + left: 50%; + transform: translateX(-50%); + color: rgba(255, 255, 255, 0.8); + font-size: 14px; + text-align: center; + max-width: 80%; +} + +.aksrt-lightbox__nav { + position: absolute; + top: 50%; + transform: translateY(-50%); + width: 48px; + height: 48px; + border: none; + border-radius: 50%; + background: rgba(255, 255, 255, 0.1); + color: #fff; + font-size: 24px; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + transition: background 0.2s; +} + +.aksrt-lightbox__nav:hover { + background: rgba(255, 255, 255, 0.25); +} + +.aksrt-lightbox__nav--prev { + left: 16px; +} + +.aksrt-lightbox__nav--next { + right: 16px; +} + +.aksrt-lightbox__counter { + position: absolute; + top: 16px; + left: 16px; + color: rgba(255, 255, 255, 0.7); + font-size: 14px; +} + +.aksrt-lightbox__download { + position: absolute; + top: 16px; + right: 64px; + width: 40px; + height: 40px; + border: none; + border-radius: 50%; + background: rgba(255, 255, 255, 0.15); + color: #fff; + font-size: 18px; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + transition: background 0.2s; +} + +.aksrt-lightbox__download:hover { + background: rgba(255, 255, 255, 0.3); +} + +/* 可缩放图片的光标 */ +.aksrt-cursor-zoom-in { + cursor: zoom-in; +} + diff --git a/assets/css/frontend/enhancements/modal-motion.css b/assets/css/frontend/enhancements/modal-motion.css new file mode 100644 index 00000000..05ee997a --- /dev/null +++ b/assets/css/frontend/enhancements/modal-motion.css @@ -0,0 +1,10 @@ +@import url("modal-motion/base.css"); +@import url("modal-motion/tabs.css"); +@import url("modal-motion/panels.css"); +@import url("modal-motion/form.css"); +@import url("modal-motion/divider.css"); +@import url("modal-motion/oauth.css"); +@import url("modal-motion/footer.css"); +@import url("modal-motion/dark-mode.css"); +@import url("modal-motion/responsive.css"); +@import url("modal-motion/dark-mode-2.css"); diff --git a/assets/css/frontend/enhancements/modal-motion/base.css b/assets/css/frontend/enhancements/modal-motion/base.css new file mode 100644 index 00000000..ab685916 --- /dev/null +++ b/assets/css/frontend/enhancements/modal-motion/base.css @@ -0,0 +1,95 @@ +/* ============================================================ + * 21. 弹窗登录/注册 + * ============================================================ */ +.aksrt-modal-auth { + position: fixed; + inset: 0; + z-index: 99999; + display: flex; + align-items: center; + justify-content: center; + opacity: 0; + visibility: hidden; + transition: opacity 0.3s, visibility 0.3s; +} + +.aksrt-modal-auth.is-open { + opacity: 1; + visibility: visible; +} + +.aksrt-modal-auth__overlay { + position: absolute; + inset: 0; + background: rgba(0, 0, 0, 0.5); + backdrop-filter: blur(4px); + -webkit-backdrop-filter: blur(4px); +} + +.aksrt-modal-auth__card { + position: relative; + background: var(--main-bg-color, #fff); + border-radius: var(--main-radius, 8px); + padding: 32px; + max-width: 400px; + width: 90%; + max-height: 90vh; + overflow-y: auto; + box-shadow: 0 0 10px var(--main-shadow, rgba(116, 116, 116, 0.08)); + z-index: 1; + transform: scale(0.9); + transition: transform 0.5s cubic-bezier(0.32, 0.85, 0.45, 1.18); +} + +.aksrt-modal-auth.is-open .aksrt-modal-auth__card { + transform: scale(1); +} + +.aksrt-modal-auth__close { + position: absolute; + top: 12px; + right: 12px; + width: 36px; + height: 36px; + border: none; + border-radius: 50%; + background: var(--surface-2, #F4F5F7); + color: var(--color-ink-3); + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + transition: background 0.2s; + font-size: 16px; +} + +.aksrt-modal-auth__close:hover { + background: var(--surface-3, #ECEEF1); +} + +.aksrt-modal-auth__header { + text-align: center; + margin-bottom: 24px; +} + +.aksrt-modal-auth__logo { + width: 56px; + height: 56px; + border-radius: var(--radius); + background: linear-gradient(135deg, var(--color-primary, var(--color-primary)), var(--color-primary-active, #5A85BD)); + color: #fff; + font-size: 22px; + font-weight: 700; + display: flex; + align-items: center; + justify-content: center; + margin: 0 auto 12px; +} + +.aksrt-modal-auth__title { + margin: 0; + font-size: 20px; + font-weight: 600; + color: var(--color-ink); +} + diff --git a/assets/css/frontend/enhancements/modal-motion/dark-mode-2.css b/assets/css/frontend/enhancements/modal-motion/dark-mode-2.css new file mode 100644 index 00000000..340d589e --- /dev/null +++ b/assets/css/frontend/enhancements/modal-motion/dark-mode-2.css @@ -0,0 +1,514 @@ +/* Dark mode */ +.theme-dark .aksrt-lang-switch__toggle, +html.dark .aksrt-lang-switch__toggle { + background: #2a2a3a; + border-color: rgba(255, 255, 255, 0.15); +} + +.theme-dark .aksrt-lang-switch__dropdown, +html.dark .aksrt-lang-switch__dropdown { + background: #2a2a3a; + border-color: rgba(255, 255, 255, 0.15); +} + +/* ============================================================ + * 响应式 + * ============================================================ */ +@media (max-width: 640px) { + .aksrt-toast-container { + right: 8px; + left: 8px; + max-width: none; + } + + .aksrt-lightbox__nav { + width: 36px; + height: 36px; + font-size: 18px; + } + + .single-cover-slider__img { + height: 240px; + } + + .single-cover-slider__title { + font-size: 18px; + } + + .reward-modal__card { + padding: 24px; + } + + .reward-modal__qr { + width: 160px; + height: 160px; + } + + .aksrt-cover-cards { + grid-template-columns: 1fr; + } + + .aksrt-cover-card { + min-height: 140px; + } +} + +/* ============================================================ + * 13. 无障碍:prefers-reduced-motion + * 用户系统设置"减少动画"时,禁用所有非必要动效 + * ============================================================ */ +@media (prefers-reduced-motion: reduce) { + *, + *::before, + *::after { + animation-duration: 0.01ms !important; + animation-iteration-count: 1 !important; + transition-duration: 0.01ms !important; + scroll-behavior: auto !important; + } + + .aksrt-skeleton { + animation: none !important; + } + + .aksrt-toast { + animation: none !important; + } + + [data-aksrt-animate] { + opacity: 1 !important; + transform: none !important; + } +} + +/* ============================================================ + * 14. 图片懒加载 blur-to-sharp 过渡 + * 模仿 zibll 的 lazy_blur 效果 + * ============================================================ */ +img.lazyload, +img.lazyloaded, +img[data-src] { + transition: filter 0.6s var(--ease), opacity 0.4s var(--ease); +} + +img.lazyload, +img[data-src] { + filter: blur(5px); + opacity: 0.7; +} + +img.lazyloaded { + filter: blur(0); + opacity: 1; +} + +/* 14b. aksrt-lazy 动画变体(按 lazyload_animation 配置切换) */ +@keyframes aksrt-lazy-blur { + from { filter: blur(8px); opacity: 0.6; } + to { filter: blur(0); opacity: 1; } +} +@keyframes aksrt-lazy-fade { + from { opacity: 0; } + to { opacity: 1; } +} +@keyframes aksrt-lazy-scale { + from { transform: scale(1.08); opacity: 0.8; } + to { transform: scale(1); opacity: 1; } +} + +img.aksrt-lazy { + transition: filter 0.5s var(--ease), opacity 0.5s var(--ease), transform 0.5s var(--ease); +} + +img.aksrt-loaded[data-lazy-animation="blur"] { + animation: aksrt-lazy-blur 0.6s ease both; +} +img.aksrt-loaded[data-lazy-animation="fade"] { + animation: aksrt-lazy-fade 0.6s ease both; +} +img.aksrt-loaded[data-lazy-animation="scale"] { + animation: aksrt-lazy-scale 0.5s ease both; +} + +/* ============================================================ + * 15. 错误反馈 shake 动画 + * 表单验证失败时的水平抖动效果 + * ============================================================ */ +@keyframes aksrtShake { + 0%, 100% { transform: translateX(0); } + 10%, 30%, 50%, 70%, 90% { transform: translateX(-4px); } + 20%, 40%, 60%, 80% { transform: translateX(4px); } +} + +.aksrt-shake { + animation: aksrtShake 0.4s ease-in-out; +} + +/* 应用于 Naive UI 表单验证 */ +.n-form-item--error .n-input, +.n-form-item--error .n-select, +.n-form-item--error .n-input-number { + animation: aksrtShake 0.3s ease-in-out; +} + +/* ============================================================ + * 16. FPS 加速模式:低端设备禁用 backdrop-filter + * 模仿 zibll 的 body.fps-accelerat 模式 + * ============================================================ */ +body.fps-accelerat .site-nav, +body.fps-accelerat .footer-tabbar, +body.fps-accelerat .float-right .float-btn, +body.fps-accelerat .aksrt-blur-bg { + backdrop-filter: none !important; + -webkit-backdrop-filter: none !important; +} + +/* 模态框内禁用 backdrop-filter 避免渲染冲突 */ +body.modal-open .site-nav, +body.dialog-open .site-nav { + backdrop-filter: none !important; + -webkit-backdrop-filter: none !important; +} + +/* ============================================================ + * 17. .blur-bg 通用工具类 + * 模仿 zibll 的 .blur-bg,可在任意元素上应用毛玻璃效果 + * ============================================================ */ +.aksrt-blur-bg { + background: var(--blur-bg); + backdrop-filter: saturate(5) blur(20px); + -webkit-backdrop-filter: saturate(5) blur(20px); +} + +/* ============================================================ + * 18. 滚动触发动画延迟支持 + * data-aksrt-delay 属性控制入场延迟 + * ============================================================ */ +[data-aksrt-animate][data-aksrt-delay="1"] { transition-delay: 0.1s; } +[data-aksrt-animate][data-aksrt-delay="2"] { transition-delay: 0.2s; } +[data-aksrt-animate][data-aksrt-delay="3"] { transition-delay: 0.3s; } +[data-aksrt-animate][data-aksrt-delay="4"] { transition-delay: 0.4s; } +[data-aksrt-animate][data-aksrt-delay="5"] { transition-delay: 0.5s; } + +/* ============================================================ + * 19. 全站动效节奏统一 + * 模仿 zibll 的统一 hover / slide / blur / drawer 语言 + * ============================================================ */ + +/* --- 全局过渡基线 --- */ +a, button, input, select, textarea { + transition: border-color var(--dur-fast) var(--ease), + box-shadow var(--dur-fast) var(--ease), + background-color var(--dur-fast) var(--ease), + color var(--dur-fast) var(--ease); +} + +/* --- 卡片 hover 统一 --- */ +.post-card, .widget, .aksrt-theme-box, .theme-box, +.comment-body, .friend-card, .special-card, +.resource-download-box, .resource-meta-box { + transition: box-shadow var(--dur) var(--ease), + border-color var(--dur) var(--ease), + transform var(--dur) var(--ease); +} + +.post-card:hover, .widget:hover, .friend-card:hover, .special-card:hover { + box-shadow: none; + transform: none; +} + +/* --- 按钮 hover 统一 --- */ +.btn-primary, .btn-outline, .btn-lg, .btn-sm, +.n-button, .aksrt-button { + transition: all var(--dur-fast) var(--ease); +} + +.btn-primary:hover, .n-button--primary-type:hover { + opacity: 0.85; +} + +.btn-primary:active, .n-button--primary-type:active { + opacity: 1; +} + +/* --- 输入框 focus 统一 --- */ +input:focus, textarea:focus, select:focus, +.n-input--focus, .n-select--focus { + box-shadow: var(--focus-ring); + transition: box-shadow var(--dur-fast) var(--ease); +} + +/* --- 抽屉/模态框动效统一 --- */ +.n-drawer, .n-modal, .n-dialog { + transition: all var(--dur) var(--ease-out); +} + +.n-drawer-mask, .n-modal-mask, .n-dialog-mask { + transition: opacity var(--dur) var(--ease); +} + +/* --- Tab 切换动效 --- */ +.n-tabs-tab, .nav-tab, .aksrt-tab { + transition: color var(--dur-fast) var(--ease), + border-color var(--dur-fast) var(--ease), + background-color var(--dur-fast) var(--ease); +} + +/* --- 下拉菜单动效 --- */ +.n-dropdown-menu, .aksrt-dropdown { + transition: opacity var(--dur-fast) var(--ease), + transform var(--dur-fast) var(--ease-out); + transform-origin: top; +} + +/* --- Toast 通知动效 --- */ +.aksrt-toast { + animation: aksrtToastIn 0.35s var(--ease-out) forwards; +} + +.aksrt-toast--out { + animation: aksrtToastOut 0.3s var(--ease) forwards; +} + +/* --- 骨架屏动效 --- */ +.aksrt-skeleton { + animation: aksrtSkeletonShimmer 1.5s infinite linear; + background: linear-gradient(90deg, var(--skeleton-base) 25%, var(--skeleton-shine) 50%, var(--skeleton-base) 75%); + background-size: 200% 100%; +} + +/* --- 页面切换动效 --- */ +.fade-slide-enter-active, +.fade-slide-leave-active { + transition: opacity var(--dur) var(--ease), + transform var(--dur) var(--ease); +} + +.fade-slide-enter-from { + opacity: 0; + transform: translateY(8px); +} + +.fade-slide-leave-to { + opacity: 0; + transform: translateY(-8px); +} + +/* --- 导航栏滚动动效 --- */ +.site-nav { + transition: transform var(--dur) var(--ease), + background-color var(--dur) var(--ease), + box-shadow var(--dur) var(--ease); +} + +.site-nav.aksrt-nav--hidden { + transform: translateY(-100%); +} + +/* --- 浮层弹出动效 --- */ +@keyframes aksrtPopIn { + 0% { opacity: 0; transform: scale(0.95) translateY(-4px); } + 100% { opacity: 1; transform: scale(1) translateY(0); } +} + +@keyframes aksrtPopOut { + 0% { opacity: 1; transform: scale(1) translateY(0); } + 100% { opacity: 0; transform: scale(0.95) translateY(-4px); } +} + +.aksrt-popover, .aksrt-tooltip, .aksrt-dropdown-panel { + animation: aksrtPopIn var(--dur-fast) var(--ease-out) forwards; +} + +/* --- 图片懒加载过渡 --- */ +img.lazyload, img.lazyloaded, img[data-src] { + transition: filter 0.6s var(--ease), opacity 0.4s var(--ease); +} + +img.lazyload, img[data-src] { + filter: blur(5px); + opacity: 0.7; +} + +img.lazyloaded { + filter: blur(0); + opacity: 1; +} + +/* --- 滚动进度条动效 --- */ +.reading-progress-bar { + transition: width 0.1s linear; +} + +/* --- 移动端抽屉动效 --- */ +@media (max-width: 767px) { + .n-drawer { + transition: transform var(--dur) var(--ease-out); + } + + .site-nav .n-drawer-body { + transition: transform var(--dur) var(--ease-out); + } +} + +/* --- 暗色模式切换动效 --- */ +html.dark { + transition: background-color 0.3s var(--ease), + color 0.3s var(--ease); +} + +html.dark * { + transition: background-color 0.3s var(--ease), + border-color 0.3s var(--ease), + color 0.3s var(--ease), + box-shadow 0.3s var(--ease); +} + +/* ============================================================ + * 18. 合作伙伴无缝滚动 (marquee) + * ============================================================ */ +.aksrt-marquee { + position: relative; + overflow: hidden; + width: 100%; +} + +.aksrt-marquee__inner { + display: flex; + gap: 24px; + white-space: nowrap; + will-change: transform; +} + +.aksrt-marquee__inner > * { + flex-shrink: 0; +} + +@media (prefers-reduced-motion: reduce) { + .aksrt-marquee__inner { + animation: none !important; + transform: none !important; + } +} + +/* ============================================================ + * 19. 视频剧集切换按钮 + * ============================================================ */ +.switch-video, +.switch-iframe { + display: inline-flex; + align-items: center; + gap: 4px; + padding: 6px 14px; + border: 1px solid var(--color-line, rgba(50, 50, 50, 0.1)); + border-radius: var(--radius, 8px); + background: var(--surface-1, #fff); + color: var(--color-ink-2, #4e5358); + font-size: 13px; + font-weight: 500; + cursor: pointer; + transition: all 0.15s ease; + text-decoration: none; +} + +.switch-video:hover, +.switch-iframe:hover { + border-color: var(--color-primary); + color: var(--color-primary); +} + +.switch-video.is-active, +.switch-iframe.is-active { + background: var(--color-primary); + border-color: var(--color-primary); + color: #fff; +} + +/* ============================================================ + * 20. 一言轮播组件 + * ============================================================ */ +.aksrt-yiyan { + padding: 16px; + text-align: center; +} + +.aksrt-yiyan__content { + min-height: 60px; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + gap: 8px; +} + +.aksrt-yiyan__icon { + font-size: 20px; + color: var(--color-primary); + opacity: 0.6; +} + +.aksrt-yiyan__text { + font-size: 14px; + line-height: 1.8; + color: var(--color-ink-2, #4e5358); + margin: 0; + transition: opacity 0.2s ease; + font-style: italic; +} + +.aksrt-yiyan__from { + font-size: 12px; + color: var(--color-ink-4, #999); + margin: 0; +} + +.aksrt-yiyan__dots { + display: flex; + align-items: center; + justify-content: center; + gap: 6px; + margin-top: 12px; +} + +.aksrt-yiyan__dot { + width: 6px; + height: 6px; + border-radius: 50%; + background: var(--color-line, rgba(50, 50, 50, 0.1)); + transition: background 0.2s; +} + +.aksrt-yiyan__dot.is-active { + background: var(--color-primary); + width: 16px; + border-radius: 3px; +} + +/* ============================================================ + * 底部弹出 Sheet — 对齐 zibll .modal.bottom + * ============================================================ */ +.aksrt-modal--bottom .aksrt-modal-auth__card, +.modal.bottom .modal-dialog { + position: fixed; + bottom: 0; + left: 0; + right: 0; + max-width: 100%; + width: 100%; + border-radius: var(--main-radius, 8px) var(--main-radius, 8px) 0 0; + transform: translateY(110%); + transition: transform 0.4s; + margin-bottom: 0; + padding-bottom: env(safe-area-inset-bottom); +} + +.aksrt-modal--bottom.is-open .aksrt-modal-auth__card, +.modal.bottom.in .modal-dialog { + transform: translateY(0); +} + +.aksrt-modal--bottom .aksrt-modal-auth__card, +.modal.bottom .modal-dialog .modal-content { + box-shadow: 0 -10px 50px rgba(0, 0, 0, 0.15); +} + diff --git a/assets/css/frontend/enhancements/modal-motion/dark-mode.css b/assets/css/frontend/enhancements/modal-motion/dark-mode.css new file mode 100644 index 00000000..8c2bcbf1 --- /dev/null +++ b/assets/css/frontend/enhancements/modal-motion/dark-mode.css @@ -0,0 +1,19 @@ +/* Dark mode */ +.theme-dark .aksrt-modal-auth__card, +html.dark .aksrt-modal-auth__card { + background: #1e1e2e; + border: 1px solid rgba(255, 255, 255, 0.1); +} + +.theme-dark .aksrt-modal-auth__field input, +html.dark .aksrt-modal-auth__field input { + background: #2a2a3a; + border-color: rgba(255, 255, 255, 0.15); + color: #e0e0e0; +} + +.theme-dark .aksrt-modal-auth__close, +html.dark .aksrt-modal-auth__close { + background: #2a2a3a; +} + diff --git a/assets/css/frontend/enhancements/modal-motion/divider.css b/assets/css/frontend/enhancements/modal-motion/divider.css new file mode 100644 index 00000000..447d1139 --- /dev/null +++ b/assets/css/frontend/enhancements/modal-motion/divider.css @@ -0,0 +1,18 @@ +/* Divider */ +.aksrt-modal-auth__divider { + display: flex; + align-items: center; + gap: 12px; + margin: 20px 0; + color: var(--color-ink-4, #8A8F98); + font-size: 12px; +} + +.aksrt-modal-auth__divider::before, +.aksrt-modal-auth__divider::after { + content: ''; + flex: 1; + height: 1px; + background: var(--color-line); +} + diff --git a/assets/css/frontend/enhancements/modal-motion/footer.css b/assets/css/frontend/enhancements/modal-motion/footer.css new file mode 100644 index 00000000..e9611509 --- /dev/null +++ b/assets/css/frontend/enhancements/modal-motion/footer.css @@ -0,0 +1,22 @@ +/* Footer */ +.aksrt-modal-auth__footer { + text-align: center; + margin-top: 20px; + font-size: 13px; + color: var(--color-ink-3); +} + +.aksrt-modal-auth__switch { + border: none; + background: none; + color: var(--color-primary, var(--color-primary)); + cursor: pointer; + font-size: 13px; + font-weight: 500; + padding: 0; +} + +.aksrt-modal-auth__switch:hover { + text-decoration: underline; +} + diff --git a/assets/css/frontend/enhancements/modal-motion/form.css b/assets/css/frontend/enhancements/modal-motion/form.css new file mode 100644 index 00000000..6205a298 --- /dev/null +++ b/assets/css/frontend/enhancements/modal-motion/form.css @@ -0,0 +1,120 @@ +/* Form */ +.aksrt-modal-auth__form { + display: flex; + flex-direction: column; + gap: 16px; +} + +.aksrt-modal-auth__error { + padding: 10px 14px; + border-radius: 8px; + background: rgba(239, 68, 68, 0.08); + color: var(--color-error, #EF4444); + font-size: 13px; + line-height: 1.5; +} + +.aksrt-modal-auth__error a { + color: var(--color-primary, var(--color-primary)); + text-decoration: underline; +} + +.aksrt-modal-auth__field label { + display: block; + font-size: 13px; + font-weight: 500; + color: var(--color-ink-2); + margin-bottom: 6px; +} + +.aksrt-modal-auth__field input { + width: 100%; + padding: 10px 14px; + border: 1px solid var(--color-line); + border-radius: 10px; + font-size: 14px; + color: var(--color-ink); + background: var(--surface-1, #fff); + transition: border-color 0.2s; + box-sizing: border-box; +} + +.aksrt-modal-auth__field input:focus { + outline: none; + border-color: var(--color-primary, var(--color-primary)); +} + +.aksrt-modal-auth__field input::placeholder { + color: var(--color-ink-4, #8A8F98); +} + +.aksrt-modal-auth__pass-wrap { + position: relative; +} + +.aksrt-modal-auth__pass-wrap input { + padding-right: 44px; +} + +.aksrt-modal-auth__pass-toggle { + position: absolute; + right: 8px; + top: 50%; + transform: translateY(-50%); + width: 32px; + height: 32px; + border: none; + background: none; + color: var(--color-ink-4, #8A8F98); + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + border-radius: 6px; +} + +.aksrt-modal-auth__pass-toggle:hover { + background: var(--surface-2, #F4F5F7); +} + +.aksrt-modal-auth__actions { + display: flex; + justify-content: flex-end; +} + +.aksrt-modal-auth__link { + font-size: 13px; + color: var(--color-primary, var(--color-primary)); + text-decoration: none; +} + +.aksrt-modal-auth__link:hover { + text-decoration: underline; +} + +.aksrt-modal-auth__submit { + width: 100%; + padding: 12px; + border: none; + border-radius: 10px; + background: var(--color-primary, var(--color-primary)); + color: #fff; + font-size: 15px; + font-weight: 600; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + gap: 8px; + transition: opacity 0.2s; +} + +.aksrt-modal-auth__submit:hover { + opacity: 0.85; +} + +.aksrt-modal-auth__submit:disabled { + opacity: 0.6; + cursor: not-allowed; +} + diff --git a/assets/css/frontend/enhancements/modal-motion/oauth.css b/assets/css/frontend/enhancements/modal-motion/oauth.css new file mode 100644 index 00000000..6234e3d7 --- /dev/null +++ b/assets/css/frontend/enhancements/modal-motion/oauth.css @@ -0,0 +1,27 @@ +/* OAuth */ +.aksrt-modal-auth__oauth { + display: flex; + justify-content: center; + gap: 12px; +} + +.aksrt-modal-auth__oauth-btn { + width: 44px; + height: 44px; + border: 1px solid var(--color-line); + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + color: var(--color-ink-2); + font-size: 18px; + text-decoration: none; + transition: all 0.2s; +} + +.aksrt-modal-auth__oauth-btn:hover { + border-color: var(--color-primary, var(--color-primary)); + color: var(--color-primary, var(--color-primary)); + background: var(--color-primary-soft, rgba(240, 68, 148, 0.1)); +} + diff --git a/assets/css/frontend/enhancements/modal-motion/panels.css b/assets/css/frontend/enhancements/modal-motion/panels.css new file mode 100644 index 00000000..1abd604b --- /dev/null +++ b/assets/css/frontend/enhancements/modal-motion/panels.css @@ -0,0 +1,9 @@ +/* Panels */ +.aksrt-modal-auth__panel { + display: none; +} + +.aksrt-modal-auth__panel.is-active { + display: block; +} + diff --git a/assets/css/frontend/enhancements/modal-motion/responsive.css b/assets/css/frontend/enhancements/modal-motion/responsive.css new file mode 100644 index 00000000..86cb6a46 --- /dev/null +++ b/assets/css/frontend/enhancements/modal-motion/responsive.css @@ -0,0 +1,139 @@ +/* Responsive */ +@media (max-width: 480px) { + .aksrt-modal-auth__card { + padding: 24px 20px; + border-radius: 12px; + } + + .aksrt-modal-auth__logo { + width: 48px; + height: 48px; + font-size: 18px; + } + + .aksrt-modal-auth__title { + font-size: 18px; + } +} + +/* ============================================================ + * 22. 语言切换器 + * ============================================================ */ +.aksrt-lang-switch { + position: relative; +} + +.aksrt-lang-switch__toggle { + display: flex; + align-items: center; + gap: 6px; + padding: 8px 12px; + border: 1px solid var(--color-line); + border-radius: var(--radius, 10px); + background: var(--surface-1, #fff); + color: var(--color-ink-2); + font-size: 13px; + cursor: pointer; + transition: border-color 0.2s; + width: 100%; +} + +.aksrt-lang-switch__toggle:hover { + border-color: var(--color-primary, var(--color-primary)); +} + +.aksrt-lang-switch__toggle img { + border-radius: 2px; +} + +.aksrt-lang-switch__dropdown { + position: absolute; + top: 100%; + left: 0; + right: 0; + margin: 4px 0 0; + padding: 4px; + list-style: none; + background: var(--surface-1, #fff); + border: 1px solid var(--color-line); + border-radius: var(--radius, 10px); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08); + z-index: 100; + opacity: 0; + visibility: hidden; + transform: translateY(4px); + transition: all 0.2s; +} + +.aksrt-lang-switch:hover .aksrt-lang-switch__dropdown, +.aksrt-lang-switch__toggle:focus + .aksrt-lang-switch__dropdown { + opacity: 1; + visibility: visible; + transform: translateY(0); +} + +.aksrt-lang-switch__item { + display: flex; + align-items: center; + gap: 8px; + padding: 8px 10px; + border-radius: 6px; + font-size: 13px; + color: var(--color-ink-2); + text-decoration: none; + transition: background 0.15s; +} + +.aksrt-lang-switch__item:hover { + background: var(--surface-2, #F4F5F7); +} + +.aksrt-lang-switch__item.is-active { + color: var(--color-primary, var(--color-primary)); + font-weight: 600; +} + +.aksrt-lang-switch__item img { + border-radius: 2px; +} + +/* 国旗模式 */ +.aksrt-lang-switch--flags { + display: flex; + flex-wrap: wrap; + gap: 8px; +} + +.aksrt-lang-switch__flag { + display: inline-flex; + align-items: center; + justify-content: center; + width: 32px; + height: 24px; + border: 2px solid transparent; + border-radius: 4px; + overflow: hidden; + transition: border-color 0.2s; + text-decoration: none; +} + +.aksrt-lang-switch__flag:hover { + border-color: var(--color-primary, var(--color-primary)); +} + +.aksrt-lang-switch__flag.is-active { + border-color: var(--color-primary, var(--color-primary)); +} + +.aksrt-lang-switch__flag img { + width: 100%; + height: 100%; + object-fit: cover; +} + +.aksrt-lang-switch__flag span { + font-size: 10px; + font-weight: 600; + color: var(--color-ink-3); +} + diff --git a/assets/css/frontend/enhancements/modal-motion/tabs.css b/assets/css/frontend/enhancements/modal-motion/tabs.css new file mode 100644 index 00000000..079a0b7a --- /dev/null +++ b/assets/css/frontend/enhancements/modal-motion/tabs.css @@ -0,0 +1,34 @@ +/* Tabs */ +.aksrt-modal-auth__tabs { + display: flex; + border-bottom: 1px solid var(--color-line); + margin-bottom: 20px; +} + +.aksrt-modal-auth__tab { + flex: 1; + padding: 10px; + border: none; + background: none; + font-size: 15px; + font-weight: 500; + color: var(--color-ink-3); + cursor: pointer; + position: relative; + transition: color 0.2s; +} + +.aksrt-modal-auth__tab.is-active { + color: var(--color-primary, var(--color-primary)); +} + +.aksrt-modal-auth__tab.is-active::after { + content: ''; + position: absolute; + bottom: -1px; + left: 0; + right: 0; + height: 2px; + background: var(--color-primary, var(--color-primary)); +} + diff --git a/assets/css/frontend/floating-buttons.css b/assets/css/frontend/floating-buttons.css new file mode 100644 index 00000000..7ddad783 --- /dev/null +++ b/assets/css/frontend/floating-buttons.css @@ -0,0 +1,350 @@ +/* ============================================================ + * Floating Buttons + * ============================================================ */ + +.float-right { + --float-btn-size: 42px; + --float-btn-spacing: 8px; + --float-btn-opacity: 1; + --float-btn-color: var(--color-ink-3); + --float-btn-bg: transparent; + --float-btn-active-color: var(--color-primary); + position: fixed; + right: 20px; + bottom: 96px; + z-index: 900; + display: flex; + flex-direction: column; + gap: var(--float-btn-spacing, 8px); + opacity: var(--float-btn-opacity, 1); + transition: transform var(--dur, 0.25s) var(--ease, ease), opacity var(--dur, 0.25s) var(--ease, ease); + padding-bottom: env(safe-area-inset-bottom, 0px); +} + +.float-right.no-shadow .float-btn { + box-shadow: none; +} + +.float-right.no-animation .float-btn { + transition: none; +} + +.float-right.no-animation .float-btn:hover { + transform: none; +} + +.float-right.position-center { + top: 50%; + bottom: auto; + transform: translateY(-50%); +} + +.float-right.square { + gap: 0; + overflow: hidden; + border-radius: var(--radius-lg, 8px); + box-shadow: var(--shadow-md, 0 10px 30px rgba(17, 24, 39, 0.12)); +} + +.float-right .float-btn { + width: var(--float-btn-size); + min-height: var(--float-btn-size); + display: inline-flex; + align-items: center; + justify-content: center; + position: relative; + color: var(--this-color, var(--float-btn-color)); + background: var(--this-bg, var(--float-btn-bg)); + border: 1px solid var(--color-line-soft, #f0f1f3); + text-decoration: none; + box-shadow: var(--shadow, 0 8px 24px rgba(17, 24, 39, 0.08)); + transition: transform var(--dur-fast, 0.15s) var(--ease, ease), box-shadow var(--dur-fast, 0.15s) var(--ease, ease), color var(--dur-fast, 0.15s) var(--ease, ease), background var(--dur-fast, 0.15s) var(--ease, ease); + cursor: pointer; + outline: none; + overflow: visible; +} + +.float-right.round .float-btn { + border-radius: 12px; +} + +.float-right.square .float-btn { + border-radius: 0; + box-shadow: none; + border-top-width: 0; +} + +.float-right.square .float-btn:first-child { + border-top-width: 1px; +} + +.float-right .float-btn:hover { + transform: translateY(-2px); + color: var(--float-btn-active-color, var(--color-primary)); + text-decoration: none; + box-shadow: var(--shadow-md, 0 10px 30px rgba(17, 24, 39, 0.12)); + z-index: 2; +} + +.float-right .float-btn:active { + transform: scale(0.96); +} + +.float-right .float-btn::after { + content: ""; + position: absolute; + inset: auto; + width: 6px; + height: 6px; + border-radius: 999px; + background: currentColor; + opacity: 0; + transform: scale(1); + pointer-events: none; +} + +.float-right .float-btn.is-rippling::after { + animation: float-btn-ripple 0.55s ease-out; +} + +.float-right .float-btn i { + font-size: 16px; + line-height: 1; +} + +.float-right .float-btn.ontop { + opacity: 0; + visibility: hidden; + pointer-events: none; +} + +.float-right .float-btn.ontop.is-visible { + opacity: 1; + visibility: visible; + pointer-events: auto; +} + +.float-right.has-blur-pc .float-btn { + backdrop-filter: saturate(1.5) blur(10px); + -webkit-backdrop-filter: saturate(1.5) blur(10px); +} + +.float-right .hover-show-con { + position: absolute; + display: block; + right: calc(100% + 12px); + top: 50%; + transform: translateY(-50%); + min-width: 180px; + max-width: 280px; + padding: 12px; + border-radius: var(--radius-lg, 8px); + background: var(--surface-1, #fff); + border: 1px solid var(--color-line); + box-shadow: var(--shadow-lg, 0 18px 40px rgba(17, 24, 39, 0.18)); + color: var(--color-ink-2); + opacity: 0; + visibility: hidden; + pointer-events: none; + transition: opacity var(--dur-fast, 0.15s) var(--ease, ease), transform var(--dur-fast, 0.15s) var(--ease, ease), visibility var(--dur-fast, 0.15s) var(--ease, ease); +} + +.float-right .hover-show-con::before { + content: ""; + position: absolute; + top: 50%; + right: -8px; + width: 16px; + height: 16px; + background: inherit; + border-top: 1px solid var(--color-line); + border-right: 1px solid var(--color-line); + transform: translateY(-50%) rotate(45deg); +} + +.float-right .hover-show-con img { + display: block; + width: 100%; + max-width: 160px; + height: auto; + margin: 0 auto 10px; + border-radius: var(--radius, 10px); +} + +.float-right .hover-show-con p { + margin: 0; + font-size: 13px; + line-height: 1.6; + color: var(--color-ink-3); +} + +.float-btn-qrcode { + display: flex; + align-items: center; + justify-content: center; + width: 100%; + min-height: 120px; + margin: 0 auto 10px; + background: #fff; + border-radius: var(--radius, 10px); +} + +.float-right .service-wechat .hover-show-con, +.float-right .service-qq .hover-show-con, +.float-right .qrcode-btn .hover-show-con { + padding: 14px; +} + +.float-right .service-wechat .hover-show-con img, +.float-right .service-qq .hover-show-con img { + margin: 0 auto; + box-shadow: 0 10px 24px rgba(17, 24, 39, 0.12); +} + +.float-right .service-wechat .hover-show-con p, +.float-right .service-qq .hover-show-con p { + display: none; +} + +.float-right .newadd-btns .hover-show-con { + min-width: 196px; + padding: 10px; +} + +.float-add-menu { + display: flex; + flex-direction: column; + gap: 6px; +} + +.float-add-menu__item { + display: flex; + align-items: center; + gap: 10px; + padding: 10px 12px; + border-radius: 10px; + color: var(--color-ink-2); + text-decoration: none; + transition: background var(--dur-fast, 0.15s) var(--ease, ease), color var(--dur-fast, 0.15s) var(--ease, ease), transform var(--dur-fast, 0.15s) var(--ease, ease); +} + +.float-add-menu__item i { + width: 18px; + text-align: center; + color: var(--color-primary, var(--color-primary)); +} + +.float-add-menu__item:hover { + background: var(--color-primary-soft, rgba(240, 68, 148, 0.1)); + color: var(--color-primary, var(--color-primary)); + transform: translateX(-2px); +} + +.float-btn-qrcode :deep(canvas), +.float-btn-qrcode :deep(img), +.float-btn-qrcode svg { + display: block; + margin: 0 auto; +} + +.float-right .float-btn:hover .hover-show-con, +.float-right .float-btn:focus-visible .hover-show-con { + opacity: 1; + visibility: visible; + pointer-events: auto; + transform: translateY(-50%) translateX(-4px); +} + +.float-right.scrolling-hide.is-hidden, +.float-right.scroll-down-hide.is-hidden { + transform: translateX(calc(100% + 24px)); +} + +.float-right.position-center.scrolling-hide.is-hidden, +.float-right.position-center.scroll-down-hide.is-hidden { + transform: translateX(calc(100% + 24px)) translateY(-50%); +} + +.float-right__html { + font-size: 13px; + line-height: 1.6; +} + +.float-right__html a { + color: var(--color-primary, var(--color-primary)); +} + +.float-right__html a:hover { + color: var(--color-primary-hover, #7099CC); +} + +@keyframes float-btn-ripple { + 0% { + opacity: 0.22; + transform: scale(1); + } + 100% { + opacity: 0; + transform: scale(14); + } +} + +.float-btn__icon-moon { + display: none; +} + +.float-btn__icon-sun { + display: inline-block; +} + +.theme-dark .float-btn__icon-moon, +html.dark .float-btn__icon-moon, +body.dark-theme .float-btn__icon-moon { + display: inline-block; +} + +.theme-dark .float-btn__icon-sun, +html.dark .float-btn__icon-sun, +body.dark-theme .float-btn__icon-sun { + display: none; +} + +.theme-dark .float-right, +html.dark .float-right, +body.dark-theme .float-right { + --float-btn-color: var(--color-ink-4); +} + +.theme-dark .float-right .hover-show-con, +html.dark .float-right .hover-show-con, +body.dark-theme .float-right .hover-show-con { + background: var(--surface-2, #1f2430); + border-color: rgba(255, 255, 255, 0.08); +} + +@media (max-width: 767px) { + .float-right { + right: 12px; + bottom: 84px; + --float-btn-size: 40px; + } + + .float-right.has-blur-mobile .float-btn { + backdrop-filter: saturate(1.5) blur(10px); + -webkit-backdrop-filter: saturate(1.5) blur(10px); + } + + .float-right .hover-show-con { + max-width: min(240px, calc(100vw - 84px)); + } + + .float-right .float-btn.hide-on-mobile { + display: none; + } +} + +@media (min-width: 768px) { + .float-right .float-btn.hide-on-pc { + display: none; + } +} diff --git a/assets/css/frontend/footer.css b/assets/css/frontend/footer.css new file mode 100644 index 00000000..f62048cd --- /dev/null +++ b/assets/css/frontend/footer.css @@ -0,0 +1,4 @@ +@import url("footer/part-1.css"); +@import url("footer/part-2.css"); +@import url("footer/part-3.css"); +@import url("footer/part-4.css"); diff --git a/assets/css/frontend/footer/part-1.css b/assets/css/frontend/footer/part-1.css new file mode 100644 index 00000000..0ebc8088 --- /dev/null +++ b/assets/css/frontend/footer/part-1.css @@ -0,0 +1,300 @@ +/* ============================================================ + * AKSRT Footer — v4.0 Zibll-Inspired + * + * 包含: + * - 页脚主体(Bootstrap Grid) + * - 浮动右侧按钮组 + * - 移动端底部 Tab 栏 + * ============================================================ */ + +/* ============================================================ + * 页脚主体 + * ============================================================ */ +:root { + --aksrt-footer-tabbar-height: 49px; +} + +.site-footer { + margin-top: auto; + background: var(--footer-bg, var(--surface-1)); + padding: 30px; +} + +.site-footer__inner { + max-width: var(--container); + margin: 0 auto; + padding: 0 16px; +} + +@media (min-width: 768px) { + .site-footer__inner { + padding: 0 24px; + } +} + +.site-footer__grid { + padding-bottom: 32px; +} + +.site-footer__brand { + margin-bottom: 24px; +} + +.site-footer__title { + font-size: 1rem; + font-weight: 700; + margin: 0 0 12px; + color: var(--color-ink); +} + +.site-footer__desc { + font-size: 14px; + color: var(--color-ink-4); + line-height: 1.6; + margin: 0 0 16px; + max-width: 360px; +} + +.site-footer__col { + margin-bottom: 24px; +} + +.site-footer__col ul { + list-style: none; + margin: 0; + padding: 0; +} + +.site-footer__col li { + margin-bottom: 8px; +} + +.site-footer__col a { + font-size: 14px; + color: var(--footer-color, var(--color-ink-3)); + transition: color 0.15s ease; +} + +.site-footer__col a:hover { + color: var(--focus-color, var(--color-primary)); +} + +/* 社交链接行 */ +.social-row { + display: flex; + flex-wrap: wrap; + gap: 8px; + margin-bottom: 16px; +} + +.social-row a { + display: inline-flex; + align-items: center; + justify-content: center; + width: 36px; + height: 36px; + border-radius: 50%; + background: var(--surface-3); + color: var(--color-ink-3); + transition: background 0.2s, color 0.2s, transform 0.2s; +} + +.social-row a:hover { + background: var(--color-primary); + color: #fff; + transform: translateY(-2px); +} + +.social-row .social-icon-link { + background: var(--surface-3); + color: var(--color-ink-3); +} + +.social-row .social-icon-link:hover { + background: var(--color-primary); + color: #fff; +} + +/* 友情链接 */ +.site-footer__friends { + margin-top: 16px; +} + +.site-footer__friends-title { + font-size: 0.8125rem; + font-weight: 600; + color: var(--color-ink-4); + margin: 0 0 8px; +} + +.site-footer__friends-list { + display: flex; + flex-wrap: wrap; + gap: 6px 12px; +} + +.site-footer__friends-list a { + font-size: 0.8125rem; + color: var(--color-ink-4); +} + +.site-footer__friends-list a:hover { + color: var(--color-primary); +} + +/* 底部栏 */ +.site-footer__bottom { + border-top: 1px solid var(--color-line); + padding: 20px 0; + text-align: center; +} + +.site-footer__filings { + display: flex; + justify-content: center; + gap: 16px; + margin-bottom: 8px; + flex-wrap: wrap; +} + +.site-footer__filings a { + font-size: 0.75rem; + color: var(--color-ink-4); +} + +.site-footer__filings a:hover { + color: var(--color-primary); +} + +.site-footer__copyright { + font-size: 12px; + color: var(--color-ink-4); + margin: 0; +} + +/* §2.3 三列结构化字段 */ + +/* 品牌 Logo */ +.site-footer__logo { + margin-bottom: 16px; +} +.site-footer__logo-img { + max-height: 48px; + width: auto; +} +.site-footer__logo-img--dark { + display: none; +} +[data-theme="dark"] .site-footer__logo-img--light { + display: none; +} +[data-theme="dark"] .site-footer__logo-img--dark { + display: inline-block; +} + +/* 标准联系项 */ +.site-footer__contact-std { + display: flex; + flex-wrap: wrap; + align-items: center; + gap: 10px; + margin: 12px 0; +} +.site-footer__contact-item { + display: inline-flex; + align-items: center; + justify-content: center; + width: 36px; + height: 36px; + border-radius: 50%; + background: var(--surface-2, rgba(0,0,0,.05)); + color: var(--color-ink-3, #888); + font-size: 16px; + position: relative; + cursor: pointer; + text-decoration: none; + transition: background .2s, color .2s; +} +.site-footer__contact-item:hover, +.site-footer__contact-item:focus { + background: var(--color-primary); + color: #fff; +} +.site-footer__contact-hover { + display: none; + position: absolute; + bottom: calc(100% + 10px); + left: 50%; + transform: translateX(-50%); + padding: 8px; + background: var(--surface-1, #fff); + border-radius: 8px; + box-shadow: 0 4px 16px rgba(0,0,0,.15); + z-index: 10; + white-space: nowrap; +} +.site-footer__contact-hover img { + width: 120px; + height: 120px; + object-fit: contain; + border-radius: 4px; +} +.site-footer__contact-item:hover .site-footer__contact-hover, +.site-footer__contact-item:focus .site-footer__contact-hover { + display: block; +} + +/* 自定义代码区域 */ +.site-footer__custom-code, +.site-footer__customize-code { + margin-top: 8px; + font-size: 0.85rem; + color: var(--color-ink-4, #999); +} + +/* 二维码图片组 */ +.site-footer__mini-qr { + display: flex; + justify-content: center; + gap: 24px; + padding: 20px 0; + border-top: 1px solid var(--color-line, #eee); +} +.site-footer__mini-qr-item { + text-align: center; +} +.site-footer__mini-qr-item img { + width: 80px; + height: 80px; + object-fit: contain; + border-radius: 6px; + border: 1px solid var(--color-line, #eee); +} +.site-footer__mini-qr-item span { + display: block; + margin-top: 6px; + font-size: 12px; + color: var(--color-ink-4, #999); +} + +/* 设备可见性工具类 */ +@media (max-width: 767px) { + .hide-on-mobile { display: none !important; } +} +@media (min-width: 768px) { + .hide-on-desktop { display: none !important; } +} + +/* ============================================================ + * 浮动右侧按钮组(模仿 zibll float-right) + * ============================================================ */ +/* 对齐 zibll: bottom 60px, z-index 1030 */ +.float-right-btns { + position: fixed; + right: 20px; + bottom: 60px; + z-index: 1030; + display: flex; + flex-direction: column; + gap: 8px; + transition: opacity 0.3s ease; diff --git a/assets/css/frontend/footer/part-2.css b/assets/css/frontend/footer/part-2.css new file mode 100644 index 00000000..97523579 --- /dev/null +++ b/assets/css/frontend/footer/part-2.css @@ -0,0 +1,300 @@ +} + +/* 对齐 zibll: 40px, 1.4em icon */ +.float-btn { + display: flex; + align-items: center; + justify-content: center; + width: 40px; + min-height: 40px; + border-radius: 50%; + border: none; + background: var(--float-btn-bg); + color: var(--color-ink-3); + box-shadow: var(--shadow-sm); + cursor: pointer; + transition: transform var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease); + font-size: 1.4em; + text-decoration: none; +} + +.float-btn:hover { + transform: translateY(-2px); + box-shadow: var(--shadow); + color: var(--color-primary); + background: var(--surface-page); + text-decoration: none; +} + +.float-btn:active { + transform: scale(0.95); +} + +/* 回到顶部按钮 — 滚动后显示 */ +.float-btn--top { + opacity: 0; + visibility: hidden; + transition: opacity 0.3s ease, visibility 0.3s ease, transform 0.2s ease; +} + +.float-btn--top.is-visible { + opacity: 1; + visibility: visible; + display: flex; +} + +/* 主题切换按钮 */ +#float-theme-toggle .float-btn__icon-moon { + display: none !important; +} + +#float-theme-toggle .float-btn__icon-sun { + display: inline-block !important; +} + +#float-theme-toggle[aria-pressed="true"] .float-btn__icon-moon, +.theme-dark #float-theme-toggle .float-btn__icon-moon, +html.dark #float-theme-toggle .float-btn__icon-moon, +body.dark-theme #float-theme-toggle .float-btn__icon-moon { + display: inline-block !important; +} + +#float-theme-toggle[aria-pressed="true"] .float-btn__icon-sun, +.theme-dark #float-theme-toggle .float-btn__icon-sun, +html.dark #float-theme-toggle .float-btn__icon-sun, +body.dark-theme #float-theme-toggle .float-btn__icon-sun { + display: none !important; +} + +/* 移动端隐藏浮动按钮(用 tabbar 代替) */ +@media (max-width: 767px) { + .float-right-btns { + right: 12px; + bottom: 80px; + } + + .float-btn { + width: 38px; + height: 38px; + font-size: 14px; + } +} + +/* ============================================================ + * 移动端底部 Tab 栏(模仿 zibll footer-tabbar) + * ============================================================ */ +.footer-tabbar { + display: none; + position: fixed; + bottom: 0; + left: 0; + right: 0; + z-index: 1035; + min-height: var(--aksrt-footer-tabbar-height); + background: var(--blur-bg); + border-top: 1px solid var(--color-line-soft); + padding: 0 0 env(safe-area-inset-bottom, 0px); + justify-content: space-around; + align-items: center; + box-shadow: 0 -4px 5px var(--main-shadow, rgba(0, 0, 0, 0.06)); + -webkit-backdrop-filter: saturate(5) blur(20px); + backdrop-filter: saturate(5) blur(20px); + --tabbar-active-color: #f04494; + --tabbar-icon-size: 24px; + --tabbar-text-size: 10px; +} + +.footer-tabbar.no-border { + border-top: none; +} + +.footer-tabbar.no-shadow { + box-shadow: none; +} + +.footer-tabbar.hide-text .tabbar-item span { + display: none; +} + +.footer-tabbar.has-animation .tabbar-item { + transition: color 0.15s ease, transform 0.15s ease; +} + +.footer-tabbar.has-animation .tabbar-item:active { + transform: scale(0.9); +} + +.footer-tabbar-placeholder { + display: none; + height: calc(var(--aksrt-footer-tabbar-height) + env(safe-area-inset-bottom, 0px)); +} + +@media (max-width: 767px) { + .footer-tabbar { + display: flex; + } + + .footer-tabbar-placeholder { + display: block; + } + + /* 有 tabbar 时页脚需要额外底部间距 */ + .site-footer { + padding-bottom: calc(var(--aksrt-footer-tabbar-height) + env(safe-area-inset-bottom, 0px)); + } +} + +.tabbar-item { + display: flex; + flex: 1 1 0; + min-width: 0; + flex-direction: column; + align-items: center; + justify-content: center; + gap: 1px; + min-height: 49px; + padding: 4px 0 3px; + color: var(--muted-color, var(--color-ink-3)); + font-size: 13px; + text-decoration: none; + border: none; + background: none; + cursor: pointer; + transition: color 0.15s ease; + -webkit-tap-highlight-color: transparent; + position: relative; +} + +/* 对齐 zibll: 24px 图标 */ +.tabbar-item i { + font-size: var(--tabbar-icon-size, 24px); + line-height: 1; +} + +.tabbar-item span { + display: block; + font-size: var(--tabbar-text-size, 10px); + font-weight: 500; + line-height: 1; + transform: scale(0.8); + transform-origin: center top; +} + +.tabbar-item:hover, +.tabbar-item.active { + color: var(--tabbar-active-color, var(--color-primary)); + text-decoration: none; +} + +.tabbar-item.active i { + font-weight: 900; +} + +.tabbar-badge { + position: absolute; + top: 2px; + right: 8px; + min-width: 16px; + height: 16px; + padding: 0 4px; + border-radius: 999px; + background: var(--color-error); + color: #fff; + font-size: 10px; + line-height: 16px; + font-style: normal; + font-weight: 700; + text-align: center; + box-shadow: 0 2px 8px rgba(239, 68, 68, 0.20); +} + +.tabbar-badge--dot { + min-width: 0; + width: 8px; + height: 8px; + padding: 0; + top: 4px; + right: 10px; + font-size: 0; + line-height: 1; + box-shadow: 0 0 0 2px var(--blur-bg); +} + +.tabbar-item--add { + margin-top: -22px; + width: 62px; + height: 62px; + min-height: 62px; + border-radius: 50%; + background: var(--color-accent); + color: #fff; + box-shadow: 0 12px 24px var(--color-accent-shadow); + flex: 0 0 62px; + z-index: 1; +} + +.tabbar-item--add i { + font-size: 22px; +} + +.tabbar-item--add span { + font-size: 11px; +} + +.tabbar-item--add:hover, +.tabbar-item--add.active { + color: #fff; +} + +.tabbar-add-backdrop { + position: fixed; + inset: 0; + z-index: 951; + background: rgba(15, 23, 42, 0.38); +} + +.tabbar-add-panel { + position: fixed; + left: 0; + right: 0; + bottom: 0; + z-index: 952; + padding: 0 12px calc(84px + env(safe-area-inset-bottom, 0px)); +} + +.tabbar-add-panel__sheet { + border-radius: 20px; + background: var(--surface-page); + box-shadow: 0 18px 50px rgba(15, 23, 42, 0.18); + overflow: hidden; +} + +.tabbar-add-panel__head { + display: flex; + align-items: center; + justify-content: space-between; + padding: 16px 18px 12px; + border-bottom: 1px solid var(--color-line); +} + +.tabbar-add-panel__close { + width: 32px; + height: 32px; + border: 0; + border-radius: 50%; + background: var(--surface-2); + color: var(--color-ink-3); +} + +.tabbar-add-panel__list { + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 12px; + padding: 18px; +} + +.tabbar-add-panel__item { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; diff --git a/assets/css/frontend/footer/part-3.css b/assets/css/frontend/footer/part-3.css new file mode 100644 index 00000000..d8d0ed4a --- /dev/null +++ b/assets/css/frontend/footer/part-3.css @@ -0,0 +1,300 @@ + gap: 8px; + min-height: 88px; + border-radius: 18px; + background: var(--surface-2); + color: var(--color-ink-3); + text-decoration: none; +} + +.tabbar-add-panel__item i { + font-size: 22px; + color: var(--color-accent); +} + +.tabbar-add-panel__item span { + font-size: 13px; + font-weight: 600; +} + +.tabbar-search-overlay { + position: fixed; + inset: 0; + z-index: 953; + background: rgba(15, 23, 42, 0.58); + display: flex; + align-items: stretch; + justify-content: center; +} + +.tabbar-search-overlay__dialog { + width: 100%; + min-height: 100%; + background: var(--surface-page); + padding: 18px 16px calc(24px + env(safe-area-inset-bottom, 0px)); +} + +.tabbar-search-overlay__head { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 16px; +} + +.tabbar-search-overlay__close { + width: 36px; + height: 36px; + border: 0; + border-radius: 50%; + background: var(--surface-2); + color: var(--color-ink-3); +} + +.tabbar-search-overlay__form { + display: grid; + grid-template-columns: 20px 1fr auto; + gap: 10px; + align-items: center; + padding: 14px 14px 14px 12px; + border-radius: 18px; + background: var(--surface-2); +} + +.tabbar-search-overlay__icon { + color: var(--color-ink-4); +} + +.tabbar-search-overlay__form input { + min-width: 0; + border: 0; + background: transparent; + color: var(--color-ink); + font-size: 15px; + outline: none; +} + +.tabbar-search-overlay__submit { + border: 0; + border-radius: 12px; + padding: 10px 14px; + background: var(--color-accent); + color: #fff; + font-weight: 700; +} + +.tabbar-search-overlay__types { + display: flex; + gap: 8px; + margin-top: 14px; +} + +.tabbar-search-overlay__type { + border: 0; + border-radius: 999px; + padding: 9px 14px; + background: var(--surface-2); + color: var(--color-ink-3); + font-size: 13px; + font-weight: 600; +} + +.tabbar-search-overlay__type.is-active { + background: var(--color-accent-soft); + color: var(--color-accent); +} + +.tabbar-search-overlay__section { + margin-top: 20px; +} + +.tabbar-search-overlay__section-head { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 12px; +} + +.tabbar-search-overlay__label { + color: var(--color-ink-3); + font-size: 13px; + font-weight: 700; +} + +.tabbar-search-overlay__clear { + border: 0; + background: transparent; + color: var(--color-accent); + font-size: 12px; + font-weight: 700; +} + +.tabbar-search-overlay__history, +.tabbar-search-overlay__suggestions { + display: flex; + flex-direction: column; + gap: 10px; +} + +.tabbar-search-overlay__history-item, +.tabbar-search-overlay__suggestion-item { + display: flex; + align-items: center; + justify-content: space-between; + gap: 12px; + width: 100%; + border: 0; + border-radius: 16px; + padding: 12px 14px; + background: var(--surface-2); + color: var(--color-ink-3); + text-decoration: none; + text-align: left; +} + +.tabbar-search-overlay__history-item i { + color: var(--color-accent); +} + +.tabbar-search-overlay__history-item span, +.tabbar-search-overlay__suggestion-item span { + flex: 1; + min-width: 0; + font-size: 14px; + font-weight: 600; +} + +.tabbar-search-overlay__suggestion-item small { + color: var(--color-ink-4); + font-size: 12px; +} + +.tabbar-search-overlay__empty { + padding: 14px; + border-radius: 16px; + background: var(--surface-2); + color: var(--color-ink-4); + font-size: 13px; + text-align: center; +} + +.tabbar-search-overlay__tags { + display: flex; + flex-wrap: wrap; + gap: 10px; +} + +.tabbar-search-overlay__tag { + padding: 10px 14px; + border-radius: 999px; + background: var(--surface-2); + color: var(--color-ink-3); + text-decoration: none; + font-size: 13px; +} + +body.tabbar-search-open, +body.tabbar-add-open { + overflow: hidden; +} + +/* 滚动时隐藏 tabbar(可选,通过 JS 添加 class) */ +.footer-tabbar.scrolling-hide { + transform: translateY(100%); + transition: transform 0.3s ease; +} + +/* 向下滚动隐藏,向上滚动显示 */ +.footer-tabbar.scroll-down-hide { + transition: transform 0.3s ease; +} + +.footer-tabbar.scroll-down-hide.is-hidden { + transform: translateY(120%); +} + +/* 返回顶部包裹项(首页按钮 + 返回顶部切换) */ +.tabbar-ontop-wrap { + position: relative; +} + +.tabbar-ontop-wrap .tabbar-ontop-btn { + display: none; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + flex-direction: column; + align-items: center; + justify-content: center; + gap: 2px; + padding: 4px 12px; + color: var(--color-primary); + font-size: 13px; + text-decoration: none; + cursor: pointer; + -webkit-tap-highlight-color: transparent; +} + +.tabbar-ontop-wrap .tabbar-ontop-btn i { + font-size: 18px; + line-height: 1; +} + +.tabbar-ontop-wrap .tabbar-ontop-btn span { + font-weight: 500; + line-height: 1; + transform: scale(0.8); + transform-origin: center top; +} + +.tabbar-ontop-wrap.is-scrolled .tabbar-ontop-btn { + display: flex; +} + +.tabbar-ontop-wrap.is-scrolled > .tabbar-item:not(.tabbar-ontop-btn) { + opacity: 0; + pointer-events: none; +} + +/* ============================================================ + * 暗色模式适配 + * ============================================================ */ +.theme-dark .site-footer, +html.dark .site-footer { + background: var(--surface-1); +} + +.theme-dark .float-btn, +html.dark .float-btn { + background: var(--float-btn-bg); + box-shadow: var(--shadow-sm); +} + +.theme-dark .footer-tabbar, +html.dark .footer-tabbar { + background: var(--blur-bg); + box-shadow: 0 -1px 3px rgba(0, 0, 0, 0.20); +} + +/* ============================================================ + * 旧版 back-to-top 按钮兼容(隐藏,用浮动按钮代替) + * ============================================================ */ +.back-to-top { + display: none !important; +} + +/* ============================================================ + * 页脚布局模板变体 + * ============================================================ */ + +/* 紧凑模板:单行版权 + 链接 */ +.site-footer--compact .site-footer__grid { + display: flex; + flex-wrap: wrap; + align-items: center; + gap: 16px; +} + +.site-footer--compact .site-footer__brand { + flex: 1 1 100%; +} diff --git a/assets/css/frontend/footer/part-4.css b/assets/css/frontend/footer/part-4.css new file mode 100644 index 00000000..a540d1c9 --- /dev/null +++ b/assets/css/frontend/footer/part-4.css @@ -0,0 +1,52 @@ + +.site-footer--compact .site-footer__brand .site-footer__desc, +.site-footer--compact .site-footer__brand .social-row, +.site-footer--compact .site-footer__brand .site-footer__friends { + display: none; +} + +.site-footer--compact .site-footer__col { + flex: 0 0 auto; +} + +.site-footer--compact .site-footer__col ul { + display: flex; + flex-wrap: wrap; + gap: 12px; + list-style: none; + padding: 0; + margin: 0; +} + +.site-footer--compact .site-footer__bottom { + border-top: 1px solid var(--color-line); + padding-top: 12px; + margin-top: 12px; +} + +/* 中央模板:居中品牌 + 链接 */ +.site-footer--centered .site-footer__grid { + text-align: center; +} + +.site-footer--centered .site-footer__brand { + flex: 1 1 100%; + display: flex; + flex-direction: column; + align-items: center; +} + +.site-footer--centered .site-footer__col { + flex: 1 1 auto; +} + +.site-footer--centered .site-footer__col ul { + list-style: none; + padding: 0; + margin: 0; + display: flex; + flex-wrap: wrap; + justify-content: center; + gap: 16px; +} + diff --git a/assets/css/frontend/forum.css b/assets/css/frontend/forum.css new file mode 100644 index 00000000..7f126d62 --- /dev/null +++ b/assets/css/frontend/forum.css @@ -0,0 +1,4 @@ +@import url("forum/board.css"); +@import url("forum/topic.css"); +@import url("forum/compose.css"); +@import url("forum/extras.css"); diff --git a/assets/css/frontend/forum/board.css b/assets/css/frontend/forum/board.css new file mode 100644 index 00000000..122ac577 --- /dev/null +++ b/assets/css/frontend/forum/board.css @@ -0,0 +1,402 @@ +/* ============================================================ + * Forum — 板块页、主题页、发帖页 + * ============================================================ */ + +/* Board page */ +.aksrt-forum-board { + padding-top: 24px; + padding-bottom: 48px; +} + +.aksrt-forum-board__header { + display: flex; + align-items: flex-start; + justify-content: space-between; + gap: 16px; + margin-bottom: 24px; + padding: 20px; + background: var(--surface-1, #fff); + border-radius: 12px; + box-shadow: 0 1px 4px rgba(0, 0, 0, 0.06); +} + +.aksrt-forum-board__title { + margin: 0 0 4px; + font-size: 22px; + font-weight: 700; + color: var(--color-ink); +} + +.aksrt-forum-board__desc { + margin: 0 0 8px; + font-size: 14px; + color: var(--color-ink-3, #8a909c); +} + +.aksrt-forum-board__meta { + display: flex; + gap: 16px; + font-size: 13px; + color: var(--color-ink-4, #8a909c); +} + +.aksrt-forum-board__meta i { + margin-right: 4px; +} + +.aksrt-forum-board__compose-btn { + display: inline-flex; + align-items: center; + gap: 6px; + padding: 8px 18px; + border-radius: 8px; + background: var(--color-primary); + color: #fff; + text-decoration: none; + font-size: 14px; + font-weight: 500; + white-space: nowrap; + transition: opacity 0.15s; +} + +.aksrt-forum-board__compose-btn:hover { + opacity: 0.85; +} + +.aksrt-forum-board__actions { + display: flex; + flex-wrap: wrap; + gap: 10px; + justify-content: flex-end; +} + +.aksrt-forum-board__manage-btn { + display: inline-flex; + align-items: center; + gap: 6px; + padding: 8px 16px; + border-radius: 8px; + border: 1px solid var(--color-line, #d9d9d9); + background: var(--surface-1, #fff); + color: var(--color-ink); + text-decoration: none; + cursor: pointer; + font-size: 13px; +} + +.aksrt-forum-board__manage-btn--danger { + border-color: var(--color-error, #f5222d); + color: var(--color-error, #f5222d); +} + +.aksrt-forum-board__manage-btn--danger:hover { + background: var(--color-error, #f5222d); + color: #fff; +} + +.aksrt-forum-board__governance { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); + gap: 16px; + margin-bottom: 20px; +} + +.aksrt-forum-board__governance-card { + padding: 18px; + background: var(--surface-1, #fff); + border-radius: 12px; + box-shadow: 0 1px 4px rgba(0, 0, 0, 0.06); +} + +.aksrt-forum-board__section-title { + margin: 0 0 10px; + font-size: 15px; + font-weight: 600; + color: var(--color-ink); +} + +.aksrt-forum-board__moderators { + display: flex; + flex-wrap: wrap; + gap: 10px; +} + +.aksrt-forum-board__moderator { + display: inline-flex; + align-items: center; + gap: 8px; + padding: 6px 10px; + border-radius: 999px; + background: var(--surface-1, #f8f9fa); +} + +.aksrt-forum-board__moderator img { + width: 36px; + height: 36px; + border-radius: 50%; +} + +.aksrt-forum-board__application-form textarea { + width: 100%; + border: 1px solid var(--color-line, #d9d9d9); + border-radius: 8px; + padding: 10px 12px; + resize: vertical; + font-family: inherit; +} + +.aksrt-forum-board__application-actions { + display: flex; + align-items: center; + gap: 10px; + margin-top: 10px; +} + +.aksrt-forum-board__apply-btn { + display: inline-flex; + align-items: center; + justify-content: center; + padding: 8px 14px; + border: none; + border-radius: 8px; + background: var(--color-primary); + color: #fff; + cursor: pointer; +} + +.aksrt-forum-board__application-note { + color: var(--color-ink-3, #8a909c); +} + +.aksrt-forum-board__application-reason { + margin: 10px 0; + padding: 10px 12px; + border-left: 3px solid var(--color-primary, #1890ff); + background: var(--surface-2, #f8fafc); + color: var(--color-ink-3, #64748b); + font-size: 13px; +} + +.aksrt-forum-board__governance-card .aksrt-forum-board__apply-btn { + text-decoration: none; +} + +/* Sticky section */ +.aksrt-forum-board__sticky { + margin-bottom: 16px; + padding: 12px 16px; + background: var(--surface-1, #fff); + border-radius: 8px; + border-left: 3px solid var(--color-primary); +} + +.aksrt-forum-board__sticky h3 { + margin: 0 0 8px; + font-size: 13px; + color: var(--color-ink-3, #8a909c); +} + +.aksrt-forum-board__sticky-item { + display: flex; + align-items: center; + justify-content: space-between; + padding: 6px 0; + text-decoration: none; + color: var(--color-ink); + font-size: 14px; +} + +.aksrt-forum-board__sticky-item:hover { + color: var(--color-primary); +} + +.aksrt-forum-board__sticky-meta { + font-size: 12px; + color: var(--color-ink-4, #c0c4cc); +} + +.aksrt-forum-board__sticky-badge { + display: inline-block; + padding: 1px 6px; + border-radius: 3px; + font-size: 11px; + font-weight: 500; + background: var(--color-primary); + color: #fff; + margin-right: 6px; + flex-shrink: 0; +} + +/* Topic list items */ +.aksrt-forum-board__topics { + display: flex; + flex-direction: column; + gap: 1px; +} + +.aksrt-forum-topic-item { + display: flex; + align-items: center; + gap: 12px; + padding: 14px 16px; + background: var(--surface-1, #fff); + transition: background 0.15s; +} + +.aksrt-forum-topic-item:first-child { + border-radius: 8px 8px 0 0; +} + +.aksrt-forum-topic-item:last-child { + border-radius: 0 0 8px 8px; +} + +.aksrt-forum-topic-item:hover { + background: var(--surface-1, #f8f9fa); +} + +.aksrt-forum-topic-item.is-sticky { + background: var(--surface-2, #f0f5ff); +} + +.aksrt-forum-topic-item.is-featured { + border-left: 3px solid var(--color-success, #52c41a); +} + +.aksrt-forum-topic-item__avatar img { + width: 40px; + height: 40px; + border-radius: 50%; +} + +.aksrt-forum-topic-item__body { + flex: 1; + min-width: 0; +} + +.aksrt-forum-topic-item__title { + font-size: 15px; + font-weight: 500; + display: flex; + align-items: center; + gap: 6px; +} + +.aksrt-forum-topic-item__title a { + color: var(--color-ink); + text-decoration: none; +} + +.aksrt-forum-topic-item__title a:hover { + color: var(--color-primary); +} + +.aksrt-forum-topic-item__badge { + display: inline-block; + padding: 1px 6px; + border-radius: 3px; + font-size: 11px; + font-weight: 500; +} + +.aksrt-forum-topic-item__badge--sticky { + background: var(--color-primary); + color: #fff; +} + +/* 置顶分级视觉区分(§7.3):超级置顶加深色,全局置顶用红色凸显。 */ +.aksrt-forum-topic-item__badge--sticky-super { + background: var(--focus-color, #fd53a1); + color: #fff; +} + +.aksrt-forum-topic-item__badge--sticky-global { + background: #e53e3e; + color: #fff; +} + +.aksrt-forum-topic-item__badge--featured { + background: var(--color-success, #52c41a); + color: #fff; +} + +.aksrt-forum-topic-item__badge--muted { + background: var(--surface-2, #f5f7fa); + color: var(--color-ink-3, #8a909c); +} + +.aksrt-forum-topic-item__lock { + color: var(--color-warning, #fa8c16); + font-size: 12px; +} + +.aksrt-forum-topic-item__meta { + display: flex; + gap: 12px; + margin-top: 3px; + font-size: 12px; + color: var(--color-ink-4, #8a909c); +} + +.aksrt-forum-topic-item__stats { + display: flex; + gap: 12px; + font-size: 12px; + color: var(--color-ink-4, #8a909c); +} + +.aksrt-forum-topic-item__stats i { + margin-right: 3px; +} + +.aksrt-forum-topic-item__actions { + display: flex; + flex-direction: column; + gap: 6px; +} + +.aksrt-forum-topic-item__action { + display: inline-flex; + align-items: center; + justify-content: center; + padding: 6px 10px; + border-radius: 999px; + border: 1px solid var(--color-line, #d9d9d9); + background: #fff; + color: var(--color-ink); + text-decoration: none; + cursor: pointer; + font-size: 12px; + white-space: nowrap; +} + +.aksrt-forum-topic-item__action--link { + background: var(--surface-1, #f8f9fa); +} + +/* Pagination */ +.aksrt-forum-board__pagination { + display: flex; + justify-content: center; + padding: 20px 0; +} + +/* Empty state */ +.aksrt-forum-board__empty { + text-align: center; + padding: 48px 24px; + color: var(--color-ink-4, #8a909c); +} + +.aksrt-forum-board__empty i { + font-size: 40px; + margin-bottom: 12px; + display: block; +} + +.aksrt-forum-board__empty a { + display: inline-block; + margin-top: 12px; + color: var(--color-primary); +} + diff --git a/assets/css/frontend/forum/compose.css b/assets/css/frontend/forum/compose.css new file mode 100644 index 00000000..e72686ab --- /dev/null +++ b/assets/css/frontend/forum/compose.css @@ -0,0 +1,709 @@ +/* ============================================================ + * Compose page + * ============================================================ */ + +.aksrt-forum-compose { + padding-top: 24px; + padding-bottom: 48px; + max-width: 1100px; + margin: 0 auto; +} + +.aksrt-forum-compose__header { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 20px; +} + +.aksrt-forum-compose__header h1 { + margin: 0; + font-size: 22px; +} + +.aksrt-forum-compose__notice { + margin: 8px 0 0; + color: var(--color-ink-3, #8a909c); +} + +.aksrt-forum-compose__back { + color: var(--color-ink-3, #8a909c); + text-decoration: none; + font-size: 14px; +} + +.aksrt-forum-compose__back:hover { + color: var(--color-primary); +} + +/* §7.4 — Two-column layout: main + sidebar */ +.aksrt-forum-compose__layout { + display: grid; + grid-template-columns: 1fr 311px; + gap: 24px; + align-items: start; +} + +.aksrt-forum-compose__main { + min-width: 0; +} + +.aksrt-forum-compose__sidebar { + display: flex; + flex-direction: column; + gap: 16px; +} + +/* §7.4 — Sidebar panels */ +.aksrt-forum-compose__panel { + background: var(--surface-1, #fff); + border: 1px solid var(--color-line, #eceff4); + border-radius: 10px; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.04); +} + +.aksrt-forum-compose__panel-title { + margin: 0; + padding: 12px 16px; + font-size: 14px; + font-weight: 600; + color: var(--color-ink); + border-bottom: 1px solid var(--color-line, #eceff4); + display: flex; + align-items: center; + gap: 6px; +} + +.aksrt-forum-compose__panel-title i { + color: var(--color-ink-3, #8a909c); + font-size: 13px; +} + +.aksrt-forum-compose__panel-body { + padding: 14px 16px; +} + +.aksrt-forum-compose__readonly { + margin: 0; + color: var(--color-ink-2, #555); + font-size: 14px; +} + +.aksrt-forum-compose__status-line { + margin: 0 0 12px; + font-size: 13px; + color: var(--color-ink-3, #8a909c); + display: flex; + align-items: center; + gap: 6px; +} + +.aksrt-forum-compose__form { + padding: 0; + background: transparent; + border-radius: 0; + box-shadow: none; +} + +.aksrt-forum-compose__main { + padding: 24px; + background: var(--surface-1, #fff); + border-radius: 12px; + box-shadow: 0 1px 4px rgba(0, 0, 0, 0.06); +} + +.aksrt-forum-compose__field { + margin-bottom: 16px; +} + +.aksrt-forum-compose__field:last-child { + margin-bottom: 0; +} + +.aksrt-forum-compose__field label { + display: block; + font-size: 14px; + font-weight: 500; + color: var(--color-ink); + margin-bottom: 6px; +} + +.aksrt-forum-compose__field .required { + color: var(--color-error, #f5222d); +} + +.aksrt-forum-compose__field select, +.aksrt-forum-compose__field input[type="text"], +.aksrt-forum-compose__field input[type="number"], +.aksrt-forum-compose__field input[type="url"] { + width: 100%; + border: 1px solid var(--color-line, #d9d9d9); + border-radius: 8px; + padding: 8px 12px; + font-size: 14px; + font-family: inherit; + box-sizing: border-box; +} + +.aksrt-forum-compose__field textarea { + width: 100%; + border: 1px solid var(--color-line, #d9d9d9); + border-radius: 8px; + padding: 10px 12px; + font-size: 14px; + resize: vertical; + font-family: inherit; + box-sizing: border-box; +} + +.aksrt-forum-compose__checkbox { + display: inline-flex; + align-items: center; + gap: 8px; + cursor: pointer; +} + +/* §7.4 — wp_editor wrapper */ +.aksrt-forum-compose__editor-wrap { + margin-bottom: 0; +} + +.aksrt-forum-compose__editor-wrap .wp-editor-wrap { + border-radius: 8px; + overflow: hidden; +} + +.aksrt-forum-compose__editor-wrap .wp-editor-container { + border: 1px solid var(--color-line, #d9d9d9); + border-radius: 8px; +} + +/* §7.4 — Character counter */ +.aksrt-forum-compose__char-counter { + display: block; + text-align: right; + font-size: 12px; + color: var(--color-ink-3, #8a909c); + margin-top: 4px; +} + +.aksrt-forum-compose__char-counter.is-near { + color: var(--color-warning, #d48806); +} + +.aksrt-forum-compose__char-counter.is-over { + color: var(--color-error, #cf1322); + font-weight: 600; +} + +/* §7.4 — Draft notice */ +.aksrt-forum-compose__draft-notice { + display: flex; + flex-wrap: wrap; + align-items: center; + gap: 8px; + margin-bottom: 20px; + padding: 12px 16px; + background: var(--color-info-bg, #e6f7ff); + border: 1px solid var(--color-info-border, #91d5ff); + border-radius: 8px; + font-size: 14px; + color: var(--color-info, #0050b3); +} + +.aksrt-forum-compose__draft-toggle { + border: none; + background: none; + color: var(--color-primary); + cursor: pointer; + font-size: 13px; + display: inline-flex; + align-items: center; + gap: 4px; + padding: 0; +} + +.aksrt-forum-compose__draft-list { + width: 100%; + margin-top: 8px; + display: flex; + flex-direction: column; + gap: 6px; +} + +.aksrt-forum-compose__draft-item { + display: flex; + align-items: center; + gap: 8px; + padding: 8px 12px; + background: var(--surface-1, #fff); + border-radius: 6px; + font-size: 13px; +} + +.aksrt-forum-compose__draft-title { + flex: 1; + color: var(--color-ink); + text-decoration: none; + font-weight: 500; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.aksrt-forum-compose__draft-title:hover { + color: var(--color-primary); +} + +.aksrt-forum-compose__draft-meta { + color: var(--color-ink-3, #8a909c); + font-size: 12px; + flex-shrink: 0; +} + +.aksrt-forum-compose__draft-delete { + border: none; + background: none; + color: var(--color-ink-3, #8a909c); + cursor: pointer; + padding: 2px; + font-size: 12px; +} + +.aksrt-forum-compose__draft-delete:hover { + color: var(--color-error, #cf1322); +} + +/* §7.4 — Remote search select */ +.aksrt-remote-select { + position: relative; +} + +.aksrt-remote-select__input { + width: 100%; +} + +.aksrt-remote-select__dropdown { + position: absolute; + top: 100%; + left: 0; + right: 0; + z-index: 100; + background: var(--surface-1, #fff); + border: 1px solid var(--color-line, #d9d9d9); + border-top: none; + border-radius: 0 0 8px 8px; + max-height: 200px; + overflow-y: auto; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); +} + +.aksrt-remote-select__option { + padding: 8px 12px; + cursor: pointer; + font-size: 14px; +} + +.aksrt-remote-select__option:hover { + background: var(--color-primary-bg, #e6f7ff); +} + +/* §7.4 — Tag tokenizer */ +.aksrt-tag-input { + position: relative; + display: flex; + flex-wrap: wrap; + align-items: center; + gap: 6px; + padding: 6px 8px; + border: 1px solid var(--color-line, #d9d9d9); + border-radius: 8px; + background: var(--surface-1, #fff); + min-height: 38px; +} + +.aksrt-tag-input__tokens { + display: flex; + flex-wrap: wrap; + gap: 4px; +} + +.aksrt-tag-input__token { + display: inline-flex; + align-items: center; + gap: 4px; + padding: 2px 8px; + background: var(--color-primary-bg, #e6f7ff); + color: var(--color-primary, #1890ff); + border-radius: 4px; + font-size: 13px; +} + +.aksrt-tag-input__token-remove { + border: none; + background: none; + color: var(--color-primary, #1890ff); + cursor: pointer; + padding: 0; + font-size: 14px; + line-height: 1; + opacity: 0.7; +} + +.aksrt-tag-input__token-remove:hover { + opacity: 1; +} + +.aksrt-tag-input__input { + flex: 1; + min-width: 80px; + border: none !important; + padding: 2px 4px !important; + font-size: 13px; + outline: none; + box-shadow: none !important; +} + +.aksrt-tag-input__dropdown { + position: absolute; + top: 100%; + left: 0; + right: 0; + z-index: 100; + background: var(--surface-1, #fff); + border: 1px solid var(--color-line, #d9d9d9); + border-top: none; + border-radius: 0 0 8px 8px; + max-height: 160px; + overflow-y: auto; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); +} + +.aksrt-tag-input__suggestion { + padding: 6px 12px; + cursor: pointer; + font-size: 13px; +} + +.aksrt-tag-input__suggestion:hover { + background: var(--color-primary-bg, #e6f7ff); +} + +.aksrt-forum-compose__vote-fields[hidden] { + display: none; +} + +.aksrt-forum-compose__vote { + margin-bottom: 20px; + padding: 18px; + border: 1px solid var(--color-line, #eceff4); + border-radius: 12px; + background: var(--surface-1, #f8f9fa); +} + +.aksrt-forum-compose__vote-head { + display: flex; + flex-direction: column; + gap: 8px; + margin-bottom: 12px; +} + +.aksrt-forum-compose__vote-head p { + margin: 0; + color: var(--color-ink-3, #8a909c); + font-size: 13px; +} + +.aksrt-forum-compose__feedback, +.aksrt-forum-board__application-feedback, +.aksrt-forum-topic__vote-feedback, +.aksrt-forum-topic__moderation-feedback { + font-size: 13px; + color: var(--color-ink-3, #8a909c); +} + +.aksrt-forum-compose__feedback.is-success, +.aksrt-forum-board__application-feedback.is-success, +.aksrt-forum-topic__vote-feedback.is-success, +.aksrt-forum-topic__moderation-feedback.is-success { + color: var(--color-success, #389e0d); +} + +.aksrt-forum-compose__feedback.is-error, +.aksrt-forum-board__application-feedback.is-error, +.aksrt-forum-topic__vote-feedback.is-error, +.aksrt-forum-topic__moderation-feedback.is-error { + color: var(--color-error, #cf1322); +} + +.aksrt-forum-compose__feedback.is-loading, +.aksrt-forum-board__application-feedback.is-loading, +.aksrt-forum-topic__vote-feedback.is-loading, +.aksrt-forum-topic__moderation-feedback.is-loading { + color: var(--color-primary); +} + +.aksrt-forum-compose__actions { + display: flex; + flex-wrap: wrap; + align-items: center; + gap: 12px; +} + +.aksrt-forum-compose__submit { + display: inline-flex; + align-items: center; + gap: 6px; + padding: 10px 24px; + border: none; + border-radius: 8px; + background: var(--color-primary); + color: #fff; + cursor: pointer; + font-size: 15px; + font-weight: 500; +} + +.aksrt-forum-compose__submit:hover { + opacity: 0.85; +} + +.aksrt-forum-compose__submit:disabled { + opacity: 0.5; + cursor: not-allowed; +} + +.aksrt-forum-compose__draft { + display: inline-flex; + align-items: center; + gap: 6px; + padding: 10px 24px; + border: 1px solid var(--color-line, #d9d9d9); + border-radius: 8px; + background: var(--surface-1, #fff); + color: var(--color-ink-3, #8a909c); + cursor: pointer; + font-size: 15px; +} + +.aksrt-forum-compose__draft:hover { + border-color: var(--color-primary); + color: var(--color-primary); +} + +/* ── topic cover (§7.3) ── */ + +.aksrt-forum-topic__cover { + margin-bottom: 20px; + border-radius: 12px; + overflow: hidden; + background: var(--surface-2, #f5f7fa); +} + +.aksrt-forum-topic__cover-img { + width: 100%; + display: block; + object-fit: cover; +} + +.aksrt-forum-topic__cover-slides { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 4px; +} + +.aksrt-forum-topic__cover-slides img { + width: 100%; + aspect-ratio: 1; + object-fit: cover; +} + +.aksrt-forum-topic__cover-player { + position: relative; + cursor: pointer; +} + +.aksrt-forum-topic__cover-poster { + width: 100%; + display: block; + object-fit: cover; +} + +.aksrt-forum-topic__cover-play-btn { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + border: none; + background: rgba(0, 0, 0, 0.5); + color: #fff; + font-size: 48px; + border-radius: 50%; + width: 72px; + height: 72px; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + transition: background 0.15s; +} + +.aksrt-forum-topic__cover-play-btn:hover { + background: rgba(0, 0, 0, 0.7); +} + +/* ── topic list cover thumbnails (§7.3) ── */ + +.aksrt-forum-topic-item__cover { + flex-shrink: 0; + width: 120px; + height: 80px; + border-radius: 8px; + overflow: hidden; + background: var(--surface-2, #f5f7fa); +} + +.aksrt-forum-topic-item__cover img { + width: 100%; + height: 100%; + object-fit: cover; + display: block; +} + +.aksrt-forum-topic-item__cover-video, +.aksrt-forum-topic-item__cover-slide { + position: relative; + width: 100%; + height: 100%; +} + +.aksrt-forum-topic-item__cover-video img, +.aksrt-forum-topic-item__cover-slide img { + width: 100%; + height: 100%; + object-fit: cover; + display: block; +} + +.aksrt-forum-topic-item__cover-video i { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + font-size: 24px; + color: #fff; + text-shadow: 0 1px 4px rgba(0, 0, 0, 0.5); +} + +.aksrt-forum-topic-item__cover-count { + position: absolute; + bottom: 4px; + right: 4px; + padding: 1px 6px; + border-radius: 3px; + background: rgba(0, 0, 0, 0.55); + color: #fff; + font-size: 11px; +} + +/* ── compose cover upload (§7.3) ── */ + +.aksrt-forum-compose__cover-upload { + margin-bottom: 20px; +} + +.aksrt-forum-compose__cover-preview { + display: flex; + flex-wrap: wrap; + gap: 8px; + margin-bottom: 10px; + min-height: 60px; +} + +.aksrt-forum-compose__cover-preview img { + width: 120px; + height: 80px; + object-fit: cover; + border-radius: 8px; + border: 1px solid var(--color-line, #d9d9d9); +} + +.aksrt-forum-compose__cover-btn { + display: inline-flex; + align-items: center; + gap: 6px; + padding: 8px 16px; + border: 1px dashed var(--color-line, #d9d9d9); + border-radius: 8px; + background: var(--surface-1, #fff); + color: var(--color-ink-3, #8a909c); + cursor: pointer; + font-size: 14px; + transition: border-color 0.15s, color 0.15s; +} + +.aksrt-forum-compose__cover-btn:hover { + border-color: var(--color-primary); + color: var(--color-primary); +} + +.aksrt-forum-compose__field input[type="url"] { + width: 100%; + border: 1px solid var(--color-line, #d9d9d9); + border-radius: 8px; + padding: 10px 12px; + font-size: 14px; + font-family: inherit; +} + +@media (max-width: 767px) { + .aksrt-forum-board__header, + .aksrt-forum-board__actions, + .aksrt-forum-topic__vote-head, + .aksrt-forum-topic__moderation-head, + .aksrt-forum-topic__vote-actions, + .aksrt-forum-topic__moderation-actions, + .aksrt-forum-compose__header, + .aksrt-forum-compose__actions { + flex-direction: column; + align-items: stretch; + } + + .aksrt-forum-topic-item { + flex-wrap: wrap; + } + + .aksrt-forum-topic-item__actions { + width: 100%; + flex-direction: row; + flex-wrap: wrap; + } + + .aksrt-forum-topic-item__cover { + width: 80px; + height: 56px; + } + + .aksrt-forum-topic__cover-slides { + grid-template-columns: repeat(2, 1fr); + } + + .aksrt-forum-topic__moderation-grid, + .aksrt-forum-compose__grid { + grid-template-columns: 1fr; + } + + /* §7.4 — Stack sidebar below main on mobile */ + .aksrt-forum-compose__layout { + grid-template-columns: 1fr; + } + + .aksrt-forum-compose__sidebar { + order: 2; + } + + .aksrt-forum-compose { + max-width: 100%; + } +} + diff --git a/assets/css/frontend/forum/extras.css b/assets/css/frontend/forum/extras.css new file mode 100644 index 00000000..527be719 --- /dev/null +++ b/assets/css/frontend/forum/extras.css @@ -0,0 +1,7 @@ +@import url("extras/base.css"); +@import url("extras/reply-header-tabs-filters.css"); +@import url("extras/load-more.css"); +@import url("extras/additional-role-badges.css"); +@import url("extras/like-button.css"); +@import url("extras/reply-action-buttons.css"); +@import url("extras/quick-post-bar.css"); diff --git a/assets/css/frontend/forum/extras/additional-role-badges.css b/assets/css/frontend/forum/extras/additional-role-badges.css new file mode 100644 index 00000000..f732d747 --- /dev/null +++ b/assets/css/frontend/forum/extras/additional-role-badges.css @@ -0,0 +1,52 @@ +/* --- additional role badges --- */ + +.aksrt-forum-reply__role-badge--author { + background: #fff7e6; + color: #d46b08; +} + +.aksrt-forum-reply__role-badge--super { + background: #f6ffed; + color: #389e0d; +} + +.aksrt-forum-reply__role-badge--catmod { + background: #fff0f6; + color: #c41d7f; +} + +/* --- hot comment (神评) badge --- */ + +.aksrt-forum-reply__badge { + display: inline-flex; + align-items: center; + gap: 3px; + padding: 1px 6px; + border-radius: var(--radius-pill, 999px); + font-size: 11px; + font-weight: 600; + line-height: 1.5; +} + +.aksrt-forum-reply__badge--hot { + background: #fff2e8; + color: #d4380d; +} + +.aksrt-forum-reply__badge--pinned { + background: #e6f7ff; + color: #096dd9; +} + +.aksrt-forum-reply.is-hot { + border-left: 3px solid #fa541c; +} + +.aksrt-forum-reply.is-pinned { + border-left: 3px solid #1890ff; +} + +.aksrt-forum-reply.is-pinned.is-hot { + border-left: 3px solid #fa541c; +} + diff --git a/assets/css/frontend/forum/extras/base.css b/assets/css/frontend/forum/extras/base.css new file mode 100644 index 00000000..5432556c --- /dev/null +++ b/assets/css/frontend/forum/extras/base.css @@ -0,0 +1,621 @@ +/* ============================================================ + * Forum tag archive page + * ============================================================ */ + +.aksrt-forum-tag { + padding-top: 24px; + padding-bottom: 48px; +} + +.aksrt-forum-tag__header { + margin-bottom: 24px; + padding: 20px; + background: var(--surface-1, #fff); + border-radius: 12px; + box-shadow: 0 1px 4px rgba(0, 0, 0, 0.06); +} + +.aksrt-forum-tag__title { + margin: 0 0 4px; + font-size: 22px; + font-weight: 700; + color: var(--color-ink); + display: flex; + align-items: center; + gap: 8px; +} + +.aksrt-forum-tag__title i { + color: var(--color-primary); +} + +.aksrt-forum-tag__desc { + margin: 0 0 8px; + font-size: 14px; + color: var(--color-ink-3, #8a909c); +} + +.aksrt-forum-tag__count { + margin: 0; + font-size: 13px; + color: var(--color-ink-4, #8a909c); +} + +.aksrt-forum-tag__list { + display: flex; + flex-direction: column; + gap: 1px; +} + +.aksrt-forum-topic-card { + display: flex; + padding: 16px; + background: var(--surface-1, #fff); + transition: background 0.15s; +} + +.aksrt-forum-topic-card:first-child { + border-radius: 8px 8px 0 0; +} + +.aksrt-forum-topic-card:last-child { + border-radius: 0 0 8px 8px; +} + +.aksrt-forum-topic-card:hover { + background: var(--surface-1, #f8f9fa); +} + +.aksrt-forum-topic-card__body { + flex: 1; + min-width: 0; +} + +.aksrt-forum-topic-card__title { + margin: 0 0 6px; + font-size: 16px; + font-weight: 500; +} + +.aksrt-forum-topic-card__title a { + color: var(--color-ink); + text-decoration: none; +} + +.aksrt-forum-topic-card__title a:hover { + color: var(--color-primary); +} + +.aksrt-forum-topic-card__excerpt { + margin: 0 0 8px; + font-size: 13px; + color: var(--color-ink-3, #8a909c); + line-height: 1.5; +} + +.aksrt-forum-topic-card__meta { + display: flex; + gap: 16px; + font-size: 12px; + color: var(--color-ink-4, #8a909c); +} + +.aksrt-forum-topic-card__meta i { + margin-right: 3px; +} + +.aksrt-forum-tag__pagination { + display: flex; + justify-content: center; + padding: 20px 0; +} + +.aksrt-forum-tag__empty { + text-align: center; + padding: 48px 24px; + color: var(--color-ink-4, #8a909c); +} + +.aksrt-forum-tag__empty i { + font-size: 40px; + margin-bottom: 12px; + display: block; +} + +/* ============================================================ + * Forum widgets + * ============================================================ */ + +.aksrt-forum-widget__list { + margin: 0; + padding: 0; + list-style: none; +} + +.aksrt-forum-widget__item { + display: flex; + align-items: center; + gap: 10px; + padding: 10px 0; + border-bottom: 1px solid var(--color-line-soft, #f0f1f3); +} + +.aksrt-forum-widget__item:last-child { + border-bottom: none; +} + +.aksrt-forum-widget__rank { + display: flex; + align-items: center; + justify-content: center; + width: 24px; + height: 24px; + border-radius: 6px; + background: var(--surface-2, #f4f5f7); + color: var(--color-ink-3, #8a909c); + font-size: 12px; + font-weight: 600; + flex-shrink: 0; +} + +.aksrt-forum-widget__item:nth-child(1) .aksrt-forum-widget__rank { + background: var(--color-error, #ef4444); + color: #fff; +} + +.aksrt-forum-widget__item:nth-child(2) .aksrt-forum-widget__rank { + background: var(--color-warning, #f59e0b); + color: #fff; +} + +.aksrt-forum-widget__item:nth-child(3) .aksrt-forum-widget__rank { + background: var(--color-info, #3b82f6); + color: #fff; +} + +.aksrt-forum-widget__link { + flex: 1; + min-width: 0; + color: var(--color-ink); + text-decoration: none; + font-size: 14px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.aksrt-forum-widget__link:hover { + color: var(--color-primary); +} + +.aksrt-forum-widget__views, +.aksrt-forum-widget__author { + font-size: 12px; + color: var(--color-ink-4, #8a909c); + white-space: nowrap; +} + +.aksrt-forum-widget__boards { + margin: 0; + padding: 0; + list-style: none; +} + +.aksrt-forum-widget__board { + padding: 8px 0; + border-bottom: 1px solid var(--color-line-soft, #f0f1f3); +} + +.aksrt-forum-widget__board:last-child { + border-bottom: none; +} + +.aksrt-forum-widget__board a { + display: flex; + align-items: center; + justify-content: space-between; + color: var(--color-ink); + text-decoration: none; + font-size: 14px; +} + +.aksrt-forum-widget__board a:hover { + color: var(--color-primary); +} + +.aksrt-forum-widget__board a i { + margin-right: 6px; + color: var(--color-primary); +} + +.aksrt-forum-widget__count { + display: inline-flex; + align-items: center; + justify-content: center; + min-width: 24px; + height: 20px; + padding: 0 6px; + background: var(--surface-2, #f4f5f7); + border-radius: var(--radius-pill, 999px); + color: var(--color-ink-3, #8a909c); + font-size: 11px; + font-weight: 600; +} + +.aksrt-forum-widget__empty { + text-align: center; + padding: 16px; + color: var(--color-ink-4, #8a909c); + font-size: 13px; +} + +/* ── bbs_type / question badges (§7.3) ── */ + +.aksrt-forum-topic__badge--question { + background: #e6f7ff; + color: #1890ff; +} + +.aksrt-forum-topic__badge--solved { + background: #f6ffed; + color: #52c41a; +} + +.aksrt-forum-topic-item__badge--question { + background: #e6f7ff; + color: #1890ff; +} + +.aksrt-forum-topic-item__badge--solved { + background: #f6ffed; + color: #52c41a; +} + +/* ── favorite button (§7.3) ── */ + +.js-aksrt-topic-favorite { + background: none; + border: none; + cursor: pointer; + transition: color .15s; +} + +.js-aksrt-topic-favorite[data-favorited="1"] { + color: var(--color-warning, #faad14); +} + +.js-aksrt-topic-favorite:disabled { + opacity: .5; + cursor: not-allowed; +} + +/* ── score actions (§7.3) ── */ + +.aksrt-forum-topic__score-actions { + display: flex; + align-items: center; + gap: 10px; + margin: 16px 0; + padding: 12px 16px; + background: var(--surface-1, #fff); + border: 1px solid var(--border-2, #e8e8e8); + border-radius: var(--radius-m, 8px); +} + +.aksrt-forum-topic__score-total { + font-size: 14px; + font-weight: 600; + color: var(--color-ink, #333); +} + +.aksrt-forum-topic__score-total i { + color: var(--color-warning, #faad14); + margin-right: 4px; +} + +.aksrt-forum-topic__score-btn { + display: inline-flex; + align-items: center; + justify-content: center; + width: 28px; + height: 28px; + border: 1px solid var(--border-2, #e0e0e0); + border-radius: var(--radius-s, 4px); + background: var(--surface-1, #fff); + cursor: pointer; + font-size: 12px; + transition: all .15s; +} + +.aksrt-forum-topic__score-btn:hover:not(:disabled) { + border-color: var(--color-primary, #1890ff); + color: var(--color-primary, #1890ff); +} + +.aksrt-forum-topic__score-btn--up:hover:not(:disabled) { + color: var(--color-success, #52c41a); + border-color: var(--color-success, #52c41a); +} + +.aksrt-forum-topic__score-btn--down:hover:not(:disabled) { + color: var(--color-error, #f5222d); + border-color: var(--color-error, #f5222d); +} + +.aksrt-forum-topic__score-btn:disabled { + opacity: .4; + cursor: not-allowed; +} + +.aksrt-forum-topic__score-badge { + color: var(--color-warning, #faad14); + font-weight: 600; +} + +.aksrt-forum-topic__score-feedback { + font-size: 13px; + color: var(--color-ink-4, #999); +} + +/* ── vote enhancements (§7.3) ── */ + +.aksrt-forum-topic__vote--pk .aksrt-forum-topic__vote-options { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 12px; +} + +.aksrt-forum-topic__vote--expired { + opacity: .7; +} + +.aksrt-forum-topic__vote-type-badge { + display: inline-block; + padding: 1px 6px; + background: var(--color-primary, #1890ff); + color: #fff; + border-radius: var(--radius-pill, 999px); + font-size: 11px; + font-weight: 700; + margin-left: 6px; +} + +.aksrt-forum-topic__vote-expired-badge { + display: inline-block; + padding: 1px 6px; + background: var(--color-error, #f5222d); + color: #fff; + border-radius: var(--radius-pill, 999px); + font-size: 11px; + font-weight: 600; + margin-left: 6px; +} + +.aksrt-forum-topic__vote-expiry-info { + color: var(--color-ink-4, #999); + font-size: 12px; + margin-left: 6px; +} + +/* ── topic_cat chip (§7.3) ── */ + +.aksrt-forum-topic__chip--topic-cat { + background: var(--color-primary-bg, #e6f7ff); + color: var(--color-primary, #1890ff); + font-weight: 600; +} + +/* ── report modal (§7.5) ── */ + +.aksrt-forum-topic__header-top { + display: flex; + flex-direction: column; + gap: 12px; +} + +.aksrt-forum-report-modal { + position: fixed; + inset: 0; + z-index: 9999; +} + +.aksrt-forum-report-modal__backdrop { + position: absolute; + inset: 0; + background: rgba(15, 23, 42, 0.55); +} + +.aksrt-forum-report-modal__dialog { + position: relative; + max-width: 520px; + margin: 8vh auto 0; + padding: 20px; + border-radius: 14px; + background: var(--surface-1, #fff); + box-shadow: 0 18px 60px rgba(15, 23, 42, 0.2); + z-index: 1; +} + +.aksrt-forum-report-modal__head { + display: flex; + align-items: center; + justify-content: space-between; + gap: 12px; + margin-bottom: 12px; +} + +.aksrt-forum-report-modal__head h2 { + margin: 0; + font-size: 18px; +} + +.aksrt-forum-report-modal__close { + border: none; + background: transparent; + font-size: 24px; + line-height: 1; + cursor: pointer; + color: var(--color-ink-3, #64748b); +} + +.aksrt-forum-report-modal__target { + margin: 0 0 14px; + color: var(--color-ink-3, #64748b); + font-size: 13px; +} + +.aksrt-forum-report-modal__actions { + display: flex; + align-items: center; + gap: 12px; +} + +.aksrt-forum-report-modal__feedback { + font-size: 13px; +} + +.is-report-modal-open { + overflow: hidden; +} + +.aksrt-forum-reply__report-btn { + display: inline-flex; + align-items: center; + gap: 4px; + border: none; + background: transparent; + color: var(--color-ink-4, #94a3b8); + cursor: pointer; + padding: 0; + font-size: 12px; +} + +.aksrt-forum-reply__report-btn:hover { + color: var(--color-error, #ef4444); +} + +/* ── moderation enhancements (§7.5) ── */ + +.aksrt-forum-topic__moderation-note { + margin-bottom: 16px; + padding: 12px 14px; + border-radius: 10px; + background: var(--surface-2, #f8fafc); + color: var(--color-ink-3, #64748b); + font-size: 13px; +} + +.aksrt-forum-topic__moderation-note strong { + color: var(--color-ink, #334155); + margin-right: 6px; +} + +.aksrt-forum-topic__field small { + display: block; + margin-top: 6px; + color: var(--color-ink-4, #94a3b8); + font-size: 12px; +} + +/* ── paywall / credits unlock (§7.3) ── */ + +.aksrt-forum-topic__pay-price { + display: inline-block; + margin-top: 12px; + padding: 6px 16px; + background: #fff7e6; + color: #d46b08; + border-radius: 8px; + font-size: 15px; + font-weight: 600; +} + +.aksrt-forum-topic__unlock-feedback { + display: block; + margin-top: 10px; + font-size: 13px; +} + +.aksrt-forum-compose__visibility-extra select[multiple] { + min-height: 90px; +} + +.aksrt-forum-compose__visibility-extra input[type="number"] { + width: 100%; + border: 1px solid var(--color-line, #d9d9d9); + border-radius: 8px; + padding: 10px 12px; + font-size: 14px; + font-family: inherit; +} + +/* ── adopted answer (§7.3) ── */ + +.aksrt-forum-reply.is-adopted { + border: 2px solid var(--color-success, #52c41a); + border-radius: var(--radius-m, 8px); + padding: 12px; + background: #f6ffed; +} + +.aksrt-forum-reply__adopted-badge { + display: inline-flex; + align-items: center; + gap: 4px; + padding: 2px 8px; + background: var(--color-success, #52c41a); + color: #fff; + border-radius: var(--radius-pill, 999px); + font-size: 11px; + font-weight: 600; +} + +.aksrt-forum-reply__adopt-btn { + display: inline-flex; + align-items: center; + gap: 4px; + padding: 4px 10px; + border: 1px solid var(--color-success, #52c41a); + border-radius: var(--radius-s, 4px); + background: transparent; + color: var(--color-success, #52c41a); + font-size: 12px; + cursor: pointer; + transition: all .15s; +} + +.aksrt-forum-reply__adopt-btn:hover:not(:disabled) { + background: var(--color-success, #52c41a); + color: #fff; +} + +.aksrt-forum-reply__adopt-btn:disabled, +.aksrt-forum-reply__adopt-btn.is-adopted { + opacity: .6; + cursor: not-allowed; +} + +/* ── moderator role badge (§7.5) ── */ + +.aksrt-forum-reply__role-badge { + display: inline-flex; + align-items: center; + padding: 1px 6px; + border-radius: var(--radius-pill, 999px); + font-size: 11px; + font-weight: 600; + line-height: 1.5; +} + +.aksrt-forum-reply__role-badge--admin { + background: #fff1f0; + color: #cf1322; +} + +.aksrt-forum-reply__role-badge--mod { + background: #e6f7ff; + color: #096dd9; +} + +/* ── §7.6 forum comment engine ── */ + diff --git a/assets/css/frontend/forum/extras/like-button.css b/assets/css/frontend/forum/extras/like-button.css new file mode 100644 index 00000000..7fd51987 --- /dev/null +++ b/assets/css/frontend/forum/extras/like-button.css @@ -0,0 +1,62 @@ +/* --- like button --- */ + +.aksrt-forum-reply__like-btn { + display: inline-flex; + align-items: center; + gap: 4px; + padding: 2px 8px; + border: none; + background: none; + color: var(--c-text-3, #999); + font-size: 13px; + cursor: pointer; + transition: color .2s; +} + +.aksrt-forum-reply__like-btn:hover { + color: var(--c-primary, #1890ff); +} + +.aksrt-forum-reply__like-btn.is-active { + color: var(--c-primary, #1890ff); +} + +.aksrt-forum-reply__like-count { + font-size: 12px; + min-width: 10px; +} + +/* --- nested reply (楼中楼) --- */ + +.aksrt-forum-reply--nested { + padding-left: 0; + margin-left: 0; +} + +.aksrt-forum-reply__children { + margin-top: 8px; + padding: 8px 0 0 12px; + border-left: 2px solid var(--c-border, #f0f0f0); +} + +.aksrt-forum-reply__children .aksrt-forum-reply { + padding: 8px 0; + margin-bottom: 0; + border-bottom: 1px solid var(--c-border-light, #f5f5f5); +} + +.aksrt-forum-reply__children .aksrt-forum-reply:last-child { + border-bottom: none; +} + +.aksrt-forum-reply__avatar--sm img { + width: 28px; + height: 28px; + border-radius: 50%; +} + +.aksrt-forum-reply__reply-to { + font-size: 12px; + color: var(--c-text-3, #999); +} + diff --git a/assets/css/frontend/forum/extras/load-more.css b/assets/css/frontend/forum/extras/load-more.css new file mode 100644 index 00000000..dd19e8e7 --- /dev/null +++ b/assets/css/frontend/forum/extras/load-more.css @@ -0,0 +1,23 @@ +/* --- load more --- */ + +.aksrt-forum-replies__load-more { + text-align: center; + padding: 16px 0; +} + +.aksrt-forum-replies__more-btn { + padding: 8px 24px; + border: 1px solid var(--c-border, #d9d9d9); + border-radius: var(--radius, 6px); + background: none; + color: var(--c-text-2, #666); + font-size: 14px; + cursor: pointer; + transition: all .2s; +} + +.aksrt-forum-replies__more-btn:hover { + border-color: var(--c-primary, #1890ff); + color: var(--c-primary, #1890ff); +} + diff --git a/assets/css/frontend/forum/extras/quick-post-bar.css b/assets/css/frontend/forum/extras/quick-post-bar.css new file mode 100644 index 00000000..5fddff0c --- /dev/null +++ b/assets/css/frontend/forum/extras/quick-post-bar.css @@ -0,0 +1,31 @@ +/* Quick post bar */ + +.aksrt-forum-quick-post { + margin-bottom: 16px; +} + +.aksrt-forum-quick-post__input { + display: flex; + align-items: center; + gap: 10px; + padding: 10px 16px; + border: 1px solid var(--c-border, #e8e8e8); + border-radius: var(--radius, 6px); + background: var(--c-fill-1, #fafafa); + color: var(--c-text-3, #999); + font-size: 14px; + text-decoration: none; + transition: border-color .2s, box-shadow .2s; +} + +.aksrt-forum-quick-post__input:hover { + border-color: var(--c-primary, #1890ff); + box-shadow: 0 0 0 2px rgba(24, 144, 255, .1); +} + +.aksrt-forum-quick-post__input img { + width: 32px; + height: 32px; + border-radius: 50%; +} + diff --git a/assets/css/frontend/forum/extras/reply-action-buttons.css b/assets/css/frontend/forum/extras/reply-action-buttons.css new file mode 100644 index 00000000..67678f9d --- /dev/null +++ b/assets/css/frontend/forum/extras/reply-action-buttons.css @@ -0,0 +1,239 @@ +/* --- reply action buttons --- */ + +.aksrt-forum-reply__reply-btn, +.aksrt-forum-reply__top-btn { + display: inline-flex; + align-items: center; + gap: 4px; + padding: 2px 8px; + border: none; + background: none; + color: var(--c-text-3, #999); + font-size: 13px; + cursor: pointer; + transition: color .2s; +} + +.aksrt-forum-reply__reply-btn:hover, +.aksrt-forum-reply__top-btn:hover { + color: var(--c-primary, #1890ff); +} + +/* ── §7.9 Forum user page tabs ── */ + +.uh-forum__subtabs { + display: flex; + gap: 4px; + margin-bottom: 16px; + padding-bottom: 12px; + border-bottom: 1px solid var(--c-border, #e8e8e8); +} + +.uh-forum__subtab { + display: inline-flex; + align-items: center; + gap: 4px; + padding: 6px 14px; + border-radius: var(--radius-pill, 999px); + font-size: 13px; + color: var(--c-text-3, #999); + text-decoration: none; + transition: all .2s; +} + +.uh-forum__subtab:hover { + color: var(--c-text-1, #333); + background: var(--c-fill-1, #f5f5f5); +} + +.uh-forum__subtab.is-active { + background: var(--c-primary, #1890ff); + color: #fff; +} + +.uh-forum__subtab-count { + font-size: 11px; + opacity: .7; +} + +.uh-forum__list { + display: flex; + flex-direction: column; +} + +.uh-forum__item { + padding: 12px 0; + border-bottom: 1px solid var(--c-border-light, #f5f5f5); +} + +.uh-forum__item:last-child { + border-bottom: none; +} + +.uh-forum__item-title { + display: block; + font-size: 15px; + font-weight: 500; + color: var(--c-text-1, #333); + text-decoration: none; + margin-bottom: 4px; +} + +.uh-forum__item-title:hover { + color: var(--c-primary, #1890ff); +} + +.uh-forum__item-meta { + display: flex; + gap: 12px; + font-size: 12px; + color: var(--c-text-3, #999); +} + +.uh-forum__item-meta i { + margin-right: 3px; +} + +.uh-forum__section-title { + font-size: 14px; + font-weight: 600; + color: var(--c-text-2, #666); + margin: 16px 0 10px; + padding-bottom: 6px; + border-bottom: 1px solid var(--c-border-light, #f5f5f5); +} + +.uh-forum__section-title i { + margin-right: 4px; + font-size: 13px; +} + +.uh-forum__plate-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); + gap: 10px; + margin-bottom: 16px; +} + +.uh-forum__plate-card { + display: block; + padding: 12px; + border: 1px solid var(--c-border, #e8e8e8); + border-radius: var(--radius, 6px); + text-decoration: none; + transition: border-color .2s, box-shadow .2s; +} + +.uh-forum__plate-card:hover { + border-color: var(--c-primary, #1890ff); + box-shadow: 0 2px 8px rgba(0, 0, 0, .06); +} + +.uh-forum__plate-name { + font-size: 14px; + font-weight: 600; + color: var(--c-text-1, #333); + margin-bottom: 6px; +} + +.uh-forum__plate-stats { + display: flex; + gap: 10px; + font-size: 12px; + color: var(--c-text-3, #999); +} + +.uh-forum__pagination { + margin-top: 16px; + text-align: center; +} + +/* ── §7.3 Hidden content block [aksrt_hide] ── */ + +.aksrt-forum-hide { + margin: 16px 0; +} + +.aksrt-forum-hide--locked { + padding: 16px; + border: 1px dashed var(--c-border, #d9d9d9); + border-radius: var(--radius, 6px); + background: var(--c-fill-1, #fafafa); + text-align: center; +} + +.aksrt-forum-hide__message { + font-size: 13px; + color: var(--c-text-3, #999); +} + +.aksrt-forum-hide__message i { + margin-right: 4px; + color: var(--c-warning, #faad14); +} + +.aksrt-forum-hide--revealed { + padding: 12px 16px; + border-left: 3px solid var(--c-success, #52c41a); + background: var(--c-fill-1, #f6ffed); + border-radius: 0 var(--radius, 6px) var(--radius, 6px) 0; +} + +/* ── §7.10 Forum home tab engine ── */ + +.aksrt-forum-home-tabs { + display: flex; + gap: 4px; + padding: 0 0 12px; + margin-bottom: 16px; + border-bottom: 1px solid var(--c-border, #e8e8e8); + overflow-x: auto; + -webkit-overflow-scrolling: touch; +} + +.aksrt-forum-home-tabs__btn { + display: inline-flex; + align-items: center; + gap: 4px; + padding: 6px 16px; + border: 1px solid var(--c-border, #d9d9d9); + border-radius: var(--radius-pill, 999px); + background: none; + color: var(--c-text-3, #999); + font-size: 14px; + font-weight: 500; + cursor: pointer; + white-space: nowrap; + transition: all .2s; +} + +.aksrt-forum-home-tabs__btn:hover { + color: var(--c-text-1, #333); + border-color: var(--c-primary, #1890ff); +} + +.aksrt-forum-home-tabs__btn.is-active { + background: var(--c-primary, #1890ff); + color: #fff; + border-color: var(--c-primary, #1890ff); +} + +.aksrt-forum-home-tabs__badge { + display: inline-block; + min-width: 18px; + height: 18px; + padding: 0 5px; + border-radius: 9px; + background: #ff4d4f; + color: #fff; + font-size: 11px; + font-weight: 700; + line-height: 18px; + text-align: center; +} + +.aksrt-forum-home__load-more { + text-align: center; + padding: 16px 0; +} + diff --git a/assets/css/frontend/forum/extras/reply-header-tabs-filters.css b/assets/css/frontend/forum/extras/reply-header-tabs-filters.css new file mode 100644 index 00000000..60655ed8 --- /dev/null +++ b/assets/css/frontend/forum/extras/reply-header-tabs-filters.css @@ -0,0 +1,69 @@ +/* --- reply header tabs & filters --- */ + +.aksrt-forum-replies__header { + display: flex; + align-items: center; + justify-content: space-between; + flex-wrap: wrap; + gap: 8px; + margin-bottom: 16px; + padding-bottom: 12px; + border-bottom: 1px solid var(--c-border, #e8e8e8); +} + +.aksrt-forum-replies__tabs { + display: flex; + align-items: center; + gap: 4px; +} + +.aksrt-forum-replies__tab { + padding: 4px 12px; + border: 1px solid var(--c-border, #d9d9d9); + border-radius: var(--radius-pill, 999px); + background: none; + color: var(--c-text-3, #999); + font-size: 13px; + cursor: pointer; + transition: all .2s; +} + +.aksrt-forum-replies__tab:hover { + color: var(--c-text-1, #333); + border-color: var(--c-primary, #1890ff); +} + +.aksrt-forum-replies__tab.is-active { + background: var(--c-primary, #1890ff); + color: #fff; + border-color: var(--c-primary, #1890ff); +} + +.aksrt-forum-replies__filter { + display: flex; + align-items: center; + gap: 4px; + font-size: 13px; + color: var(--c-text-3, #999); + cursor: pointer; + margin-left: 8px; +} + +.aksrt-forum-replies__filter input[type="checkbox"] { + width: 14px; + height: 14px; +} + +.aksrt-forum-replies__empty { + padding: 40px 0; + text-align: center; + color: var(--c-text-3, #bbb); + font-size: 14px; +} + +.aksrt-forum-replies__empty i { + font-size: 24px; + display: block; + margin-bottom: 8px; +} + diff --git a/assets/css/frontend/forum/topic.css b/assets/css/frontend/forum/topic.css new file mode 100644 index 00000000..e4ded01f --- /dev/null +++ b/assets/css/frontend/forum/topic.css @@ -0,0 +1,331 @@ +/* ============================================================ + * Topic detail page + * ============================================================ */ + +.aksrt-forum-topic { + padding-top: 24px; + padding-bottom: 48px; + max-width: 800px; + margin: 0 auto; +} + +.aksrt-forum-topic__breadcrumb { + font-size: 13px; + color: var(--color-ink-4, #8a909c); + margin-bottom: 16px; +} + +.aksrt-forum-topic__breadcrumb a { + color: var(--color-primary); + text-decoration: none; +} + +.aksrt-forum-topic__sep { + margin: 0 6px; +} + +.aksrt-forum-topic__header { + margin-bottom: 20px; +} + +.aksrt-forum-topic__title { + margin: 0 0 8px; + font-size: 22px; + font-weight: 700; + color: var(--color-ink); + display: flex; + align-items: center; + gap: 8px; + flex-wrap: wrap; +} + +.aksrt-forum-topic__badge { + display: inline-block; + padding: 2px 8px; + border-radius: 4px; + font-size: 12px; + font-weight: 500; +} + +.aksrt-forum-topic__badge--sticky { + background: var(--color-primary); + color: #fff; +} + +.aksrt-forum-topic__badge--sticky-super { + background: var(--focus-color, #fd53a1); + color: #fff; +} + +.aksrt-forum-topic__badge--sticky-global { + background: #e53e3e; + color: #fff; +} + +.aksrt-forum-topic__badge--featured { + background: var(--color-success, #52c41a); + color: #fff; +} + +.aksrt-forum-topic__badge--locked { + background: #fff7e6; + color: #d46b08; +} + +.aksrt-forum-topic__badge--visibility { + background: var(--surface-2, #f5f7fa); + color: var(--color-ink-3, #8a909c); +} + +.aksrt-forum-topic__meta { + display: flex; + flex-wrap: wrap; + gap: 16px; + font-size: 13px; + color: var(--color-ink-4, #8a909c); +} + +.aksrt-forum-topic__author { + display: flex; + align-items: center; + gap: 6px; +} + +.aksrt-forum-topic__author img { + border-radius: 50%; +} + +.aksrt-forum-topic__quick-actions { + display: flex; + flex-wrap: wrap; + gap: 10px; + margin-top: 14px; +} + +.aksrt-forum-topic__quick-action, +.aksrt-forum-topic__primary-btn { + display: inline-flex; + align-items: center; + gap: 8px; + padding: 9px 16px; + border: none; + border-radius: 999px; + background: var(--surface-1, #fff); + color: var(--color-ink); + text-decoration: none; + cursor: pointer; +} + +.aksrt-forum-topic__primary-btn { + background: var(--color-primary); + color: #fff; +} + +.aksrt-forum-topic__taxonomy { + display: flex; + flex-wrap: wrap; + gap: 8px; + margin-bottom: 20px; +} + +.aksrt-forum-topic__chip { + display: inline-flex; + align-items: center; + padding: 6px 10px; + border-radius: 999px; + background: var(--surface-2, #f5f7fa); + color: var(--color-ink-3, #8a909c); + text-decoration: none; + font-size: 13px; +} + +.aksrt-forum-topic__chip--special { + background: #fff1f0; + color: #cf1322; +} + +.aksrt-forum-topic__content { + padding: 20px; + background: var(--surface-1, #fff); + border-radius: 12px; + box-shadow: 0 1px 4px rgba(0, 0, 0, 0.06); + margin-bottom: 24px; + line-height: 1.8; + font-size: 15px; +} + +.aksrt-forum-topic__content img { + max-width: 100%; + border-radius: 8px; +} + +.aksrt-forum-topic__vote, +.aksrt-forum-topic__moderation { + margin-bottom: 24px; + padding: 20px; + background: var(--surface-1, #fff); + border-radius: 12px; + box-shadow: 0 1px 4px rgba(0, 0, 0, 0.06); +} + +.aksrt-forum-topic__vote-head, +.aksrt-forum-topic__moderation-head { + display: flex; + align-items: center; + justify-content: space-between; + gap: 12px; + margin-bottom: 16px; +} + +.aksrt-forum-topic__vote-head h2, +.aksrt-forum-topic__moderation-head h2 { + margin: 0; + font-size: 18px; +} + +.aksrt-forum-topic__vote-head span, +.aksrt-forum-topic__moderation-head p { + color: var(--color-ink-3, #8a909c); + font-size: 13px; +} + +.aksrt-forum-topic__vote-options { + display: grid; + gap: 10px; +} + +.aksrt-forum-topic__vote-option { + display: grid; + grid-template-columns: auto 1fr auto; + align-items: center; + gap: 10px; + padding: 12px 14px; + border-radius: 10px; + background: var(--surface-1, #f8f9fa); +} + +.aksrt-forum-topic__vote-option.is-selected { + outline: 1px solid var(--color-primary); +} + +.aksrt-forum-topic__vote-count { + font-size: 12px; + color: var(--color-ink-4, #8a909c); +} + +.aksrt-forum-topic__vote-actions, +.aksrt-forum-topic__moderation-actions { + display: flex; + align-items: center; + gap: 12px; + margin-top: 16px; +} + +.aksrt-forum-topic__moderation-grid, +.aksrt-forum-compose__grid { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 16px; +} + +.aksrt-forum-topic__field select, +.aksrt-forum-topic__field textarea, +.aksrt-forum-compose__field input[type="text"], +.aksrt-forum-compose__field textarea, +.aksrt-forum-compose__field select { + width: 100%; +} + +.aksrt-forum-topic__field label { + display: block; + margin-bottom: 6px; + font-size: 14px; + font-weight: 500; +} + +.aksrt-forum-topic__field select, +.aksrt-forum-topic__field textarea { + border: 1px solid var(--color-line, #d9d9d9); + border-radius: 8px; + padding: 10px 12px; + font-family: inherit; + font-size: 14px; +} + +.aksrt-forum-topic__denied { + padding: 56px 24px; + text-align: center; + background: var(--surface-1, #fff); + border-radius: 12px; +} + +.aksrt-forum-topic__denied i { + font-size: 42px; + margin-bottom: 14px; + color: var(--color-ink-4, #8a909c); +} + +.aksrt-forum-topic__replies { + margin-bottom: 24px; +} + +.aksrt-forum-topic__replies-title { + font-size: 16px; + font-weight: 600; + margin-bottom: 16px; + color: var(--color-ink); +} + +.aksrt-forum-topic__reply-form { + padding: 20px; + background: var(--surface-1, #fff); + border-radius: 12px; + box-shadow: 0 1px 4px rgba(0, 0, 0, 0.06); +} + +.aksrt-forum-topic__reply-form h2, +.aksrt-forum-topic__reply-form h3 { + margin: 0 0 12px; + font-size: 15px; + color: var(--color-ink); +} + +.aksrt-forum-topic__reply-field textarea { + width: 100%; + border: 1px solid var(--color-line, #d9d9d9); + border-radius: 8px; + padding: 12px; + font-size: 14px; + resize: vertical; + font-family: inherit; +} + +.aksrt-forum-topic__reply-btn { + display: inline-flex; + align-items: center; + gap: 6px; + padding: 8px 20px; + border: none; + border-radius: 8px; + background: var(--color-primary); + color: #fff; + cursor: pointer; + font-size: 14px; +} + +.aksrt-forum-topic__reply-btn:hover { + opacity: 0.85; +} + +.aksrt-forum-topic__locked-notice, +.aksrt-forum-topic__login-notice { + text-align: center; + padding: 20px; + color: var(--color-ink-3, #8a909c); + font-size: 14px; +} + +.aksrt-forum-topic__login-notice a { + color: var(--color-primary); +} + diff --git a/assets/css/frontend/header-components.css b/assets/css/frontend/header-components.css new file mode 100644 index 00000000..ad48dad3 --- /dev/null +++ b/assets/css/frontend/header-components.css @@ -0,0 +1,6 @@ +@import url("header-components/base.css"); +@import url("header-components/widget-device-visibility.css"); +@import url("header-components/admin-hint.css"); +@import url("header-components/dark-theme.css"); +@import url("header-components/card-device-visibility.css"); +@import url("header-components/search-keywords-row.css"); diff --git a/assets/css/frontend/header-components/admin-hint.css b/assets/css/frontend/header-components/admin-hint.css new file mode 100644 index 00000000..dc520795 --- /dev/null +++ b/assets/css/frontend/header-components/admin-hint.css @@ -0,0 +1,90 @@ +/* Admin hint */ +.header-components__admin-hint { + margin: 16px auto 0; + padding: 8px 14px; + border-radius: var(--radius-pill, 999px); + background: rgba(0, 0, 0, 0.32); + color: rgba(255, 255, 255, 0.95); + font: 500 13px/1.4 var(--font-ui); + display: inline-flex; + align-items: center; + gap: 8px; + flex-wrap: wrap; + justify-content: center; +} + +.header-components__admin-link { + color: #fff; + text-decoration: underline; + text-decoration-thickness: 1px; + text-underline-offset: 2px; + font-weight: 600; +} + +.header-components__admin-link:hover { + color: #ffe082; +} + +/* ============================================================ + * Layer 2: 搜索覆盖模块(在轮播内部 absolute 定位) + * ============================================================ */ +.header-components-search { + position: absolute; + bottom: 25%; + left: 50%; + transform: translateX(-50%); + z-index: 10; + width: 100%; + max-width: 600px; + padding: 0 16px; +} + +.header-components-search__form { + display: flex; + align-items: center; + background: rgba(255, 255, 255, 0.95); + border-radius: 50px; + padding: 4px 4px 4px 20px; + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15); + backdrop-filter: blur(10px); + transition: box-shadow 0.3s ease, transform 0.2s ease; +} + +.header-components-search__form:focus-within { + box-shadow: 0 6px 30px rgba(0, 0, 0, 0.2); + transform: translateY(-1px); +} + +.header-components-search__icon { + color: var(--color-ink-3, #999); + font-size: 16px; + margin-right: 12px; + flex-shrink: 0; +} + +.header-components-search__input { + flex: 1; + border: none !important; + background: transparent !important; + box-shadow: none !important; + font-size: 15px; + padding: 10px 0; + color: var(--color-ink); +} + +.header-components-search__input:focus { + outline: none; +} + +.header-components-search__input::placeholder { + color: var(--color-ink-4, #aaa); +} + +.header-components-search__btn { + border-radius: 50px; + padding: 10px 24px; + font-size: 14px; + font-weight: 500; + flex-shrink: 0; +} + diff --git a/assets/css/frontend/header-components/base.css b/assets/css/frontend/header-components/base.css new file mode 100644 index 00000000..36d09f1d --- /dev/null +++ b/assets/css/frontend/header-components/base.css @@ -0,0 +1,176 @@ +/* ============================================================ + * AKSRT Header Slider — v5.0 Zibll-Aligned + * + * 三层架构: + * - Layer 1: Swiper 全宽轮播背景 + * - Layer 2: 搜索覆盖模块 + * - Layer 3: 图标卡片网格覆盖 + * + * 对标 zibll 的 new-swiper 体系: + * - CSS 变量高度控制 (--pc-height / --m-height) + * - data-* 属性驱动配置 + * - 缩略图分页器、视差、懒加载 + * ============================================================ */ + +/* ============================================================ + * .new-swiper 基础样式(对标 zibll) + * ============================================================ */ +.aksrt-slider-wrapper { + position: relative; + margin-bottom: 20px; +} + +.new-swiper { + position: relative; + overflow: hidden; + --pc-height: auto; + --m-height: auto; +} + +.new-swiper .swiper-wrapper { + height: var(--pc-height); +} + +.new-swiper .swiper-slide { + position: relative; + overflow: hidden; +} + +.new-swiper .swiper-slide img { + width: 100%; + height: 100%; + object-fit: cover; +} + +/* 懒加载预加载器 */ +.new-swiper .swiper-lazy-preloader { + position: absolute; + top: 50%; + left: 50%; + width: 42px; + height: 42px; + margin: -21px 0 0 -21px; + border: 3px solid rgba(255,255,255,0.3); + border-top-color: #fff; + border-radius: 50%; + animation: aksrt-swiper-spin 0.8s linear infinite; +} + +@keyframes aksrt-swiper-spin { + from { transform: rotate(0deg); } + to { transform: rotate(360deg); } +} + +/* 懒加载图片 */ +.new-swiper .swiper-lazy { + opacity: 0; + transition: opacity 0.3s; +} + +.new-swiper .swiper-lazy.lazyloaded, +.new-swiper .swiper-slide-visible .swiper-lazy { + opacity: 1; +} + +/* 缩略图分页器 */ +.new-swiper .pagination-thumbnail-item { + width: 60px; + height: 40px; + border-radius: 4px; + overflow: hidden; + opacity: 0.5; + transition: opacity 0.3s, border-color 0.3s; + border: 2px solid transparent; + cursor: pointer; + display: inline-block; +} + +.new-swiper .pagination-thumbnail-item img { + width: 100%; + height: 100%; + object-fit: cover; +} + +.new-swiper .pagination-thumbnail-item-active { + opacity: 1; + border-color: #fff; +} + +/* 视差层 */ +.new-swiper [data-swiper-parallax] { + transition: none; +} + +/* 比例高度模式 */ +.new-swiper.scale-height .swiper-wrapper { + height: 0; + padding-bottom: var(--scale-ratio, 45%); +} + +/* 幻灯片文字覆盖层 */ +.aksrt-slide-text { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + z-index: 2; + width: calc(100% - 32px); + max-width: 920px; + text-align: center; + color: #fff; +} + +.aksrt-slide-text__title { + font-family: var(--font-display, var(--font-ui)); + font-size: clamp(1.75rem, 4vw, 3rem); + font-weight: 700; + margin: 0 0 12px; + line-height: 1.2; + text-shadow: 0 2px 8px rgba(0, 0, 0, 0.5); +} + +.aksrt-slide-text__desc { + font-size: clamp(0.9rem, 1.4vw, 1.125rem); + margin: 0; + line-height: 1.6; + color: rgba(255, 255, 255, 0.9); + text-shadow: 0 1px 4px rgba(0, 0, 0, 0.4); +} + +/* 移动端高度 */ +@media (max-width: 767px) { + .new-swiper .swiper-wrapper { + height: var(--m-height); + } +} + +/* ============================================================ + * Container — 三层叠加的父容器 + * ============================================================ */ +.header-components-container { + position: relative; + isolation: isolate; /* 创建独立堆叠上下文,内部 z-index 不外泄 */ + width: 100%; + margin-bottom: 20px; +} + +/* ============================================================ + * Device Visibility for Hero/Banner slides + * ============================================================ */ + +/* PC-only slides: hidden on mobile */ +@media (max-width: 767.98px) { + .hero-slide--pc-only, + .banner-slide--pc-only { + display: none !important; + } +} + +/* Mobile-only slides: hidden on PC */ +@media (min-width: 768px) { + .hero-slide--mobile-only, + .banner-slide--mobile-only { + display: none !important; + } +} + diff --git a/assets/css/frontend/header-components/card-device-visibility.css b/assets/css/frontend/header-components/card-device-visibility.css new file mode 100644 index 00000000..57955416 --- /dev/null +++ b/assets/css/frontend/header-components/card-device-visibility.css @@ -0,0 +1,169 @@ +/* ===== Card device visibility ===== */ +@media (min-width: 768px) { + .hide-cards-pc .header-components-card { display: none; } +} +@media (max-width: 767px) { + .hide-cards-mobile .header-components-card { display: none; } +} + +.theme-dark .header-components-search .line-form, +html.dark .header-components-search .line-form { + background: rgba(30, 30, 30, 0.86); + color: #ddd; +} + +.header-components-search .search-input-text { + position: relative; + padding: 3px 42px 3px 8px; +} + +.header-components-search .line-form-input { + width: 100%; + padding: 0.65em 0 0.2em 0; + font-size: 16px; + border: none !important; + outline: 0 !important; + background: transparent !important; + box-shadow: none !important; + opacity: 0.92; + color: var(--color-ink); +} + +.theme-dark .header-components-search .line-form-input, +html.dark .header-components-search .line-form-input { + color: #f2f2f2; +} + +.header-components-search .line-form-input::placeholder { + color: transparent; +} + +.header-components-search .line-form-line, +.header-components-search .line-form-line::before { + position: absolute; + left: 0; + bottom: 0; + width: 100%; + height: 1px; + transition: 0.4s; + background: rgba(255, 255, 255, 0.34); +} + +.header-components-search .line-form-line::before { + content: ""; + width: 0; + background: rgba(255, 255, 255, 0.92); +} + +.header-components-search .line-form-input:focus ~ .line-form-line::before, +.header-components-search .line-form-input:not(:placeholder-shown) ~ .line-form-line::before { + width: 100%; +} + +.header-components-search .scale-placeholder { + position: absolute; + left: 0; + bottom: 0.72em; + opacity: 0.68; + transition: transform 0.2s, font-size 0.2s, color 0.2s, opacity 0.2s; + pointer-events: none; + transform-origin: left top; +} + +.header-components-search .scale-placeholder.is-focus, +.header-components-search .line-form-input:focus ~ .scale-placeholder, +.header-components-search .line-form-input:not(:placeholder-shown) ~ .scale-placeholder { + transform: translateY(-1.45em); + font-size: 12px; + color: #fff; + opacity: 0.92; +} + +.header-components-search .line-form .abs-right { + position: absolute; + right: -6px; + top: 50%; + transform: translateY(-50%); + margin: 0; +} + +.header-components-search__submit { + width: 34px; + height: 34px; + border: none; + border-radius: 999px; + background: var(--color-primary, var(--color-primary)); + color: #fff; + display: inline-flex; + align-items: center; + justify-content: center; + cursor: pointer; +} + +.header-components-search__submit svg { + width: 15px; + height: 15px; +} + +/* Search add-ons: category dropdown */ +.header-components-search__cat { + appearance: none; + -webkit-appearance: none; + background: transparent; + border: none; + border-right: 1px solid rgba(255, 255, 255, 0.25); + color: inherit; + font-size: 13px; + padding: 0 12px; + min-width: 90px; + max-width: 140px; + cursor: pointer; + outline: none; + height: 40px; +} + +.header-components-search__cat option { + color: #333; + background: #fff; +} + +/* Search add-ons: type switcher */ +.header-components-search__types { + display: flex; + align-items: center; + gap: 4px; + padding: 0 8px; + border-right: 1px solid rgba(255, 255, 255, 0.25); +} + +.header-components-search__type-label { + display: inline-flex; + align-items: center; + cursor: pointer; + font-size: 12px; + padding: 3px 8px; + border-radius: 100px; + transition: background 0.2s, color 0.2s; + white-space: nowrap; +} + +.header-components-search__type-radio { + display: none; +} + +.header-components-search__type-radio:checked + .header-components-search__type-text { + color: var(--color-primary, #4a90d9); + font-weight: 600; +} + +/* has-addons: pill adjustments */ +.line-form.has-addons { + display: flex; + align-items: center; +} + +.line-form.has-addons .search-input-text { + flex: 1; + min-width: 0; +} + diff --git a/assets/css/frontend/header-components/dark-theme.css b/assets/css/frontend/header-components/dark-theme.css new file mode 100644 index 00000000..73a762a9 --- /dev/null +++ b/assets/css/frontend/header-components/dark-theme.css @@ -0,0 +1,377 @@ +/* Dark theme */ +.theme-dark .header-components-search__form, +html.dark .header-components-search__form, +body.dark-theme .header-components-search__form { + background: rgba(30, 30, 30, 0.9); +} + +.theme-dark .header-components-search__input, +html.dark .header-components-search__input, +body.dark-theme .header-components-search__input { + color: #eee; +} + +/* ============================================================ + * Layer 3: 图标卡片(模仿 zibll — 骑在 hero 底部边界线上) + * + * 关键技术:卡片在 DOM 中位于轮播之后, + * 使用 margin-top: -40px 向上拉,使其骑在 hero 底部边界线上 + * ============================================================ */ +.header-components-card { + position: relative; + z-index: 10; + margin-top: -40px; +} + +.header-components-card__container { + max-width: var(--container, 1280px); + margin: 0 auto; + padding: 0 16px; +} + +/* 卡片行:flex 水平排列 */ +.header-components-card__row { + display: flex; + gap: 10px; + padding-top: 4px; /* 为 hover 上浮留出空间 */ +} + +/* 每个卡片项等宽 */ +.header-components-card__item { + flex: 1; + min-width: 0; +} + +/* 共享背景模式:一个大卡片包裹 */ +.header-components-card__wrap--shared { + background: var(--surface-page); + border-radius: 8px; + padding: 10px; + box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08); + border: 1px solid var(--color-line); +} + +/* 独立背景模式:每个卡片有自己的背景 */ +.header-components-card__item-bg { + background: var(--surface-page); + border-radius: 8px; + padding: 12px 14px; + box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08); + border: 1px solid var(--color-line); + height: 100%; + transition: transform 0.2s ease, box-shadow 0.2s ease; +} + +.header-components-card__item-bg:hover { + transform: none; + box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08); +} + +/* 毛玻璃效果 */ +.filter-blur .header-components-card__wrap--shared, +.filter-blur .header-components-card__item-bg { + background: rgba(255, 255, 255, 0.75); + backdrop-filter: saturate(3) blur(20px); + -webkit-backdrop-filter: saturate(3) blur(20px); + border-color: rgba(255, 255, 255, 0.3); +} + +.theme-dark .filter-blur .header-components-card__wrap--shared, +html.dark .filter-blur .header-components-card__wrap--shared, +body.dark-theme .filter-blur .header-components-card__wrap--shared, +.theme-dark .filter-blur .header-components-card__item-bg, +html.dark .filter-blur .header-components-card__item-bg, +body.dark-theme .filter-blur .header-components-card__item-bg { + background: rgba(30, 30, 30, 0.75); + border-color: rgba(255, 255, 255, 0.1); +} + +/* ============================================================ + * 单个图标卡片样式(模仿 zibll icon-cover-card) + * 结构:左侧圆形图标 + 右侧标题/描述 + * ============================================================ */ +.icon-cover-card { + display: flex; + align-items: center; + gap: 10px; + padding: 8px; + border-radius: 6px; + text-decoration: none; + color: var(--color-ink); + transition: background 0.15s ease; +} + +a.icon-cover-card:hover { + background: var(--surface-3); + text-decoration: none; + color: var(--color-ink); +} + +/* 图标容器 — 圆形 */ +.icon-cover-icon { + display: inline-flex; + align-items: center; + justify-content: center; + width: 40px; + height: 40px; + min-width: 40px; + border-radius: 50%; + font-size: 18px; + flex-shrink: 0; +} + +/* 方形图标 */ +.icon-cover-icon.radius4 { + border-radius: 6px; +} + +/* 图标颜色类(模仿 zibll 的调色板) */ +.icon-cover-icon.c-blue { + background: rgba(66, 133, 244, 0.12); + color: #4285f4; +} +.icon-cover-icon.c-yellow { + background: rgba(251, 188, 4, 0.12); + color: #fbbc04; +} +.icon-cover-icon.c-green { + background: rgba(52, 168, 83, 0.12); + color: #34a853; +} +.icon-cover-icon.c-red { + background: rgba(234, 67, 53, 0.12); + color: #ea4335; +} +.icon-cover-icon.c-orange { + background: rgba(255, 152, 0, 0.12); + color: #ff9800; +} +.icon-cover-icon.c-cyan { + background: rgba(0, 188, 212, 0.12); + color: #00bcd4; +} +.icon-cover-icon.c-pink { + background: rgba(233, 30, 99, 0.12); + color: #e91e63; +} + +/* 渐变图标背景 */ +.icon-cover-icon.jb-cyan { + background: linear-gradient(135deg, #4facfe, #00f2fe); + color: #fff; +} +.icon-cover-icon.jb-green { + background: linear-gradient(135deg, #43e97b, #38f9d7); + color: #fff; +} +.icon-cover-icon.jb-orange { + background: linear-gradient(135deg, #fa709a, #fee140); + color: #fff; +} + +/* 文字区 */ +.icon-cover-desc { + flex: 1; + min-width: 0; + overflow: hidden; +} + +.icon-cover-title { + font-size: 13px; + font-weight: 600; + line-height: 1.3; + color: var(--color-ink); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.icon-cover-subtitle { + font-size: 11px; + color: var(--color-ink-4); + margin-top: 2px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + line-height: 1.3; +} + +/* ============================================================ + * 响应式 + * ============================================================ */ +@media (max-width: 767px) { + .header-components-card { + margin-top: -35px; + } + + .header-components-card__row { + flex-wrap: wrap; + gap: 6px; + } + + /* 移动端 2 列 */ + .header-components-card__item { + flex: 0 0 calc(50% - 3px); + } + + .header-components-card__item-bg { + padding: 10px; + } + + .header-components-card__wrap--shared { + padding: 6px; + } + + .icon-cover-card { + gap: 6px; + padding: 6px; + } + + .icon-cover-icon { + width: 32px; + height: 32px; + min-width: 32px; + font-size: 14px; + } + + .icon-cover-title { + font-size: 12px; + } + + .icon-cover-subtitle { + display: none; + } +} + +@media (max-width: 480px) { + .icon-cover-card { + gap: 4px; + padding: 2px; + } + + .icon-cover-icon { + width: 28px; + height: 28px; + min-width: 28px; + font-size: 12px; + } +} + +/* ============================================================ + * Nav 透明模式(轮播可见时 nav 变透明) + * ============================================================ */ + +/* ============================================================ + * Zibll-aligned text/search structure overrides + * ============================================================ */ +.header-components__content.slide-text { + width: calc(100% - 32px); + max-width: 920px; + top: 42%; + z-index: 12; + padding-top: 0; +} + +.header-components__content.slide-text .slide-title { + font-size: clamp(1.75rem, 4vw, 3rem); + line-height: 1.2; + margin: 0 0 12px; +} + +.header-components__content.slide-text .slide-desc { + max-width: 680px; + margin: 0 auto; + font-size: clamp(0.9rem, 1.4vw, 1.125rem); + line-height: 1.6; + color: rgba(255, 255, 255, 0.9); +} + +.header-components-search { + top: calc(50% + 56px); + bottom: auto; + max-width: 680px; + padding: 0 20px; + font-size: 16px; +} + +.card-0 .header-components-search { + top: calc(50% + 76px); +} + +.header-components-search .search-input { + max-width: 620px; + margin: 0 auto; +} + +.header-components-search .search-form { + margin: 0; + display: block; + background: transparent; + border-radius: 0; + padding: 0; + box-shadow: none; + -webkit-backdrop-filter: none; + backdrop-filter: none; + transform: none; +} + +.header-components-search .search-form:focus-within { + box-shadow: none; + transform: none; +} + +.header-components-search .line-form { + position: relative; + border-radius: 100px; + padding: 0.35em 1em; + background: rgba(255, 255, 255, 0.82); + color: #555; + box-shadow: 0 8px 24px rgba(0, 0, 0, 0.16); + -webkit-backdrop-filter: saturate(5) blur(20px); + backdrop-filter: saturate(5) blur(20px); +} + +.filter-blur .header-components-search .line-form { + background: rgba(255, 255, 255, 0.75); +} + +/* ===== Container-level blur: PC/Mobile split ===== */ +@media (min-width: 768px) { + .has-blur-pc .header-components-card__wrap--shared, + .has-blur-pc .header-components-card__item-bg { + background: rgba(255, 255, 255, 0.75); + backdrop-filter: saturate(3) blur(20px); + -webkit-backdrop-filter: saturate(3) blur(20px); + border-color: rgba(255, 255, 255, 0.3); + } + .has-blur-pc .header-components-search .line-form { + background: rgba(255, 255, 255, 0.75); + } + .theme-dark .has-blur-pc .header-components-card__wrap--shared, + html.dark .has-blur-pc .header-components-card__wrap--shared, + .theme-dark .has-blur-pc .header-components-card__item-bg, + html.dark .has-blur-pc .header-components-card__item-bg { + background: rgba(30, 30, 30, 0.75); + border-color: rgba(255, 255, 255, 0.1); + } +} +@media (max-width: 767px) { + .has-blur-mobile .header-components-card__wrap--shared, + .has-blur-mobile .header-components-card__item-bg { + background: rgba(255, 255, 255, 0.75); + backdrop-filter: saturate(3) blur(20px); + -webkit-backdrop-filter: saturate(3) blur(20px); + border-color: rgba(255, 255, 255, 0.3); + } + .has-blur-mobile .header-components-search .line-form { + background: rgba(255, 255, 255, 0.75); + } + .theme-dark .has-blur-mobile .header-components-card__wrap--shared, + html.dark .has-blur-mobile .header-components-card__wrap--shared, + .theme-dark .has-blur-mobile .header-components-card__item-bg, + html.dark .has-blur-mobile .header-components-card__item-bg { + background: rgba(30, 30, 30, 0.75); + border-color: rgba(255, 255, 255, 0.1); + } +} + diff --git a/assets/css/frontend/header-components/search-keywords-row.css b/assets/css/frontend/header-components/search-keywords-row.css new file mode 100644 index 00000000..b3097e68 --- /dev/null +++ b/assets/css/frontend/header-components/search-keywords-row.css @@ -0,0 +1,455 @@ +/* Search keywords row */ +.header-components-search__keywords { + display: flex; + flex-wrap: wrap; + gap: 6px; + margin-top: 10px; + justify-content: center; +} + +.header-components-search__kw-tag { + display: inline-block; + padding: 3px 10px; + font-size: 12px; + line-height: 1.4; + border-radius: 100px; + background: rgba(255, 255, 255, 0.2); + backdrop-filter: blur(6px); + color: inherit; + text-decoration: none; + transition: background 0.2s; +} + +.header-components-search__kw-tag:hover { + background: rgba(255, 255, 255, 0.4); +} + +@media (max-width: 991px) { + .header-components { + height: var(--pc-height); + } + + .header-components-search { + top: calc(50% + 44px); + max-width: 560px; + } +} + +@media (max-width: 767px) { + .header-components { + height: var(--m-height); + } + + .header-components__content.slide-text { + width: calc(100% - 28px); + max-width: 480px; + top: 40%; + padding-top: 0; + } + + .header-components__content.slide-text .slide-title { + font-size: clamp(1.25rem, 5vw, 1.75rem); + margin-bottom: 10px; + } + + .header-components__content[style*="--hero-text-size-m"] .slide-title { + font-size: var(--hero-text-size-m); + } + + .header-components__content.slide-text .slide-desc { + font-size: 0.875rem; + line-height: 1.5; + } + + .header-components-search { + top: calc(50% + 20px); + width: calc(100% - 24px); + max-width: 420px; + padding: 0 12px; + font-size: 12px; + } + + .card-1 .header-components-search, + .card-2 .header-components-search { + top: calc(50% + 46px); + } + + .card-5 .header-components-search, + .card-6 .header-components-search { + top: calc(50% - 22px); + } + + .card-7 .header-components-search, + .card-8 .header-components-search { + top: calc(50% - 52px); + } + + .header-components-search .line-form { + font-size: 14px; + padding: 4px 12px; + } + + .header-components-search .scale-placeholder.is-focus, + .header-components-search .line-form-input:focus ~ .scale-placeholder { + transform: translateY(-32px); + font-size: 12px; + color: #fff; + } + + .header-components-card { + margin-top: -35px; + } + + .header-components-card__container { + padding: 0 10px; + } + + .header-components-card__row { + flex-wrap: wrap; + gap: 6px; + } + + .header-components-card__item { + flex: 0 0 calc(50% - 3px); + } + + .header-components-card__item-bg { + padding: 8px 10px; + } + + .header-components-card__wrap--shared { + padding: 6px; + } + + .icon-cover-card { + gap: 6px; + padding: 4px; + min-height: 52px; + border-radius: 6px; + } + + .icon-cover-icon { + width: 30px; + height: 30px; + min-width: 30px; + font-size: 14px; + } + + .icon-cover-title { + font-size: 12px; + } + + .icon-cover-subtitle { + display: none; + } +} + +@media (max-width: 480px) { + .header-components { + height: var(--m-height); + } + + .header-components__content.slide-text .slide-title { + font-size: clamp(1.1rem, 5.4vw, 1.4rem); + margin-bottom: 8px; + } + + .header-components__content.slide-text .slide-desc { + font-size: 0.8125rem; + } + + .header-components-search { + top: calc(50% + 26px); + width: calc(100% - 20px); + padding: 0 10px; + } + + .card-5 .header-components-search, + .card-6 .header-components-search { + top: calc(50% - 12px); + } + + .card-7 .header-components-search, + .card-8 .header-components-search { + top: calc(50% - 40px); + } + + .header-components-search .search-input-text { + padding-right: 40px; + } + + .header-components-search__submit { + width: 34px; + height: 34px; + } +} + +.site-nav.nav-transparent { + background-color: transparent; + border-bottom-color: transparent; + color: #fff; +} + +.site-nav.nav-transparent .site-brand, +.site-nav.nav-transparent .site-brand__name { + color: #fff; +} + +.site-nav.nav-transparent .icon-btn { + color: rgba(255, 255, 255, 0.9); +} + +.site-nav.nav-transparent .icon-btn:hover { + background: rgba(255, 255, 255, 0.15); + color: #fff; +} + +.site-nav.nav-transparent ul.nav-desktop a { + color: rgba(255, 255, 255, 0.85); +} + +.site-nav.nav-transparent ul.nav-desktop a:hover { + color: #fff; + background: rgba(255, 255, 255, 0.15); +} + +.site-nav.nav-transparent ul.nav-desktop .current-menu-item > a, +.site-nav.nav-transparent ul.nav-desktop .current_page_item > a { + background: rgba(255, 255, 255, 0.2); + color: #fff; +} + +.site-nav.nav-transparent .nav-auth .btn-outline { + border-color: rgba(255, 255, 255, 0.6); + color: #fff; +} + +.site-nav.nav-transparent .nav-auth .btn-outline:hover { + background: rgba(255, 255, 255, 0.15); + border-color: #fff; +} + +.site-nav.nav-transparent .nav-user__toggle { + border-color: rgba(255, 255, 255, 0.5); +} + +/* 滚动后恢复实心 */ +.site-nav.nav-transparent.is-scrolled { + background-color: var(--surface-page); + border-bottom-color: var(--color-line); + color: var(--color-ink); +} + +.site-nav.nav-transparent.is-scrolled .site-brand, +.site-nav.nav-transparent.is-scrolled .site-brand__name { + color: var(--color-ink); +} + +.site-nav.nav-transparent.is-scrolled .icon-btn { + color: var(--color-ink-3); +} + +.site-nav.nav-transparent.is-scrolled ul.nav-desktop a { + color: var(--color-ink-3); +} + +.site-nav.nav-transparent.is-scrolled .nav-auth .btn-outline { + border-color: var(--color-line); + color: var(--color-ink); +} + +.site-nav.nav-transparent.is-scrolled .nav-user__toggle { + border-color: var(--color-line); +} + +/* ============================================================ + * Header Slider — Swiper Navigation & Pagination (Zibll-style) + * ============================================================ */ +.header-components .swiper-button-prev, +.header-components .swiper-button-next { + width: 30px; + height: 40px; + color: #fff; + text-shadow: 0 0 6px #444; + opacity: 0; + transition: opacity 0.3s, background-color 0.3s; + z-index: 10; +} + +.header-components .swiper-button-prev::after, +.header-components .swiper-button-next::after { + font-size: 16px; + font-weight: 700; +} + +.header-slider:hover .swiper-button-prev, +.header-slider:hover .swiper-button-next { + opacity: 0.8; +} + +.header-components .swiper-button-prev:hover, +.header-components .swiper-button-next:hover { + opacity: 1; + background-color: rgba(0, 0, 0, 0.3); +} + +.header-components .swiper-pagination-bullet { + width: 10px; + height: 10px; + background: transparent; + border: 2px solid rgba(255, 255, 255, 0.6); + opacity: 0.7; + border-radius: 20px; + transition: 0.4s; +} + +.header-components .swiper-pagination-bullet-active { + background: #fff; + border-color: #fff; + opacity: 1; +} + +@media (max-width: 640px) { + .header-components .swiper-button-prev, + .header-components .swiper-button-next { + display: none; + } +} + +/* ============================================================ + * Banner Module — 内联轮播条(模仿 zibll) + * ============================================================ */ +.banner-module { + position: relative; + width: 100%; + border-radius: 12px; + overflow: hidden; + box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08); +} + +.banner-module__swiper { + position: relative; + width: 100%; + height: clamp(180px, 22vw, 300px); +} + +.banner-module__swiper .swiper-slide { + position: relative; + overflow: hidden; + cursor: pointer; + height: 100%; +} + +.banner-module__slide-bg { + position: absolute; + inset: 0; + width: 100%; + height: 100%; +} + +.banner-module__slide-bg img, +.banner-module__slide-bg .fit-cover { + width: 100%; + height: 100%; + object-fit: cover; +} + +.banner-module__slide-fallback { + width: 100%; + height: 100%; + background: linear-gradient(135deg, var(--color-primary), var(--color-primary-dark, #5a8bc4)); +} + +.banner-module__slide-overlay { + position: absolute; + inset: 0; + background: linear-gradient( + to bottom, + rgba(0, 0, 0, 0) 0%, + rgba(0, 0, 0, 0.15) 50%, + rgba(0, 0, 0, 0.5) 100% + ); + pointer-events: none; +} + +.banner-module__content { + position: absolute; + bottom: 24px; + left: 24px; + right: 24px; + z-index: 2; + color: #fff; + max-width: 680px; +} + +.banner-module__title { + font-family: var(--font-display, var(--font-ui)); + font-size: clamp(1.125rem, 2vw, 1.5rem); + font-weight: 700; + margin: 0 0 4px; + line-height: 1.3; + text-shadow: 0 1px 4px rgba(0, 0, 0, 0.4); +} + +.banner-module__subtitle { + font-size: clamp(0.8125rem, 1.2vw, 0.9375rem); + margin: 0; + opacity: 0.9; + line-height: 1.5; + text-shadow: 0 1px 3px rgba(0, 0, 0, 0.3); +} + +/* Swiper 导航箭头 */ +.banner-module .swiper-button-prev, +.banner-module .swiper-button-next { + width: 36px; + height: 36px; + border-radius: 50%; + background: rgba(255, 255, 255, 0.85); + color: var(--color-ink); + opacity: 0; + pointer-events: none; + z-index: 10; + transition: opacity 0.3s ease, transform 0.2s ease; +} + +.banner-module .swiper-button-prev::after, +.banner-module .swiper-button-next::after { + font-size: 14px; + font-weight: 700; +} + +.banner-module:hover .swiper-button-prev, +.banner-module:hover .swiper-button-next { + opacity: 1; + pointer-events: auto; +} + +.banner-module .swiper-button-prev:hover, +.banner-module .swiper-button-next:hover { + transform: scale(1.1); + background: #fff; +} + +/* Banner 响应式 */ +@media (max-width: 767px) { + .banner-module { + border-radius: 8px; + } + + .banner-module__swiper { + height: clamp(120px, 30vw, 180px); + } + + .banner-module__content { + bottom: 12px; + left: 12px; + right: 12px; + } + + .banner-module .swiper-button-prev, + .banner-module .swiper-button-next { + display: none; + } +} + diff --git a/assets/css/frontend/header-components/widget-device-visibility.css b/assets/css/frontend/header-components/widget-device-visibility.css new file mode 100644 index 00000000..fb92aca8 --- /dev/null +++ b/assets/css/frontend/header-components/widget-device-visibility.css @@ -0,0 +1,198 @@ +/* Widget device visibility */ +@media (max-width: 767.98px) { + .aksrt-widget--mobile-only { + display: none !important; + } +} + +@media (min-width: 768px) { + .aksrt-widget--pc-only { + display: none !important; + } +} + +/* 首页首屏模块:向上抵消导航占位,保证 Hero 与导航重叠显示 */ +.home-modules > .header-components-container:first-child, +.home-modules--fullbleed > .header-components-container:first-child { + margin-top: calc(var(--nav-height, 60px) * -1); +} + +/* WordPress Admin Bar 已全局禁用,无需偏移规则 */ + +/* ============================================================ + * Layer 1: Swiper 轮播 + * ============================================================ */ +.header-components { + position: relative; + width: 100%; + --pc-height: 550px; + --m-height: 280px; + height: var(--pc-height); + max-height: none; + overflow: hidden; + background: #111; +} + +/* slide-header 模式:背景保持满铺,仅将文本层下移避开导航 */ +.header-components.slide-header { + padding-top: 0; +} + +.header-components.slide-header .header-components__content.slide-text { + padding-top: var(--nav-height, 60px); +} + +/* WordPress Admin Bar 已全局禁用,无需偏移规则 */ + +/* 渐变兜底 */ +.header-components--gradient { + background: linear-gradient(135deg, var(--color-primary) 0%, var(--color-primary-active, var(--color-primary-dark)) 100%); + display: flex; + align-items: center; + justify-content: center; +} + +.header-components--gradient::before { + content: ""; + position: absolute; + inset: 0; + background: radial-gradient(ellipse 80% 60% at 20% 20%, rgba(255, 255, 255, 0.15), transparent), + radial-gradient(ellipse 50% 50% at 80% 80%, rgba(0, 0, 0, 0.2), transparent); + pointer-events: none; +} + +/* Swiper 内部 */ +.header-components .swiper-wrapper { + position: absolute; + inset: 0; + height: 100%; + width: 100%; +} + +.header-components .swiper-slide { + position: relative; + height: 100%; + overflow: hidden; + cursor: pointer; +} + +/* 幻灯片背景图 */ +.header-components__slide-bg { + position: absolute; + inset: 0; + overflow: hidden; +} + +.header-components__slide-bg img, +.header-components__slide-bg .fit-cover { + width: 100%; + height: 100%; + object-fit: cover; +} + +.header-components__slide-fallback { + width: 100%; + height: 100%; + background: linear-gradient(135deg, var(--color-primary), var(--color-primary-dark)); +} + +/* 视频背景 */ +.header-components__video { + position: absolute; + inset: 0; + width: 100%; + height: 100%; + object-fit: cover; + z-index: 0; +} + +/* 图片图层(视差叠加) */ +.header-components__layer { + position: absolute; + inset: 0; + background-size: cover; + background-repeat: no-repeat; + background-position: center; + pointer-events: none; +} + +.header-components__layer--free-size { + background-size: auto; +} + +.header-components__layer--parallax { + will-change: transform, opacity; + opacity: var(--layer-parallax-opacity, 0.6); + transform: translateY(calc(var(--scroll-y, 0) * var(--layer-parallax-scale, 0.3) * 1px)); +} + +/* 文字视差 */ +.has-text-parallax { + will-change: transform; + transform: translate(-50%, calc(-50% + var(--scroll-y, 0) * var(--hero-text-parallax, 0) * 0.15px)); +} + +/* 文字尺寸覆盖 */ +.header-components__content[style*="--hero-text-size-pc"] .slide-title { + font-size: var(--hero-text-size-pc); +} + +/* 幻灯片遮罩 */ +.header-components__slide-overlay { + position: absolute; + inset: 0; + background: linear-gradient( + to bottom, + rgba(0, 0, 0, 0.1) 0%, + rgba(0, 0, 0, 0.25) 40%, + rgba(0, 0, 0, 0.55) 100% + ); + z-index: 1; + pointer-events: none; +} + +/* 幻灯片文字内容 */ +.header-components__content { + position: absolute; + bottom: auto; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + z-index: 2; + width: calc(100% - 32px); + max-width: 920px; + text-align: center; + color: #fff; +} + +.header-components__title { + font-family: var(--font-display, var(--font-ui)); + font-size: clamp(1.75rem, 4vw, 3rem); + font-weight: 700; + margin: 0 0 12px; + line-height: 1.2; + letter-spacing: -0.02em; + color: #fff; + text-shadow: 0 2px 8px rgba(0, 0, 0, 0.5), 0 1px 3px rgba(0, 0, 0, 0.4); +} + +.header-components__subtitle { + font-size: clamp(0.9rem, 1.4vw, 1.125rem); + margin: 0; + max-width: 680px; + margin-left: auto; + margin-right: auto; + line-height: 1.6; + color: rgba(255, 255, 255, 0.9); + text-shadow: 0 1px 4px rgba(0, 0, 0, 0.4); +} + +.header-components__description { + font-size: clamp(0.8rem, 1.2vw, 0.95rem); + margin: 8px auto 0; + max-width: 600px; + line-height: 1.5; + color: rgba(255, 255, 255, 0.8); + text-shadow: 0 1px 3px rgba(0, 0, 0, 0.3); +} + diff --git a/assets/css/frontend/home-modules.css b/assets/css/frontend/home-modules.css new file mode 100644 index 00000000..94cbed32 --- /dev/null +++ b/assets/css/frontend/home-modules.css @@ -0,0 +1,16 @@ +@import url("home-modules/base.css"); +@import url("home-modules/tabs.css"); +@import url("home-modules/tag-cloud.css"); +@import url("home-modules/ranking.css"); +@import url("home-modules/friend-links.css"); +@import url("home-modules/html-module.css"); +@import url("home-modules/responsive.css"); +@import url("home-modules/text-title.css"); +@import url("home-modules/button-group.css"); +@import url("home-modules/spacing.css"); +@import url("home-modules/faq.css"); +@import url("home-modules/data-grid.css"); +@import url("home-modules/highlight-cards.css"); +@import url("home-modules/partner-marquee.css"); +@import url("home-modules/product-showcase.css"); +@import url("home-modules/user-cards.css"); diff --git a/assets/css/frontend/home-modules/base.css b/assets/css/frontend/home-modules/base.css new file mode 100644 index 00000000..1a3a6882 --- /dev/null +++ b/assets/css/frontend/home-modules/base.css @@ -0,0 +1,89 @@ +/** + * Home Modules · CMS 形态首页模块系统样式 + * + * 仅在 site_profile=cms 时(首页)加载。 + * + * 宽度模型: + * - .home-modules > .home-module 锁定到 --container(默认 1280) + * - .home-modules > .hero 走 full-bleed(不在此处约束) + * - banner 模块的精细微调见 hero.css `.banner-slider.home-modules__banner` + */ + +.home-modules { + display: flex; + flex-direction: column; + gap: var(--space-9, 48px); + padding-bottom: var(--space-9, 48px); +} + +.home-modules--fullbleed { + width: 100%; +} + +.home-modules--fullbleed > .home-module { + max-width: 100%; + padding-left: 0; + padding-right: 0; +} + +/* 容器宽度统一:所有非 hero 的 home-module 都对齐到 --container */ +.home-modules > .home-module { + width: 100%; + max-width: var(--container); + margin-left: auto; + margin-right: auto; + padding-left: 16px; + padding-right: 16px; + box-sizing: border-box; +} + +@media (min-width: 768px) { + .home-modules > .home-module { + padding-left: 24px; + padding-right: 24px; + } +} + +/* ============ 公共 header ============ */ +.home-module__header { + display: flex; + align-items: baseline; + justify-content: space-between; + gap: var(--space-3, 12px); + margin-bottom: var(--space-5, 20px); + padding-bottom: var(--space-3, 12px); + border-bottom: 1px solid var(--color-line); +} + +.home-module__title { + display: flex; + align-items: center; + gap: 8px; + font: 700 22px/1.2 var(--font-display); + margin: 0; + color: var(--color-ink); +} + +.home-module__title i { + color: var(--color-primary); +} + +.home-module__more { + display: inline-flex; + align-items: center; + gap: 4px; + font: 500 13px/1 var(--font-ui); + color: var(--color-primary); + text-decoration: none; +} + +.home-module__more:hover { + color: var(--color-primary-active); +} + +.home-module__admin-tools { + display: flex; + justify-content: flex-end; + margin-top: 14px; +} + diff --git a/assets/css/frontend/home-modules/button-group.css b/assets/css/frontend/home-modules/button-group.css new file mode 100644 index 00000000..2a704e77 --- /dev/null +++ b/assets/css/frontend/home-modules/button-group.css @@ -0,0 +1,46 @@ +/* Button Group */ +.home-module--button-group { + padding: 32px 0; +} + +.home-module__buttons { + display: flex; + flex-wrap: wrap; + justify-content: center; + gap: 12px; + margin-top: 16px; +} + +.aksrt-btn { + display: inline-flex; + align-items: center; + gap: 6px; + padding: 10px 24px; + border-radius: var(--radius-md, 8px); + font-size: 14px; + font-weight: 500; + text-decoration: none; + transition: opacity 0.2s, transform 0.2s; +} + +.aksrt-btn:hover { + opacity: 0.85; + transform: translateY(-1px); +} + +.aksrt-btn--primary { + background: var(--color-primary); + color: #fff; +} + +.aksrt-btn--outline { + background: transparent; + color: var(--color-primary); + border: 1px solid var(--color-primary); +} + +.aksrt-btn--ghost { + background: transparent; + color: var(--color-ink); +} + diff --git a/assets/css/frontend/home-modules/data-grid.css b/assets/css/frontend/home-modules/data-grid.css new file mode 100644 index 00000000..4f77deee --- /dev/null +++ b/assets/css/frontend/home-modules/data-grid.css @@ -0,0 +1,38 @@ +/* Data Grid */ +.home-module--data-grid { + padding: 32px 0; +} + +.home-module__data-grid { + display: grid; + gap: 16px; + text-align: center; +} + +.aksrt-data-cell { + padding: 24px 16px; + background: var(--surface-1, #fff); + border-radius: var(--radius-md, 8px); + border: 1px solid var(--color-line, #e8e8e8); +} + +.aksrt-data-cell i { + font-size: 24px; + color: var(--color-primary); + margin-bottom: 8px; + display: block; +} + +.aksrt-data-cell__value { + font-size: 28px; + font-weight: 700; + color: var(--color-ink); + display: block; + margin-bottom: 4px; +} + +.aksrt-data-cell__label { + font-size: 13px; + color: var(--color-ink-3); +} + diff --git a/assets/css/frontend/home-modules/faq.css b/assets/css/frontend/home-modules/faq.css new file mode 100644 index 00000000..b41693b9 --- /dev/null +++ b/assets/css/frontend/home-modules/faq.css @@ -0,0 +1,48 @@ +/* FAQ */ +.home-module--faq { + padding: 32px 0; +} + +.home-module__faq-grid { + column-gap: 24px; +} + +.aksrt-faq-item { + break-inside: avoid; + margin-bottom: 12px; + border: 1px solid var(--color-line, #e8e8e8); + border-radius: var(--radius-md, 8px); + overflow: hidden; +} + +.aksrt-faq-item__question { + padding: 14px 16px; + font-size: 15px; + font-weight: 600; + cursor: pointer; + background: var(--surface-1, #fff); + list-style: none; +} + +.aksrt-faq-item__question::-webkit-details-marker { + display: none; +} + +.aksrt-faq-item__question::after { + content: '+'; + float: right; + font-weight: 400; + transition: transform 0.2s; +} + +.aksrt-faq-item[open] .aksrt-faq-item__question::after { + content: '−'; +} + +.aksrt-faq-item__answer { + padding: 0 16px 14px; + font-size: 14px; + color: var(--color-ink-3); + line-height: 1.7; +} + diff --git a/assets/css/frontend/home-modules/friend-links.css b/assets/css/frontend/home-modules/friend-links.css new file mode 100644 index 00000000..6e57bf90 --- /dev/null +++ b/assets/css/frontend/home-modules/friend-links.css @@ -0,0 +1,55 @@ +/* ============ Friend Links ============ */ +.home-module__friends-list { + list-style: none; + margin: 0; + padding: 0; + display: grid; + grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); + gap: var(--space-3, 12px); +} + +.home-module__friend-card { + display: flex; + align-items: center; + gap: var(--space-3, 12px); + padding: 12px; + border-radius: var(--radius); + border: 1px solid var(--color-line); + background: var(--surface-1); + color: var(--color-ink); + text-decoration: none; + transition: border-color .18s ease, transform .18s ease; +} + +.home-module__friend-card:hover { + border-color: var(--color-primary); + transform: translateY(-1px); +} + +.home-module__friend-avatar { + width: 40px; + height: 40px; + border-radius: 50%; + object-fit: cover; + flex: 0 0 40px; +} + +.home-module__friend-meta { + display: flex; + flex-direction: column; + gap: 2px; + min-width: 0; +} + +.home-module__friend-meta strong { + font: 600 14px/1.2 var(--font-ui); +} + +.home-module__friend-meta span { + font-size: 12px; + color: var(--color-ink-3); + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + diff --git a/assets/css/frontend/home-modules/highlight-cards.css b/assets/css/frontend/home-modules/highlight-cards.css new file mode 100644 index 00000000..21818ffc --- /dev/null +++ b/assets/css/frontend/home-modules/highlight-cards.css @@ -0,0 +1,57 @@ +/* Highlight Cards */ +.home-module--highlight-cards { + padding: 32px 0; +} + +.home-module__highlight-grid { + display: grid; + gap: 16px; +} + +.aksrt-highlight-card { + padding: 24px; + background: var(--surface-1, #fff); + border-radius: var(--radius-md, 8px); + border: 1px solid var(--color-line, #e8e8e8); + text-decoration: none; + color: inherit; + transition: box-shadow 0.2s, transform 0.2s; +} + +.aksrt-highlight-card:hover { + box-shadow: none; + transform: none; +} + +.aksrt-highlight-card__image { + width: 100%; + border-radius: var(--radius-sm, 4px); + margin-bottom: 12px; +} + +.aksrt-highlight-card__icon { + width: 48px; + height: 48px; + display: flex; + align-items: center; + justify-content: center; + border-radius: var(--radius-md, 8px); + background: var(--color-primary-softer); + color: var(--color-primary); + font-size: 20px; + margin-bottom: 12px; +} + +.aksrt-highlight-card__title { + font-size: 16px; + font-weight: 600; + margin: 0 0 8px; +} + +.aksrt-highlight-card__desc { + font-size: 13px; + color: var(--color-ink-3); + margin: 0; + line-height: 1.6; +} + diff --git a/assets/css/frontend/home-modules/html-module.css b/assets/css/frontend/home-modules/html-module.css new file mode 100644 index 00000000..fcf5a000 --- /dev/null +++ b/assets/css/frontend/home-modules/html-module.css @@ -0,0 +1,7 @@ +/* ============ HTML Module ============ */ +.home-module--html .home-module__html-body { + color: var(--color-ink); + font-size: 15px; + line-height: 1.7; +} + diff --git a/assets/css/frontend/home-modules/partner-marquee.css b/assets/css/frontend/home-modules/partner-marquee.css new file mode 100644 index 00000000..f18cf509 --- /dev/null +++ b/assets/css/frontend/home-modules/partner-marquee.css @@ -0,0 +1,42 @@ +/* Partner Marquee */ +.home-module--partner-marquee { + padding: 32px 0; + overflow: hidden; +} + +.aksrt-marquee { + overflow: hidden; + width: 100%; +} + +.aksrt-marquee__track { + display: flex; + gap: 32px; + width: max-content; + animation: aksrt-marquee-scroll var(--marquee-duration, 30s) linear infinite; +} + +.aksrt-marquee__item { + flex-shrink: 0; + display: flex; + align-items: center; + justify-content: center; + padding: 8px 16px; +} + +.aksrt-marquee__item img { + height: 40px; + width: auto; + opacity: 0.7; + transition: opacity 0.2s; +} + +.aksrt-marquee__item:hover img { + opacity: 1; +} + +@keyframes aksrt-marquee-scroll { + 0% { transform: translateX(0); } + 100% { transform: translateX(-50%); } +} + diff --git a/assets/css/frontend/home-modules/product-showcase.css b/assets/css/frontend/home-modules/product-showcase.css new file mode 100644 index 00000000..60c974eb --- /dev/null +++ b/assets/css/frontend/home-modules/product-showcase.css @@ -0,0 +1,58 @@ +/* Product Showcase */ +.home-module--product-showcase { + padding: 32px 0; +} + +.home-module__product-grid { + display: grid; + gap: 16px; +} + +.aksrt-product-card { + background: var(--surface-1, #fff); + border-radius: var(--radius-md, 8px); + border: 1px solid var(--color-line, #e8e8e8); + overflow: hidden; + text-decoration: none; + color: inherit; + transition: box-shadow 0.2s, transform 0.2s; +} + +.aksrt-product-card:hover { + box-shadow: none; + transform: none; +} + +.aksrt-product-card__image img { + width: 100%; + aspect-ratio: 4/3; + object-fit: cover; +} + +.aksrt-product-card__body { + padding: 16px; +} + +.aksrt-product-card__title { + font-size: 15px; + font-weight: 600; + margin: 0 0 6px; +} + +.aksrt-product-card__desc { + font-size: 13px; + color: var(--color-ink-3); + margin: 0 0 8px; + line-height: 1.5; + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + overflow: hidden; +} + +.aksrt-product-card__price { + font-size: 18px; + font-weight: 700; + color: var(--color-error); +} + diff --git a/assets/css/frontend/home-modules/ranking.css b/assets/css/frontend/home-modules/ranking.css new file mode 100644 index 00000000..a33019a1 --- /dev/null +++ b/assets/css/frontend/home-modules/ranking.css @@ -0,0 +1,60 @@ +/* ============ Ranking ============ */ +.home-module__ranking-list { + list-style: none; + margin: 0; + padding: 0; + display: grid; + grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); + gap: var(--space-3, 12px); +} + +.home-module__ranking-item { + display: flex; + align-items: center; + gap: var(--space-3, 12px); + padding: 12px 14px; + background: var(--surface-1); + border: 1px solid var(--color-line); + border-radius: var(--radius); +} + +.home-module__ranking-num { + flex: 0 0 32px; + display: inline-flex; + align-items: center; + justify-content: center; + width: 32px; + height: 32px; + border-radius: 50%; + background: var(--surface-2); + color: var(--color-ink-3); + font: 700 13px/1 var(--font-ui); +} + +.home-module__ranking-item--top .home-module__ranking-num { + background: linear-gradient(135deg, #f59e0b 0%, #f97316 100%); + color: #fff; + box-shadow: 0 4px 8px rgba(245, 158, 11, .25); +} + +.home-module__ranking-link { + flex: 1 1 auto; + color: var(--color-ink); + text-decoration: none; + font: 500 14px/1.4 var(--font-ui); + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.home-module__ranking-link:hover { + color: var(--color-primary); +} + +.home-module__ranking-value { + flex: 0 0 auto; + color: var(--color-ink-3); + font-variant-numeric: tabular-nums; + font: 500 12px/1 var(--font-ui); +} + diff --git a/assets/css/frontend/home-modules/responsive.css b/assets/css/frontend/home-modules/responsive.css new file mode 100644 index 00000000..73b80ce2 --- /dev/null +++ b/assets/css/frontend/home-modules/responsive.css @@ -0,0 +1,294 @@ +/* ============ Responsive ============ */ +@media (max-width: 640px) { + .home-modules { + gap: var(--space-7, 32px); + } + .home-module__header { + flex-wrap: wrap; + } + .home-module__title { + font-size: 18px; + } +} + +/* ============ Hotspot 热点推荐 ============ */ + +/* 手机端隐藏 */ +.hotspot--desktop-only { + display: none; +} + +@media (min-width: 768px) { + .hotspot--desktop-only { + display: block; + } +} + +.hotspot__list { + list-style: none; + margin: 0; + padding: 0; +} + +.hotspot__item { + display: flex; + align-items: flex-start; + gap: var(--space-4, 16px); + padding: var(--space-4, 16px) 0; + border-bottom: 1px solid var(--color-line); +} + +.hotspot__item:last-child { + border-bottom: none; +} + +.hotspot__num { + flex: 0 0 32px; + display: inline-flex; + align-items: center; + justify-content: center; + width: 32px; + height: 32px; + border-radius: var(--radius-avatar, 50%); + font: 700 13px/1 var(--font-ui); + background: var(--surface-2); + color: var(--color-ink-3); +} + +.hotspot__num--top { + background: var(--color-primary); + color: var(--color-on-primary, #fff); +} + +.hotspot__body { + flex: 1; + min-width: 0; +} + +.hotspot__title { + display: block; + font: 600 15px/1.4 var(--font-ui); + color: var(--color-ink); + text-decoration: none; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + transition: color 0.18s ease; +} + +.hotspot__title:hover { + color: var(--color-primary); +} + +.hotspot__meta { + display: flex; + align-items: center; + gap: var(--space-3, 12px); + margin-top: var(--space-2, 8px); + font: 400 12px/1 var(--font-ui); + color: var(--color-ink-3); +} + +.hotspot__cat { + display: inline-block; + padding: 2px 8px; + border-radius: var(--radius-pill, 999px); + background: var(--surface-2); + font-size: 11px; + font-weight: 500; +} + +/* ============ 分类推荐卡片 ============ */ + +.cat-cards-grid { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 20px; +} + +.cat-card { + background: var(--surface-2, #fff); + border-radius: 10px; + padding: 22px; + box-shadow: 0 1px 6px rgba(0, 0, 0, 0.08); + transition: box-shadow 0.2s ease, border-color 0.2s ease; +} + +.cat-card:hover { + box-shadow: var(--shadow-md); +} + +/* 上部:封面 + 信息 */ +.cat-card__top { + display: flex; + align-items: flex-start; + gap: 18px; + margin-bottom: 18px; +} + +.cat-card__banner { + width: 145px; + height: 95px; + border-radius: 8px; + overflow: hidden; + position: relative; + flex-shrink: 0; + background: var(--surface-3, #f5f5f5); +} + +.cat-card__cover { + width: 100%; + height: 100%; + object-fit: cover; + display: block; + transition: transform 0.3s ease; +} + +.cat-card:hover .cat-card__cover { + transform: scale(1.02); +} + +/* 浏览量胶囊:红底白字 */ +.cat-card__views { + position: absolute; + top: 8px; + right: 8px; + background: #f54343; + color: #fff; + font-size: 12px; + font-weight: 600; + padding: 2px 7px; + border-radius: 15px; + pointer-events: none; + z-index: 1; +} + +.cat-card__info { + flex: 1; + height: 95px; + display: flex; + flex-direction: column; + justify-content: space-between; +} + +.cat-card__name { + font-size: 19px; + font-weight: 600; + color: var(--color-ink); + line-height: 1.3; +} + +.cat-card__desc { + font-size: 13px; + color: var(--color-ink-3); + margin-top: 4px; + line-height: 1.5; + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + overflow: hidden; +} + +.cat-card__foot { + display: flex; + justify-content: space-between; + align-items: center; + font-size: 13px; + color: var(--color-ink-4); +} + +.cat-card__more { + color: var(--color-primary); + text-decoration: none; + font-weight: 500; +} + +.cat-card__more:hover { + text-decoration: underline; +} + +/* 下部:文章列表 */ +.cat-card__list { + list-style: none; + margin: 0; + padding: 0; +} + +.cat-card__list li { + display: flex; + align-items: flex-start; + font-size: 13.5px; + color: var(--color-ink); + line-height: 1.6; + padding: 5px 0; +} + +.cat-card__list li::before { + content: "\25CF"; + color: var(--color-primary); + font-size: 10px; + margin-right: 8px; + margin-top: 3px; + flex-shrink: 0; +} + +.cat-card__list li a { + color: inherit; + text-decoration: none; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + flex: 1; + min-width: 0; + transition: color 0.15s ease; +} + +.cat-card__list li a:hover { + color: var(--color-primary); +} + +.cat-card__time { + color: var(--color-ink-4); + font-size: 12px; + margin-left: auto; + padding-left: 12px; + white-space: nowrap; + flex-shrink: 0; +} + +/* 懒加载骨架 */ +.cat-card__banner .aksrt-skeleton { + position: absolute; + inset: 0; +} + +.cat-card__banner img.aksrt-lazy { + opacity: 0; + transition: opacity 0.3s ease; +} + +.cat-card__banner img.aksrt-loaded { + opacity: 1; +} + +/* 响应式 */ +@media (max-width: 767px) { + .cat-cards-grid { + grid-template-columns: 1fr; + gap: 16px; + } + + .cat-card__name { + font-size: 16px; + } + + .cat-card__info { + height: auto; + min-height: 95px; + } +} + +/* ============================================================ + * Phase 5: 运营型模块样式 + * ============================================================ */ + diff --git a/assets/css/frontend/home-modules/spacing.css b/assets/css/frontend/home-modules/spacing.css new file mode 100644 index 00000000..c03325ac --- /dev/null +++ b/assets/css/frontend/home-modules/spacing.css @@ -0,0 +1,5 @@ +/* Spacing */ +.home-module--spacing { + pointer-events: none; +} + diff --git a/assets/css/frontend/home-modules/tabs.css b/assets/css/frontend/home-modules/tabs.css new file mode 100644 index 00000000..4af252d7 --- /dev/null +++ b/assets/css/frontend/home-modules/tabs.css @@ -0,0 +1,56 @@ +/* ============ Tabs ============ */ +.home-module__header--tabs { + flex-wrap: wrap; + border-bottom: 0; + padding-bottom: 0; +} + +.home-module__tabs { + display: flex; + flex-wrap: wrap; + gap: var(--space-1, 4px); + border-bottom: 1px solid var(--color-line); + margin-top: var(--space-3, 12px); + width: 100%; +} + +.home-module__tab { + background: transparent; + border: 0; + padding: 8px 16px; + font: 500 14px/1 var(--font-ui); + color: var(--color-ink-2); + cursor: pointer; + border-radius: 8px 8px 0 0; + border-bottom: 2px solid transparent; + transition: color .18s ease, border-color .18s ease; +} + +.home-module__tab:hover { + color: var(--color-ink); +} + +.home-module__tab.is-active { + color: var(--color-primary); + border-bottom-color: var(--color-primary); +} + +.home-module__tab-panel { + margin-top: var(--space-5, 20px); +} + +.index-tab-main .home-module__tab-panel.tab-pane[hidden], +.home-tab-content .home-module__tab-panel.tab-pane[hidden] { + display: none; +} + +.home-module__tab-panel[hidden] { + display: none; +} + +.home-module__empty { + color: var(--color-ink-3); + text-align: center; + padding: var(--space-7, 32px) 0; +} + diff --git a/assets/css/frontend/home-modules/tag-cloud.css b/assets/css/frontend/home-modules/tag-cloud.css new file mode 100644 index 00000000..8f204418 --- /dev/null +++ b/assets/css/frontend/home-modules/tag-cloud.css @@ -0,0 +1,33 @@ +/* ============ Tag Cloud ============ */ +.home-module__tag-cloud { + list-style: none; + margin: 0; + padding: 0; + display: flex; + flex-wrap: wrap; + gap: var(--space-2, 8px); +} + +.home-module__tag { + display: inline-flex; + align-items: center; + gap: 6px; + padding: 6px 12px; + border-radius: var(--radius-pill); + background: var(--surface-2); + color: var(--color-ink-2); + font: 500 13px/1 var(--font-ui); + text-decoration: none; + transition: background .18s ease, color .18s ease; +} + +.home-module__tag:hover { + background: var(--color-primary); + color: var(--color-on-primary); +} + +.home-module__tag-count { + font-variant-numeric: tabular-nums; + opacity: .7; +} + diff --git a/assets/css/frontend/home-modules/text-title.css b/assets/css/frontend/home-modules/text-title.css new file mode 100644 index 00000000..3a6782e9 --- /dev/null +++ b/assets/css/frontend/home-modules/text-title.css @@ -0,0 +1,17 @@ +/* Text Title */ +.home-module--text-title { + padding: 24px 0; +} + +.home-module--text-title .home-module__title { + font-size: 28px; + font-weight: 700; + margin: 0 0 8px; +} + +.home-module--text-title .home-module__subtitle { + font-size: 15px; + color: var(--color-ink-3); + margin: 0; +} + diff --git a/assets/css/frontend/home-modules/user-cards.css b/assets/css/frontend/home-modules/user-cards.css new file mode 100644 index 00000000..35ac1504 --- /dev/null +++ b/assets/css/frontend/home-modules/user-cards.css @@ -0,0 +1,180 @@ +/* ============ User Cards ============ */ +.home-module__users-grid { + display: grid; + grid-template-columns: repeat(var(--cols, 4), 1fr); + gap: var(--space-4, 16px); +} + +.home-module__user-card { + display: flex; + flex-direction: column; + align-items: center; + text-align: center; + padding: 20px 16px; + border-radius: var(--radius); + border: 1px solid var(--color-line); + background: var(--surface-1); + transition: border-color .18s ease, transform .18s ease; +} + +.home-module__user-card:hover { + border-color: var(--color-line); + transform: none; +} + +.home-module__user-link { + display: flex; + flex-direction: column; + align-items: center; + gap: 8px; + text-decoration: none; + color: var(--color-ink); +} + +.home-module__user-avatar { + width: 64px; + height: 64px; + border-radius: 50%; + object-fit: cover; +} + +.home-module__user-name { + font: 600 14px/1.2 var(--font-ui); +} + +.home-module__user-bio { + font-size: 12px; + color: var(--color-ink-3); + margin: 4px 0 0; + line-height: 1.4; + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + overflow: hidden; +} + +.home-module__user-stats { + display: flex; + gap: 12px; + margin-top: 8px; + font-size: 12px; + color: var(--color-ink-2); +} + +.home-module__user-stat { + display: inline-flex; + align-items: center; + gap: 4px; +} + +.home-module__user-stat i { + font-size: 11px; + color: var(--color-ink-3); +} + +/* ============ More (Discover Categories) ============ */ +.home-module__more-grid { + display: grid; + grid-template-columns: repeat(var(--cols, 3), 1fr); + gap: var(--space-4, 16px); +} + +.home-module__more-card { + border-radius: var(--radius); + border: 1px solid var(--color-line); + background: var(--surface-1); + overflow: hidden; + transition: border-color .18s ease, transform .18s ease; +} + +.home-module__more-card:hover { + border-color: var(--color-line); + transform: none; +} + +.home-module__more-link { + display: block; + text-decoration: none; + color: inherit; +} + +.home-module__more-cover { + aspect-ratio: 16 / 9; + overflow: hidden; + background: var(--color-fill-2); +} + +.home-module__more-cover img { + width: 100%; + height: 100%; + object-fit: cover; +} + +.home-module__more-cover--placeholder { + display: flex; + align-items: center; + justify-content: center; + font-size: 28px; + color: var(--color-ink-3); +} + +.home-module__more-body { + padding: 12px; + display: flex; + flex-direction: column; + gap: 2px; +} + +.home-module__more-name { + font: 600 14px/1.3 var(--font-ui); +} + +.home-module__more-count { + font-size: 12px; + color: var(--color-ink-3); +} + +.home-module__more-posts { + list-style: none; + margin: 0; + padding: 0 12px 12px; +} + +.home-module__more-posts li { + border-top: 1px solid var(--color-line-light, rgba(0,0,0,.06)); +} + +.home-module__more-posts a { + display: block; + padding: 6px 0; + font-size: 13px; + color: var(--color-ink-2); + text-decoration: none; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + transition: color .15s ease; +} + +.home-module__more-posts a:hover { + color: var(--color-primary); +} + +/* 响应式 */ +@media (max-width: 767px) { + .home-module__data-grid, + .home-module__highlight-grid, + .home-module__product-grid { + grid-template-columns: 1fr !important; + } + + .home-module__faq-grid { + column-count: 1 !important; + } + + .home-module__users-grid, + .home-module__more-grid { + grid-template-columns: 1fr 1fr !important; + } +} + diff --git a/assets/css/frontend/homepage-fixed.css b/assets/css/frontend/homepage-fixed.css new file mode 100644 index 00000000..3f61bf97 --- /dev/null +++ b/assets/css/frontend/homepage-fixed.css @@ -0,0 +1,3 @@ +@import url("homepage-fixed/base.css"); +@import url("homepage-fixed/ajax-tab-skeleton-placeholder.css"); +@import url("homepage-fixed/ajax-tab-error-state.css"); diff --git a/assets/css/frontend/homepage-fixed/ajax-tab-error-state.css b/assets/css/frontend/homepage-fixed/ajax-tab-error-state.css new file mode 100644 index 00000000..f867ad90 --- /dev/null +++ b/assets/css/frontend/homepage-fixed/ajax-tab-error-state.css @@ -0,0 +1,197 @@ +/* AJAX tab error state */ +.aksrt-homepage__tab-error { + padding: 32px 16px; + text-align: center; + color: var(--color-ink-4, #999); + font-size: 14px; +} + +.aksrt-homepage__tab-retry { + display: inline-flex; + align-items: center; + gap: 6px; + margin-top: 12px; + padding: 6px 14px; + border: 1px solid var(--color-line); + border-radius: var(--radius, 8px); + background: var(--surface-1, #fff); + color: var(--color-ink-3, #777); + font-size: 13px; + cursor: pointer; + transition: color 0.2s, border-color 0.2s; +} + +.aksrt-homepage__tab-retry:hover { + color: var(--color-primary, var(--color-primary)); + border-color: var(--color-primary, var(--color-primary)); +} + +/* ================================================================ + 14. RESPONSIVE — TABLET (max-width: 991px) + ================================================================ */ + +@media (max-width: 991.98px) { + .aksrt-homepage__shell.content-shell, + .aksrt-homepage__fluid-zone.content-shell { + padding-top: 16px; + } + + .aksrt-homepage__posts > .posts-item.list { + padding: 15px; + gap: 14px; + } + + .aksrt-homepage__posts > .posts-item.list .item-thumbnail { + width: 160px; + min-width: 160px; + padding-bottom: calc(160px * 0.7); + } + + .aksrt-homepage__posts > .posts-item.list.mult-thumb .thumb-items > span { + width: calc(33.333% - 6px); + padding-bottom: calc(var(--posts-list-scale, 70%) / 3); + } + + .aksrt-homepage__posts > .posts-item.list.mult-thumb .thumb-items > span:nth-child(4) { + display: none; + } + + /* Card mode: 2 columns */ + .aksrt-homepage__posts[data-view="card"] > .posts-item { + width: calc(50% - 16px); + } +} + +/* ================================================================ + 15. RESPONSIVE — MOBILE (max-width: 767px) + ================================================================ */ + +@media (max-width: 767px) { + .aksrt-homepage__shell.content-shell { + padding-left: 10px; + padding-right: 10px; + } + + .aksrt-homepage__posts > .posts-item.list { + padding: 12px; + gap: 12px; + margin-bottom: 10px; + } + + .aksrt-homepage__posts > .posts-item.list .item-thumbnail { + width: 120px; + min-width: 120px; + padding-bottom: calc(120px * 0.7); + } + + .aksrt-homepage__posts .item-heading { + font-size: 15px; + line-height: 1.4; + } + + .aksrt-homepage__posts .item-excerpt { + display: none; + } + + .aksrt-homepage__posts .meta-right { + display: none; + } + + /* Card mode: 2 columns (match Zibll) */ + .aksrt-homepage__posts[data-view="card"] > .posts-item { + width: calc(50% - 10px); + margin: 5px; + } + + /* Tab skeleton: smaller thumb */ + .aksrt-homepage__tab-skeleton-thumb { + width: 120px; + min-width: 120px; + height: 84px; + } +} + +/* ================================================================ + 16. RESPONSIVE — SMALL MOBILE (max-width: 640px) + ================================================================ */ + +@media (max-width: 640px) { + .aksrt-homepage__tabs, + .aksrt-homepage__titlebox { + margin-bottom: 8px; + } + + .aksrt-homepage__admin-link { + margin-left: 0; + margin-top: 12px; + } + + .aksrt-homepage__tabs.home-tab-nav-box[data-sticky-tabs="true"].is-stuck, + .aksrt-homepage__tabs.home-tab-nav-box[data-sticky-tabs="true"].is-affixed { + padding: 8px 10px; + border-radius: 10px; + } + + .aksrt-homepage__sortbar { + gap: 10px; + margin-bottom: 12px; + padding-bottom: 12px; + font-size: 13px; + } + + .aksrt-homepage__posts > .posts-item.list { + padding: 10px; + gap: 10px; + border-radius: var(--radius, 8px); + } + + .aksrt-homepage__posts > .posts-item.list .item-thumbnail { + width: 96px; + min-width: 96px; + padding-bottom: calc(96px * 0.7); + border-radius: 6px; + } + + .aksrt-homepage__posts .item-heading { + font-size: 15px; + -webkit-line-clamp: 2; + } + + .aksrt-homepage__posts .item-tags .badge { + font-size: 11px; + padding: 2px 5px; + } + + .aksrt-homepage__posts .item-meta { + flex-wrap: wrap; + gap: 8px; + font-size: 12px; + } + + .aksrt-homepage__posts .meta-avatar { + width: 20px; + height: 20px; + } + + .aksrt-homepage__posts .meta-item { + font-size: 12px; + } + + /* Card mode: single column */ + .aksrt-homepage__posts[data-view="card"] { + margin: 0; + } + + .aksrt-homepage__posts[data-view="card"] > .posts-item { + width: 100%; + margin: 0 0 10px; + } + + /* Tab skeleton: adapt */ + .aksrt-homepage__tab-skeleton-thumb { + width: 96px; + min-width: 96px; + height: 67px; + } +} + diff --git a/assets/css/frontend/homepage-fixed/ajax-tab-skeleton-placeholder.css b/assets/css/frontend/homepage-fixed/ajax-tab-skeleton-placeholder.css new file mode 100644 index 00000000..7a6e577d --- /dev/null +++ b/assets/css/frontend/homepage-fixed/ajax-tab-skeleton-placeholder.css @@ -0,0 +1,51 @@ +/* AJAX tab skeleton placeholder */ +.aksrt-homepage__tab-skeleton { + display: flex; + flex-direction: column; + gap: 15px; + padding: 10px 0; +} + +.aksrt-homepage__tab-skeleton-item { + display: flex; + gap: 16px; + padding: 20px; + background: var(--surface-1, #fff); + border-radius: var(--radius, 8px); + animation: aksrt-skeleton-pulse 1.5s ease-in-out infinite; +} + +.aksrt-homepage__tab-skeleton-thumb { + width: 190px; + min-width: 190px; + height: 133px; + background: var(--surface-2, #eee); + border-radius: var(--radius, 8px); +} + +.aksrt-homepage__tab-skeleton-body { + flex: 1; + display: flex; + flex-direction: column; + gap: 10px; +} + +.aksrt-homepage__tab-skeleton-line { + height: 14px; + background: var(--surface-2, #eee); + border-radius: 4px; +} + +.aksrt-homepage__tab-skeleton-line:first-child { + width: 70%; + height: 18px; +} + +.aksrt-homepage__tab-skeleton-line:nth-child(2) { + width: 100%; +} + +.aksrt-homepage__tab-skeleton-line:nth-child(3) { + width: 40%; +} + diff --git a/assets/css/frontend/homepage-fixed/base-1.css b/assets/css/frontend/homepage-fixed/base-1.css new file mode 100644 index 00000000..3ca9aa28 --- /dev/null +++ b/assets/css/frontend/homepage-fixed/base-1.css @@ -0,0 +1,401 @@ +/** + * Homepage Fixed Layout — Zibll Visual Parity + * + * Implements Zibll's homepage visual language: + * - System font stack with Chinese fallbacks + * - 1200px container, 311px sidebar + * - Post cards: list mode (190px thumb) + card mode (3-col grid) + * - Zibll shadow/radius/spacing values + * - scale(1.02) thumbnail hover + * - Lazy-load animations (blur/fade/scale) + * - Full responsive: 1200/991/767/640px breakpoints + */ + +/* ================================================================ + 0. ANIMATIONS + ================================================================ */ + +@keyframes aksrt-lazy-blur { + from { filter: blur(5px); opacity: 0.6; } + to { filter: blur(0); opacity: 1; } +} + +@keyframes aksrt-lazy-fade { + from { opacity: 0; } + to { opacity: 1; } +} + +@keyframes aksrt-lazy-scale { + from { transform: scale(1.1); opacity: 0.8; } + to { transform: scale(1); opacity: 1; } +} + +@keyframes aksrt-skeleton-pulse { + 0%, 100% { opacity: 1; } + 50% { opacity: 0.4; } +} + +/* ================================================================ + 1. HOMEPAGE CONTAINER & TYPOGRAPHY + ================================================================ */ + +.aksrt-homepage { + font-family: "Helvetica Neue", Helvetica, Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", sans-serif; + font-size: 16px; + line-height: 1.42857143; + color: var(--main-color, #4e5358); + background: transparent; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.aksrt-homepage a[href] { + transition: color 0.2s, background 0.3s, opacity 0.3s, box-shadow 0.3s, transform 0.3s; +} + +.aksrt-homepage img.aksrt-loaded { + animation: aksrt-lazy-blur 0.6s ease; +} + +.aksrt-homepage img.aksrt-loaded.img-icon { + animation: aksrt-lazy-fade 0.6s ease; +} + +.aksrt-homepage .aksrt-skeleton { + animation: aksrt-skeleton-pulse 1.5s ease-in-out infinite; +} + +/* ================================================================ + 2. LAYOUT SHELL + ================================================================ */ + +.aksrt-homepage__fluid-zone.content-shell, +.aksrt-homepage__shell.content-shell { + max-width: min(100%, var(--container, 1200px)); +} + +.aksrt-homepage__fluid-zone.content-shell { + padding-top: 18px; + padding-bottom: 0; +} + +.aksrt-homepage__hero { + width: 100vw; + max-width: 100vw; + margin: 0 calc(-50vw + 50%) 24px; +} + +.aksrt-homepage__hero .header-components-container { + margin-bottom: 0; +} + +.aksrt-homepage__shell.content-shell { + padding-top: 0; + padding-bottom: 36px; +} + +.aksrt-homepage__content-layout { + gap: 20px; +} + +@media (min-width: 992px) { + .aksrt-homepage__content-layout { + grid-template-columns: minmax(0, 1fr) var(--sidebar-width, 311px); + } +} + +@media (max-width: 1200px) { + .aksrt-homepage__fluid-zone.content-shell, + .aksrt-homepage__shell.content-shell { + max-width: 95%; + } +} + +.aksrt-homepage__content-zone, +.aksrt-homepage__fluid-zone, +.aksrt-homepage__aside { + display: block; +} + +.aksrt-homepage__system-modules { + gap: 0; + padding-bottom: 0; +} + +.aksrt-homepage__content-zone.aksrt-homepage__system-modules { + margin-bottom: 20px; +} + +.aksrt-homepage__content-zone--featured { + margin-bottom: 20px; +} + +.aksrt-homepage__content-zone--featured.home-modules { + gap: 24px; + padding-bottom: 0; +} + +.aksrt-homepage__content-zone .widget-card:last-child, +.aksrt-homepage__aside .widget:last-child, +.aksrt-homepage__fluid-zone .widget-fluid:last-child { + margin-bottom: 0; +} + +/* ================================================================ + 3. FLUID WIDGETS + ================================================================ */ + +.aksrt-homepage__fluid-zone .widget-fluid { + margin-bottom: 20px; + background: transparent; + padding: 0; + border: 0; + box-shadow: none; +} + +.aksrt-homepage .widget-fluid.widget_aksrt_tab_posts, +.aksrt-homepage .widget-fluid.widget_aksrt_category_block, +.aksrt-homepage .widget-fluid.widget_aksrt_category_tabs, +.aksrt-homepage .widget-fluid.widget_aksrt_category_recommend { + padding: 15px; + background: var(--surface-1, #fff); + border-radius: var(--radius, 8px); + box-shadow: 0 0 10px var(--shadow, rgba(116, 116, 116, 0.08)); +} + +.aksrt-homepage__content-zone .widget-card, +.aksrt-homepage__aside .widget { + background: var(--surface-1, #fff); + padding: 15px; + border: none; + border-radius: var(--radius, 8px); + box-shadow: 0 0 10px var(--shadow, rgba(116, 116, 116, 0.08)); +} + +/* ================================================================ + 4. STREAM CONTAINER + ================================================================ */ + +.aksrt-homepage__stream, +.aksrt-homepage__stream.widget-card { + overflow: visible; + padding: 0; + background: transparent; + border: 0; + border-radius: 0; + box-shadow: none; + margin-bottom: 0; +} + +/* ================================================================ + 5. TABS + ================================================================ */ + +.aksrt-homepage__tabs, +.aksrt-homepage__titlebox { + margin-bottom: 10px; + padding-bottom: 0; + border-bottom: 0; +} + +.aksrt-homepage__tabs.box-body, +.aksrt-homepage__titlebox.box-body { + padding: 0; +} + +.aksrt-homepage__tabs-sentinel { + width: 100%; + height: 1px; + margin: 0; + pointer-events: none; +} + +.aksrt-homepage__tabs.home-tab-nav-box { + position: static; + z-index: auto; + background: transparent; +} + +.aksrt-homepage__tabs.home-tab-nav-box[data-sticky-tabs="true"] { + position: sticky; + top: var(--nav-height, 60px); + z-index: 995; + background: transparent; + transition: background-color 0.2s ease, + box-shadow 0.2s ease, + border-radius 0.2s ease, + padding 0.2s ease, + margin 0.2s ease, + backdrop-filter 0.2s ease, + -webkit-backdrop-filter 0.2s ease; +} + +.aksrt-homepage__tabs.home-tab-nav-box[data-sticky-tabs="true"].is-stuck, +.aksrt-homepage__tabs.home-tab-nav-box[data-sticky-tabs="true"].is-affixed { + margin-bottom: 14px; + padding: 10px 16px; + background: rgba(255, 255, 255, 0.92); + border-radius: 12px; + box-shadow: 0 10px 28px rgba(24, 24, 24, 0.08); + backdrop-filter: saturate(1.6) blur(20px); + -webkit-backdrop-filter: saturate(1.6) blur(20px); +} + +.aksrt-homepage__tabs.home-tab-nav-box[data-sticky-tabs="true"].is-affixed { + position: fixed; +} + +html.dark .aksrt-homepage__tabs.home-tab-nav-box[data-sticky-tabs="true"].is-stuck, +html.dark .aksrt-homepage__tabs.home-tab-nav-box[data-sticky-tabs="true"].is-affixed, +html.dark .aksrt-homepage__tabs.home-tab-nav-box[data-sticky-tabs="true"].is-stuck, +html.dark .aksrt-homepage__tabs.home-tab-nav-box[data-sticky-tabs="true"].is-affixed { + background: rgba(24, 24, 24, 0.82); + box-shadow: 0 12px 30px rgba(0, 0, 0, 0.24); +} + +.aksrt-homepage__tab-list { + list-style: none; + display: flex; + align-items: center; + gap: 4px; + margin: 0; + padding: 0; +} + +.aksrt-homepage__admin-link { + margin-left: auto; +} + +.scroll-x { + overflow-x: auto; + overflow-y: hidden; +} + +.no-scrollbar { + -ms-overflow-style: none; + scrollbar-width: none; +} + +.no-scrollbar::-webkit-scrollbar { + display: none; +} + +.aksrt-homepage__tab-item { + display: inline-flex; + flex: 0 0 auto; + padding: 0; + margin: 0; + border-radius: 20px; + font-weight: 500; + transition: background 0.2s ease, color 0.2s ease; +} + +.aksrt-homepage__tab-button { + padding: 6px 14px; + border: 0; + background: transparent; + color: var(--color-ink); + font-family: inherit; + font-size: 14px; + font-weight: inherit; + line-height: 1.2; + white-space: nowrap; + border-radius: inherit; + cursor: pointer; +} + +.aksrt-homepage__tab-button:hover { + color: var(--color-primary, var(--color-primary)); +} + +.aksrt-homepage__tab-item.is-active { + background: var(--color-primary, var(--color-primary)); +} + +.aksrt-homepage__tab-item.is-active .aksrt-homepage__tab-button, +.aksrt-homepage__tab-button[aria-selected="true"] { + color: #fff !important; +} + +/* ================================================================ + 6. SORTBAR + VIEW TOGGLE + ================================================================ */ + +.aksrt-homepage__sortbar { + display: flex; + align-items: center; + gap: 14px; + margin-bottom: 16px; + padding: 2px 0 14px; + border-bottom: 1px solid var(--color-line, rgba(50, 50, 50, 0.06)); + color: var(--color-ink-3, #777); + font-size: 14px; +} + +.aksrt-homepage__sortbar-label { + flex: 0 0 auto; + color: var(--color-ink); + font-weight: 700; +} + +.aksrt-homepage__sortbar-links { + display: flex; + align-items: center; + flex-wrap: wrap; + gap: 0; + flex: 1 1 auto; +} + +.aksrt-homepage__sortbar-link { + position: relative; + display: inline-flex; + align-items: center; + padding: 0 12px; + color: var(--color-ink-3, #777); + text-decoration: none; + line-height: 1.4; +} + +.aksrt-homepage__sortbar-link:first-child { + padding-left: 0; +} + +.aksrt-homepage__sortbar-link + .aksrt-homepage__sortbar-link::before { + content: "\00b7"; + position: absolute; + left: -2px; + color: var(--color-ink-4, #b1b1b1); +} + +.aksrt-homepage__sortbar-link:hover, +.aksrt-homepage__sortbar-link.is-active { + color: var(--color-ink); +} + +.aksrt-homepage__view-toggle { + display: inline-flex; + align-items: center; + gap: 6px; + margin-left: auto; + flex: 0 0 auto; +} + +.aksrt-homepage__view-btn { + display: inline-flex; + align-items: center; + justify-content: center; + width: 28px; + height: 28px; + padding: 0; + border: 0; + background: transparent; + color: var(--color-ink-4, #999); + border-radius: 4px; + cursor: pointer; + transition: color 0.2s, background 0.2s; +} + +.aksrt-homepage__view-btn:hover { + color: var(--color-ink); + background: var(--surface-2, #eee); +} diff --git a/assets/css/frontend/homepage-fixed/base-2.css b/assets/css/frontend/homepage-fixed/base-2.css new file mode 100644 index 00000000..3f33502b --- /dev/null +++ b/assets/css/frontend/homepage-fixed/base-2.css @@ -0,0 +1,400 @@ + +.aksrt-homepage__view-btn.is-active { + color: var(--color-primary, var(--color-primary)); +} + +.aksrt-homepage__view-btn svg { + width: 16px; + height: 16px; + fill: currentColor; +} + +/* ================================================================ + 7. TITLE THEME (sidebar section headers) + ================================================================ */ + +.title-theme { + position: relative; + padding-left: 1.2em; + font-size: 15px; + font-weight: 700; + line-height: 1.4; +} + +.title-theme::before { + position: absolute; + content: ""; + width: 4px; + background: var(--color-primary, var(--color-primary)); + top: 10%; + left: 2px; + bottom: 10%; + border-radius: 5px; + box-shadow: 1px 1px 3px -1px var(--color-primary, var(--color-primary)); +} + +.aksrt-homepage__page-indicator { + margin-left: 10px; + font-size: 80%; + font-weight: 400; + opacity: 0.7; +} + +/* ================================================================ + 8. PANELS + ================================================================ */ + +.aksrt-homepage__panel[hidden] { + display: none !important; +} + +.aksrt-homepage__panels { + display: block; +} + +.home-tab-content { + display: block; +} + +.index-tab-main .tab-pane[hidden], +.home-tab-content .tab-pane[hidden] { + display: none !important; +} + +.aksrt-homepage__panel { + opacity: 0; + transition: opacity 0.3s ease; +} + +.aksrt-homepage__panel.is-active, +.aksrt-homepage__panel:not([hidden]) { + opacity: 1; +} + +/* ================================================================ + 9. POST LIST — LIST MODE + ================================================================ */ + +.aksrt-homepage__posts { + display: block; + margin: 0; +} + +.aksrt-homepage__posts > .posts-item.list { + width: 100%; + margin: 15px 0; + padding: 20px; + display: flex; + flex-direction: row; + gap: 16px; + min-width: 0; + background: var(--surface-1, #fff); + border: none; + border-radius: var(--radius, 8px); + box-shadow: 0 0 10px var(--shadow, rgba(116, 116, 116, 0.08)); + overflow: hidden; + transition: box-shadow 0.2s, transform 0.2s; +} + +.aksrt-homepage__posts > .posts-item.list:last-child { + margin-bottom: 0; +} + +.aksrt-homepage__posts > .posts-item.list:hover { + box-shadow: 0 4px 16px rgba(116, 116, 116, 0.16); + transform: translateY(-1px); +} + +html.dark .aksrt-homepage__posts > .posts-item.list:hover, +html.dark .aksrt-homepage__posts > .posts-item.list:hover { + box-shadow: 0 4px 16px rgba(24, 24, 24, 0.22); +} + +.aksrt-homepage__posts > .posts-item.list .item-thumbnail { + position: relative; + width: 190px; + min-width: 190px; + height: 0; + padding-top: 0; + padding-bottom: calc(190px * 0.7); + border-radius: var(--radius, 8px); + overflow: hidden; + flex-shrink: 0; +} + +.aksrt-homepage__posts > .posts-item.list .item-thumbnail > a { + position: absolute; + inset: 0; + display: block; +} + +.aksrt-homepage__posts > .posts-item.list .item-thumbnail img { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + object-fit: cover; + transition: transform 0.3s; +} + +.aksrt-homepage__posts > .posts-item.list:hover .item-thumbnail img { + transform: scale(1.02); +} + +.aksrt-homepage__posts > .posts-item.list .item-thumbnail .aksrt-skeleton { + position: absolute; + inset: 0; + background: var(--surface-2, #eee); + border-radius: inherit; +} + +.aksrt-homepage__posts > .posts-item.list .item-thumbnail .img-badge { + position: absolute; + top: 8px; + left: 8px; + padding: 2px 6px; + border-radius: 4px; + font-size: 11px; + font-weight: 500; + line-height: 1.4; + background: rgba(0, 0, 0, 0.6); + color: #fff; + z-index: 1; +} + +.aksrt-homepage__posts > .posts-item.list .thumb-items { + display: none; +} + +.aksrt-homepage__posts > .posts-item.list.mult-thumb { + display: block; +} + +.aksrt-homepage__posts > .posts-item.list.mult-thumb .item-thumbnail { + display: none; +} + +.aksrt-homepage__posts > .posts-item.list.mult-thumb .thumb-items { + display: block; + margin: 0 -3px 6px; +} + +.aksrt-homepage__posts > .posts-item.list.mult-thumb .thumb-items > span { + position: relative; + display: inline-block; + width: calc(25% - 6px); + height: 0; + margin: 0 3px; + padding-bottom: calc(var(--posts-list-scale, 70%) / 4); +} + +.aksrt-homepage__posts > .posts-item.list.mult-thumb .thumb-items.contain > span { + overflow: hidden; + background: var(--color-line, rgba(50, 50, 50, 0.06)); + border-radius: var(--radius, 8px); +} + +.aksrt-homepage__posts > .posts-item.list.mult-thumb .thumb-items > span .aksrt-skeleton, +.aksrt-homepage__posts > .posts-item.list.mult-thumb .thumb-items > span > img { + position: absolute; + inset: 0; + width: 100%; + height: 100%; +} + +.aksrt-homepage__posts > .posts-item.list.mult-thumb .thumb-items > span > img { + object-fit: cover; + transition: transform 0.3s; +} + +.aksrt-homepage__posts > .posts-item.list.mult-thumb:hover .thumb-items > span > img { + transform: scale(1.02); +} + +.aksrt-homepage__posts > .posts-item.list.mult-thumb .item-body { + width: 100%; + padding: 2px 0 0; +} + +.aksrt-homepage__posts > .posts-item.list .item-body { + display: flex; + flex-direction: column; + justify-content: space-between; + gap: 8px; + margin: 0; + padding: 2px 0; + min-width: 0; + flex: 1 1 auto; +} + +.aksrt-homepage__posts .item-heading { + margin: 0 0 2px; + font-size: 18px; + font-weight: 500; + line-height: 1.4; + min-height: 0; + max-height: 2.8em; + overflow: hidden; + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + color: var(--color-ink); +} + +.aksrt-homepage__posts .item-heading a { + color: inherit; + text-decoration: none; +} + +.aksrt-homepage__posts .item-heading a:hover { + color: var(--color-primary, var(--color-primary)); +} + +.aksrt-homepage__posts .item-excerpt { + margin: 0; + color: var(--main-color, #4e5358); + font-size: 14px; + line-height: 1.6; + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + overflow: hidden; +} + +.aksrt-homepage__posts .item-tags { + display: flex; + align-items: center; + min-height: 0; + margin-bottom: 0; + gap: 5px; + flex-wrap: wrap; + overflow: visible; +} + +.aksrt-homepage__posts .item-tags .badge { + min-height: auto; + margin-right: 0; + padding: 2px 5px; + border-radius: 4px; + font-size: 11px; + line-height: 1.4; + font-weight: 400; +} + +.aksrt-homepage__posts .item-meta { + display: flex; + align-items: center; + justify-content: space-between; + margin: 0; + padding-top: 0; + border-top: 0; + font-size: 13px; + color: var(--color-ink-3, #777); +} + +.aksrt-homepage__posts .meta-author, +.aksrt-homepage__posts .meta-right { + display: flex; + align-items: center; + gap: 8px; +} + +.aksrt-homepage__posts .meta-avatar { + width: 24px; + height: 24px; + border-radius: 50%; +} + +.aksrt-homepage__posts .meta-name { + color: var(--color-ink); + font-weight: 500; +} + +.aksrt-homepage__posts .meta-dot { + width: 4px; + height: 4px; + border-radius: 999px; + background: var(--color-ink-4, #b1b1b1); +} + +.aksrt-homepage__posts .meta-item { + display: inline-flex; + align-items: center; + gap: 4px; + font-size: 13px; + white-space: nowrap; + color: var(--color-ink-3, #777); +} + +.aksrt-homepage__posts .meta-item i { + font-size: 12px; +} + +/* ================================================================ + 10. POST CARDS — CARD MODE (3-column grid) + ================================================================ */ + +.aksrt-homepage__posts[data-view="card"] { + display: flex; + flex-wrap: wrap; + margin: -8px; +} + +.aksrt-homepage__posts[data-view="card"] > .posts-item { + width: calc(33.333% - 16px); + margin: 8px; + padding: 10px; + display: flex; + flex-direction: column; + background: var(--surface-1, #fff); + border: none; + border-radius: var(--radius, 8px); + box-shadow: none; + overflow: hidden; + transition: box-shadow 0.3s, transform 0.2s; +} + +.aksrt-homepage__posts[data-view="card"] > .posts-item:hover { + box-shadow: 0 0 10px var(--shadow, rgba(116, 116, 116, 0.08)); +} + +.aksrt-homepage__posts[data-view="card"] > .posts-item.style2 { + background: transparent; + box-shadow: none; +} + +.aksrt-homepage__posts[data-view="card"] > .posts-item.style2:hover { + background: var(--surface-1, #fff); + box-shadow: 0 0 10px var(--shadow, rgba(116, 116, 116, 0.08)); +} + +.aksrt-homepage__posts[data-view="card"] > .posts-item.style3 { + padding: 0; +} + +.aksrt-homepage__posts[data-view="card"] > .posts-item .item-thumbnail { + position: relative; + display: block; + width: 100%; + height: 0; + padding-top: 0; + padding-bottom: var(--posts-card-scale, 70%); + min-width: unset; + border-radius: var(--radius, 8px); + overflow: hidden; +} + +.aksrt-homepage__posts[data-view="card"] > .posts-item .item-thumbnail > a { + position: absolute; + inset: 0; + display: block; +} + +.aksrt-homepage__posts[data-view="card"] > .posts-item .item-thumbnail img { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + object-fit: cover; diff --git a/assets/css/frontend/homepage-fixed/base-3.css b/assets/css/frontend/homepage-fixed/base-3.css new file mode 100644 index 00000000..5e2fb9d7 --- /dev/null +++ b/assets/css/frontend/homepage-fixed/base-3.css @@ -0,0 +1,245 @@ + transition: transform 0.3s; +} + +.aksrt-homepage__posts[data-view="card"] > .posts-item.mult-thumb .thumb-items { + display: none; +} + +.aksrt-homepage__posts[data-view="card"] > .posts-item.mult-thumb .item-thumbnail { + display: block; +} + +.aksrt-homepage__posts[data-view="card"] > .posts-item.style3 .item-thumbnail, +.aksrt-homepage__posts[data-view="card"] > .posts-item.style3 .item-thumbnail img { + border-radius: var(--radius, 8px) var(--radius, 8px) 0 0; +} + +.aksrt-homepage__posts[data-view="card"] > .posts-item:hover .item-thumbnail img { + transform: scale(1.02); +} + +.aksrt-homepage__posts[data-view="card"] > .posts-item .item-body { + width: 100%; + margin: 10px 0 0; + padding: 0; + gap: 6px; +} + +.aksrt-homepage__posts[data-view="card"] > .posts-item.style3 .item-body { + margin: 0; + padding: 10px; +} + +.aksrt-homepage__posts[data-view="card"] > .posts-item .item-heading { + font-size: 14px; + font-weight: 500; + line-height: 1.4; + min-height: 2.8em; + -webkit-line-clamp: 2; +} + +.aksrt-homepage__posts[data-view="card"] > .posts-item .item-excerpt { + display: none; +} + +.aksrt-homepage__posts[data-view="card"] > .posts-item .item-meta { + font-size: 12px; +} + +.aksrt-homepage__posts[data-view="card"] > .posts-item .meta-right { + display: none; +} + +/* ================================================================ + 11. PAGINATION + ================================================================ */ + +.aksrt-homepage__panel-footer { + display: flex; + justify-content: center; + margin-top: 18px; +} + +.aksrt-homepage__more, +.aksrt-homepage .aksrt-load-more-btn { + display: inline-flex; + align-items: center; + justify-content: center; + min-height: 34px; + padding: 0 14px; + border: 1px solid var(--color-line, rgba(50, 50, 50, 0.06)); + border-radius: var(--radius, 8px); + background: var(--surface-1, #fff); + color: var(--color-ink-3, #777); + font-size: 13px; + font-weight: 500; + transition: border-color 0.2s ease, color 0.2s ease, background 0.2s ease; +} + +.aksrt-homepage__more:hover, +.aksrt-homepage .aksrt-load-more-btn:hover { + color: var(--color-primary, var(--color-primary)); + border-color: var(--color-primary, var(--color-primary)); + box-shadow: none; + transform: none; +} + +.aksrt-homepage .ajax-pagination { + display: flex; + flex-direction: column; + align-items: center; + gap: 10px; + margin-top: 20px; +} + +.aksrt-homepage .navigation.pagination .nav-links, +.aksrt-homepage .pagination { + gap: 0; + margin: 20px 0 10px; +} + +.aksrt-homepage .navigation.pagination .page-numbers, +.aksrt-homepage .pagination .page-numbers { + min-width: 31px; + height: auto; + padding: 6px 9px 5px; + margin: 3px; + border: 0; + border-radius: 3px; + background: var(--surface-2, #eee); + color: var(--color-ink-3, #777); + font-size: 13px; + line-height: 1.4; +} + +.aksrt-homepage .navigation.pagination .page-numbers:hover, +.aksrt-homepage .pagination .page-numbers:hover { + opacity: 0.7; +} + +.aksrt-homepage .navigation.pagination .current, +.aksrt-homepage .pagination .current { + background: var(--color-primary, var(--color-primary)) !important; + color: #fff !important; +} + +/* ================================================================ + 12. SIDEBAR + ================================================================ */ + +.aksrt-homepage__aside .widget-list li, +.aksrt-homepage__aside .widget_recent_entries li, +.aksrt-homepage__aside .recent-posts-row { + padding-top: 8px; + padding-bottom: 8px; +} + +.aksrt-homepage__aside .widget-title, +.aksrt-homepage__content-zone .widget-title { + margin-bottom: 12px; +} + +.aksrt-homepage__aside .widget-title { + position: relative; + margin: 0 0 10px; + padding-left: 1.2em; + padding-bottom: 8px; + font-size: 15px; + font-weight: 700; + line-height: 1.4; +} + +.aksrt-homepage__aside .widget-title::before { + content: ""; + position: absolute; + top: 10%; + bottom: 10%; + left: 2px; + width: 4px; + height: auto; + background: var(--color-primary, var(--color-primary)); + border-radius: 5px; + box-shadow: 1px 1px 3px -1px var(--color-primary, var(--color-primary)); + transition: transform 0.4s ease; + transform-origin: left; +} + +.aksrt-homepage__aside .widget_recent_entries li a, +.aksrt-homepage__aside .widget-list li a { + font-size: 13px; + font-weight: 500; + line-height: 1.5; +} + +.aksrt-homepage__aside .widget_recent_entries li { + display: block; +} + +.aksrt-homepage__aside .widget_search .search-field { + height: 40px; + border-radius: 30px; + background: var(--surface-2, #eee); +} + +.aksrt-homepage__aside .widget_search .search-submit { + top: 4px; + right: 4px; + height: 32px; + padding: 0 12px; + border-radius: 30px; + font-size: 12px; +} + +.aksrt-homepage__aside .tag-cloud { + gap: 6px; +} + +.aksrt-homepage__aside .tag-cloud a { + padding: 4px 10px; + border-radius: 20px; + font-size: 12px; + border: 0; + background: var(--surface-2, #eee); + transition: background 0.2s, color 0.2s; +} + +.aksrt-homepage__aside .tag-cloud a:hover { + background: var(--color-primary, var(--color-primary)); + color: #fff; +} + +.aksrt-homepage .widget.notop, +.aksrt-homepage .box-body.notop { + padding-top: 0; +} + +.aksrt-homepage .widget.nobottom, +.aksrt-homepage .box-body.nobottom { + padding-bottom: 0; +} + +.aksrt-homepage .widget.widget_custom_html { + padding: 0; + background: transparent; + box-shadow: none; + border-radius: 0; +} + +/* ================================================================ + 13. LOADING & EMPTY STATES + ================================================================ */ + +.aksrt-homepage .aksrt-loading-indicator { + display: flex; + align-items: center; + gap: 8px; + color: var(--color-ink-3, #777); + font-size: 13px; +} + +.aksrt-homepage__stream .no-results { + padding: 32px 16px; + text-align: center; + color: var(--color-ink-4, #999); +} + diff --git a/assets/css/frontend/homepage-fixed/base.css b/assets/css/frontend/homepage-fixed/base.css new file mode 100644 index 00000000..4e615659 --- /dev/null +++ b/assets/css/frontend/homepage-fixed/base.css @@ -0,0 +1,3 @@ +@import url("base-1.css"); +@import url("base-2.css"); +@import url("base-3.css"); diff --git a/assets/css/frontend/layout.css b/assets/css/frontend/layout.css new file mode 100644 index 00000000..8b0530e9 --- /dev/null +++ b/assets/css/frontend/layout.css @@ -0,0 +1,516 @@ +/* ========== 面包屑 — 对齐 zibll .breadcrumb ========== */ +.breadcrumbs { + font-size: 13px; + color: var(--muted-2-color, #999); + margin-bottom: 12px; + opacity: 0.8; +} + +.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; + } +} + +/* 封面内面包屑 */ +.single-cover-con .breadcrumbs { + font-size: 13px; + margin: 5px 0 0 -6px; + opacity: unset; +} + +/* ========== 主布局 ========== */ +.content-shell { + width: 100%; + margin: 0 auto; + padding: 32px 16px 48px; + max-width: var(--container); +} + +@media (min-width: 768px) { + .content-shell { + padding: 40px 24px 56px; + } +} + +/* page.php 专用:阅读宽度收窄 */ +.content-shell--page { + max-width: var(--container-page, 860px); +} + +.content-shell--cms { + max-width: 100%; + padding: 0; +} + +/* page.php 内的元素 */ +.entry-page .entry-thumb { + margin: 0 0 var(--space-6, 24px); + border-radius: var(--radius-lg, 12px); + overflow: hidden; +} + +.entry-page .page-links { + margin-top: var(--space-6, 24px); + font-size: var(--text-sm, 0.875rem); + color: var(--color-ink-3, var(--color-ink-3)); +} + +.entry-page .page-links-title { + margin-right: 8px; + font-weight: 600; +} + +.content-layout { + display: grid; + grid-template-columns: 1fr; + gap: 20px; + align-items: start; +} + +@media (min-width: 992px) { + .content-layout { + grid-template-columns: minmax(0, 1fr) var(--sidebar-width, 311px); + gap: 20px; + } +} + +.content-layout__primary { + min-width: 0; +} + +.content-layout__aside { + min-width: 0; +} + +@media (min-width: 992px) { + .content-layout__aside { + position: sticky; + top: calc(var(--nav-height, 60px) + 16px); + align-self: start; + } + + /* WordPress Admin Bar 已全局禁用,无需偏移规则 */ +} + +@media (min-width: 992px) { + .has-static-nav .content-layout__aside { + top: 16px; + } +} + +.content-layout--no-sidebar { + grid-template-columns: 1fr; +} + +.content-layout--no-sidebar .content-layout__primary { + width: 100%; + max-width: var(--content-no-sidebar-max, 1080px); + margin: 0 auto; +} + +/* 三栏布局变体:侧边栏在左侧 */ +@media (min-width: 992px) { + .content-layout--sidebar-left { + grid-template-columns: var(--sidebar-width, 311px) minmax(0, 1fr); + } + + .content-layout--sidebar-left .content-layout__aside { + order: -1; + } +} + +/* ========== 页面标题区 ========== */ +.page-header { + margin-bottom: 28px; +} + +.page-header .entry-title { + margin-bottom: 8px; +} + +.page-header p { + color: var(--color-ink-3); + margin: 0; + max-width: 720px; +} + +.term-page-header { + position: relative; + overflow: hidden; + border: 1px solid var(--color-line-soft, rgba(15, 23, 42, 0.08)); + border-radius: var(--radius-lg); + background: var(--surface-1); + box-shadow: var(--shadow-sm, 0 1px 6px rgba(15, 23, 42, 0.04)); +} + +.term-page-header__body { + position: relative; + z-index: 1; + display: flex; + align-items: flex-start; + justify-content: space-between; + gap: 16px; + padding: 24px; +} + +.term-page-header__eyebrow { + margin: 0 0 8px; + font-size: 0.8125rem; + font-weight: 700; + letter-spacing: 0.08em; + text-transform: uppercase; + color: var(--color-primary); +} + +.term-page-header__desc { + margin-top: 10px; +} + +.term-page-header__cover { + min-height: 140px; + background-position: center; + background-size: cover; + border-top: 1px solid var(--color-line-soft, rgba(15, 23, 42, 0.08)); +} + +.term-page-header--simple .term-page-header__cover { + display: none; +} + +/* Card style: accent top border, slightly more padding */ +.term-page-header--card { + border-top: 3px solid var(--color-primary, #f04494); +} + +.term-page-header--card .term-page-header__body { + padding: 28px 24px; +} + +/* Cover style: full-width hero with background image */ +.term-page-header--cover { + border: none; + border-radius: var(--radius-lg); + background: transparent; + box-shadow: none; + min-height: 220px; + display: flex; + flex-direction: column; +} + +.term-page-header__cover-bg { + position: absolute; + inset: 0; + background-position: center; + background-size: cover; + border-radius: var(--radius-lg); +} + +.term-page-header__cover-overlay { + position: absolute; + inset: 0; + background: linear-gradient(135deg, rgba(0, 0, 0, 0.55) 0%, rgba(0, 0, 0, 0.25) 100%); + border-radius: var(--radius-lg); +} + +.term-page-header--cover .term-page-header__body { + flex: 1; + align-items: flex-end; + z-index: 2; +} + +.term-page-header__body--overlay .entry-title, +.term-page-header__body--overlay .term-page-header__desc, +.term-page-header__body--overlay .term-page-header__eyebrow { + color: #fff; +} + +.term-page-header__body--overlay .term-page-header__eyebrow { + color: rgba(255, 255, 255, 0.8); +} + +@media (max-width: 767px) { + .term-page-header--cover { + min-height: 160px; + } +} + +.aksrt-admin-quicklink { + display: inline-flex; + align-items: center; + gap: 8px; + min-height: 36px; + padding: 0 14px; + border: 1px solid var(--color-line); + border-radius: var(--radius-pill, 999px); + background: var(--surface-2); + color: var(--color-ink-2); + text-decoration: none; + white-space: nowrap; + font-size: 0.875rem; + font-weight: 600; +} + +.aksrt-admin-quicklink:hover { + color: var(--color-primary); + border-color: var(--color-primary); + background: var(--color-primary-soft, rgba(59, 130, 246, 0.08)); +} + +.archive-filter-bar { + display: flex; + align-items: center; + justify-content: space-between; + gap: 16px; + flex-wrap: wrap; + margin: -8px 0 24px; + padding: 16px 18px; + border-radius: var(--radius-lg); + background: var(--surface-2); + border: 1px solid var(--color-line-soft, rgba(15, 23, 42, 0.06)); +} + +.archive-filter-bar__main { + display: flex; + align-items: center; + gap: 12px; + flex-wrap: wrap; +} + +.archive-filter-bar__label { + color: var(--color-ink-4); + font-size: 0.8125rem; + font-weight: 600; +} + +.archive-filter-bar__chips { + display: flex; + align-items: center; + flex-wrap: wrap; + gap: 8px; +} + +.archive-filter-bar__chip { + display: inline-flex; + align-items: center; + min-height: 34px; + padding: 0 12px; + border-radius: var(--radius-pill, 999px); + background: var(--surface-1); + color: var(--color-ink-2); + text-decoration: none; + font-size: 0.875rem; + font-weight: 500; +} + +.archive-filter-bar__chip.is-active, +.archive-filter-bar__chip:hover { + background: var(--color-primary); + color: var(--color-on-primary, #fff); +} + +.archive-filter-bar__meta { + color: var(--color-ink-4); + font-size: 0.8125rem; + font-weight: 600; +} + +.archive-filter-bar__sort { + display: flex; + align-items: center; + gap: 8px; + margin-left: auto; +} + +.archive-filter-bar__main--tags { + border-top: 1px solid var(--color-line-soft, rgba(15, 23, 42, 0.06)); + padding-top: 10px; + margin-top: 10px; +} + +/* §3.4 custom_filter dimension rows */ +.archive-filter-bar__main--custom { + border-top: 1px solid var(--color-line-soft, rgba(15, 23, 42, 0.06)); + padding-top: 10px; + margin-top: 10px; +} + +/* AJAX 筛选加载状态 */ +.archive__ajax-wrap { + position: relative; + transition: opacity 0.2s ease; +} + +.archive__ajax-wrap.is-loading { + opacity: 0.5; + pointer-events: none; +} + +.archive__ajax-loading { + display: none; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + align-items: center; + justify-content: center; + z-index: 5; + background: rgba(255, 255, 255, 0.6); + backdrop-filter: blur(1px); +} + +.archive__ajax-loading.is-loading { + display: flex; +} + +.archive__ajax-spinner { + display: inline-block; + width: 28px; + height: 28px; + border: 3px solid var(--surface-3, #e8e8e8); + border-top-color: var(--color-primary, #f04494); + border-radius: 50%; + animation: aksrt-spin 0.6s linear infinite; +} + +@media (max-width: 767px) { + .term-page-header__body { + flex-direction: column; + align-items: stretch; + padding: 20px; + } + + .aksrt-admin-quicklink { + width: fit-content; + } +} + +/* ========== AJAX 分页(加载更多 / 无限滚动) ========== */ +.aksrt-pagination-ajax { + display: flex; + flex-direction: column; + align-items: center; + gap: 16px; + margin: 40px 0 8px; +} + +.aksrt-load-more-btn { + min-width: 180px; + height: 44px; + padding: 0 32px; + border-radius: var(--radius-btn); + border: 1px solid var(--color-line); + background: var(--surface-page); + color: var(--color-ink); + font-size: 14px; + font-weight: 600; + cursor: pointer; + transition: border-color 0.2s, color 0.2s, background 0.2s; + display: inline-flex; + align-items: center; + justify-content: center; + gap: 8px; +} + +.aksrt-load-more-btn:hover { + border-color: var(--color-primary); + color: var(--color-primary); +} + +.aksrt-load-more-btn:disabled { + opacity: 0.5; + pointer-events: none; +} + +.aksrt-loading-indicator { + display: none; + align-items: center; + gap: 8px; + font-size: 14px; + color: var(--color-ink-4); +} + +.aksrt-loading-indicator i { + font-size: 16px; +} + +.aksrt-scroll-sentinel { + width: 100%; + height: 1px; + pointer-events: none; +} + +/* ========== 移动端/平板隐藏侧栏(与 zibll 一致:991px 以下隐藏) ========== */ +@media (max-width: 991px) { + .content-layout__aside { + display: none; + } +} + +/* CMS 模块在侧栏布局中的适配 */ +.content-layout__primary--cms { + min-width: 0; +} + +.content-layout__primary--cms .home-modules { + gap: var(--space-7, 32px); +} + +.content-layout__primary--cms .home-modules > .home-module { + max-width: 100%; + padding-left: 0; + padding-right: 0; +} + +/* ============================================================ + * Phase 2 — 背景遮罩层级修正 + * body.aksrt-bg-overlay 的 ::before 需要 z-index: -1 让内容在其上方 + * ============================================================ */ +body.aksrt-bg-overlay { + position: relative; +} + +body.aksrt-bg-overlay::before { + z-index: -1; +} + +body.aksrt-bg-overlay .site-wrapper { + position: relative; + z-index: 0; +} + +/* ============================================================ + * Phase 2 — 侧栏 widget 内链接增强 + * ============================================================ */ +.content-layout__aside .widget a { + transition: color var(--dur-fast, 0.15s) var(--ease); +} + +.content-layout__aside .widget a:hover { + color: var(--color-primary); +} + +/* ============================================================ + * Phase 5 — 文章操作卡片增强 + * ============================================================ */ + +/* ============================================================ + * Phase 6 — 评论卡片容器 + * ============================================================ */ +.comments-card { + overflow: hidden; +} diff --git a/assets/css/frontend/menu-decorations.css b/assets/css/frontend/menu-decorations.css new file mode 100644 index 00000000..82554756 --- /dev/null +++ b/assets/css/frontend/menu-decorations.css @@ -0,0 +1,280 @@ +/** + * AKSRT Menu Decorations + * + * 菜单图标、徽章、多列下拉、图文卡片子菜单样式。 + * 所有选择器均带 aksrt- 或 .site-nav 命名空间。 + */ + +/* ========== 菜单图标 ========== */ +.nav-desktop .menu-item > a .menu-icon, +.nav-desktop .menu-item > a > i:first-child { + display: inline-flex; + align-items: center; + margin-right: 6px; + font-size: 14px; + opacity: 0.75; + transition: opacity 0.2s ease; +} + +.nav-desktop .menu-item:hover > a .menu-icon, +.nav-desktop .menu-item:hover > a > i:first-child { + opacity: 1; +} + +/* ========== 菜单徽章 ========== */ +.nav-desktop .menu-item > a .menu-badge, +.nav-desktop .menu-item > a .aksrt-menu-badge { + display: inline-flex; + align-items: center; + justify-content: center; + margin-left: 6px; + padding: 1px 6px; + font-size: 10px; + font-weight: 700; + line-height: 1.4; + letter-spacing: 0.02em; + border-radius: 8px; + white-space: nowrap; + vertical-align: middle; + transform: translateY(-1px); +} + +.aksrt-menu-badge--new { + background: var(--color-primary); + color: #fff; +} + +.aksrt-menu-badge--hot { + background: #ff4d4f; + color: #fff; +} + +.aksrt-menu-badge--info { + background: var(--color-info, #1890ff); + color: #fff; +} + +.aksrt-menu-badge--success { + background: var(--color-success, #52c41a); + color: #fff; +} + +.aksrt-menu-badge--warning { + background: var(--color-warning, #faad14); + color: #fff; +} + +/* ========== Hover 效果 ========== */ +/* 下划线效果 */ +.aksrt-menu-hover--underline .nav-desktop .menu-item > a { + position: relative; +} + +.aksrt-menu-hover--underline .nav-desktop .menu-item > a::after { + content: ''; + position: absolute; + bottom: 0; + left: 50%; + width: 0; + height: 2px; + background: var(--color-primary); + border-radius: 1px; + transform: translateX(-50%); + transition: width 0.25s ease; +} + +.aksrt-menu-hover--underline .nav-desktop .menu-item:hover > a::after, +.aksrt-menu-hover--underline .nav-desktop .menu-item.current-menu-item > a::after, +.aksrt-menu-hover--underline .nav-desktop .menu-item.current_page_item > a::after { + width: 70%; +} + +/* 背景色效果 */ +.aksrt-menu-hover--background .nav-desktop .menu-item > a { + border-radius: 6px; + transition: background-color 0.2s ease; +} + +.aksrt-menu-hover--background .nav-desktop .menu-item:hover > a { + background-color: var(--color-primary-soft, rgba(240, 68, 148, 0.08)); +} + +/* 文字变色效果 */ +.aksrt-menu-hover--color .nav-desktop .menu-item > a { + transition: color 0.2s ease; +} + +.aksrt-menu-hover--color .nav-desktop .menu-item:hover > a { + color: var(--color-primary); +} + +/* ========== 多列 Mega 下拉 ========== */ +.nav-desktop .menu-item .aksrt-mega-submenu { + position: absolute; + top: 100%; + left: 50%; + z-index: 999; + min-width: var(--aksrt-mega-width, 480px); + padding: 16px 20px; + background: var(--surface-page, #fff); + border: 1px solid var(--color-line, #e8e8e8); + border-radius: 8px; + box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12); + opacity: 0; + visibility: hidden; + transform: translateX(-50%) translateY(8px); + transition: opacity 0.2s ease, transform 0.2s ease, visibility 0.2s ease; +} + +.nav-desktop .menu-item:hover .aksrt-mega-submenu { + opacity: 1; + visibility: visible; + transform: translateX(-50%) translateY(0); +} + +.aksrt-mega-submenu__grid { + display: grid; + gap: 12px; +} + +.aksrt-mega-submenu__grid--cols-2 { grid-template-columns: repeat(2, 1fr); } +.aksrt-mega-submenu__grid--cols-3 { grid-template-columns: repeat(3, 1fr); } +.aksrt-mega-submenu__grid--cols-4 { grid-template-columns: repeat(4, 1fr); } +.aksrt-mega-submenu__grid--cols-5 { grid-template-columns: repeat(5, 1fr); } + +.aksrt-mega-submenu__item { + display: flex; + align-items: flex-start; + gap: 10px; + padding: 10px 12px; + border-radius: 6px; + text-decoration: none; + color: var(--color-ink); + transition: background-color 0.15s ease; +} + +.aksrt-mega-submenu__item:hover { + background-color: var(--color-primary-soft, rgba(240, 68, 148, 0.08)); +} + +.aksrt-mega-submenu__item-icon { + flex-shrink: 0; + display: flex; + align-items: center; + justify-content: center; + width: 32px; + height: 32px; + border-radius: 6px; + background: var(--color-primary-soft, rgba(240, 68, 148, 0.08)); + color: var(--color-primary); + font-size: 14px; +} + +.aksrt-mega-submenu__item-content { + flex: 1; + min-width: 0; +} + +.aksrt-mega-submenu__item-title { + font-size: 13px; + font-weight: 500; + line-height: 1.4; + color: var(--color-ink); +} + +.aksrt-mega-submenu__item-desc { + margin-top: 2px; + font-size: 12px; + line-height: 1.4; + color: var(--text-tertiary, #8a909c); + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +/* ========== 图文卡片子菜单 ========== */ +.nav-desktop .menu-item .aksrt-card-submenu { + position: absolute; + top: 100%; + left: 50%; + z-index: 999; + display: flex; + gap: 12px; + padding: 16px; + background: var(--surface-page, #fff); + border: 1px solid var(--color-line, #e8e8e8); + border-radius: 8px; + box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12); + opacity: 0; + visibility: hidden; + transform: translateX(-50%) translateY(8px); + transition: opacity 0.2s ease, transform 0.2s ease, visibility 0.2s ease; +} + +.nav-desktop .menu-item:hover .aksrt-card-submenu { + opacity: 1; + visibility: visible; + transform: translateX(-50%) translateY(0); +} + +.aksrt-card-submenu__item { + display: flex; + flex-direction: column; + width: var(--aksrt-card-width, 160px); + text-decoration: none; + border-radius: 8px; + overflow: hidden; + transition: transform 0.2s ease, box-shadow 0.2s ease; +} + +.aksrt-card-submenu__item:hover { + transform: none; + box-shadow: none; +} + +.aksrt-card-submenu__thumb { + width: 100%; + aspect-ratio: 16 / 10; + object-fit: cover; + background: var(--color-fill, #f5f5f5); +} + +.aksrt-card-submenu__body { + padding: 8px 10px; +} + +.aksrt-card-submenu__title { + font-size: 13px; + font-weight: 500; + line-height: 1.4; + color: var(--color-ink); + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.aksrt-card-submenu__desc { + margin-top: 2px; + font-size: 11px; + line-height: 1.4; + color: var(--text-tertiary, #8a909c); + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +/* ========== 暗色模式适配 ========== */ +html.dark .aksrt-mega-submenu, +body.dark-theme .aksrt-mega-submenu, +html.dark .aksrt-card-submenu, +body.dark-theme .aksrt-card-submenu { + background: var(--surface-page); + border-color: var(--color-line, #2d2d3f); +} + +html.dark .aksrt-mega-submenu__item-title, +body.dark-theme .aksrt-mega-submenu__item-title, +html.dark .aksrt-card-submenu__title, +body.dark-theme .aksrt-card-submenu__title { + color: var(--color-ink); +} diff --git a/assets/css/frontend/messages.css b/assets/css/frontend/messages.css new file mode 100644 index 00000000..f05eba2b --- /dev/null +++ b/assets/css/frontend/messages.css @@ -0,0 +1,580 @@ +/* ============================================================ + * Messages Center — 独立消息中心页面 + * ============================================================ */ + +.messages-center { + display: grid; + grid-template-columns: 220px 1fr; + gap: 24px; + min-height: 60vh; + padding-top: 24px; + padding-bottom: 48px; +} + +/* ---- 左侧导航 ---- */ +.messages-center__nav { + position: sticky; + top: calc(var(--nav-height, 60px) + 24px); + align-self: start; + background: var(--surface-card, #fff); + border-radius: 12px; + padding: 16px 12px; + box-shadow: 0 1px 4px rgba(0, 0, 0, 0.06); +} + +.messages-nav__list { + list-style: none; + margin: 0; + padding: 0; +} + +.messages-nav__item { + display: flex; + align-items: center; + justify-content: space-between; + padding: 10px 12px; + border-radius: 8px; + color: var(--color-ink); + text-decoration: none; + font-size: 14px; + transition: background 0.15s, color 0.15s; + cursor: pointer; +} + +.messages-nav__item:hover { + background: var(--surface-hover, rgba(0, 0, 0, 0.04)); +} + +.messages-nav__item.is-active { + background: var(--color-primary-light, rgba(59, 130, 246, 0.08)); + color: var(--color-primary, #3b82f6); + font-weight: 600; +} + +.messages-nav__badge { + display: inline-flex; + align-items: center; + justify-content: center; + min-width: 20px; + height: 20px; + padding: 0 6px; + border-radius: 10px; + background: var(--color-primary, #3b82f6); + color: #fff; + font-size: 11px; + font-weight: 600; + line-height: 1; +} + +.messages-nav__badge:empty, +.messages-nav__badge[data-count="0"] { + display: none; +} + +.messages-nav__actions { + display: flex; + flex-direction: column; + gap: 6px; + margin-top: 16px; + padding-top: 12px; + border-top: 1px solid var(--color-line); +} + +.messages-nav__action-btn { + display: block; + width: 100%; + padding: 8px 12px; + border: none; + border-radius: 6px; + background: var(--surface-hover, rgba(0, 0, 0, 0.04)); + color: var(--color-ink-3, #666); + font-size: 13px; + cursor: pointer; + text-align: center; + transition: background 0.15s; +} + +.messages-nav__action-btn:hover { + background: var(--surface-active, rgba(0, 0, 0, 0.08)); +} + +/* ---- 右侧内容 ---- */ +.messages-center__content { + min-width: 0; +} + +.messages-list { + display: flex; + flex-direction: column; + gap: 1px; + background: var(--surface-card, #fff); + border-radius: 12px; + overflow: hidden; + box-shadow: 0 1px 4px rgba(0, 0, 0, 0.06); +} + +.message-item { + display: flex; + align-items: flex-start; + gap: 12px; + padding: 16px 20px; + background: var(--surface-card, #fff); + border-bottom: 1px solid var(--color-border-light, #f3f4f6); + transition: background 0.15s; +} + +.message-item:last-child { + border-bottom: none; +} + +.message-item:hover { + background: var(--surface-hover, rgba(0, 0, 0, 0.02)); +} + +.message-item.is-unread { + border-left: 3px solid var(--color-primary, #3b82f6); +} + +.message-item.is-unread .message-item__title { + font-weight: 600; +} + +.message-item__icon { + display: flex; + align-items: center; + justify-content: center; + width: 36px; + height: 36px; + min-width: 36px; + border-radius: 50%; + background: var(--color-primary-light, rgba(59, 130, 246, 0.1)); + color: var(--color-primary, #3b82f6); + font-size: 14px; +} + +.message-item__body { + flex: 1; + min-width: 0; +} + +.message-item__title { + font-size: 14px; + color: var(--color-ink); + margin-bottom: 4px; + display: flex; + align-items: center; + gap: 8px; +} + +.message-item__new-badge { + display: inline-block; + padding: 1px 6px; + border-radius: 3px; + background: var(--color-danger, #ef4444); + color: #fff; + font-size: 10px; + font-weight: 600; + line-height: 1.4; +} + +.message-item__desc { + font-size: 13px; + color: var(--color-ink-3, #666); + margin-bottom: 4px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.message-item__time { + font-size: 12px; + color: var(--color-ink-4, #999); +} + +.message-item__actions { + display: flex; + align-items: center; + gap: 8px; + flex-shrink: 0; +} + +.message-item__action-btn { + padding: 4px 10px; + border: none; + border-radius: 4px; + background: transparent; + color: var(--color-ink-3, #666); + font-size: 12px; + cursor: pointer; + transition: background 0.15s, color 0.15s; +} + +.message-item__action-btn:hover { + background: var(--surface-hover, rgba(0, 0, 0, 0.06)); + color: var(--color-primary, #3b82f6); +} + +.message-item__action-btn--danger:hover { + color: var(--color-danger, #ef4444); +} + +/* ---- 空状态 ---- */ +.messages-empty { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 64px 24px; + background: var(--surface-card, #fff); + border-radius: 12px; + box-shadow: 0 1px 4px rgba(0, 0, 0, 0.06); +} + +.messages-empty__icon { + font-size: 48px; + color: var(--color-ink-4, #ccc); + margin-bottom: 16px; +} + +.messages-empty__text { + font-size: 14px; + color: var(--color-ink-3, #666); +} + +.messages-empty__hint { + margin-top: 4px; + font-size: 12px; + color: var(--color-ink-4, #999); +} + +/* ---- 分页 ---- */ +.messages-pagination { + display: flex; + justify-content: center; + gap: 8px; + margin-top: 24px; +} + +/* ---- 响应式 ---- */ +@media (max-width: 767px) { + .messages-center { + grid-template-columns: 1fr; + gap: 16px; + padding-top: 16px; + } + + .messages-center__nav { + position: static; + padding: 12px; + border-radius: 8px; + } + + .messages-nav__list { + display: flex; + overflow-x: auto; + gap: 4px; + scrollbar-width: none; + } + + .messages-nav__list::-webkit-scrollbar { + display: none; + } + + .messages-nav__item { + white-space: nowrap; + padding: 8px 12px; + font-size: 13px; + border-radius: 20px; + } + + .messages-nav__actions { + flex-direction: row; + margin-top: 12px; + padding-top: 10px; + } + + .message-item { + padding: 12px 14px; + } + + .message-item__actions { + flex-direction: column; + gap: 4px; + } +} + +/* ---- 暗色模式 ---- */ +html.dark .messages-center__nav, +html.dark .messages-center__nav { + background: var(--surface-1); + box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3); +} + +html.dark .messages-nav__item:hover, +html.dark .messages-nav__item:hover { + background: rgba(255, 255, 255, 0.05); +} + +html.dark .messages-nav__item.is-active, +html.dark .messages-nav__item.is-active { + background: var(--color-primary-soft, rgba(240, 68, 148, 0.16)); +} + +html.dark .messages-nav__action-btn, +html.dark .messages-nav__action-btn { + background: var(--surface-2); + color: var(--color-ink-3); +} + +html.dark .messages-nav__action-btn:hover, +html.dark .messages-nav__action-btn:hover { + background: var(--surface-3); +} + +html.dark .messages-list, +html.dark .messages-list { + background: var(--surface-1); + box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3); +} + +html.dark .message-item, +html.dark .message-item { + background: var(--surface-1); + border-bottom-color: var(--color-line); +} + +html.dark .message-item:hover, +html.dark .message-item:hover { + background: var(--surface-2); +} + +html.dark .message-item__icon, +html.dark .message-item__icon { + background: var(--color-primary-soft, rgba(240, 68, 148, 0.16)); +} + +html.dark .message-item__action-btn:hover, +html.dark .message-item__action-btn:hover { + background: var(--surface-3); +} + +html.dark .messages-empty, +html.dark .messages-empty { + background: var(--surface-1); + box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3); +} + +html.dark .messages-nav__actions, +html.dark .messages-nav__actions { + border-top-color: var(--color-line); +} + +/* ============================================================ + * Private Messages / Conversations + * ============================================================ */ + +.aksrt-pm__list { + display: flex; + flex-direction: column; +} + +.aksrt-pm__item { + display: flex; + align-items: center; + gap: 12px; + padding: 14px 16px; + cursor: pointer; + border-bottom: 1px solid var(--color-line, #f0f0f0); + transition: background 0.15s; +} + +.aksrt-pm__item:hover { + background: var(--surface-1, #f8f9fa); +} + +.aksrt-pm__item.is-unread { + background: var(--surface-2, #f0f5ff); +} + +.aksrt-pm__avatar { + width: 44px; + height: 44px; + border-radius: 50%; + object-fit: cover; + flex-shrink: 0; +} + +.aksrt-pm__info { + flex: 1; + min-width: 0; +} + +.aksrt-pm__name { + font-size: 14px; + font-weight: 500; + color: var(--color-ink); + display: flex; + align-items: center; + gap: 8px; +} + +.aksrt-pm__badge { + display: inline-flex; + align-items: center; + justify-content: center; + min-width: 18px; + height: 18px; + border-radius: 9px; + background: var(--color-primary); + color: #fff; + font-size: 11px; + font-weight: 600; + padding: 0 5px; +} + +.aksrt-pm__preview { + font-size: 12px; + color: var(--text-secondary, #8a909c); + margin-top: 3px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.aksrt-pm__time { + font-size: 11px; + color: var(--text-tertiary, #c0c4cc); + flex-shrink: 0; +} + +/* Thread view */ +.aksrt-pm__thread { + display: flex; + flex-direction: column; + height: 100%; + min-height: 400px; +} + +.aksrt-pm__thread-header { + display: flex; + align-items: center; + gap: 12px; + padding: 12px 16px; + border-bottom: 1px solid var(--color-line, #f0f0f0); +} + +.aksrt-pm__back-btn { + background: none; + border: none; + color: var(--color-primary); + cursor: pointer; + font-size: 13px; + padding: 4px 8px; + border-radius: 4px; +} + +.aksrt-pm__back-btn:hover { + background: var(--surface-1, #f0f5ff); +} + +.aksrt-pm__thread-name { + font-size: 15px; + font-weight: 600; + color: var(--color-ink); +} + +.aksrt-pm__messages { + flex: 1; + overflow-y: auto; + padding: 16px; + display: flex; + flex-direction: column; + gap: 12px; +} + +.aksrt-pm__msg { + display: flex; + max-width: 75%; +} + +.aksrt-pm__msg--mine { + align-self: flex-end; +} + +.aksrt-pm__msg--mine .aksrt-pm__msg-bubble { + background: var(--color-primary); + color: #fff; + border-radius: 12px 12px 4px 12px; +} + +.aksrt-pm__msg:not(.aksrt-pm__msg--mine) .aksrt-pm__msg-bubble { + background: var(--surface-2, #f0f0f0); + color: var(--color-ink); + border-radius: 12px 12px 12px 4px; +} + +.aksrt-pm__msg-bubble { + padding: 10px 14px; + font-size: 14px; + line-height: 1.5; + word-break: break-word; +} + +.aksrt-pm__msg-time { + font-size: 11px; + margin-top: 4px; + opacity: 0.6; +} + +.aksrt-pm__compose { + display: flex; + align-items: flex-end; + gap: 8px; + padding: 12px 16px; + border-top: 1px solid var(--color-line, #f0f0f0); +} + +.aksrt-pm__compose textarea { + flex: 1; + border: 1px solid var(--color-line, #d9d9d9); + border-radius: 8px; + padding: 8px 12px; + font-size: 14px; + resize: none; + outline: none; + font-family: inherit; +} + +.aksrt-pm__compose textarea:focus { + border-color: var(--color-primary); +} + +.aksrt-pm__send-btn { + width: 40px; + height: 40px; + border-radius: 50%; + border: none; + background: var(--color-primary); + color: #fff; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0; + transition: opacity 0.15s; +} + +.aksrt-pm__send-btn:hover { + opacity: 0.85; +} + +/* Dark mode */ +html.dark .aksrt-pm__item:hover, +html.dark .aksrt-pm__item:hover { + background: var(--surface-2); +} + +html.dark .aksrt-pm__item.is-unread, +html.dark .aksrt-pm__item.is-unread { + background: rgba(240, 68, 148, 0.08); +} diff --git a/assets/css/frontend/nav.css b/assets/css/frontend/nav.css new file mode 100644 index 00000000..01861f5b --- /dev/null +++ b/assets/css/frontend/nav.css @@ -0,0 +1,12 @@ +@import url("nav/base.css"); +@import url("nav/dark-mode-submenu.css"); +@import url("nav/dark-mode-mega-menu.css"); +@import url("nav/responsive-mega-menu.css"); +@import url("nav/mobile-toggle.css"); +@import url("nav/mobile-theme-toggle-in-drawer.css"); +@import url("nav/menu-item-icon.css"); +@import url("nav/menu-item-badge.css"); +@import url("nav/hover-effects.css"); +@import url("nav/mega-submenu.css"); +@import url("nav/cards-submenu.css"); +@import url("nav/nav-fixed-mobile-fallback.css"); diff --git a/assets/css/frontend/nav/base.css b/assets/css/frontend/nav/base.css new file mode 100644 index 00000000..357f4dd6 --- /dev/null +++ b/assets/css/frontend/nav/base.css @@ -0,0 +1,332 @@ +/* ============================================================ + * AKSRT Navigation — Editorial v3.4 + * + * - 高度 60px (--nav-h) + * - 字体使用 --font-ui (Inter / 思源黑体) + * - 主色蓝调,hover 改为 primary-soft 浅底 + * - 永远实心:白底深字 + 1px 分隔线,滚动后追加 box-shadow + * - 移动端:≤768 显示汉堡菜单 + * ============================================================ */ + +.site-nav { + position: sticky; + top: 0; + z-index: 1000; + min-height: var(--nav-height, 60px); + background-color: var(--blur-bg); + backdrop-filter: saturate(5) blur(20px); + -webkit-backdrop-filter: saturate(5) blur(20px); + transition: background-color 0.25s ease, + border-color 0.25s ease, + color 0.25s ease, + box-shadow 0.25s ease, + transform 0.3s ease; /* 滚动隐藏过渡 */ +} + +/* 滚动隐藏头部 — 对齐 zibll .scroll-down.nav-fixed .header.scroll-down-hide */ +.site-nav.is-hidden { + transform: translateY(-105%); +} + +.site-nav--static { + position: relative; +} + +.site-nav--transparent { + background: transparent; /* 对齐 zibll .header.show-slide: 透明覆盖在 slider 上 */ + border-bottom-color: transparent; +} + +.site-nav--transparent:not(.is-scrolled) { + --header-color: #fff; /* 对齐 zibll --header-color:#fff */ + color: #fff; +} + +.site-nav--transparent:not(.is-scrolled) a { + color: inherit; +} + +.site-nav--transparent.is-scrolled { + background: var(--blur-bg); /* 滚动后恢复毛玻璃背景 */ + border-bottom-color: var(--color-line-soft); +} + +.site-nav--blur { + background: var(--blur-bg); + backdrop-filter: saturate(5) blur(20px); + -webkit-backdrop-filter: saturate(5) blur(20px); + border-bottom-color: transparent; +} + +html.dark .site-nav--transparent:not(.is-scrolled), +html.dark .site-nav--blur:not(.is-scrolled), +body.dark-theme .site-nav--transparent:not(.is-scrolled), +body.dark-theme .site-nav--blur:not(.is-scrolled) { + background: transparent; + border-bottom-color: transparent; +} + +html.dark .site-nav--transparent.is-scrolled, +html.dark .site-nav--blur.is-scrolled, +body.dark-theme .site-nav--transparent.is-scrolled, +body.dark-theme .site-nav--blur.is-scrolled { + background: var(--blur-bg); + border-bottom-color: var(--color-line-soft); +} + +/* 滚动后追加阴影 — 对齐 zibll .body-scroll .header */ +.site-nav.is-scrolled { + box-shadow: 0 4px 10px var(--main-shadow, rgba(116, 116, 116, 0.08)); +} + +/* WordPress Admin Bar 已全局禁用,无需偏移规则 */ + +/* ============================================================ + * Inner / Row layout + * ============================================================ */ +.site-nav__inner { + max-width: var(--nav-max-width, var(--container)); + margin: 0 auto; + padding: 0 20px; + display: flex; + flex-direction: column; + gap: 0; +} + +.site-nav__row { + display: flex; + align-items: center; + justify-content: flex-start; + gap: 12px; + width: 100%; + min-height: var(--nav-height, 60px); +} + +/* ============================================================ + * Brand + * ============================================================ */ +.site-brand { + display: inline-flex; + align-items: center; + gap: 10px; + min-width: 0; + max-width: min(48vw, 360px); + padding: 7px 10px; + color: var(--color-ink); + font-size: 17px; + font-weight: 700; + letter-spacing: -0.01em; + flex-shrink: 0; + text-decoration: none; +} + +.site-brand:hover { + color: var(--color-ink); + text-decoration: none; +} + +.site-brand--has-logo { + gap: 0; +} + +.site-brand__logo { + width: 36px; + height: 36px; + border-radius: 8px; + display: flex; + align-items: center; + justify-content: center; + font-weight: 800; + font-size: 13px; + color: var(--color-on-primary, #fff); + background: linear-gradient(135deg, var(--color-primary), var(--color-primary-active, var(--color-primary-dark))); + letter-spacing: 0.02em; + overflow: hidden; +} + +.site-brand__media { + display: block; + flex: 0 1 auto; + max-width: 100%; + padding: 0 30px; + line-height: 0; + box-sizing: border-box; + background: transparent !important; + border: 0; + border-radius: 0; + box-shadow: none; + filter: none !important; + opacity: 1; +} + +.site-brand__img { + display: block; + height: 36px; + width: auto; + max-width: 100%; + object-fit: contain; + object-position: left center; + background: transparent !important; + border-radius: 0; + box-shadow: none; + filter: none !important; + mix-blend-mode: normal !important; + opacity: 1; + transform: none !important; +} + +.site-brand__name { + font-weight: 700; + letter-spacing: -0.01em; + white-space: nowrap; +} + +/* Light/dark logo toggle */ +.site-brand__logo-img--dark { + display: none; +} + +html.dark .site-brand__logo-img--light, +[data-theme="dark"] .site-brand__logo-img--light, +body.dark-theme .site-brand__logo-img--light { + display: none; +} + +html.dark .site-brand__logo-img--dark, +[data-theme="dark"] .site-brand__logo-img--dark, +body.dark-theme .site-brand__logo-img--dark { + display: inline-block; +} + +/* ============================================================ + * Desktop menu + * ============================================================ */ +ul.nav-desktop { + display: none; + list-style: none; + margin: 0; + padding: 0; + align-items: center; + flex: 1 1 auto; + min-width: 0; +} + +.nav-desktop--fallback { + display: none; + align-items: center; + flex: 1 1 auto; + min-width: 0; +} + +ul.nav-desktop a, +.nav-desktop--fallback a { + color: var(--color-ink-3); + font-weight: 500; + padding: 0 10px; /* 对齐 zibll:仅水平 padding,垂直居中靠 flex 行高 */ + border-radius: 4px; + transition: color var(--dur-fast, 0.15s) var(--ease), + background var(--dur-fast, 0.15s) var(--ease); +} + +/* Hover — 对齐 zibll: 仅变色,无背景 */ +ul.nav-desktop a:hover, +.nav-desktop--fallback a:hover { + color: var(--color-primary); + background: transparent; +} + +/* Active page — 对齐 zibll: 仅变色(指示器走下方胶囊条) */ +ul.nav-desktop .current-menu-item > a, +ul.nav-desktop .current_page_item > a { + color: var(--color-primary); + background: transparent; +} + +/* ============================================================ + * Desktop submenu (dropdown) + * ============================================================ */ +ul.nav-desktop .menu-item { + position: relative; +} + +/* 顶部 hover/current 胶囊指示器 — 对齐 zibll .navbar-nav>li:before + (5px 高、底部 15px 圆角,从 header 顶缘垂下)。 + stretch 链(row→ul→li)让 li 充满 60px 行高,::before top:0 即锚定 header 顶部; + ::before 为 absolute 不进入 flex 流,不挤压链接。 */ +ul.nav-desktop { + align-self: stretch; +} + +ul.nav-desktop > .menu-item { + align-self: stretch; + display: flex; + align-items: center; +} + +ul.nav-desktop > .menu-item::before { + content: ''; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 5px; + background: var(--focus-color, var(--color-primary)); + border-radius: 0 0 15px 15px; + opacity: 0; + transition: opacity 0.3s; + pointer-events: none; +} + +ul.nav-desktop > .menu-item:hover::before, +ul.nav-desktop > .current-menu-item::before, +ul.nav-desktop > .current_page_item::before { + opacity: 1; +} + +ul.nav-desktop .sub-menu { + position: absolute; + top: 100%; + left: 0; + z-index: 998; /* 保留较高 z-index(zibll 用 99,AKSRT 栈更深,避免被覆盖) */ + min-width: 120px; + list-style: none; + margin: 4px 0 0; + padding: 10px 5px; + background: var(--main-bg-color, #fff); + border: 1px solid var(--main-border-color, rgba(50, 50, 50, 0.06)); + border-radius: var(--main-radius, 8px); + box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); + opacity: 0; + visibility: hidden; + transform: translateY(6px); + transition: opacity 0.4s ease, transform 0.4s ease, visibility 0.4s ease; +} + +ul.nav-desktop .menu-item:hover > .sub-menu { + opacity: 1; + visibility: visible; + transform: translateY(0); +} + +ul.nav-desktop .sub-menu .menu-item > a { + display: flex; + align-items: center; + gap: 8px; + padding: 8px 15px; + font-size: 14px; + border-radius: 4px; + white-space: nowrap; +} + +ul.nav-desktop .sub-menu .menu-item > a:hover { + background: var(--color-primary-soft, rgba(240, 68, 148, 0.08)); + color: var(--color-primary); +} + +/* Nested submenus fly out to the right — 对齐 zibll top:-10px,去 margin-left */ +ul.nav-desktop .sub-menu .sub-menu { + top: -10px; + left: 100%; + margin: 0; +} + diff --git a/assets/css/frontend/nav/cards-submenu.css b/assets/css/frontend/nav/cards-submenu.css new file mode 100644 index 00000000..272b996d --- /dev/null +++ b/assets/css/frontend/nav/cards-submenu.css @@ -0,0 +1,128 @@ +/* Cards submenu */ +.aksrt-nav__cards { + display: grid; + gap: 12px; + padding: 8px; +} + +.aksrt-nav__card { + display: flex; + align-items: center; + gap: 12px; + padding: 10px 12px; + border-radius: 6px; + text-decoration: none; + color: inherit; + transition: background 0.15s; +} + +.aksrt-nav__card:hover { + background: var(--color-primary-soft, rgba(240, 68, 148, 0.06)); +} + +.aksrt-nav__card-icon { + width: 36px; + height: 36px; + border-radius: 8px; + display: flex; + align-items: center; + justify-content: center; + background: var(--color-primary-soft, #e6f4ff); + color: var(--color-primary); + font-size: 16px; + flex-shrink: 0; +} + +.aksrt-nav__card-text { + flex: 1; + min-width: 0; +} + +.aksrt-nav__card-title { + font-size: 13px; + font-weight: 600; + color: var(--color-ink); + margin: 0; +} + +.aksrt-nav__card-desc { + font-size: 11px; + color: var(--color-ink-4); + margin: 2px 0 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +/* ============================================================ + * 导航溢出「更多」下拉 + * ============================================================ */ +.aksrt-nav-more { + position: relative; +} + +.aksrt-nav-more__btn { + display: inline-flex; + align-items: center; + gap: 4px; + padding: 6px 12px; + border: none; + background: none; + color: var(--color-ink-2); + font-size: 14px; + font-weight: 500; + cursor: pointer; + border-radius: var(--radius, 8px); + transition: background 0.15s, color 0.15s; +} + +.aksrt-nav-more__btn:hover { + background: var(--color-primary-soft, rgba(240, 68, 148, 0.08)); + color: var(--color-primary); +} + +.aksrt-nav-more__dropdown { + display: none; + position: absolute; + top: 100%; + right: 0; + min-width: 160px; + padding: 6px 0; + background: var(--surface-1, #fff); + border: 1px solid var(--color-line, rgba(50, 50, 50, 0.06)); + border-radius: var(--radius, 8px); + box-shadow: var(--shadow-lg, 0 0 10px rgba(116, 116, 116, 0.12)); + z-index: var(--z-dropdown, 100); + list-style: none; + margin: 4px 0 0; +} + +.aksrt-nav-more__dropdown.is-open { + display: block; +} + +.aksrt-nav-more__dropdown li { + display: block; +} + +.aksrt-nav-more__dropdown li a, +.aksrt-nav-more__dropdown li button { + display: block; + width: 100%; + padding: 8px 16px; + border: none; + background: none; + color: var(--color-ink-2); + font-size: 14px; + text-align: left; + text-decoration: none; + cursor: pointer; + transition: background 0.15s, color 0.15s; +} + +.aksrt-nav-more__dropdown li a:hover, +.aksrt-nav-more__dropdown li button:hover { + background: var(--color-primary-soft, rgba(240, 68, 148, 0.08)); + color: var(--color-primary); +} + diff --git a/assets/css/frontend/nav/dark-mode-mega-menu.css b/assets/css/frontend/nav/dark-mode-mega-menu.css new file mode 100644 index 00000000..28994298 --- /dev/null +++ b/assets/css/frontend/nav/dark-mode-mega-menu.css @@ -0,0 +1,12 @@ +/* Dark mode Mega Menu */ +html.dark ul.nav-desktop .mega-menu-item > .mega-menu__panel, +body.dark-theme ul.nav-desktop .mega-menu-item > .mega-menu__panel { + background: var(--surface-page); + border-color: var(--color-line, #2d2d3f); +} + +html.dark .mega-menu__panel > .menu-item:hover, +body.dark-theme .mega-menu__panel > .menu-item:hover { + background: var(--surface-2); +} + diff --git a/assets/css/frontend/nav/dark-mode-submenu.css b/assets/css/frontend/nav/dark-mode-submenu.css new file mode 100644 index 00000000..2e253195 --- /dev/null +++ b/assets/css/frontend/nav/dark-mode-submenu.css @@ -0,0 +1,109 @@ +/* Dark mode submenu */ +html.dark ul.nav-desktop .sub-menu, +body.dark-theme ul.nav-desktop .sub-menu { + background: var(--surface-page); + border-color: var(--color-line, #2d2d3f); +} + +/* ============================================================ + * Mega Menu (图文超级菜单) + * ============================================================ */ + +/* Mega Menu 容器:全宽定位 */ +ul.nav-desktop .mega-menu-item { + position: static; +} + +ul.nav-desktop .mega-menu-item > .mega-menu__panel { + position: fixed; /* 对齐 zibll .senior-submenu: position:fixed 全视口宽 */ + top: var(--nav-height, 60px); + left: 0; + right: 0; + transform: none; + max-width: var(--container); + margin: 0 auto; /* 内容区居中 */ + padding: 20px 16px; /* 对齐 zibll 垂直 20px + 水平内边距 */ + box-shadow: 0 10px 10px rgba(0, 0, 0, 0.05); /* 对齐 zibll shadow */ +} + +/* 列布局 */ +.mega-menu__columns-2 { + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: 8px; +} + +.mega-menu__columns-3 { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 8px; +} + +.mega-menu__columns-4 { + display: grid; + grid-template-columns: repeat(4, 1fr); + gap: 8px; +} + +.mega-menu__columns-5 { + display: grid; + grid-template-columns: repeat(5, 1fr); + gap: 8px; +} + +/* Mega Menu 子项(卡片样式) */ +.mega-menu__panel > .menu-item { + border-radius: 8px; + transition: background 0.15s; +} + +.mega-menu__panel > .menu-item:hover { + background: var(--surface-2, #F4F5F7); +} + +.mega-menu__panel > .menu-item > a { + display: flex; + align-items: center; + gap: 10px; + padding: 10px 12px; + font-size: 14px; + border-radius: 8px; + white-space: normal; + line-height: 1.4; +} + +.mega-menu__panel > .menu-item > a i { + width: 20px; + text-align: center; + color: var(--color-primary, var(--color-primary)); + flex-shrink: 0; +} + +/* 描述文字 */ +.mega-menu__item-desc { + display: block; + font-size: 12px; + color: var(--color-ink-4, #8A8F98); + margin-top: 2px; + line-height: 1.3; +} + +/* Mega Menu 标题分组 */ +.mega-menu__panel .mega-menu__group-title { + grid-column: 1 / -1; + padding: 8px 12px 4px; + font-size: 12px; + font-weight: 600; + color: var(--color-ink-3); + text-transform: uppercase; + letter-spacing: 0.05em; +} + +/* Mega Menu 底部区域(可放图片/CTA) */ +.mega-menu__panel .mega-menu__footer { + grid-column: 1 / -1; + padding: 12px 0 0; + margin-top: 8px; + border-top: 1px solid var(--color-line); +} + diff --git a/assets/css/frontend/nav/hover-effects.css b/assets/css/frontend/nav/hover-effects.css new file mode 100644 index 00000000..2e127318 --- /dev/null +++ b/assets/css/frontend/nav/hover-effects.css @@ -0,0 +1,35 @@ +/* Hover effects */ +.aksrt-nav__item--hover-underline > a::after { + content: ''; + position: absolute; + bottom: 0; + left: 50%; + width: 0; + height: 2px; + background: var(--color-primary); + transition: width 0.2s ease, left 0.2s ease; + border-radius: 1px; +} + +.aksrt-nav__item--hover-underline:hover > a::after { + width: 60%; + left: 20%; +} + +.aksrt-nav__item--hover-background > a { + transition: background-color 0.2s; + border-radius: 4px; +} + +.aksrt-nav__item--hover-background:hover > a { + background-color: var(--color-primary-soft, rgba(240, 68, 148, 0.08)); +} + +.aksrt-nav__item--hover-color > a { + transition: color 0.2s; +} + +.aksrt-nav__item--hover-color:hover > a { + color: var(--color-primary); +} + diff --git a/assets/css/frontend/nav/mega-submenu.css b/assets/css/frontend/nav/mega-submenu.css new file mode 100644 index 00000000..d41a4464 --- /dev/null +++ b/assets/css/frontend/nav/mega-submenu.css @@ -0,0 +1,28 @@ +/* Mega submenu */ +.aksrt-nav__mega { + position: absolute; + top: 100%; + left: 0; + z-index: 1001; + background: var(--surface-1); + border: 1px solid var(--color-line); + border-radius: var(--radius); + box-shadow: var(--shadow-lg); + padding: 16px; + opacity: 0; + visibility: hidden; + transform: translateY(8px); + transition: opacity 0.2s ease, transform 0.2s ease, visibility 0.2s ease; +} + +.aksrt-nav__item:hover > .aksrt-nav__mega { + opacity: 1; + visibility: visible; + transform: translateY(0); +} + +.aksrt-nav__mega--columns { + display: grid; + gap: 16px; +} + diff --git a/assets/css/frontend/nav/menu-item-badge.css b/assets/css/frontend/nav/menu-item-badge.css new file mode 100644 index 00000000..5a6b5379 --- /dev/null +++ b/assets/css/frontend/nav/menu-item-badge.css @@ -0,0 +1,41 @@ +/* Menu item badge */ +.aksrt-nav__badge { + display: inline-flex; + align-items: center; + justify-content: center; + font-size: 10px; + font-weight: 600; + line-height: 1; + padding: 2px 5px; + border-radius: 3px; + margin-left: 4px; + white-space: nowrap; + vertical-align: middle; + transform: translateY(-1px); +} + +.aksrt-nav__badge--new { + color: #fff; + background: var(--color-error); +} + +.aksrt-nav__badge--hot { + color: #fff; + background: var(--color-warning); +} + +.aksrt-nav__badge--info { + color: #fff; + background: var(--color-info); +} + +.aksrt-nav__badge--success { + color: #fff; + background: var(--color-success); +} + +.aksrt-nav__badge--vip { + color: #fff; + background: linear-gradient(135deg, var(--color-warning), var(--color-error)); +} + diff --git a/assets/css/frontend/nav/menu-item-icon.css b/assets/css/frontend/nav/menu-item-icon.css new file mode 100644 index 00000000..67ccce61 --- /dev/null +++ b/assets/css/frontend/nav/menu-item-icon.css @@ -0,0 +1,20 @@ +/* Menu item icon */ +.aksrt-nav__icon { + font-size: 0.85em; + width: 1.2em; + text-align: center; + margin-right: 4px; + opacity: 0.7; + transition: opacity 0.2s; +} + +.aksrt-nav__item--has-icon > a { + display: inline-flex; + align-items: center; + gap: 4px; +} + +.aksrt-nav__item--has-icon:hover .aksrt-nav__icon { + opacity: 1; +} + diff --git a/assets/css/frontend/nav/mobile-theme-toggle-in-drawer.css b/assets/css/frontend/nav/mobile-theme-toggle-in-drawer.css new file mode 100644 index 00000000..728acaf9 --- /dev/null +++ b/assets/css/frontend/nav/mobile-theme-toggle-in-drawer.css @@ -0,0 +1,18 @@ +/* Mobile theme toggle in drawer */ +.nav-drawer__theme-toggle { + padding: 0 20px 16px; +} + +.nav-drawer__theme-toggle .theme-toggle-mobile { + width: 100%; + min-height: 44px; + justify-content: center; + gap: 8px; + display: flex; + align-items: center; +} + +/* ============================================================ + * Menu Decoration — Icons, Badges, Hover Effects + * ============================================================ */ + diff --git a/assets/css/frontend/nav/mobile-toggle.css b/assets/css/frontend/nav/mobile-toggle.css new file mode 100644 index 00000000..24f200a8 --- /dev/null +++ b/assets/css/frontend/nav/mobile-toggle.css @@ -0,0 +1,604 @@ +/* Mobile toggle */ +.nav-toggle { + display: flex; +} + +@media (max-width: 991px) { + .site-brand { + max-width: min(46vw, 311px); + } + + .site-brand__media { + padding: 0 8px; + } + + .nav-publish-btn { + display: none; + } +} + +/* Desktop search icon: hide on mobile (use drawer search instead) */ +@media (max-width: 767px) { + .site-brand { + max-width: min(62vw, 260px); + padding: 7px 0; + } + + .site-brand__media { + padding: 0; + } + + #search-toggle { + display: none; + } + /* Search panel only makes sense alongside the desktop search icon */ + .nav-search-panel { + display: none !important; + } +} + +@media (min-width: 768px) { + ul.nav-desktop, + .nav-desktop--fallback { + display: flex; + } + + .nav-auth { + display: flex; + } + + .nav-auth-dropdown { + display: flex; + } + + .nav-toggle { + display: none; + } +} + +/* ============================================================ + * Header Layout Variants (desktop ≥768px) + * Layout 1: Standard — brand left, nav flex-1, actions right + * Layout 2: Centered — brand left, nav centered with flex, actions right + * Layout 3: Compact — brand left, nav pushed right, actions right + * ============================================================ */ +@media (min-width: 768px) { + /* Layout 2: center the nav between brand and actions */ + body.header-layout-2 .nav-desktop { + flex: 1; + justify-content: center; + } + + body.header-layout-2 .nav-actions { + flex-shrink: 0; + } + + /* Layout 3: push nav to the right side */ + body.header-layout-3 .site-nav__row { + justify-content: flex-start; + } + + body.header-layout-3 .nav-desktop { + flex: 1; + justify-content: flex-end; + margin-left: 24px; + } + + body.header-layout-3 .nav-actions { + margin-left: 8px; + } +} + +.nav-mobile-strip { + display: none; + width: calc(100% + 8px); + margin: 0 -4px; + padding: 0 0 12px; +} + +.nav-mobile-strip__menu, +.nav-mobile-strip__menu ul { + display: flex; + align-items: center; + gap: 8px; + overflow-x: auto; + margin: 0; + padding: 0; + list-style: none; + scrollbar-width: none; + -ms-overflow-style: none; +} + +.nav-mobile-strip__menu::-webkit-scrollbar, +.nav-mobile-strip__menu ul::-webkit-scrollbar { + display: none; +} + +.nav-mobile-strip__menu a { + display: inline-flex; + align-items: center; + min-height: 34px; + padding: 0 12px; + border-radius: var(--radius-pill, 999px); + background: var(--surface-2); + color: var(--color-ink-2); + white-space: nowrap; + text-decoration: none; + font-size: 0.875rem; + font-weight: 500; +} + +.nav-mobile-strip__menu .current-menu-item > a, +.nav-mobile-strip__menu .current_page_item > a { + background: var(--color-primary); + color: var(--color-on-primary, #fff); +} + +@media (max-width: 767px) { + .nav-mobile-strip { + display: block; + } +} + +/* ============================================================ + * User avatar + dropdown + * ============================================================ */ +.nav-user { + position: relative; +} + +.nav-user__toggle { + width: 36px; + height: 36px; + border-radius: var(--radius-avatar); + padding: 0; + border: none; /* 对齐 zibll:头像无边框 */ + cursor: pointer; + overflow: hidden; + background: var(--surface-2); + transition: box-shadow var(--dur-fast, 0.15s) var(--ease); +} + +.nav-user__toggle:hover { + box-shadow: 0 0 0 2px var(--color-primary-soft); +} + +.nav-user__toggle img { + width: 100%; + height: 100%; + object-fit: cover; + display: block; +} + +.user-dropdown { + position: absolute; + top: calc(100% + 8px); + right: 0; + width: 260px; + max-width: calc(100vw - 32px); + padding: 12px 0; + background: var(--surface-1); + border: 1px solid var(--color-line); + border-radius: var(--radius-lg, 8px); + box-shadow: var(--shadow-lg); + z-index: 1100; + opacity: 0; + visibility: hidden; + transform: translateY(-6px); + transition: opacity 0.2s, transform 0.2s, visibility 0.2s; +} + +.user-dropdown.is-open { + opacity: 1; + visibility: visible; + transform: translateY(0); +} + +.user-dropdown__profile { + display: flex; + align-items: center; + gap: 12px; + padding: 8px 16px 14px; +} + +.user-dropdown__profile img { + width: 44px; + height: 44px; + border-radius: var(--radius-avatar); + object-fit: cover; + flex-shrink: 0; +} + +.user-dropdown__name { + font-weight: 700; + font-size: 0.9375rem; + color: var(--color-ink); +} + +.user-dropdown__email { + font-size: 0.75rem; + color: var(--color-ink-4); + word-break: break-all; + margin-top: 2px; +} + +.user-dropdown__sep { + height: 1px; + background: var(--color-line); + margin: 6px 0; +} + +.user-dropdown a, +.user-dropdown button { + display: flex; + align-items: center; + gap: 10px; + width: 100%; + padding: 0 16px; + height: 44px; + border: none; + background: none; + font-size: 0.875rem; + color: var(--color-ink); + text-align: left; + cursor: pointer; + transition: background var(--dur-fast, 0.15s) var(--ease), + color var(--dur-fast, 0.15s) var(--ease); +} + +.user-dropdown a:hover, +.user-dropdown button:hover { + background: var(--surface-3); + color: var(--color-primary-active); +} + +/* dropdown 项内的 SVG 图标 */ +.user-dropdown__item svg { + width: 16px; + height: 16px; + flex-shrink: 0; + opacity: 0.85; +} + +.user-dropdown__item span:first-of-type:not(.user-dropdown__pill) { + flex: 1; + min-width: 0; +} + +/* 未读消息数 badge */ +.user-dropdown__badge { + display: inline-flex; + align-items: center; + justify-content: center; + min-width: 18px; + height: 18px; + padding: 0 5px; + margin-left: auto; + font-size: 11px; + font-weight: 600; + color: #fff; + background: var(--color-error, #ef4444); + border-radius: 9px; + line-height: 1; +} + +.user-dropdown__credits { + display: flex; + align-items: center; + gap: 10px; + padding: 0 16px; + height: 44px; + font-size: 0.875rem; + color: var(--color-ink-2); +} + +.user-dropdown__credits i { + color: var(--color-warning); + flex-shrink: 0; +} + +.user-dropdown__credits-label { + flex: 1; +} + +.user-dropdown__credits-value { + font-weight: 600; + color: var(--color-primary); +} + +.user-dropdown__logout { + color: var(--color-error) !important; +} + +.user-dropdown__logout svg { + color: var(--color-error); +} + +.user-dropdown__logout:hover { + background: rgba(239, 68, 68, 0.08) !important; + color: var(--color-error) !important; +} + +.user-dropdown .badge-dot { + margin-left: auto; + min-width: 8px; + height: 8px; + border-radius: var(--radius-pill); + background: var(--color-error); +} + +/* ============================================================ + * Search panel + * ============================================================ */ +.nav-search-panel { + display: none; + padding: 12px 0 16px; + border-top: 1px solid var(--color-line); +} + +.nav-search-panel.is-open { + display: block; +} + +.nav-searchbox { + margin: 0; +} + +.nav-searchbox__field { + display: flex; + align-items: center; + gap: 10px; + min-height: 42px; + padding: 0 6px 0 14px; + border: 1px solid var(--color-line); + border-radius: var(--radius-pill, 999px); + background: var(--surface-3); + box-sizing: border-box; + transition: border-color var(--dur-fast, 0.15s) var(--ease), box-shadow var(--dur-fast, 0.15s) var(--ease), background var(--dur-fast, 0.15s) var(--ease); +} + +.nav-searchbox__icon { + order: 1; + flex: 0 0 16px; + width: 16px; + height: 16px; + color: var(--color-ink-4); + pointer-events: none; +} + +.nav-searchbox__input { + order: 2; + flex: 1; + min-width: 0; + width: auto; + height: 40px; + padding: 0; + border: 0; + background: transparent; + color: var(--color-ink); + font-size: 0.9rem; + line-height: 1.2; + box-sizing: border-box; +} + +.nav-searchbox__input:focus { + outline: none; +} + +.nav-searchbox__input::placeholder { + color: var(--color-ink-4); +} + +.nav-searchbox__submit { + order: 3; + flex: 0 0 auto; + height: 30px; + min-width: 64px; + padding: 0 14px; + border: 0; + border-radius: var(--radius-pill, 999px); + background: var(--color-primary); + color: #fff; + font-size: 0.8125rem; + font-weight: 600; + line-height: 1; + white-space: nowrap; + cursor: pointer; +} + +.nav-searchbox__field:focus-within { + border-color: var(--color-primary); + box-shadow: 0 0 0 3px var(--color-primary-soft); + background: var(--surface-1); +} + +.nav-searchbox__submit:hover { + background: var(--color-primary-active); +} + +/* ============================================================ + * Mobile drawer / mobile header + * ============================================================ */ +.mobile-header.nav-drawer-backdrop { + position: fixed; + inset: 0; + background: rgba(0, 0, 0, 0.45); + z-index: 1200; + opacity: 0; + visibility: hidden; + transition: opacity 0.3s ease, visibility 0.3s; +} + +.mobile-header.nav-drawer-backdrop.is-open { + opacity: 1; + visibility: visible; +} + +.mobile-header.nav-drawer { + position: fixed; + top: 0; + right: 0; + width: min(100vw, 360px); + height: 100vh; + max-height: 100dvh; + background: var(--surface-page); + z-index: 1210; + box-shadow: var(--shadow-drawer); + transform: translateX(100%); + transition: transform 0.32s var(--ease-out, ease); + display: flex; + flex-direction: column; + overflow: auto; + pointer-events: none; + visibility: hidden; +} + +.mobile-header.nav-drawer.is-open { + transform: translateX(0); + pointer-events: auto; + visibility: visible; +} + +.mobile-navbar { + display: flex; + flex-direction: column; + min-height: 100%; +} + +.mobile-navbar .navbar-brand { + max-width: calc(100% - 52px); + padding: 7px 0; +} + +.mobile-navbar .navbar-logo { + padding: 0; +} + +.nav-drawer-backdrop { + position: fixed; + inset: 0; + background: rgba(0, 0, 0, 0.45); + z-index: 1200; + opacity: 0; + visibility: hidden; + transition: opacity 0.3s ease, visibility 0.3s; +} + +.nav-drawer-backdrop.is-open { + opacity: 1; + visibility: visible; +} + +.nav-drawer { + position: fixed; + top: 0; + right: 0; + width: min(100vw, 360px); + height: 100vh; + max-height: 100dvh; + background: var(--surface-page); + z-index: 1210; + box-shadow: var(--shadow-drawer); + transform: translateX(100%); + transition: transform 0.32s var(--ease-out, ease); + display: flex; + flex-direction: column; + overflow: auto; + pointer-events: none; + visibility: hidden; +} + +.nav-drawer.is-open { + transform: translateX(0); + pointer-events: auto; + visibility: visible; +} + +.nav-drawer__head { + display: flex; + align-items: center; + justify-content: space-between; + gap: 16px; + padding: 16px 20px; + border-bottom: 1px solid var(--color-line); + font-weight: 700; + font-size: 1rem; +} + +.site-brand--drawer { + max-width: calc(100% - 52px); + padding: 7px 0; +} + +.site-brand--drawer .site-brand__media { + padding: 0; +} + +.nav-drawer__search { + padding: 16px 20px 0; +} + +.nav-drawer__search .nav-searchbox__field { + min-height: 40px; +} + +.nav-drawer__search .nav-searchbox__input { + height: 38px; +} + +.nav-drawer__search .nav-searchbox__submit { + height: 28px; + min-width: 58px; + padding: 0 12px; + font-size: 0.75rem; +} + +.nav-drawer__menu { + flex: 1; + padding: 16px 20px 32px; +} + +.nav-drawer__menu a { + display: block; + padding: 14px 0; + font-size: 1rem; + font-weight: 500; + color: var(--color-ink); + border-bottom: 1px solid var(--color-line-soft); +} + +.nav-drawer__menu a:hover { + color: var(--color-primary-active); +} + +.nav-drawer__menu ul { + list-style: none; + margin: 0; + padding: 0; +} + +.nav-drawer__auth { + padding: 20px; + display: flex; + flex-direction: column; + gap: 12px; + border-top: 1px solid var(--color-line); +} + +.nav-drawer__auth .btn-outline, +.nav-drawer__auth .btn-primary { + width: 100%; + height: 44px; +} + +.nav-drawer__publish { + padding: 0 20px 20px; +} + +.nav-drawer__publish .btn-primary { + width: 100%; + min-height: 44px; + justify-content: center; + gap: 8px; +} + diff --git a/assets/css/frontend/nav/nav-fixed-mobile-fallback.css b/assets/css/frontend/nav/nav-fixed-mobile-fallback.css new file mode 100644 index 00000000..9490453e --- /dev/null +++ b/assets/css/frontend/nav/nav-fixed-mobile-fallback.css @@ -0,0 +1,10 @@ +/* ===== nav_fixed mobile fallback ===== */ +/* On mobile, static nav should remain sticky so the hamburger toggle stays accessible */ +@media (max-width: 767px) { + .has-static-nav .site-nav--static { + position: sticky; + top: 0; + z-index: 1000; + } +} + diff --git a/assets/css/frontend/nav/responsive-mega-menu.css b/assets/css/frontend/nav/responsive-mega-menu.css new file mode 100644 index 00000000..bff4a837 --- /dev/null +++ b/assets/css/frontend/nav/responsive-mega-menu.css @@ -0,0 +1,106 @@ +/* Responsive Mega Menu */ +@media (max-width: 767px) { + ul.nav-desktop .mega-menu-item > .mega-menu__panel { + position: static; + transform: none; + width: 100%; + max-width: none; + margin: 0; + box-shadow: none; + } + + .mega-menu__columns-2, + .mega-menu__columns-3, + .mega-menu__columns-4, + .mega-menu__columns-5 { + grid-template-columns: 1fr; + } +} + +/* ============================================================ + * Right actions (icons + auth) + * ============================================================ */ +.nav-actions { + display: flex; + align-items: center; + gap: 4px; + flex-shrink: 0; + margin-left: auto; +} + +.nav-settings-link, +.nav-publish-btn { + flex-shrink: 0; +} + +.nav-settings-link svg { + width: 18px; + height: 18px; +} + +.nav-publish-btn { + display: inline-flex; + align-items: center; + gap: 8px; + height: 36px; + padding: 0 14px; + font-size: 0.875rem; + font-weight: 600; +} + +.nav-publish-btn i { + font-size: 0.8125rem; +} + +.theme-toggle.is-animating svg { + transform: rotate(360deg); +} + +/* ============================================================ + * Auth buttons (in nav, when logged out) + * ============================================================ */ +.nav-auth { + display: none; + align-items: center; + gap: 8px; +} + +/* btn-outline / btn-primary 复用 core/buttons.css 的定义, + * 这里仅做导航专用调整(高度对齐、字体) */ +.nav-auth .btn-outline, +.nav-auth .btn-primary { + height: 36px; + font-size: 0.875rem; + padding: 0 16px; +} + +/* Auth dropdown variant (layouts 1/3) — icon trigger + panel */ +.nav-auth-dropdown { + position: relative; + display: none; + align-items: center; +} + +.nav-auth-dropdown__trigger { + width: 36px; + height: 36px; +} + +.nav-auth-dropdown__trigger svg { + width: 20px; + height: 20px; +} + +.nav-auth-dropdown__panel { + display: none; + position: absolute; + top: calc(100% + 8px); + right: 0; + min-width: 180px; + z-index: 1100; +} + +.nav-auth-dropdown.is-open .nav-auth-dropdown__panel { + display: block; +} + diff --git a/assets/css/frontend/overlay-primitives.css b/assets/css/frontend/overlay-primitives.css new file mode 100644 index 00000000..6c2c90e7 --- /dev/null +++ b/assets/css/frontend/overlay-primitives.css @@ -0,0 +1,78 @@ +/** + * AKSRT Overlay / Glass Primitives + * + * Provides backdrop-filter glass surfaces used by header, footer-tabbar, + * floating buttons and search overlays — matching zibll's blur system. + * + * @package AKSRT + */ + +/* ============================================================ + * .aksrt-blur-bg — generic glass surface + * Use on any element that needs a translucent blurred background. + * ============================================================ */ +.aksrt-blur-bg { + -webkit-backdrop-filter: saturate(5) blur(20px); + backdrop-filter: saturate(5) blur(20px); + background: var(--blur-bg); +} + +/* ============================================================ + * Glass on site-nav (when using fixed/sticky mode) + * Applied via .site-nav--blur already; this adds the zibll-grade + * saturate(5) blur(20px) instead of the lighter saturate(1.5) blur(18px). + * ============================================================ */ +.site-nav--glass { + -webkit-backdrop-filter: saturate(5) blur(20px); + backdrop-filter: saturate(5) blur(20px); + background: var(--blur-bg); + border-bottom-color: transparent; +} + +.site-nav--glass.is-scrolled { + box-shadow: 0 4px 10px rgba(20, 28, 48, 0.06); + border-bottom-color: var(--color-line-soft); +} + +html.dark .site-nav--glass.is-scrolled, +html.dark .site-nav--glass.is-scrolled { + box-shadow: 0 4px 10px rgba(0, 0, 0, 0.25); +} + +/* ============================================================ + * Glass on footer-tabbar (already uses backdrop-filter in footer.css; + * this class can be toggled to match zibll's exact blur spec) + * ============================================================ */ +.footer-tabbar--glass { + -webkit-backdrop-filter: saturate(5) blur(20px); + backdrop-filter: saturate(5) blur(20px); + background: var(--blur-bg); + box-shadow: 0 -4px 5px rgba(20, 28, 48, 0.06); +} + +html.dark .footer-tabbar--glass, +html.dark .footer-tabbar--glass { + box-shadow: 0 -4px 5px rgba(0, 0, 0, 0.25); +} + +/* ============================================================ + * Glass on floating buttons (lighter blur: saturate(2) blur(10px)) + * ============================================================ */ +.float-right--glass .float-btn { + -webkit-backdrop-filter: saturate(2) blur(10px); + backdrop-filter: saturate(2) blur(10px); + background: var(--float-btn-bg); + border-color: transparent; +} + +/* ============================================================ + * Scroll shadow on glass header (zibll: .body-scroll .header) + * ============================================================ */ +body.has-scrolled .site-nav--glass { + box-shadow: 0 4px 10px rgba(20, 28, 48, 0.06); +} + +html.dark body.has-scrolled .site-nav--glass, +html.dark body.has-scrolled .site-nav--glass { + box-shadow: 0 4px 10px rgba(0, 0, 0, 0.25); +} diff --git a/assets/css/frontend/pages.css b/assets/css/frontend/pages.css new file mode 100644 index 00000000..c6342ebc --- /dev/null +++ b/assets/css/frontend/pages.css @@ -0,0 +1,5 @@ +@import url("pages/base.css"); +@import url("pages/board-cards.css"); +@import url("pages/topic-rows.css"); +@import url("pages/sidebar.css"); +@import url("pages/empty-state.css"); diff --git a/assets/css/frontend/pages/base-1.css b/assets/css/frontend/pages/base-1.css new file mode 100644 index 00000000..9017c280 --- /dev/null +++ b/assets/css/frontend/pages/base-1.css @@ -0,0 +1,400 @@ +/* ========== 归档时间轴 ========== */ +.archive-timeline__group { + margin-bottom: 40px; +} + +.archive-timeline__heading { + display: flex; + align-items: center; + gap: 12px; + margin-bottom: 20px; + font-size: 1.125rem; + font-weight: 700; +} + +.archive-timeline__badge { + font-size: 12px; + font-weight: 600; + padding: 4px 10px; + border-radius: var(--radius-pill); + background: var(--color-primary-50); + color: var(--color-primary-dark); +} + +html.dark .archive-timeline__badge, +html.dark .archive-timeline__badge { + color: var(--color-primary-light); +} + +/* ========== 认证页 / 表单页 ========== */ +.auth-page .site-nav__inner { + max-width: 100%; +} + +.auth-shell { + min-height: calc(100vh - var(--nav-height)); + display: flex; + align-items: center; + justify-content: center; + padding: 48px 16px 64px; +} + +.auth-card { + width: 100%; + max-width: 400px; + padding: 32px 28px; + border-radius: var(--radius-lg); + border: 1px solid var(--color-line); + background: var(--surface-2); + box-shadow: var(--shadow-md); +} + +.auth-card__logo { + width: 80px; + height: 80px; + margin: 0 auto 16px; + border-radius: var(--radius-lg); + background: linear-gradient(135deg, var(--color-primary), var(--color-primary-dark)); + display: flex; + align-items: center; + justify-content: center; + color: #fff; + font-weight: 800; + font-size: 28px; +} + +.auth-card__title { + text-align: center; + font-weight: 800; + font-size: 1.5rem; + margin: 0 0 4px; +} + +.auth-card__subtitle { + text-align: center; + color: var(--color-ink-3); + font-size: 14px; + margin: 0 0 24px; +} + +/* 绑定/登录会话过期状态 */ +.auth-card__expired { + text-align: center; + padding: var(--space-8, 40px) var(--space-5, 20px); +} + +.auth-card__expired p { + color: var(--color-ink-3); + margin-bottom: var(--space-5, 20px); +} + +.auth-card__expired-action { + display: inline-flex; + text-decoration: none; + padding: 10px 32px; +} + +.form-field { + margin-bottom: 16px; + position: relative; +} + +.form-field label { + display: block; + font-size: 13px; + font-weight: 600; + margin-bottom: 6px; + color: var(--color-ink-3); +} + +.input-wrap { + position: relative; +} + +.input-wrap .input-icon { + position: absolute; + left: 14px; + top: 50%; + transform: translateY(-50%); + font-size: 14px; + opacity: 0.6; + pointer-events: none; +} + +.form-field input:not([type="checkbox"]) { + width: 100%; + height: 44px; + padding: 0 16px 0 40px; + border-radius: var(--radius-btn); + border: 1px solid var(--color-line); + background: var(--surface-page); + color: var(--color-ink); + font-size: 14px; + box-sizing: border-box; +} + +.form-field input:focus { + outline: none; + border-color: var(--color-primary); + box-shadow: 0 0 0 3px var(--color-primary-50); +} + +.form-field--pwd input { + padding-right: 44px; +} + +.input-wrap .toggle-pwd { + position: absolute; + right: 4px; + top: 50%; + transform: translateY(-50%); + width: 40px; + height: 40px; + border: none; + background: none; + cursor: pointer; + color: var(--color-ink-4); +} + +.form-row-between { + display: flex; + justify-content: space-between; + align-items: center; + flex-wrap: wrap; + gap: 8px; + margin-bottom: 20px; + font-size: 13px; +} + +/* 社交登录分隔线 */ +.social-login-divider { + display: flex; + align-items: center; + margin: 24px 0 16px; + color: var(--color-ink-3, #94a3b8); + font-size: 13px; +} +.social-login-divider::before, +.social-login-divider::after { + content: ''; + flex: 1; + height: 1px; + background: var(--color-line, #e2e8f0); +} +.social-login-divider span { + padding: 0 16px; + white-space: nowrap; +} + +.oauth-row { + display: flex; + flex-wrap: wrap; + gap: 10px; + justify-content: center; + margin-top: 16px; +} + +.oauth-btn { + width: 44px; + height: 44px; + border-radius: var(--radius-btn); + border: 1px solid var(--color-line); + display: flex; + align-items: center; + justify-content: center; + color: var(--color-ink-3); + transition: border-color 0.2s, color 0.2s; +} +.oauth-btn svg { + width: 22px; + height: 22px; + display: block; + fill: currentColor; +} + +.oauth-btn:hover { + border-color: var(--color-primary); + color: var(--color-primary); +} + +.auth-footer-link { + text-align: center; + margin-top: 20px; + font-size: 14px; + color: var(--color-ink-3); +} + +.auth-footer-link a { + color: var(--color-primary); + font-weight: 600; +} + +/* ========== 用户中心 Dashboard ========== */ +.dashboard { + max-width: 960px; + margin: 0 auto; +} + +.dashboard-tabs { + display: flex; + flex-wrap: wrap; + gap: 4px; + border-bottom: 1px solid var(--color-line); + margin-bottom: 24px; + position: sticky; + top: var(--nav-height); + z-index: 50; + background: var(--surface-page); + padding-top: 8px; +} + +/* WordPress Admin Bar 已全局禁用,无需偏移规则 */ + +.dashboard-tabs button { + padding: 12px 16px; + border: none; + background: none; + font-size: 14px; + font-weight: 600; + color: var(--color-ink-3); + cursor: pointer; + border-bottom: 2px solid transparent; + margin-bottom: -1px; + transition: color 0.2s, border-color 0.2s; +} + +.dashboard-tabs__link { + padding: 12px 16px; + font-size: 14px; + font-weight: 600; + color: var(--color-ink-3); + text-decoration: none; + border-bottom: 2px solid transparent; + display: inline-flex; + align-items: center; + gap: 6px; + margin-bottom: -1px; + transition: color 0.15s; +} + +.dashboard-tabs__link:hover { + color: var(--color-primary); +} + +.dashboard-tabs button:hover { + color: var(--color-ink); +} + +.dashboard-tabs button.is-active { + color: var(--color-primary); + border-bottom-color: var(--color-primary); +} + +@media (max-width: 767px) { + .dashboard-tabs button { + padding: 10px 12px; + font-size: 13px; + } + .tab-hide-mobile { display: none !important; } +} + +@media (min-width: 768px) { + .tab-hide-pc { display: none !important; } +} + +.dashboard-panel { + display: none; +} + +.dashboard-panel.is-active { + display: block; +} + +.data-table-wrap { + overflow-x: auto; + border-radius: var(--radius-lg); + border: 1px solid var(--color-line); +} + +.data-table { + width: 100%; + border-collapse: collapse; + font-size: 14px; +} + +.data-table th, +.data-table td { + padding: 12px 16px; + text-align: left; + border-bottom: 1px solid var(--color-line); +} + +.data-table th { + background: var(--surface-3); + font-weight: 600; +} + +.data-table tr:nth-child(even) { + background: var(--surface-2); +} + +html.dark .data-table tr:nth-child(even), +html.dark .data-table tr:nth-child(even) { + background: rgba(255, 255, 255, 0.02); +} + +.notif-list { + border: 1px solid var(--color-line); + border-radius: var(--radius-lg); + overflow: hidden; +} + +.notif-item { + display: flex; + gap: 12px; + padding: 16px 18px; + border-bottom: 1px solid var(--color-line); + background: var(--surface-2); +} + +.notif-item:last-child { + border-bottom: none; +} + +.notif-item--unread { + border-left: 3px solid var(--color-info); + padding-left: 15px; +} + +.notif-item--unread .notif-title { + font-weight: 700; +} + +.notif-title { + font-size: 14px; + margin: 0 0 4px; +} + +.notif-meta { + font-size: 12px; + color: var(--color-ink-4); +} +/* ========== About / 友链 / 404 ========== */ +.about-hero { + max-width: 640px; + margin: 0 auto; + text-align: center; + padding: 24px 20px 40px; + border-radius: var(--radius-lg); + border: 1px solid var(--color-line); + background: var(--surface-2); +} + +.about-avatar { + width: 150px; + height: 150px; + border-radius: var(--radius-avatar); + object-fit: cover; + margin-bottom: 16px; + border: 4px solid var(--color-line); +} diff --git a/assets/css/frontend/pages/base-2.css b/assets/css/frontend/pages/base-2.css new file mode 100644 index 00000000..61dda31f --- /dev/null +++ b/assets/css/frontend/pages/base-2.css @@ -0,0 +1,400 @@ + +.skill-tags { + display: flex; + flex-wrap: wrap; + gap: 8px; + justify-content: center; + margin-top: 16px; +} + +.skill-tags span { + padding: 6px 12px; + border-radius: var(--radius-pill); + border: 1px solid var(--color-line); + font-size: 13px; + color: var(--color-ink-3); +} + +.timeline { + max-width: 560px; + margin: 40px auto 0; + padding-left: 20px; + border-left: 2px solid var(--color-line); +} + +.timeline__item { + position: relative; + padding: 0 0 24px 20px; +} + +.timeline__item::before { + content: ""; + position: absolute; + left: -27px; + top: 4px; + width: 12px; + height: 12px; + border-radius: var(--radius-avatar); + background: var(--color-primary); + border: 2px solid var(--surface-page); +} + +.friends-grid { + display: grid; + grid-template-columns: 1fr; + gap: 20px; +} + +@media (min-width: 768px) { + .friends-grid { + grid-template-columns: repeat(3, 1fr); + } +} + +.friend-card { + border-radius: var(--radius-lg); + border: 1px solid var(--color-line); + padding: 20px; + text-align: center; + background: var(--surface-2); + transition: transform 0.25s, box-shadow 0.25s; + color: inherit; + text-decoration: none; + display: block; +} + +.friend-card:hover { + transform: translateY(-4px); + box-shadow: var(--shadow-md); + color: inherit; +} + +.friend-card img { + width: 80px; + height: 80px; + object-fit: contain; + border-radius: var(--radius-btn); + margin-bottom: 12px; +} + +.friend-card h3 { + font-size: 1rem; + margin: 0 0 8px; +} + +.friend-card p { + font-size: 12px; + color: var(--color-ink-3); + margin: 0; + line-height: 1.5; +} + +.error-hero { + text-align: center; + padding: 80px 20px 60px; + max-width: 720px; + margin: 0 auto; +} + +.error-hero__icon { + font-size: 4rem; + margin: 0 0 8px; + color: var(--color-primary); +} + +.error-hero__code { + font-size: clamp(4rem, 12vw, 7rem); + font-weight: 800; + color: var(--color-ink-4, var(--color-ink-3)); + line-height: 1; + margin-bottom: 8px; +} + +.error-hero__title { + font: 700 clamp(20px, 3vw, 28px)/1.3 var(--font-display); + margin: 0 0 12px; + color: var(--color-ink); +} + +.error-hero__desc { + color: var(--color-ink-2); + max-width: 480px; + margin: 0 auto 28px; + line-height: 1.65; +} + +.error-hero__search { + display: flex; + align-items: center; + gap: 8px; + max-width: 480px; + margin: 0 auto 24px; + padding: 6px 6px 6px 14px; + border: 1px solid var(--color-line); + border-radius: var(--radius-pill); + background: var(--surface-1); + transition: border-color .18s ease, box-shadow .18s ease; +} + +.error-hero__search:focus-within { + border-color: var(--color-primary); + box-shadow: 0 0 0 3px rgba(240, 68, 148, 0.15); +} + +.error-hero__search-icon { + color: var(--color-ink-3); + display: inline-flex; +} + +.error-hero__search input[type="search"] { + flex: 1 1 auto; + border: 0; + background: transparent; + outline: none; + font: 500 14px/1 var(--font-ui); + color: var(--color-ink); + padding: 8px 0; +} + +.error-hero__actions { + display: flex; + gap: 12px; + justify-content: center; + flex-wrap: wrap; +} + +.error-section { + max-width: 720px; + margin: 40px auto; + padding: 24px; + background: var(--surface-1); + border: 1px solid var(--color-line); + border-radius: var(--radius-lg); +} + +.error-section__title { + font: 600 16px/1.2 var(--font-ui); + margin: 0 0 16px; + color: var(--color-ink); +} + +.error-section__chips { + display: flex; + flex-wrap: wrap; + gap: 8px; +} + +.error-section__chip { + display: inline-flex; + align-items: center; + gap: 6px; + padding: 6px 12px; + border-radius: var(--radius-pill); + background: var(--surface-2); + color: var(--color-ink-2); + text-decoration: none; + font: 500 13px/1 var(--font-ui); + transition: background .18s ease, color .18s ease; +} + +.error-section__chip:hover { + background: var(--color-primary); + color: var(--color-on-primary); +} + +.error-section__chip span { + opacity: .7; + font-variant-numeric: tabular-nums; +} + +.error-section__list { + list-style: none; + margin: 0; + padding: 0; +} + +.error-section__list li + li { + border-top: 1px dashed var(--color-line); +} + +.error-section__list a { + display: flex; + align-items: center; + justify-content: space-between; + gap: 12px; + padding: 12px 0; + color: var(--color-ink); + text-decoration: none; + transition: color .18s ease; +} + +.error-section__list a:hover .error-section__list-title { + color: var(--color-primary); +} + +.error-section__list-title { + flex: 1 1 auto; + font: 500 14px/1.4 var(--font-ui); + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.error-section__list-meta { + flex: 0 0 auto; + color: var(--color-ink-3); + font: 500 12px/1 var(--font-ui); + font-variant-numeric: tabular-nums; +} + +/* ============================================================ + * 首页分类推荐模块 + * ============================================================ */ +.category-recommend { + max-width: var(--container); + margin: 40px auto; + padding: 0 20px; +} + +.category-recommend__header { + margin-bottom: 24px; +} + +.category-recommend__title { + font-size: 24px; + font-weight: 700; + color: var(--color-ink); + position: relative; + padding-left: 16px; + margin: 0; +} + +.category-recommend__title::before { + content: ''; + position: absolute; + left: 0; + top: 4px; + bottom: 4px; + width: 4px; + border-radius: 2px; + background: var(--color-primary); +} + +.category-recommend__grid { + display: grid; + grid-template-columns: repeat(var(--cr-columns, 2), 1fr); + gap: 20px; +} + +.category-recommend-card { + border: 1px solid var(--color-line); + border-radius: var(--radius-lg); + background: var(--surface-2); + overflow: hidden; + transition: box-shadow 0.2s ease, border-color 0.2s ease; +} + +.category-recommend-card:hover { + box-shadow: var(--shadow-md); + border-color: var(--color-primary); +} + +.category-recommend-card__hero { + position: relative; + aspect-ratio: 16 / 9; + overflow: hidden; + background: var(--surface-3); +} + +.category-recommend-card__hero a { + display: block; + width: 100%; + height: 100%; +} + +.category-recommend-card__cover { + width: 100%; + height: 100%; + object-fit: cover; + display: block; + transition: transform 0.3s ease; +} + +.category-recommend-card:hover .category-recommend-card__cover { + transform: scale(1.02); +} + +.category-recommend-card__badge { + position: absolute; + top: 12px; + right: 12px; + background: rgba(0, 0, 0, 0.6); + color: #fff; + font-size: 12px; + font-weight: 600; + padding: 4px 10px; + border-radius: var(--radius-pill); + backdrop-filter: blur(4px); + pointer-events: none; +} + +.category-recommend-card__meta { + padding: 16px 16px 12px; +} + +.category-recommend-card__name { + margin: 0 0 8px; + font-size: 18px; + font-weight: 700; + line-height: 1.3; +} + +.category-recommend-card__name a { + color: var(--color-ink); +} + +.category-recommend-card__name a:hover { + color: var(--color-primary); +} + +.category-recommend-card__desc { + margin: 0; + font-size: 14px; + color: var(--color-ink-3); + line-height: 1.5; + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + overflow: hidden; +} + +.category-recommend-card__posts { + list-style: none; + margin: 0; + padding: 0 16px; + border-top: 1px solid var(--color-line); +} + +.category-recommend-card__post-item { + display: flex; + align-items: center; + justify-content: space-between; + gap: 8px; + padding: 10px 0; + border-bottom: 1px solid var(--color-line); +} + +.category-recommend-card__post-item:last-child { + border-bottom: none; +} + +.category-recommend-card__post-title { + flex: 1; + font-size: 14px; + color: var(--color-ink); + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + min-width: 0; +} + diff --git a/assets/css/frontend/pages/base-3.css b/assets/css/frontend/pages/base-3.css new file mode 100644 index 00000000..fc690cf4 --- /dev/null +++ b/assets/css/frontend/pages/base-3.css @@ -0,0 +1,193 @@ +.category-recommend-card__post-title:hover { + color: var(--color-primary); +} + +.category-recommend-card__post-date { + flex-shrink: 0; + font-size: 12px; + color: var(--color-ink-4); +} + +.category-recommend-card__more { + padding: 12px 16px; + text-align: center; + border-top: 1px solid var(--color-line); +} + +.category-recommend-card__more a { + font-size: 14px; + font-weight: 600; + color: var(--color-primary); + transition: color 0.15s ease; +} + +.category-recommend-card__more a:hover { + color: var(--color-primary-dark); + text-decoration: underline; +} + +/* 分类推荐懒加载骨架 */ +.category-recommend-card__hero .aksrt-skeleton { + position: absolute; + inset: 0; +} + +.category-recommend-card__hero img.aksrt-lazy { + opacity: 0; + transition: opacity 0.3s ease; +} + +.category-recommend-card__hero img.aksrt-loaded { + opacity: 1; +} + +/* 分类推荐响应式 */ +@media (max-width: 767px) { + .category-recommend { + margin: 24px auto; + padding: 0 16px; + } + + .category-recommend__title { + font-size: 20px; + } + + .category-recommend__grid { + grid-template-columns: 1fr; + gap: 16px; + } + + .category-recommend-card__name { + font-size: 16px; + } + + .category-recommend-card__meta { + padding: 12px 14px 10px; + } + + .category-recommend-card__posts { + padding: 0 14px; + } +} + +/* ============================================================ + * 通知"敬请期待"占位(profile dashboard) + * ============================================================ */ +.notif-coming-soon { + text-align: center; + padding: var(--space-9, 48px) var(--space-5, 20px) !important; +} + +.notif-coming-soon__icon { + width: 64px; + height: 64px; + margin: 0 auto var(--space-4, 16px); + display: inline-flex; + align-items: center; + justify-content: center; + border-radius: var(--radius-pill); + background: var(--color-primary-soft, var(--color-primary-50)); + color: var(--color-primary); +} + +.notif-coming-soon__icon svg { + width: 32px; + height: 32px; +} + +.notif-coming-soon__title { + font-size: var(--text-lg, 1.25rem); + font-weight: 700; + margin: 0 0 var(--space-2, 8px); + color: var(--color-ink); +} + +.notif-coming-soon__pill { + display: inline-block; + padding: 4px 12px; + margin: 0 0 var(--space-3, 12px); + font-size: 0.75rem; + font-weight: 600; + letter-spacing: 0.04em; + background: var(--color-primary-soft, var(--color-primary-50)); + color: var(--color-primary-active, var(--color-primary-dark)); + border-radius: var(--radius-pill); +} + +.notif-coming-soon__desc { + max-width: 420px; + margin: 0 auto; + font-size: var(--text-sm, 0.875rem); + line-height: var(--leading-relaxed, 1.7); + color: var(--color-ink-3); +} + +/* ============================================================ + * Forum Page + * ============================================================ */ + +.aksrt-forum-header { + padding: clamp(32px, 5vw, 64px) 0 clamp(16px, 3vw, 32px); + background: linear-gradient(135deg, var(--color-primary-soft, #e6f4ff) 0%, var(--surface-2, #f5f7fa) 100%); + margin-bottom: 32px; + text-align: center; +} + +.aksrt-forum-header__title { + font: 700 clamp(28px, 4vw, 40px)/1.15 var(--font-display, inherit); + margin: 0 0 8px; + color: var(--color-ink); +} + +.aksrt-forum-header__desc { + margin: 0 0 24px; + color: var(--color-ink-2, #666); + font-size: 15px; +} + +.aksrt-forum-header__stats { + display: flex; + justify-content: center; + gap: 32px; +} + +.aksrt-forum-header__stat-num { + display: block; + font-size: 28px; + font-weight: 700; + color: var(--color-primary); +} + +.aksrt-forum-header__stat-label { + font-size: 13px; + color: var(--color-ink-3, #999); +} + +.aksrt-forum__layout { + display: grid; + grid-template-columns: 1fr 280px; + gap: 24px; +} + +@media (max-width: 1023px) { + .aksrt-forum__layout { + grid-template-columns: 1fr; + } +} + +.aksrt-forum-section__title { + display: flex; + align-items: center; + gap: 8px; + font-size: 16px; + font-weight: 600; + color: var(--color-ink); + margin: 0 0 16px; + padding-bottom: 8px; + border-bottom: 1px solid var(--color-line, #e8e8e8); +} + +.aksrt-forum-section__title i { + color: var(--color-primary); +} + diff --git a/assets/css/frontend/pages/base.css b/assets/css/frontend/pages/base.css new file mode 100644 index 00000000..4e615659 --- /dev/null +++ b/assets/css/frontend/pages/base.css @@ -0,0 +1,3 @@ +@import url("base-1.css"); +@import url("base-2.css"); +@import url("base-3.css"); diff --git a/assets/css/frontend/pages/board-cards.css b/assets/css/frontend/pages/board-cards.css new file mode 100644 index 00000000..93fc53c6 --- /dev/null +++ b/assets/css/frontend/pages/board-cards.css @@ -0,0 +1,58 @@ +/* Board cards */ +.aksrt-forum-boards__grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); + gap: 12px; + margin-bottom: 32px; +} + +.aksrt-forum-board-card { + display: flex; + gap: 12px; + padding: 16px; + background: var(--surface-1, #fff); + border: 1px solid var(--color-line, #e8e8e8); + border-radius: 8px; + transition: box-shadow 0.2s; +} + +.aksrt-forum-board-card:hover { + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.06); +} + +.aksrt-forum-board-card__icon { + width: 48px; + height: 48px; + display: flex; + align-items: center; + justify-content: center; + border-radius: 8px; + background: var(--color-primary-soft, #e6f4ff); + color: var(--color-primary); + font-size: 20px; + flex-shrink: 0; +} + +.aksrt-forum-board-card__title { + margin: 0 0 4px; + font-size: 14px; + font-weight: 600; + color: var(--color-ink); +} + +.aksrt-forum-board-card__desc { + margin: 0 0 8px; + font-size: 12px; + color: var(--color-ink-3, #999); + line-height: 1.5; +} + +.aksrt-forum-board-card__meta { + font-size: 11px; + color: var(--color-ink-3, #999); +} + +.aksrt-forum-board-card__meta i { + margin-right: 3px; +} + diff --git a/assets/css/frontend/pages/empty-state.css b/assets/css/frontend/pages/empty-state.css new file mode 100644 index 00000000..33ef4e63 --- /dev/null +++ b/assets/css/frontend/pages/empty-state.css @@ -0,0 +1,292 @@ +/* Empty state */ +.aksrt-forum__empty { + text-align: center; + padding: 48px 24px; + color: var(--color-ink-3, #999); +} + +.aksrt-forum__empty i { + font-size: 48px; + margin-bottom: 16px; + opacity: 0.3; +} + +.aksrt-forum-header { + text-align: left; +} + +.aksrt-forum-header__content { + display: flex; + flex-wrap: wrap; + align-items: flex-end; + justify-content: space-between; + gap: 20px; + width: min(1200px, calc(100% - 32px)); + margin: 0 auto 20px; +} + +.aksrt-forum-header__actions { + display: flex; + flex-wrap: wrap; + gap: 10px; +} + +.aksrt-forum-header__action { + display: inline-flex; + align-items: center; + gap: 8px; + padding: 10px 16px; + border-radius: 999px; + border: 1px solid var(--color-line, #d9e2f2); + background: rgba(255, 255, 255, 0.78); + color: var(--color-ink); + text-decoration: none; +} + +.aksrt-forum-header__action--primary { + border-color: var(--color-primary); + background: var(--color-primary); + color: #fff; +} + +.aksrt-forum-header__stats { + flex-wrap: wrap; +} + +.aksrt-forum-header__stat { + min-width: 92px; +} + +.aksrt-forum-ops { + margin-bottom: 24px; +} + +.aksrt-forum-ops__card { + padding: 20px; + background: var(--surface-1, #fff); + border: 1px solid var(--color-line, #e8e8e8); + border-radius: 12px; +} + +.aksrt-forum-ops__list { + margin: 0; + padding-left: 18px; + color: var(--color-ink-2, #666); + line-height: 1.7; +} + +.aksrt-forum-board-card__link { + display: flex; + gap: 12px; + width: 100%; + color: inherit; + text-decoration: none; +} + +.aksrt-forum-board-card__head { + display: flex; + align-items: center; + justify-content: space-between; + gap: 10px; +} + +.aksrt-forum-board-card__status { + display: inline-flex; + align-items: center; + padding: 2px 8px; + border-radius: 999px; + background: var(--surface-2, #f0f5ff); + color: var(--color-primary); + font-size: 11px; +} + +.aksrt-forum-topic-row__title-wrap { + display: flex; + align-items: center; + flex-wrap: wrap; + gap: 6px; + margin-bottom: 4px; +} + +.aksrt-forum-topic-row__badge { + display: inline-flex; + align-items: center; + padding: 2px 8px; + border-radius: 999px; + font-size: 11px; + font-weight: 600; +} + +.aksrt-forum-topic-row__badge--sticky { + background: #e6f4ff; + color: #1677ff; +} + +.aksrt-forum-topic-row__badge--featured { + background: #f6ffed; + color: #389e0d; +} + +.aksrt-forum-topic-row__board { + color: var(--color-primary); + text-decoration: none; +} + +.aksrt-forum-sidebar-card__empty { + margin: 0; + color: var(--color-ink-3, #999); + font-size: 13px; +} + +.aksrt-forum-sidebar-card__item--stack { + display: block; +} + +.aksrt-forum-sidebar-card__item--stack strong, +.aksrt-forum-sidebar-card__item--stack span { + display: block; +} + +@media (max-width: 767px) { + .aksrt-forum-header__content { + width: calc(100% - 24px); + } + + .aksrt-forum-header__actions { + width: 100%; + } + + .aksrt-forum-header__action { + width: 100%; + justify-content: center; + } +} + +/* ============================================================ + * 文章归档(page-archives.php + [aksrt_archive] 短代码) + * Phase 10 视觉收口:此前 .aksrt-archives 无样式。 + * ============================================================ */ +.aksrt-archives__year { + font-size: 1.5rem; + font-weight: 700; + color: var(--color-ink); + margin: 28px 0 12px; + padding-bottom: 8px; + border-bottom: 2px solid var(--color-line); +} + +.aksrt-archives__year:first-child { + margin-top: 0; +} + +.aksrt-archives__month { + font-size: 0.95rem; + font-weight: 600; + color: var(--color-ink-3, #666); + margin: 16px 0 8px; +} + +.aksrt-archives__list { + list-style: none; + margin: 0 0 8px; + padding: 0; +} + +.aksrt-archives__item { + display: flex; + align-items: baseline; + gap: 12px; + padding: 6px 0; + border-bottom: 1px dashed var(--color-line); +} + +.aksrt-archives__date { + flex-shrink: 0; + font-variant-numeric: tabular-nums; + font-size: 0.8125rem; + color: var(--color-ink-4, #999); +} + +.aksrt-archives__link { + color: var(--color-ink); + text-decoration: none; + transition: color 0.15s ease; +} + +.aksrt-archives__link:hover { + color: var(--color-primary); +} + +.aksrt-archives--empty { + padding: 24px; + text-align: center; + color: var(--color-ink-4, #999); +} + +/* ============================================================ + * 个人资料卡短代码([aksrt_profile]) + * ============================================================ */ +.aksrt-profile-card { + display: flex; + gap: 14px; + align-items: flex-start; + padding: 16px; + border: 1px solid var(--color-line); + border-radius: var(--radius, 8px); + background: var(--surface-1, #fff); +} + +.aksrt-profile-card--guest { + flex-direction: column; + align-items: flex-start; + gap: 10px; +} + +.aksrt-profile-card__avatar img { + width: 64px; + height: 64px; + border-radius: 50%; + object-fit: cover; +} + +.aksrt-profile-card__body { + flex: 1; + min-width: 0; +} + +.aksrt-profile-card__name { + font-size: 1rem; + font-weight: 600; + color: var(--color-ink); + text-decoration: none; +} + +.aksrt-profile-card__name:hover { + color: var(--color-primary); +} + +.aksrt-profile-card__bio { + margin: 4px 0 8px; + font-size: 0.8125rem; + color: var(--color-ink-3, #666); + line-height: 1.5; +} + +.aksrt-profile-card__stats { + display: flex; + gap: 18px; +} + +.aksrt-profile-card__stat { + display: flex; + flex-direction: column; + font-size: 0.75rem; + color: var(--color-ink-4, #999); +} + +.aksrt-profile-card__stat strong { + font-size: 1.05rem; + color: var(--color-ink); + line-height: 1.2; +} + diff --git a/assets/css/frontend/pages/sidebar.css b/assets/css/frontend/pages/sidebar.css new file mode 100644 index 00000000..1b7466cf --- /dev/null +++ b/assets/css/frontend/pages/sidebar.css @@ -0,0 +1,98 @@ +/* Sidebar */ +.aksrt-forum-sidebar-card { + background: var(--surface-1, #fff); + border: 1px solid var(--color-line, #e8e8e8); + border-radius: 8px; + padding: 16px; + margin-bottom: 16px; +} + +.aksrt-forum-sidebar-card__title { + display: flex; + align-items: center; + gap: 8px; + margin: 0 0 12px; + font-size: 14px; + font-weight: 600; + color: var(--color-ink); +} + +.aksrt-forum-sidebar-card__title i { + color: var(--color-primary); +} + +.aksrt-forum-sidebar-card__list { + list-style: none; + margin: 0; + padding: 0; +} + +.aksrt-forum-sidebar-card__item { + display: flex; + align-items: center; + gap: 8px; + padding: 8px 0; + border-bottom: 1px solid var(--color-line, #f0f0f0); +} + +.aksrt-forum-sidebar-card__item:last-child { + border-bottom: none; +} + +.aksrt-forum-sidebar-card__rank { + width: 20px; + height: 20px; + display: flex; + align-items: center; + justify-content: center; + border-radius: 4px; + background: var(--surface-2, #f5f7fa); + font-size: 11px; + font-weight: 600; + color: var(--color-ink-3, #999); + flex-shrink: 0; +} + +.aksrt-forum-sidebar-card__item:nth-child(1) .aksrt-forum-sidebar-card__rank { background: #fff1f0; color: #f5222d; } +.aksrt-forum-sidebar-card__item:nth-child(2) .aksrt-forum-sidebar-card__rank { background: #fff7e6; color: #fa8c16; } +.aksrt-forum-sidebar-card__item:nth-child(3) .aksrt-forum-sidebar-card__rank { background: var(--color-primary-soft); color: var(--color-primary); } + +.aksrt-forum-sidebar-card__link { + flex: 1; + font-size: 13px; + color: var(--color-ink-2, #666); + text-decoration: none; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.aksrt-forum-sidebar-card__link:hover { + color: var(--color-primary); +} + +.aksrt-forum-sidebar-card__views { + font-size: 11px; + color: var(--color-ink-3, #999); + flex-shrink: 0; +} + +.aksrt-forum-sidebar-card__content ul { + list-style: none; + margin: 0; + padding: 0; +} + +.aksrt-forum-sidebar-card__content li { + padding: 4px 0; + font-size: 13px; + color: var(--color-ink-2, #666); + line-height: 1.6; +} + +.aksrt-forum-sidebar-card__content li::before { + content: '•'; + color: var(--color-primary); + margin-right: 6px; +} + diff --git a/assets/css/frontend/pages/topic-rows.css b/assets/css/frontend/pages/topic-rows.css new file mode 100644 index 00000000..fe6336e7 --- /dev/null +++ b/assets/css/frontend/pages/topic-rows.css @@ -0,0 +1,55 @@ +/* Topic rows */ +.aksrt-forum-topics__list { + display: flex; + flex-direction: column; + gap: 8px; + margin-bottom: 32px; +} + +.aksrt-forum-topic-row { + display: flex; + gap: 12px; + padding: 12px; + background: var(--surface-1, #fff); + border: 1px solid var(--color-line, #e8e8e8); + border-radius: 8px; + transition: border-color 0.2s; +} + +.aksrt-forum-topic-row:hover { + border-color: var(--color-primary); +} + +.aksrt-forum-topic-row__avatar img { + width: 40px; + height: 40px; + border-radius: 50%; + object-fit: cover; +} + +.aksrt-forum-topic-row__title { + margin: 0 0 4px; + font-size: 14px; + font-weight: 600; +} + +.aksrt-forum-topic-row__title a { + color: var(--color-ink); + text-decoration: none; +} + +.aksrt-forum-topic-row__title a:hover { + color: var(--color-primary); +} + +.aksrt-forum-topic-row__meta { + display: flex; + gap: 12px; + font-size: 11px; + color: var(--color-ink-3, #999); +} + +.aksrt-forum-topic-row__meta i { + margin-right: 3px; +} + diff --git a/assets/css/frontend/pagination.css b/assets/css/frontend/pagination.css new file mode 100644 index 00000000..e13a1072 --- /dev/null +++ b/assets/css/frontend/pagination.css @@ -0,0 +1,230 @@ +/* ========== 分页 — 对齐 zibll pagination ========== */ +.pagination, +.aksrt-pagination, +.navigation.pagination .nav-links, +.pagenav.ajax-pag { + display: flex; + align-items: center; + justify-content: center; + gap: 4px; + padding: 20px 0; + flex-wrap: wrap; +} + +.pagination a, +.pagination span, +.aksrt-pagination a, +.aksrt-pagination span, +.navigation.pagination a, +.navigation.pagination span, +.pagenav.ajax-pag a, +.pagenav.ajax-pag span { + display: inline-flex; + align-items: center; + justify-content: center; + min-width: 31px; + padding: 6px 9px 5px; + font-size: 13px; + line-height: 1.4; + color: var(--muted-color, var(--color-ink-3)); + background: var(--main-border-color, rgba(50, 50, 50, 0.06)); + border: none; + border-radius: 3px; + text-decoration: none; + transition: all 0.2s; + user-select: none; +} + +.pagination a:hover, +.aksrt-pagination a:hover, +.navigation.pagination a:hover, +.pagenav.ajax-pag a:hover { + opacity: 0.7; +} + +.pagination .current, +.aksrt-pagination .current, +.navigation.pagination .current, +.pagenav.ajax-pag .current { + color: var(--color-on-primary, #fff); + background: var(--color-primary, #f04494); + border-color: var(--color-primary, #f04494); + font-weight: 500; +} + +.pagination .dots, +.aksrt-pagination .dots, +.navigation.pagination .dots, +.pagenav.ajax-pag .dots { + border: none; + background: none; + color: var(--color-ink-4, #999); + cursor: default; + min-width: auto; + padding-left: 4px; + padding-right: 4px; +} + +.pagination .prev, +.pagination .next, +.aksrt-pagination .prev, +.aksrt-pagination .next, +.navigation.pagination .prev, +.navigation.pagination .next, +.pagenav.ajax-pag .prev, +.pagenav.ajax-pag .next { + font-size: 12px; +} + +.pagination .prev i, +.pagination .next i, +.aksrt-pagination .prev i, +.aksrt-pagination .next i, +.navigation.pagination .prev i, +.navigation.pagination .next i, +.pagenav.ajax-pag .prev i, +.pagenav.ajax-pag .next i { + font-size: 11px; +} + +.pagenav.ajax-pag .pag-jump, +.aksrt-pagination .pag-jump, +.navigation.pagination .pag-jump { + display: inline-flex; + align-items: center; + gap: 6px; + margin-left: 6px; +} + +.pagenav.ajax-pag .jump-input, +.aksrt-pagination .jump-input, +.navigation.pagination .jump-input { + width: 64px; + min-width: 64px; + padding: 6px 8px 5px; + font-size: 13px; + line-height: 1.4; + color: var(--muted-color, var(--color-ink-3)); + background: var(--main-bg-color, #fff); + border: 1px solid var(--main-border-color, rgba(50, 50, 50, 0.06)); + border-radius: 3px; + box-shadow: none; +} + +.pagenav.ajax-pag .jump-input:focus, +.aksrt-pagination .jump-input:focus, +.navigation.pagination .jump-input:focus { + outline: none; + border-color: var(--focus-color, var(--color-primary, #f04494)); +} + +.pagenav.ajax-pag .pag-jump .ajax-next, +.aksrt-pagination .pag-jump .ajax-next, +.navigation.pagination .pag-jump .ajax-next { + min-width: auto; + cursor: pointer; +} + +/* 上一页/下一页 */ +.pagination__nav { + display: flex; + gap: 8px; + justify-content: center; + margin-top: 8px; +} + +.pagination__nav a { + display: inline-flex; + align-items: center; + gap: 4px; + padding: 6px 14px; + font-size: 13px; + color: var(--color-ink-2, #4e5358); + background: var(--surface-1, #fff); + border: 1px solid var(--color-line, rgba(50, 50, 50, 0.06)); + border-radius: 6px; + text-decoration: none; + transition: all 0.2s; +} + +.pagination__nav a:hover { + color: var(--color-primary, #f04494); + border-color: var(--color-primary, #f04494); +} + +/* AJAX 加载更多 */ +.load-more { + text-align: center; + padding: 20px 0; +} + +.load-more__btn { + display: inline-flex; + align-items: center; + gap: 6px; + padding: 10px 24px; + font-size: 13px; + color: var(--color-ink-2, #4e5358); + background: var(--surface-1, #fff); + border: 1px solid var(--color-line, rgba(50, 50, 50, 0.06)); + border-radius: 20px; + cursor: pointer; + transition: all 0.2s; +} + +.load-more__btn:hover { + color: var(--color-primary, #f04494); + border-color: var(--color-primary, #f04494); +} + +.load-more__btn:disabled { + opacity: 0.5; + cursor: not-allowed; +} + +.load-more__spinner { + display: inline-block; + width: 16px; + height: 16px; + border: 2px solid var(--surface-3, #e8e8e8); + border-top-color: var(--color-primary, #f04494); + border-radius: 50%; + animation: spin 0.6s linear infinite; +} + +@keyframes spin { + to { transform: rotate(360deg); } +} + +/* 移动端 */ +@media (max-width: 767px) { + .pagination a, + .pagination span, + .aksrt-pagination a, + .aksrt-pagination span, + .navigation.pagination a, + .navigation.pagination span, + .pagenav.ajax-pag a, + .pagenav.ajax-pag span { + min-width: 28px; + font-size: 12px; + margin: 2px; + } + + .pagenav.ajax-pag .pag-jump, + .aksrt-pagination .pag-jump, + .navigation.pagination .pag-jump { + width: 100%; + justify-content: center; + margin-left: 0; + margin-top: 6px; + } + + .pagenav.ajax-pag .jump-input, + .aksrt-pagination .jump-input, + .navigation.pagination .jump-input { + width: 58px; + min-width: 58px; + font-size: 12px; + } +} diff --git a/assets/css/frontend/post-card-cms.css b/assets/css/frontend/post-card-cms.css new file mode 100644 index 00000000..491fb686 --- /dev/null +++ b/assets/css/frontend/post-card-cms.css @@ -0,0 +1,60 @@ +/** + * Post Card · CMS (grid-cms layout) + */ + +.post-grid--grid-cms { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); + gap: 20px; +} + +.post-grid--grid-cms .posts-item.card.posts-item--cms { + height: 100%; + border-radius: 16px; +} + +.post-grid--grid-cms .posts-item--cms .item-body { + gap: 10px; +} + +.post-grid--grid-cms .posts-item--cms .item-excerpt { + -webkit-line-clamp: 2; +} + +.post-grid--grid-cms .posts-item--cms .item-cms-strip { + display: flex; + flex-wrap: wrap; + gap: 8px; + list-style: none; + margin: 0; + padding: 0; +} + +.post-grid--grid-cms .posts-item--cms .item-cms-strip li { + display: inline-flex; + align-items: center; + min-height: 24px; + padding: 0 10px; + border-radius: 999px; + background: var(--surface-2); + color: var(--color-ink-4); + font-size: 12px; + font-weight: 500; +} + +.post-grid--grid-cms .posts-item--cms .item-cms-strip li::before { + display: none; +} + +@media (max-width: 640px) { + .post-grid--grid-cms { + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 14px; + } +} + +@media (max-width: 380px) { + .post-grid--grid-cms { + grid-template-columns: 1fr; + } +} diff --git a/assets/css/frontend/post-card.css b/assets/css/frontend/post-card.css new file mode 100644 index 00000000..00d9e483 --- /dev/null +++ b/assets/css/frontend/post-card.css @@ -0,0 +1,584 @@ +/** + * AKSRT Post Card / List — 1:1 Zibll Alignment + * + * 对齐 zibll main.css 的 .posts-item 系统 + * - 默认 = 列表模式(无额外类名) + * - .card = 卡片模式 + * + * 布局:inline-block(对齐 zibll,不用 Grid) + */ + +/* ============================================================ + * 列表容器 — 对齐 zibll .posts-row + * ============================================================ */ +.post-grid { + margin-left: -8px; + margin-right: -8px; + font-size: 0; /* 消除 inline-block 间隙 */ +} + +.post-grid--list { + margin-left: 0; + margin-right: 0; +} + +/* ============================================================ + * 通用 posts-item 基础 — 对齐 zibll line 7585 + * ============================================================ */ +.posts-item { + padding: 20px; + margin: 15px 0; + background: var(--main-bg-color, #fff); + overflow: hidden; + transition: 0.2s; + box-shadow: 0 0 10px var(--main-shadow, rgba(116, 116, 116, 0.08)); + border-radius: var(--main-radius, 8px); +} + +/* ============================================================ + * 卡片模式 .posts-item.card — 对齐 zibll line 7733 + * ============================================================ */ +.posts-item.card { + width: calc(33.333% - 16px); + display: inline-block; + margin: 8px; + padding: 10px; + vertical-align: top; + transition: 0.3s; + font-size: 1rem; /* 重置容器 font-size: 0 */ +} + +@media (max-width: 991px) { + .posts-item.card { + width: calc(33.333% - 12px); + margin: 6px; + } +} + +@media (max-width: 767px) { + .posts-item.card { + width: calc(50% - 10px); + margin: 5px; + padding: 8px; + } +} + +/* ============================================================ + * 缩略图 — 对齐 zibll line 7604 + * ============================================================ */ +.item-thumbnail { + position: relative; + overflow: hidden; + border-radius: var(--main-radius, 8px); +} + +/* 列表模式缩略图 */ +.posts-item:not(.card) .item-thumbnail { + width: 190px; + height: 0; + padding-bottom: var(--posts-list-scale, 70%); + float: left; + margin-right: 20px; +} + +/* 卡片模式缩略图 */ +.posts-item.card .item-thumbnail { + width: 100%; + height: 0; + padding-bottom: var(--posts-card-scale, 70%); +} + +.item-thumbnail a { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + display: block; +} + +.item-thumbnail img, +.item-thumbnail .fit-cover { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + object-fit: cover; + transition: transform 0.3s ease; +} + +.posts-item:hover .item-thumbnail img { + transform: scale(1.05); +} + +/* 图片徽章 */ +.img-badge { + position: absolute; + top: 8px; + padding: 2px 8px; + border-radius: 4px; + font-size: 11px; + font-weight: 600; + color: #fff; + z-index: 2; +} + +.img-badge.left { + left: 8px; +} + +.badge-sticky { + background: var(--color-error, #ef4444); +} + +/* ============================================================ + * 标题 — 对齐 zibll line 7669 + * ============================================================ */ +.item-heading { + margin-top: 0; + margin-bottom: 5px; + font-size: 18px; + line-height: 1.4em; + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-line-clamp: 2; + overflow: hidden; + max-height: 2.8em; +} + +.item-heading--bold { + font-weight: 700; +} + +.fit-cover { + object-fit: cover; +} + +.fit-contain { + object-fit: contain; +} + +.posts-item.card .item-heading { + font-size: 14px; + min-height: 2.8em; /* 对齐 zibll:定高使无摘要卡片底部 meta 对齐;line-height/max-height 继承基类 1.4em/2.8em */ +} + +.item-heading a { + color: var(--key-color, #333); +} + +.item-heading a:hover { + color: var(--focus-color, #f04494); +} + +/* ============================================================ + * 摘要 — 对齐 zibll 单行 ellipsis + * ============================================================ */ +.item-excerpt { + font-size: 13px; + color: var(--muted-color, #777); + line-height: 1.5; + margin: 5px 0; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; +} + +/* ============================================================ + * 元信息 — 对齐 zibll line 7701 + * ============================================================ */ +.item-meta { + font-size: 13px; + color: var(--muted-2-color, #999); + margin-top: 10px; +} + +.item-meta item { + margin-right: 8px; +} + +.meta-author { + display: inline-flex; + align-items: center; + gap: 6px; +} + +.meta-avatar { + width: 20px; + height: 20px; + border-radius: 50%; + object-fit: cover; +} + +.meta-time { + font-size: 12px; +} + +.meta-right { + display: inline-flex; + align-items: center; + gap: 10px; + float: right; +} + +.meta-item { + display: inline-flex; + align-items: center; + gap: 3px; +} + +.meta-item i { + font-size: 11px; + opacity: 0.7; +} + +.meta-dot { + width: 4px; + height: 4px; + border-radius: 999px; + background: currentColor; + opacity: 0.3; + display: inline-block; +} + +/* ============================================================ + * 标签 — 对齐 zibll line 7723 + * ============================================================ */ +.item-tags { + margin-top: 8px; +} + +.item-tags .badge { + display: inline-block; + font-size: 11px; + padding: 2px 5px; + margin-right: 5px; + border-radius: 50px; + text-decoration: none; + transition: 0.15s; +} + +.badge-price { + background: rgba(239, 68, 68, 0.1); + color: var(--color-error, #ef4444); +} + +.badge-category { + background: var(--focus-shadow-color, rgba(253, 83, 161, 0.12)); + color: var(--focus-color, #f04494); +} + +.badge-category:hover { + background: var(--focus-shadow-color, rgba(253, 83, 161, 0.2)); + color: var(--focus-color, #f04494); + text-decoration: none; +} + +.badge-tag { + background: var(--muted-bg-color, #eee); + color: var(--muted-2-color, #999); +} + +.badge-tag:hover { + background: var(--focus-shadow-color, rgba(253, 83, 161, 0.12)); + color: var(--focus-color, #f04494); + text-decoration: none; +} + +/* ============================================================ + * 卡片模式 body — 对齐 zibll padding: 10px 整体 + * ============================================================ */ +.posts-item.card .item-body { + width: 100%; + margin: 10px 0 0; + padding: 0; +} + +/* ============================================================ + * 列表模式 clearfix — 对齐 zibll float 布局 + * ============================================================ */ +.posts-item:not(.card)::after { + content: ""; + display: table; + clear: both; +} + +/* ============================================================ + * Mini 文章列表 — 对齐 zibll .posts-mini line 7903 + * ============================================================ */ +.posts-mini { + padding: 10px; + display: inline-flex; + width: 50%; + vertical-align: top; + font-size: 1rem; +} + +.posts-mini .item-thumbnail { + width: 96px; + min-width: 96px; + height: 0; + padding-bottom: 70%; + float: none; + margin-right: 12px; + margin-top: 2px; +} + +.posts-mini .item-heading { + font-size: 14px; + line-height: 1.5; + -webkit-line-clamp: 2; + max-height: 3em; +} + +@media (max-width: 767px) { + .posts-mini { + width: 100%; + } +} + +/* ============================================================ + * AJAX 翻页 — 对齐 zibll + * ============================================================ */ +.ajax-pagination { + text-align: center; + padding: 20px 0; +} + +.ajax-pagination .ajax-next { + display: inline-flex; + align-items: center; + gap: 8px; + padding: 5px 15px; + border-radius: 30px; + background: var(--muted-bg-color, #eee); + color: var(--muted-color, #777); + font-size: 14px; + cursor: pointer; + transition: 0.15s; + border: none; + text-decoration: none; +} + +.ajax-pagination .ajax-next:hover { + background: var(--focus-shadow-color, rgba(253, 83, 161, 0.12)); + color: var(--focus-color, #f04494); + text-decoration: none; +} + +.ajax-pagination .ajax-next.is-loading { + pointer-events: none; + opacity: 0.7; +} + +.ajax-pagination .ajax-nomore { + color: var(--muted-2-color, #999); + font-size: 13px; +} + +/* ============================================================ + * 骨架屏(AKSRT 保留,Zibll 无此特性) + * ============================================================ */ +.skeleton-card { + background: var(--main-bg-color, #fff); + border-radius: var(--main-radius, 8px); + overflow: hidden; + box-shadow: 0 0 10px var(--main-shadow, rgba(116, 116, 116, 0.08)); +} + +.skeleton-card__thumb { + width: 100%; + padding-top: var(--posts-card-scale, 70%); + background: var(--muted-bg-color, #eee); + animation: skeleton-pulse 1.5s ease-in-out infinite; +} + +.skeleton-card__body { + padding: 10px; +} + +.skeleton-card__line { + height: 14px; + border-radius: 4px; + background: var(--muted-bg-color, #eee); + margin-bottom: 8px; + animation: skeleton-pulse 1.5s ease-in-out infinite; +} + +.skeleton-card__line--short { + width: 60%; +} + +.skeleton-card__line--meta { + width: 40%; + height: 12px; + margin-top: 12px; +} + +@keyframes skeleton-pulse { + 0%, 100% { opacity: 1; } + 50% { opacity: 0.5; } +} + +/* ============================================================ + * 卡片样式变体 — 对齐 zibll main.css 7682–7900 + * ============================================================ */ + +/* 卡片标签占位高度(无标签卡片不塌陷) */ +.posts-item.card .item-tags { + min-height: 23px; +} + +/* style2:透明底,hover 才出卡片底 + 阴影 */ +.posts-item.card.style2 { + background: transparent; + box-shadow: none; +} + +.posts-item.card.style2:hover { + background: var(--main-bg-color, #fff); + box-shadow: 0 0 10px var(--main-shadow, rgba(116, 116, 116, 0.08)); +} + +/* style3:padding 0,缩略图顶部圆角,body 内 padding 10px */ +.posts-item.card.style3 { + padding: 0; +} + +.posts-item.card.style3 .item-thumbnail, +.posts-item.card.style3 .item-thumbnail img { + border-radius: var(--main-radius, 8px) var(--main-radius, 8px) 0 0; +} + +.posts-item.card.style3 .item-body { + padding: 10px; + margin: 0; +} + +/* 窄缩略图列表变体 .list.style2:130px 缩略图 + 单行标题 ellipsis */ +.posts-item.list.style2 .item-thumbnail { + width: 130px; +} + +.posts-item.list.style2 .item-heading { + text-overflow: ellipsis; + white-space: nowrap; + display: unset; + max-height: 1.4em; +} + +/* 多图卡片 .mult-thumb:九宫格缩略图(每行 4 列) */ +.posts-item.mult-thumb .thumb-items { + margin: 0 -3px 6px -3px; +} + +.posts-item.mult-thumb .thumb-items > span { + width: calc(25% - 6px); + display: inline-block; + height: 0; + padding-bottom: calc(var(--posts-list-scale, 70%) / 4); + margin: 0 3px; + position: relative; +} + +.posts-item.mult-thumb .thumb-items > span > img { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + object-fit: cover; +} + +.posts-item.mult-thumb .thumb-items.contain > span { + background: var(--main-border-color, rgba(50, 50, 50, 0.06)); + border-radius: var(--main-radius, 8px); + overflow: hidden; +} + +.posts-item.mult-thumb .thumb-items.contain > span > img { + object-fit: contain; + border-radius: 0; +} + +/* 无间距连排 .no_margin:首尾圆角,中间无圆角无阴影 */ +.posts-item.no_margin { + margin: 0; + box-shadow: none; + border-radius: 0; +} + +.posts-item.no_margin:first-of-type { + margin-top: 10px; + border-radius: var(--main-radius, 8px) var(--main-radius, 8px) 0 0; +} + +.posts-item.no_margin:last-of-type { + margin-bottom: 15px; + border-radius: 0 0 var(--main-radius, 8px) var(--main-radius, 8px); +} + +.posts-item + .pagenav, +.posts-item + .aksrt-pagination, +.posts-item + .pagination, +.posts-item + .navigation.pagination { + margin-top: -15px; +} + +.posts-item.card + .pagenav, +.posts-item.card + .aksrt-pagination, +.posts-item.card + .pagination, +.posts-item.card + .navigation.pagination { + margin-top: -10px; +} + +/* mini 列表缩略图 hover 放大(对齐 zibll .posts-item:hover 缩略图) */ +.posts-mini:hover .item-thumbnail img { + transform: scale(1.05); +} + +/* 瀑布流 .waterfall-box:缩略图保持原始比例(配合瀑布流 JS 时启用) */ +.waterfall-box { + position: relative; +} + +.waterfall-box .card .item-thumbnail { + padding-bottom: 0; + height: auto; +} + +.waterfall-box .card .item-thumbnail img { + position: relative; + width: 100%; + height: 100%; + object-fit: cover; +} + +/* ============================================================ + * 暗色模式 — 对齐 zibll + * ============================================================ */ +.theme-dark .posts-item, +html.dark .posts-item { + background: var(--main-bg-color, #323335); + border-color: var(--main-border-color, rgba(114, 114, 114, 0.1)); +} + +/* ============================================================ + * 无缩略图状态 + * ============================================================ */ +.posts-item.no-thumb { + overflow: visible; +} + +.posts-item.no-thumb .item-body { + width: 100%; +} + +.posts-item.has-no-thumb { + overflow: visible; +} + +.posts-item.has-no-thumb .item-body { + width: 100%; +} diff --git a/assets/css/frontend/print.css b/assets/css/frontend/print.css new file mode 100644 index 00000000..8fae6ba5 --- /dev/null +++ b/assets/css/frontend/print.css @@ -0,0 +1,105 @@ +/** + * AKSRT Print Stylesheet + * + * 优化内容打印:隐藏导航、悬浮按钮、侧栏,保留正文和图片。 + * + * @package AKSRT + */ + +@media print { + /* 隐藏非内容元素 */ + .site-nav, + .site-footer, + .footer-tabbar, + .float-right, + .float-btn, + .aksrt-toast-container, + .resource-mobile-fab, + .resource-mobile-download-bar, + .sidebar, + .aksrt-sidebar, + .widget-area, + .comments-area, + .post-navigation, + .aksrt-breadcrumbs, + .reading-progress-bar, + .aksrt-admin-bar, + #wpadminbar, + .aksrt-blur-bg { + display: none !important; + } + + /* 正文优化 */ + body { + font-family: Georgia, "Noto Serif SC", serif; + font-size: 12pt; + line-height: 1.6; + color: #000; + background: #fff; + } + + .site-main, + .entry-content, + .article-content { + max-width: 100%; + margin: 0; + padding: 0; + } + + /* 标题 */ + h1, h2, h3, h4, h5, h6 { + page-break-after: avoid; + page-break-inside: avoid; + } + + /* 图片 */ + img { + max-width: 100% !important; + height: auto !important; + page-break-inside: avoid; + } + + /* 链接显示 URL */ + a[href^="http"]::after { + content: " (" attr(href) ")"; + font-size: 0.8em; + color: #666; + word-break: break-all; + } + + /* 代码块 */ + pre, code { + page-break-inside: avoid; + border: 1px solid #ccc; + padding: 4px; + } + + /* 表格 */ + table { + page-break-inside: avoid; + border-collapse: collapse; + } + + th, td { + border: 1px solid #ccc; + padding: 6px; + } + + /* 资源元信息 */ + .resource-meta-box, + .resource-download-box { + border: 1px solid #ccc; + padding: 12px; + margin: 16px 0; + } + + .resource-download-box__btn { + display: none; + } + + /* 分页避免 */ + .post-card, + .entry-card { + page-break-inside: avoid; + } +} diff --git a/assets/css/frontend/product-archive.css b/assets/css/frontend/product-archive.css new file mode 100644 index 00000000..04dd094b --- /dev/null +++ b/assets/css/frontend/product-archive.css @@ -0,0 +1,711 @@ +/** + * AKSRT Product Archive — 商品归档页样式 + * + * 商品分类页、标签页共用样式。 + * 卡片网格、价格徽章、空状态。 + * + * Tokens: 颜色 / 间距 / 圆角 / 阴影 全部来自 core/tokens.css + */ + +/* ================================================ + * 页面头:标题 + 计数 + * ================================================ */ +.aksrt-product-archive { + padding-top: var(--space-6); + padding-bottom: var(--space-9); +} + +.aksrt-product-archive__header { + margin-bottom: var(--space-6); + padding: var(--space-5); + background: var(--surface-1, #fff); + border-radius: var(--radius-lg, 8px); + box-shadow: 0 1px 4px rgba(0, 0, 0, 0.06); +} + +.aksrt-product-archive__title { + margin: 0 0 4px; + font-size: 22px; + font-weight: 700; + color: var(--color-ink); + display: flex; + align-items: center; + gap: 8px; +} + +.aksrt-product-archive__title i { + color: var(--color-primary, var(--color-primary)); +} + +.aksrt-product-archive__desc { + margin: 0 0 8px; + font-size: 14px; + color: var(--color-ink-3); + line-height: 1.6; +} + +.aksrt-product-archive__count { + margin: 0; + font-size: 13px; + color: var(--color-ink-4, #8A8F98); +} + +/* ================================================ + * 商品网格 + * ================================================ */ +.aksrt-product-archive__grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); + gap: var(--space-5); + margin-bottom: var(--space-8); +} + +/* ================================================ + * 商品卡片 + * ================================================ */ +.aksrt-product-card { + display: flex; + flex-direction: column; + background: var(--surface-1, #fff); + border: 1px solid var(--color-line); + border-radius: var(--radius-lg, 8px); + overflow: hidden; + box-shadow: 0 1px 4px rgba(0, 0, 0, 0.04); + transition: transform 0.18s ease, box-shadow 0.18s ease, border-color 0.18s ease; +} + +.aksrt-product-card:hover { + transform: translateY(-3px); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08); + border-color: var(--color-primary, var(--color-primary)); +} + +.aksrt-product-card__link { + display: flex; + flex-direction: column; + flex: 1; + text-decoration: none; + color: inherit; +} + +/* 商品图片 */ +.aksrt-product-card__image { + position: relative; + aspect-ratio: 4 / 3; + background-color: var(--surface-2, #F4F5F7); + overflow: hidden; +} + +.aksrt-product-card__image img { + width: 100%; + height: 100%; + object-fit: cover; + transition: transform 0.3s ease; +} + +.aksrt-product-card:hover .aksrt-product-card__image img { + transform: scale(1.02); +} + +.aksrt-product-card__image--placeholder { + display: flex; + align-items: center; + justify-content: center; + color: var(--color-ink-4, #8A8F98); + font-size: 32px; +} + +/* 卡片正文 */ +.aksrt-product-card__body { + display: flex; + flex-direction: column; + gap: var(--space-2); + padding: var(--space-4); + flex: 1; +} + +.aksrt-product-card__title { + margin: 0; + font-size: 15px; + font-weight: 600; + line-height: 1.4; + color: var(--color-ink); + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + overflow: hidden; +} + +.aksrt-product-card__excerpt { + margin: 0; + font-size: 13px; + color: var(--color-ink-3); + line-height: 1.5; + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + overflow: hidden; +} + +/* 底部:价格 + 销量 */ +.aksrt-product-card__footer { + display: flex; + align-items: baseline; + justify-content: space-between; + margin-top: auto; + padding-top: var(--space-3); + border-top: 1px solid var(--color-line-soft, #F0F1F3); +} + +.aksrt-product-card__price { + font-size: 18px; + font-weight: 700; + color: var(--color-error, #EF4444); +} + +.aksrt-product-card__sales { + font-size: 12px; + color: var(--color-ink-4, #8A8F98); +} + +/* ================================================ + * 分页 + * ================================================ */ +.aksrt-product-archive__pagination { + display: flex; + justify-content: center; + padding: var(--space-5) 0; +} + +.aksrt-product-archive__pagination .page-numbers { + display: inline-flex; + align-items: center; + justify-content: center; + min-width: 36px; + height: 36px; + padding: 0 8px; + margin: 0 4px; + border: 1px solid var(--color-line); + border-radius: var(--radius, 10px); + background: var(--surface-1, #fff); + color: var(--color-ink-2); + font-size: 14px; + text-decoration: none; + transition: all 0.15s ease; +} + +.aksrt-product-archive__pagination .page-numbers:hover { + border-color: var(--color-primary, var(--color-primary)); + color: var(--color-primary, var(--color-primary)); +} + +.aksrt-product-archive__pagination .page-numbers.current { + background: var(--color-primary, var(--color-primary)); + border-color: var(--color-primary, var(--color-primary)); + color: #fff; +} + +/* ================================================ + * 空状态 + * ================================================ */ +.aksrt-product-archive__empty { + text-align: center; + padding: var(--space-9) var(--space-5); + color: var(--color-ink-3); +} + +.aksrt-product-archive__empty i { + font-size: 48px; + color: var(--color-ink-4, #8A8F98); + margin-bottom: var(--space-4); + display: block; +} + +.aksrt-product-archive__empty p { + margin: 0; + font-size: 15px; +} + +/* ================================================ + * 响应式 + * ================================================ */ +@media (max-width: 640px) { + .aksrt-product-archive__grid { + grid-template-columns: repeat(2, 1fr); + gap: var(--space-3); + } + + .aksrt-product-card__body { + padding: var(--space-3); + } + + .aksrt-product-card__title { + font-size: 14px; + } + + .aksrt-product-card__price { + font-size: 16px; + } +} + +@media (max-width: 380px) { + .aksrt-product-archive__grid { + grid-template-columns: 1fr; + } +} + +/* ================================================ + * 产品详情页样式补充 + * ================================================ */ +.aksrt-product { + padding-top: var(--space-6); + padding-bottom: var(--space-9); +} + +.aksrt-product__layout { + display: grid; + grid-template-columns: 1fr 1fr; + gap: var(--space-7); + margin-bottom: var(--space-7); +} + +.aksrt-product__image { + border-radius: var(--radius-lg, 8px); + overflow: hidden; + background: var(--surface-2, #F4F5F7); +} + +.aksrt-product__img { + width: 100%; + display: block; +} + +.aksrt-product__img-placeholder { + aspect-ratio: 1; + display: flex; + align-items: center; + justify-content: center; + color: var(--color-ink-4, #8A8F98); + font-size: 64px; +} + +.aksrt-product__info { + display: flex; + flex-direction: column; + gap: var(--space-4); +} + +.aksrt-product__title { + margin: 0; + font-size: 24px; + font-weight: 700; + color: var(--color-ink); + line-height: 1.3; +} + +.aksrt-product__price-row { + display: flex; + align-items: baseline; + gap: var(--space-3); +} + +.aksrt-product__price { + font-size: 28px; + font-weight: 700; + color: var(--color-error, #EF4444); +} + +.aksrt-product__sales { + font-size: 13px; + color: var(--color-ink-4, #8A8F98); +} + +.aksrt-product__excerpt { + margin: 0; + font-size: 14px; + color: var(--color-ink-3); + line-height: 1.6; +} + +.aksrt-product__meta { + font-size: 14px; + color: var(--color-ink-2); +} + +.aksrt-product__meta i { + margin-right: 4px; +} + +.aksrt-product__actions { + margin-top: var(--space-4); +} + +.aksrt-product__buy-btn { + display: inline-flex; + align-items: center; + gap: 8px; + padding: 12px 32px; + border: none; + border-radius: var(--radius, 10px); + background: var(--color-primary, var(--color-primary)); + color: #fff; + font-size: 16px; + font-weight: 600; + cursor: pointer; + transition: opacity 0.15s; +} + +.aksrt-product__buy-btn:hover { + opacity: 0.85; +} + +.aksrt-product__detail { + padding: var(--space-6); + background: var(--surface-1, #fff); + border-radius: var(--radius-lg, 8px); + box-shadow: 0 1px 4px rgba(0, 0, 0, 0.06); +} + +.aksrt-product__detail-title { + margin: 0 0 var(--space-4); + font-size: 18px; + font-weight: 600; + color: var(--color-ink); +} + +.aksrt-product__detail-content { + font-size: 15px; + line-height: 1.8; + color: var(--color-ink-2); +} + +.aksrt-product__detail-content img { + max-width: 100%; + border-radius: var(--radius, 10px); +} + +.aksrt-product__empty { + text-align: center; + padding: var(--space-10) var(--space-5); + color: var(--color-ink-3); +} + +.aksrt-product__empty i { + display: block; + margin-bottom: var(--space-4); +} + +.aksrt-product__empty p { + margin: 0; + font-size: 16px; +} + +/* 产品详情页响应式 */ +@media (max-width: 767px) { + .aksrt-product__layout { + grid-template-columns: 1fr; + gap: var(--space-5); + } + + .aksrt-product__title { + font-size: 20px; + } + + .aksrt-product__price { + font-size: 24px; + } +} + +/* ================================================ + * 购物车页样式 + * ================================================ */ +.aksrt-cart { + padding-top: var(--space-6); + padding-bottom: var(--space-9); +} + +.aksrt-cart__title { + margin: 0 0 var(--space-6); + font-size: 24px; + font-weight: 700; + color: var(--color-ink); +} + +.aksrt-cart__layout { + display: grid; + grid-template-columns: 1fr 320px; + gap: var(--space-6); +} + +.aksrt-cart__items { + min-height: 200px; +} + +.aksrt-cart__item { + display: flex; + align-items: center; + gap: var(--space-4); + padding: var(--space-4); + background: var(--surface-1, #fff); + border: 1px solid var(--color-line); + border-radius: var(--radius, 10px); + margin-bottom: var(--space-3); +} + +.aksrt-cart__item-img { + width: 80px; + height: 80px; + object-fit: cover; + border-radius: var(--radius-sm, 6px); +} + +.aksrt-cart__item-info { + flex: 1; + min-width: 0; +} + +.aksrt-cart__item-info h4 { + margin: 0 0 4px; + font-size: 15px; + font-weight: 500; + color: var(--color-ink); +} + +.aksrt-cart__item-price { + font-size: 14px; + color: var(--color-ink-3); +} + +.aksrt-cart__item-qty { + display: flex; + align-items: center; + gap: var(--space-2); +} + +.aksrt-cart__qty-btn { + width: 28px; + height: 28px; + border: 1px solid var(--color-line); + border-radius: var(--radius-sm, 6px); + background: var(--surface-1, #fff); + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + font-size: 14px; +} + +.aksrt-cart__qty-btn:hover { + border-color: var(--color-primary, var(--color-primary)); +} + +.aksrt-cart__item-subtotal { + font-weight: 600; + color: var(--color-error, #EF4444); + min-width: 80px; + text-align: right; +} + +.aksrt-cart__remove-btn { + width: 32px; + height: 32px; + border: none; + background: none; + cursor: pointer; + color: var(--color-ink-4, #8A8F98); + display: flex; + align-items: center; + justify-content: center; + border-radius: var(--radius-sm, 6px); +} + +.aksrt-cart__remove-btn:hover { + background: var(--surface-2, #F4F5F7); + color: var(--color-error, #EF4444); +} + +.aksrt-cart__sidebar { + position: sticky; + top: 24px; +} + +.aksrt-cart__summary { + padding: var(--space-5); + background: var(--surface-1, #fff); + border: 1px solid var(--color-line); + border-radius: var(--radius-lg, 8px); +} + +.aksrt-cart__summary-title { + margin: 0 0 var(--space-4); + font-size: 16px; + font-weight: 600; + color: var(--color-ink); +} + +.aksrt-cart__summary-row { + display: flex; + justify-content: space-between; + margin-bottom: var(--space-3); + font-size: 14px; + color: var(--color-ink-2); +} + +.aksrt-cart__summary-total { + display: flex; + justify-content: space-between; + padding-top: var(--space-3); + border-top: 1px solid var(--color-line); + margin-bottom: var(--space-5); + font-weight: 600; +} + +.aksrt-cart__total-price { + font-size: 20px; + color: var(--color-error, #EF4444); +} + +.aksrt-cart__checkout-btn { + width: 100%; + padding: 12px; + border: none; + border-radius: var(--radius, 10px); + background: var(--color-primary, var(--color-primary)); + color: #fff; + font-size: 16px; + font-weight: 600; + cursor: pointer; + transition: opacity 0.15s; +} + +.aksrt-cart__checkout-btn:hover { + opacity: 0.85; +} + +.aksrt-cart__checkout-btn:disabled { + opacity: 0.5; + cursor: not-allowed; +} + +.aksrt-cart__empty { + text-align: center; + padding: var(--space-9) var(--space-5); + color: var(--color-ink-3); +} + +.aksrt-cart__empty i { + display: block; + margin-bottom: var(--space-4); +} + +.aksrt-cart__empty p { + margin: 0 0 var(--space-4); + font-size: 15px; +} + +/* 购物车响应式 */ +@media (max-width: 767px) { + .aksrt-cart__layout { + grid-template-columns: 1fr; + } + + .aksrt-cart__sidebar { + position: static; + } +} + +/* ================================================ + * 商品编辑页样式 + * ================================================ */ +.aksrt-product-edit { + padding-top: var(--space-6); + padding-bottom: var(--space-9); + max-width: 720px; + margin: 0 auto; +} + +.aksrt-product-edit__title { + margin: 0 0 var(--space-6); + font-size: 24px; + font-weight: 700; + color: var(--color-ink); +} + +.aksrt-product-edit__form { + padding: var(--space-6); + background: var(--surface-1, #fff); + border-radius: var(--radius-lg, 8px); + box-shadow: 0 1px 4px rgba(0, 0, 0, 0.06); +} + +.aksrt-product-edit__field { + margin-bottom: var(--space-5); +} + +.aksrt-product-edit__field label { + display: block; + font-size: 14px; + font-weight: 500; + color: var(--color-ink); + margin-bottom: var(--space-2); +} + +.aksrt-product-edit__field input, +.aksrt-product-edit__field textarea { + width: 100%; + padding: 10px 14px; + font-size: 14px; + color: var(--color-ink); + background: var(--surface-1, #fff); + border: 1px solid var(--color-line); + border-radius: var(--radius, 10px); + transition: border-color 0.15s; +} + +.aksrt-product-edit__field input:focus, +.aksrt-product-edit__field textarea:focus { + outline: none; + border-color: var(--color-primary, var(--color-primary)); +} + +.aksrt-product-edit__field textarea { + resize: vertical; + min-height: 100px; +} + +.aksrt-product-edit__actions { + display: flex; + gap: var(--space-3); + margin-top: var(--space-6); +} + +.aksrt-product-edit__actions .btn-primary { + padding: 10px 24px; + border: none; + border-radius: var(--radius, 10px); + background: var(--color-primary, var(--color-primary)); + color: #fff; + font-size: 15px; + font-weight: 500; + cursor: pointer; + transition: opacity 0.15s; +} + +.aksrt-product-edit__actions .btn-primary:hover { + opacity: 0.85; +} + +.aksrt-product-edit__actions .btn-ghost { + padding: 10px 24px; + border: 1px solid var(--color-line); + border-radius: var(--radius, 10px); + background: var(--surface-1, #fff); + color: var(--color-ink-2); + font-size: 15px; + text-decoration: none; + transition: border-color 0.15s; +} + +.aksrt-product-edit__actions .btn-ghost:hover { + border-color: var(--color-primary, var(--color-primary)); +} diff --git a/assets/css/frontend/resource-archive.css b/assets/css/frontend/resource-archive.css new file mode 100644 index 00000000..f14d1771 --- /dev/null +++ b/assets/css/frontend/resource-archive.css @@ -0,0 +1,598 @@ +/** + * Resource Archive · /resources + * + * 仅在 is_post_type_archive('aksrt_resource') 时加载。 + */ + +.content-shell--cms { + max-width: 100%; + padding: 0; +} + +/* ============ Header ============ */ +.resource-archive-header { + padding: clamp(40px, 6vw, 80px) 0 clamp(24px, 4vw, 48px); + background: linear-gradient(135deg, var(--color-primary-soft) 0%, var(--surface-2) 100%); +} + +.resource-archive-header__breadcrumbs { + font-size: 13px; + color: var(--color-ink-3); + margin-bottom: var(--space-3, 12px); +} + +.resource-archive-header__breadcrumbs a { + color: var(--color-ink-2); + text-decoration: none; +} + +.resource-archive-header__breadcrumbs a:hover { + color: var(--color-primary); +} + +.resource-archive-header__title { + font: 700 clamp(28px, 4vw, 44px)/1.15 var(--font-display); + margin: 0; + color: var(--color-ink); +} + +.resource-archive-header__sub { + margin: var(--space-2, 8px) 0 0; + color: var(--color-ink-3); + font-size: 14px; +} + +/* ============ Toolbar ============ */ +.resource-archive { + padding-top: var(--space-6, 24px); + padding-bottom: var(--space-9, 48px); +} + +.resource-archive__toolbar { + display: flex; + flex-wrap: wrap; + align-items: center; + gap: var(--space-4, 16px) var(--space-5, 20px); + margin-bottom: var(--space-5, 20px); + padding-bottom: var(--space-4, 16px); + border-bottom: 1px solid var(--color-line); +} + +.resource-archive__filter-group { + display: flex; + align-items: center; + gap: var(--space-2, 8px); +} + +.resource-archive__filter-label { + font: 500 12px/1 var(--font-ui); + color: var(--color-ink-3); + letter-spacing: .04em; + text-transform: uppercase; +} + +.resource-archive__sort { + list-style: none; + margin: 0; + padding: 0; + display: flex; + gap: var(--space-1, 4px); +} + +.resource-archive__sort-link { + display: inline-flex; + align-items: center; + height: 30px; + padding: 0 12px; + border-radius: var(--radius-pill); + font: 500 13px/1 var(--font-ui); + color: var(--color-ink-2); + text-decoration: none; + transition: background .18s ease, color .18s ease; +} + +.resource-archive__sort-link:hover { + background: var(--surface-2); + color: var(--color-ink); +} + +.resource-archive__sort-link.is-active { + background: var(--color-primary); + color: var(--color-on-primary); +} + +.resource-archive__price-range { + display: flex; + align-items: center; + gap: var(--space-2, 8px); + margin-left: auto; +} + +.resource-archive__price-input { + display: flex; + flex-direction: column; + gap: 2px; + font: 500 11px/1 var(--font-ui); + color: var(--color-ink-3); +} + +.resource-archive__price-input input { + width: 80px; + height: 30px; + padding: 0 10px; + border: 1px solid var(--color-line); + border-radius: var(--radius); + background: var(--surface-1); + font: 500 13px/1 var(--font-ui); + color: var(--color-ink); +} + +.resource-archive__price-input input:focus { + outline: 0; + border-color: var(--color-primary); + box-shadow: 0 0 0 3px rgba(240, 68, 148, 0.15); +} + +.resource-archive__price-sep { + color: var(--color-ink-3); + font-weight: 500; + margin-top: 12px; +} + +.resource-archive__price-range button { + margin-top: 12px; +} + +.resource-archive__reset { + display: inline-flex; + align-items: center; + gap: 6px; + font: 500 13px/1 var(--font-ui); + color: var(--color-ink-3); + text-decoration: none; +} + +.resource-archive__reset:hover { + color: #ef4444; +} + +@media (max-width: 767px) { + .resource-archive__price-range { + margin-left: 0; + flex-basis: 100%; + flex-wrap: wrap; + } +} + +/* ============================================================ + * Download Center Page + * ============================================================ */ + +/* Hero section */ +.aksrt-download-hero { + position: relative; + padding: clamp(40px, 6vw, 80px) 0 clamp(24px, 4vw, 48px); + background: linear-gradient(135deg, var(--color-primary-soft, #e6f4ff) 0%, var(--surface-2, #f5f7fa) 100%); + margin-bottom: 32px; +} + +.aksrt-download-hero__content { + max-width: var(--container, 1280px); + margin: 0 auto; + padding: 0 24px; +} + +.aksrt-download-hero__title { + font: 700 clamp(28px, 4vw, 44px)/1.15 var(--font-display, inherit); + margin: 0 0 8px; + color: var(--color-ink); +} + +.aksrt-download-hero__desc { + margin: 0 0 24px; + color: var(--color-ink-2, #666); + font-size: 16px; + line-height: 1.6; +} + +.aksrt-download-hero__stats { + display: flex; + gap: 32px; + margin-bottom: 24px; +} + +.aksrt-download-hero__stat-num { + display: block; + font-size: 28px; + font-weight: 700; + color: var(--color-primary); +} + +.aksrt-download-hero__stat-label { + font-size: 13px; + color: var(--color-ink-3, #999); +} + +.aksrt-download-hero__filters { + display: flex; + flex-wrap: wrap; + gap: 8px; +} + +.aksrt-download-hero__filter { + display: inline-flex; + align-items: center; + gap: 6px; + padding: 6px 14px; + border-radius: 20px; + background: var(--surface-1, #fff); + color: var(--color-ink-2, #666); + text-decoration: none; + font-size: 13px; + transition: all 0.2s; + border: 1px solid var(--color-line, #e8e8e8); +} + +.aksrt-download-hero__filter:hover { + color: var(--color-primary); + border-color: var(--color-primary); +} + +.aksrt-download-hero__filter--active { + background: var(--color-primary); + color: #fff; + border-color: var(--color-primary); +} + +.aksrt-download-hero__filter-count { + font-size: 11px; + opacity: 0.7; +} + +/* Download center layout */ +.aksrt-download-center__layout { + display: grid; + grid-template-columns: 1fr 311px; + gap: 24px; +} + +@media (max-width: 991px) { + .aksrt-download-center__layout { + grid-template-columns: 1fr; + } +} + +.aksrt-download-center__grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); + gap: 16px; + margin-bottom: 24px; +} + +.aksrt-download-card { + background: var(--surface-1, #fff); + border: 1px solid var(--color-line, #e8e8e8); + border-radius: 8px; + overflow: hidden; + transition: box-shadow 0.2s; +} + +.aksrt-download-card:hover { + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08); +} + +.aksrt-download-card__thumb { + aspect-ratio: 16/9; + overflow: hidden; +} + +.aksrt-download-card__thumb img { + width: 100%; + height: 100%; + object-fit: cover; +} + +.aksrt-download-card__body { + padding: 12px; +} + +.aksrt-download-card__title { + margin: 0 0 6px; + font-size: 14px; + font-weight: 600; +} + +.aksrt-download-card__title a { + color: var(--color-ink); + text-decoration: none; +} + +.aksrt-download-card__title a:hover { + color: var(--color-primary); +} + +.aksrt-download-card__excerpt { + margin: 0 0 8px; + font-size: 12px; + color: var(--color-ink-3, #999); + line-height: 1.5; +} + +.aksrt-download-card__meta { + display: flex; + gap: 12px; + font-size: 11px; + color: var(--color-ink-3, #999); +} + +.aksrt-download-card__meta i { + margin-right: 3px; +} + +/* Download sidebar */ +.aksrt-download-center__sidebar { + display: flex; + flex-direction: column; + gap: 16px; +} + +.aksrt-dl-sidebar-card { + background: var(--surface-1, #fff); + border: 1px solid var(--color-line, #e8e8e8); + border-radius: 8px; + padding: 16px; +} + +.aksrt-dl-sidebar-card__title { + margin: 0 0 12px; + font-size: 14px; + font-weight: 600; + color: var(--color-ink); + display: flex; + align-items: center; + gap: 8px; +} + +.aksrt-dl-sidebar-card__title i { + color: var(--color-primary); +} + +.aksrt-dl-sidebar-card__list { + list-style: none; + margin: 0; + padding: 0; +} + +.aksrt-dl-sidebar-card__list li { + border-bottom: 1px solid var(--color-line, #f0f0f0); +} + +.aksrt-dl-sidebar-card__list li:last-child { + border-bottom: none; +} + +.aksrt-dl-sidebar-card__list a { + display: flex; + justify-content: space-between; + align-items: center; + padding: 8px 4px; + color: var(--color-ink-2, #666); + text-decoration: none; + font-size: 13px; + transition: color 0.2s; +} + +.aksrt-dl-sidebar-card__list a:hover, +.aksrt-dl-sidebar-card__list li.is-active a { + color: var(--color-primary); +} + +.aksrt-dl-sidebar-card__list .count { + font-size: 11px; + color: var(--color-ink-3, #999); +} + +/* Permission card */ +.aksrt-dl-perm-card { + background: var(--surface-1, #fff); + border: 1px solid var(--color-line, #e8e8e8); + border-radius: 8px; + padding: 16px; +} + +.aksrt-dl-perm-card__status { + display: flex; + align-items: center; + gap: 8px; + margin-bottom: 12px; + font-size: 14px; + font-weight: 600; +} + +.aksrt-dl-perm-card__icon--success { color: #52c41a; } +.aksrt-dl-perm-card__icon--warning { color: #faad14; } + +.aksrt-dl-perm-card__cost { + display: flex; + align-items: center; + gap: 6px; + margin-bottom: 12px; + font-size: 13px; + color: var(--color-ink-2, #666); +} + +.aksrt-dl-perm-card__balance { + color: var(--color-ink-3, #999); + font-size: 12px; +} + +.aksrt-dl-perm-card__actions { + display: flex; + gap: 8px; +} + +.aksrt-dl-perm-card__btn { + display: inline-flex; + align-items: center; + gap: 6px; + padding: 8px 16px; + border-radius: 6px; + font-size: 13px; + font-weight: 500; + text-decoration: none; + transition: all 0.2s; +} + +.aksrt-dl-perm-card__btn--primary { + background: var(--color-primary); + color: #fff; +} + +.aksrt-dl-perm-card__btn--primary:hover { + background: var(--color-primary-hover, #40a9ff); +} + +.aksrt-dl-perm-card__btn--outline { + background: transparent; + color: var(--color-primary); + border: 1px solid var(--color-primary); +} + +.aksrt-dl-perm-card__btn--outline:hover { + background: var(--color-primary-soft, #e6f4ff); +} + +/* Empty state */ +.aksrt-download-center__empty { + text-align: center; + padding: 48px 24px; + color: var(--color-ink-3, #999); +} + +.aksrt-download-center__empty i { + font-size: 48px; + margin-bottom: 16px; + opacity: 0.3; +} + +/* ============================================================ + * Download Status Bar + * ============================================================ */ +.aksrt-dl-status-bar { + display: flex; + align-items: center; + flex-wrap: wrap; + gap: 16px; + padding: 14px 20px; + margin-bottom: 24px; + background: var(--surface-1, #fff); + border: 1px solid var(--color-line, #e8e8e8); + border-radius: 8px; + font-size: 13px; +} + +.aksrt-dl-status-bar__item { + display: inline-flex; + align-items: center; + gap: 6px; + color: var(--color-ink-2, #666); +} + +.aksrt-dl-status-bar__item i { + color: var(--color-primary); + font-size: 14px; +} + +.aksrt-dl-status-bar__label { + color: var(--color-ink-3, #999); + font-size: 12px; +} + +.aksrt-dl-status-bar__value { + font-weight: 700; + color: var(--color-ink); + font-size: 15px; +} + +.aksrt-dl-status-bar__item--hint { + flex: 1; +} + +.aksrt-dl-status-bar__item--hint i { + color: var(--color-ink-3, #999); +} + +.aksrt-dl-status-bar__actions { + display: flex; + gap: 8px; + margin-left: auto; +} + +/* Download card footer with price */ +.aksrt-download-card__footer { + display: flex; + align-items: center; + justify-content: space-between; + padding-top: 8px; + border-top: 1px solid var(--color-line, #f0f0f0); + margin-top: 8px; +} + +.aksrt-download-card__price { + font-size: 12px; + font-weight: 600; + padding: 2px 8px; + border-radius: 4px; +} + +.aksrt-download-card__price.is-free { + background: #f6ffed; + color: #52c41a; +} + +.aksrt-download-card__price.is-paid { + background: #fff7e6; + color: #fa8c16; +} + +.aksrt-download-card__action { + display: inline-flex; + align-items: center; + gap: 4px; + font-size: 12px; + color: var(--color-primary); + text-decoration: none; + font-weight: 500; + transition: gap 0.2s; +} + +.aksrt-download-card__action:hover { + gap: 6px; +} + +/* Download sidebar tips */ +.aksrt-dl-sidebar-card__tips p { + display: flex; + align-items: center; + gap: 8px; + font-size: 12px; + color: var(--color-ink-2, #666); + margin: 0 0 8px; + line-height: 1.5; +} + +.aksrt-dl-sidebar-card__tips p:last-child { + margin-bottom: 0; +} + +.aksrt-dl-sidebar-card__tips i { + color: var(--color-primary); + font-size: 11px; + flex-shrink: 0; +} + +/* Permission card disabled state */ +.aksrt-dl-perm-card__btn--disabled { + opacity: 0.6; + cursor: not-allowed; +} diff --git a/assets/css/frontend/resource-meta.css b/assets/css/frontend/resource-meta.css new file mode 100644 index 00000000..3cf61c98 --- /dev/null +++ b/assets/css/frontend/resource-meta.css @@ -0,0 +1,5 @@ +@import url("resource-meta/part-1.css"); +@import url("resource-meta/part-2.css"); +@import url("resource-meta/part-3.css"); +@import url("resource-meta/part-4.css"); +@import url("resource-meta/part-5.css"); diff --git a/assets/css/frontend/resource-meta/part-1.css b/assets/css/frontend/resource-meta/part-1.css new file mode 100644 index 00000000..0a110a0f --- /dev/null +++ b/assets/css/frontend/resource-meta/part-1.css @@ -0,0 +1,300 @@ +/* ============================================================ + * 桌面端 .resource-download-box 基础样式 + * ============================================================ */ + +.resource-download-box { + padding: 20px; + background: var(--surface-page, #fff); + border: 1px solid var(--color-line, rgba(0,0,0,0.08)); + border-radius: var(--radius-lg, 10px); + box-shadow: 0 2px 12px rgba(0,0,0,0.06), 0 1px 4px rgba(0,0,0,0.04); +} + +/* ============================================================ + * v2 双栏布局 — 模仿 zibll pay-box + * ============================================================ */ +.resource-download-box--v2 { + position: relative; + overflow: visible; +} + +.resource-download-box--v2::before { + content: ''; + position: absolute; + top: 0; + left: 0; + right: 0; + height: 3px; + background: linear-gradient(90deg, var(--color-primary), var(--color-accent)); + border-radius: var(--radius-lg) var(--radius-lg) 0 0; +} + +.resource-download-box__body { + display: grid; + grid-template-columns: 200px 1fr; + gap: 20px; + align-items: start; +} + +/* 缩略图列 */ +.resource-download-box__thumb-col { + position: relative; +} + +.resource-download-box__thumb { + width: 100%; + aspect-ratio: 4 / 3; + object-fit: cover; + border-radius: var(--radius); + background: var(--surface-2); +} + +.resource-download-box__pay-tag { + position: absolute; + top: 8px; + left: 8px; +} + +/* 内容列 */ +.resource-download-box__content-col { + min-width: 0; +} + +/* 价格区 */ +.resource-download-box__pricing { + display: flex; + align-items: center; + gap: 8px; + flex-wrap: wrap; + margin: 12px 0; +} + +.resource-download-box__original-price { + font-size: 13px; + color: var(--color-ink-4); + text-decoration: line-through; +} + +/* VIP 价格区 */ +.resource-download-box__vip-pricing { + display: flex; + gap: 8px; + flex-wrap: wrap; + margin-bottom: 12px; +} + +.resource-download-box__vip-badge { + display: inline-flex; + align-items: center; + gap: 4px; + font-size: 12px; + font-weight: 600; + padding: 4px 10px; + border-radius: 6px; + cursor: default; +} + +.resource-download-box__vip-badge--1 { + background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%); + color: #fff; +} + +.resource-download-box__vip-badge--2 { + background: linear-gradient(135deg, #8b5cf6 0%, #7c3aed 100%); + color: #fff; +} + +.resource-download-box__vip-badge i { + font-size: 11px; +} + +/* 服务保障 */ +.resource-download-box__guarantees { + display: flex; + gap: 16px; + flex-wrap: wrap; + margin-top: 12px; + padding-top: 12px; + border-top: 1px solid var(--color-line-soft); +} + +.resource-download-box__guarantee { + display: inline-flex; + align-items: center; + gap: 4px; + font-size: 12px; + color: var(--color-success, #10B981); +} + +.resource-download-box__guarantee i { + font-size: 12px; +} + +/* 响应式 */ +@media (max-width: 640px) { + .resource-download-box__body { + grid-template-columns: 1fr; + } + + .resource-download-box__thumb-col { + display: none; + } + + .resource-download-box__guarantees { + gap: 12px; + } +} + +/* 头部:标题 + 价格 */ +.resource-download-box__header { + display: flex; + align-items: center; + justify-content: space-between; + gap: 12px; + margin-bottom: 14px; + padding-bottom: 12px; + border-bottom: 1px solid var(--color-line, rgba(0,0,0,0.06)); +} + +.resource-download-box__title-wrap { + display: flex; + align-items: center; + gap: 8px; + min-width: 0; + flex: 1; +} + +.resource-download-box__title { + font-size: 15px; + font-weight: 700; + margin: 0; + color: var(--color-ink); + display: flex; + align-items: center; + gap: 6px; + line-height: 1.3; +} + +.resource-download-box__title i { + color: var(--color-primary, #3B82F6); + font-size: 15px; +} + +.resource-download-box__count { + font-size: 11px; + color: var(--color-ink-4, #8A8F98); + white-space: nowrap; + flex-shrink: 0; +} + +/* 价格标签 */ +.resource-download-box__price { + display: inline-flex; + align-items: center; + gap: 4px; + font-size: 13px; + font-weight: 700; + padding: 4px 10px; + border-radius: 20px; + white-space: nowrap; + flex-shrink: 0; +} + +.resource-download-box__price:not(.is-free) { + color: var(--color-error, #EF4444); + background: #FEF2F2; +} + +.resource-download-box__price.is-free { + color: var(--color-success, #10B981); + background: #F0FDF4; +} + +/* 空状态 */ +.resource-download-box__notice--empty { + padding: 14px 16px; + background: var(--surface-2, #F4F5F7); + border-radius: 8px; + text-align: center; +} + +.resource-download-box__notice--empty p { + margin: 0; + font-size: 13px; + color: var(--color-ink-3); + display: flex; + align-items: center; + justify-content: center; + gap: 6px; +} + +/* 下载源列表 */ +.resource-download-box__list { + list-style: none; + margin: 0 0 14px; + padding: 0; + display: flex; + flex-direction: column; + gap: 10px; +} + +.resource-download-box__item { + margin: 0; +} + +/* 下载按钮 */ +.resource-download-box__btn { + display: flex; + align-items: center; + justify-content: center; + gap: 8px; + width: 100%; + min-height: 44px; + padding: 10px 18px; + border: none; + border-radius: 10px; + background: var(--color-primary, #3B82F6); + color: #fff; + font-size: 14px; + font-weight: 600; + cursor: pointer; + text-decoration: none; + transition: background 0.2s ease, transform 0.15s ease, box-shadow 0.2s ease, opacity 0.2s ease; + box-shadow: 0 2px 8px rgba(59,130,246,0.25); +} + +.resource-download-box__btn:hover { + background: var(--color-primary-active, #2563EB); + box-shadow: 0 4px 14px rgba(59,130,246,0.35); + transform: translateY(-1px); +} + +.resource-download-box__btn:active { + transform: scale(0.97); + transition-duration: 0.1s; +} + +.resource-download-box__btn i { + font-size: 15px; + flex-shrink: 0; +} + +.resource-download-box__btn span { + flex-shrink: 0; +} + +/* 按钮副文案 */ +.resource-download-box__btn-sub { + display: block; + font-size: 11px; + font-weight: 400; + opacity: 0.85; + margin-top: 2px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +/* 类型标签 */ +.resource-download-box__type-tag { + display: inline-flex; diff --git a/assets/css/frontend/resource-meta/part-2.css b/assets/css/frontend/resource-meta/part-2.css new file mode 100644 index 00000000..f42eee80 --- /dev/null +++ b/assets/css/frontend/resource-meta/part-2.css @@ -0,0 +1,300 @@ + align-items: center; + padding: 2px 8px; + margin-left: auto; + border-radius: 10px; + font-size: 11px; + font-weight: 500; + background: rgba(255,255,255,0.2); + flex-shrink: 0; +} + +/* -- 按钮状态变体 -- */ +.resource-download-box__btn--login { + background: var(--color-primary, #3B82F6); +} + +.resource-download-box__btn--credit-low { + background: var(--color-ink-4, #8A8F98) !important; + box-shadow: none !important; + cursor: not-allowed; + opacity: 0.7; +} + +.resource-download-box__btn--credit-low:hover { + transform: none !important; +} + +.resource-download-box__btn--paid { + background: linear-gradient(135deg, #3B82F6 0%, #2563EB 100%); +} + +/* 提示文字区 */ +.resource-download-box__hint { + margin: 0 0 14px; + padding: 10px 14px; + border-radius: 8px; + font-size: 12px; + line-height: 1.5; + display: flex; + align-items: flex-start; + gap: 8px; +} + +.resource-download-box__hint i { + font-size: 13px; + flex-shrink: 0; + margin-top: 1px; +} + +.resource-download-box__hint--login { + color: var(--color-primary, #3B82F6); + background: rgba(59,130,246,0.06); +} + +.resource-download-box__hint--login i { + color: var(--color-primary, #3B82F6); +} + +.resource-download-box__hint--credit { + color: #D97706; + background: #FFFBEB; +} + +.resource-download-box__hint--credit i { + color: #F59E0B; +} + +/* 验证码表单区 - bind模式隐藏 */ +.resource-download-box__captcha { + margin: 0 0 14px; + padding: 14px; + border: 1px dashed var(--color-line, rgba(0,0,0,0.12)); + border-radius: 8px; + background: var(--surface-2, #FAFAFB); +} + +/* bind 模式:容器保留但视觉隐藏(仍作为挂载点) */ +.resource-download-box__captcha--hidden { + padding: 0 !important; + border: none !important; + background: transparent !important; + margin: 0 !important; + min-height: 0; + overflow: hidden; + /* 极验bind按钮也隐藏,通过JS触发 */ +} +.resource-download-box__captcha--hidden > * { + visibility: hidden; + height: 0; + overflow: hidden; + pointer-events: none; +} + +/* 底部免责 */ +.resource-download-box__footer { + margin: 0; + padding-top: 12px; + border-top: 1px solid var(--color-line, rgba(0,0,0,0.06)); +} + +.resource-download-box__notice-text { + margin: 0; + font-size: 11px; + line-height: 1.6; + color: var(--color-ink-4, #8A8F98); + display: flex; + align-items: flex-start; + gap: 6px; +} + +.resource-download-box__notice-text i { + font-size: 12px; + flex-shrink: 0; + margin-top: 2px; + color: var(--color-ink-4, #8A8F98); +} + +/* 被拦截态(登录/积分不足)不透明 */ +.resource-download-box.is-blocked { + opacity: 1; +} + + +/* ============================================================ + * v4.3 资源侧栏下载卡片(垂直布局,适合 300px 侧栏宽度) + * ============================================================ */ + +.resource-sidebar-sticky { + display: flex; + flex-direction: column; + gap: 16px; +} + +/* 下载卡片 */ +.resource-download-card { + overflow: hidden; +} + +.resource-download-card__thumb { + width: 100%; + aspect-ratio: 16 / 10; + overflow: hidden; + border-radius: 8px 8px 0 0; +} + +.resource-download-card__thumb img { + width: 100%; + height: 100%; + object-fit: cover; +} + +.resource-download-card__body { + padding: 16px; + display: flex; + flex-direction: column; + gap: 10px; +} + +.resource-download-card__title { + font-size: 15px; + font-weight: 700; + margin: 0; + line-height: 1.35; + color: var(--color-ink); + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + overflow: hidden; +} + +.resource-download-card__desc { + font-size: 13px; + color: var(--color-ink-4); + line-height: 1.5; + margin: 0; +} + +/* 价格 */ +.resource-download-card__price { + padding: 6px 0; +} + +.resource-price { + display: inline-flex; + align-items: center; + gap: 4px; + font-size: 14px; + font-weight: 700; +} + +.resource-price--paid { + color: var(--color-error, #ef4444); +} + +.resource-price--paid i { + color: #f59e0b; +} + +.resource-price--paid strong { + font-size: 1.25rem; +} + +.resource-price--paid small { + font-size: 12px; + font-weight: 400; + color: var(--color-ink-4); +} + +.resource-price--free { + color: var(--color-success, #34a853); +} + +/* 下载按钮区 */ +.resource-download-card__actions { + padding: 4px 0; +} + +/* 已下载数 */ +.resource-download-card__sales { + font-size: 12px; + color: var(--color-ink-4); + display: flex; + align-items: center; + gap: 4px; +} + +/* 演示链接 */ +.resource-download-card__demo { + display: flex; + align-items: center; + justify-content: center; + gap: 6px; + padding: 8px; + border-radius: 6px; + background: var(--surface-3); + color: var(--color-ink-3); + font-size: 13px; + text-decoration: none; + transition: background 0.2s, color 0.2s; +} + +.resource-download-card__demo:hover { + background: var(--color-primary-soft, rgba(240, 68, 148, 0.12)); + color: var(--color-primary); + text-decoration: none; +} + +/* 资源属性卡片 */ +.resource-meta-card__title { + font-size: 13px; + font-weight: 700; + margin: 0 0 10px; + color: var(--color-ink); +} + +.resource-meta-card__list { + margin: 0; + display: flex; + flex-direction: column; + gap: 8px; +} + +.resource-meta-card__row { + display: flex; + justify-content: space-between; + align-items: center; + font-size: 13px; +} + +.resource-meta-card__row dt { + color: var(--color-ink-4); + margin: 0; +} + +.resource-meta-card__row dd { + color: var(--color-ink); + font-weight: 500; + margin: 0; + text-align: right; +} + +/* 服务保障卡片 */ +.resource-guarantee-card__list { + display: flex; + flex-wrap: wrap; + gap: 12px; + font-size: 12px; + color: var(--color-ink-4); +} + +.resource-guarantee-card__list span { + display: inline-flex; + align-items: center; + gap: 4px; +} + +.resource-guarantee-card__list i { + color: var(--color-success, #34a853); + font-size: 13px; +} + diff --git a/assets/css/frontend/resource-meta/part-3.css b/assets/css/frontend/resource-meta/part-3.css new file mode 100644 index 00000000..b14b11ea --- /dev/null +++ b/assets/css/frontend/resource-meta/part-3.css @@ -0,0 +1,300 @@ +/* 移动端:侧栏变为正文下方(由 layout.css 统一处理隐藏) */ + +/* ============================================================ + * v5.0 移动端下载区域重构(992px 以下生效) + * + * 设计原则: + * - 块级卡片容器,匹配 .theme-box.box-body.radius8 风格 + * - 下载项纵向堆叠,每项独立卡片,触摸友好(min-height:48px) + * - 纯色配色,禁止渐变/紫色,使用 Font Awesome 图标包 + * ============================================================ */ + +/* ----- 移动端下载区域容器(块级卡片) ----- */ +.resource-mobile-download-bar { + display: none; /* 默认隐藏,媒体查询中启用 */ + margin: 16px 0; + background: var(--surface-page, #fff); + border: 1px solid var(--color-line, rgba(0,0,0,0.08)); + border-radius: var(--radius-lg, 10px); + box-shadow: 0 2px 12px rgba(0,0,0,0.06), 0 1px 4px rgba(0,0,0,0.04); + overflow: hidden; +} + +/* ===== resource-download-box 组件移动端样式 ===== */ + +/* 组件根 */ +.resource-mobile-download-bar .resource-download-box { + padding: 0; + margin: 0; +} + +.resource-mobile-download-bar .resource-download-box.is-blocked { + opacity: 1; +} + +/* ---- 头部区:标题 + 价格 + 源数量 ---- */ +.resource-mobile-download-bar .resource-download-box__header { + display: flex; + align-items: center; + justify-content: space-between; + gap: 12px; + padding: 16px 16px 12px; + border-bottom: 1px solid var(--color-line, rgba(0,0,0,0.06)); +} + +.resource-mobile-download-bar .resource-download-box__title-wrap { + display: flex; + align-items: center; + gap: 8px; + min-width: 0; + flex: 1; +} + +.resource-mobile-download-bar .resource-download-box__title { + font-size: 15px; + font-weight: 700; + margin: 0; + color: var(--color-ink); + display: flex; + align-items: center; + gap: 6px; + line-height: 1.3; +} + +.resource-mobile-download-bar .resource-download-box__title i { + color: var(--color-primary, #3B82F6); + font-size: 15px; +} + +.resource-mobile-download-bar .resource-download-box__count { + font-size: 11px; + color: var(--color-ink-4, #8A8F98); + white-space: nowrap; + flex-shrink: 0; +} + +/* 头部价格标签 */ +.resource-mobile-download-bar .resource-download-box__price { + display: inline-flex; + align-items: center; + gap: 4px; + font-size: 13px; + font-weight: 700; + padding: 4px 10px; + border-radius: 20px; + white-space: nowrap; + flex-shrink: 0; +} + +.resource-mobile-download-bar .resource-download-box__price:not(.is-free) { + color: var(--color-error, #EF4444); + background: #FEF2F2; +} + +.resource-mobile-download-bar .resource-download-box__price.is-free { + color: var(--color-success, #10B981); + background: #F0FDF4; +} + +/* ---- 空状态提示 ---- */ +.resource-mobile-download-bar .resource-download-box__notice--empty { + margin: 16px; + padding: 14px 16px; + background: var(--surface-2, #F4F5F7); + border-radius: 8px; + text-align: center; +} + +.resource-mobile-download-bar .resource-download-box__notice--empty p { + margin: 0; + font-size: 13px; + color: var(--color-ink-3); + display: flex; + align-items: center; + justify-content: center; + gap: 6px; +} + +.resource-mobile-download-bar .resource-download-box__notice--empty i { + color: var(--color-primary, #3B82F6); +} + +/* ---- 下载源列表 ---- */ +.resource-mobile-download-bar .resource-download-box__list { + list-style: none; + margin: 0; + padding: 12px 16px 16px; + display: flex; + flex-direction: column; + gap: 10px; +} + +/* ---- 下载项(每个一行) ---- */ +.resource-mobile-download-bar .resource-download-box__item { + margin: 0; +} + +/* ---- 下载按钮(核心交互元素)---- */ +.resource-mobile-download-bar .resource-download-box__btn { + display: flex; + align-items: center; + justify-content: center; + gap: 8px; + width: 100%; + min-height: 50px; /* 触摸友好 */ + padding: 12px 20px; + border: none; + border-radius: 10px; + background: var(--color-primary, #3B82F6); + color: #fff; + font-size: 14px; + font-weight: 600; + cursor: pointer; + text-decoration: none; + position: relative; + overflow: hidden; + transition: background 0.2s ease, transform 0.15s ease, box-shadow 0.2s ease, opacity 0.2s ease; + box-shadow: 0 2px 8px rgba(59,130,246,0.3); + -webkit-tap-highlight-color: transparent; +} + +.resource-mobile-download-bar .resource-download-box__btn i { + font-size: 16px; + flex-shrink: 0; +} + +.resource-mobile-download-bar .resource-download-box__btn span { + flex-shrink: 0; +} + +/* 按钮副文案(来源名称 / 余额信息)*/ +.resource-mobile-download-bar .resource-download-box__btn-sub { + display: block; + font-size: 11px; + font-weight: 400; + opacity: 0.85; + margin-top: 2px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + max-width: 100%; +} + +/* 类型标签(网盘/外链)*/ +.resource-mobile-download-bar .resource-download-box__type-tag { + display: inline-flex; + align-items: center; + padding: 2px 8px; + margin-left: auto; + border-radius: 10px; + font-size: 11px; + font-weight: 500; + background: rgba(255,255,255,0.2); + flex-shrink: 0; +} + +/* -- 按钮状态变体 -- */ + +/* 正常态 hover */ +.resource-mobile-download-bar .resource-download-box__btn:hover { + background: var(--color-primary-active, #2563EB); + box-shadow: 0 4px 14px rgba(59,130,246,0.4); + transform: translateY(-1px); +} + +/* active 按压反馈 */ +.resource-mobile-download-bar .resource-download-box__btn:active { + transform: scale(0.97); + transition-duration: 0.1s; +} + +/* 登录拦截态 */ +.resource-mobile-download-bar .resource-download-box__btn--login { + background: var(--color-primary, #3B82F6); +} + +/* 余额不足态(禁用外观)*/ +.resource-mobile-download-bar .resource-download-box__btn--credit-low { + background: var(--color-ink-4, #8A8F98); + box-shadow: none; + cursor: not-allowed; + opacity: 0.7; +} + +.resource-mobile-download-bar .resource-download-box__btn--credit-low:hover { + transform: none; + box-shadow: none; + background: var(--color-ink-4, #8A8F98); +} + +/* 付费下载态 */ +.resource-mobile-download-bar .resource-download-box__btn--paid { + background: linear-gradient(135deg, #3B82F6 0%, #2563EB 100%); +} + +/* ---- 提示文字区 ---- */ +.resource-mobile-download-bar .resource-download-box__hint { + margin: 0 16px 12px; + padding: 10px 14px; + border-radius: 8px; + font-size: 12px; + line-height: 1.5; + display: flex; + align-items: flex-start; + gap: 8px; +} + +.resource-mobile-download-bar .resource-download-box__hint i { + font-size: 14px; + flex-shrink: 0; + margin-top: 1px; +} + +.resource-mobile-download-bar .resource-download-box__hint--login { + color: var(--color-primary, #3B82F6); + background: rgba(59,130,246,0.06); +} + +.resource-mobile-download-bar .resource-download-box__hint--login i { + color: var(--color-primary, #3B82F6); +} + +.resource-mobile-download-bar .resource-download-box__hint--credit { + color: #D97706; + background: #FFFBEB; +} + +.resource-mobile-download-bar .resource-download-box__hint--credit i { + color: #F59E0B; +} + +/* ---- 验证码表单区 ---- */ +.resource-mobile-download-bar .resource-download-box__captcha { + margin: 0 16px 16px; + padding: 14px; + border: 1px dashed var(--color-line, rgba(0,0,0,0.12)); + border-radius: 8px; + background: var(--surface-2, #FAFAFB); +} + +/* ---- 底部免责声明 ---- */ +.resource-mobile-download-bar .resource-download-box__footer { + margin: 0; + padding: 12px 16px; + border-top: 1px solid var(--color-line, rgba(0,0,0,0.06)); +} + +.resource-mobile-download-bar .resource-download-box__notice-text { + margin: 0; + font-size: 11px; + line-height: 1.6; + color: var(--color-ink-4, #8A8F98); + display: flex; + align-items: flex-start; + gap: 6px; +} + +.resource-mobile-download-bar .resource-download-box__notice-text i { + font-size: 12px; + flex-shrink: 0; + margin-top: 2px; diff --git a/assets/css/frontend/resource-meta/part-4.css b/assets/css/frontend/resource-meta/part-4.css new file mode 100644 index 00000000..8aa36b91 --- /dev/null +++ b/assets/css/frontend/resource-meta/part-4.css @@ -0,0 +1,300 @@ + color: var(--color-ink-4, #8A8F98); +} + + +/* ----- 移动端悬浮下载按钮(FAB) ----- */ +.resource-mobile-fab { + display: none; /* 默认隐藏,移动端媒体查询中启用 */ + position: fixed; + bottom: 72px; + right: 20px; + z-index: 950; + width: 56px; + height: 56px; + border-radius: 50%; + background: var(--color-primary, #3B82F6); + color: #fff; + text-decoration: none; + display: flex; /* 覆盖上面的 display:none */ + align-items: center; + justify-content: center; + font-size: 22px; + box-shadow: 0 4px 16px rgba(59,130,246,0.35), 0 2px 6px rgba(0,0,0,0.1); + opacity: 0; + transform: scale(0.8) translateY(10px); + transition: opacity 0.35s cubic-bezier(0.4, 0, 0.2, 1), transform 0.35s cubic-bezier(0.4, 0, 0.2, 1), box-shadow 0.3s ease; + pointer-events: none; + -webkit-tap-highlight-color: transparent; + animation: fabFadeIn 0.5s 1.5s forwards; +} + +@keyframes fabFadeIn { + to { + opacity: 1; + transform: scale(1) translateY(0); + pointer-events: auto; + } +} + +.resource-mobile-fab:hover { + transform: scale(1.08) translateY(-2px); + box-shadow: 0 6px 24px rgba(59,130,246,0.45), 0 4px 10px rgba(0,0,0,0.15); + color: #fff; +} + +.resource-mobile-fab:active { + transform: scale(0.95); + transition-duration: 0.1s; +} + +/* FAB脉冲效果(吸引注意) */ +.resource-mobile-fab::after { + content: ''; + position: absolute; + inset: -4px; + border-radius: 50%; + background: transparent; + border: 2px solid var(--color-primary, #3B82F6); + opacity: 0; + animation: fabPulse 2s 2.5s infinite; +} + +@keyframes fabPulse { + 0% { transform: scale(1); opacity: 0.6; } + 100% { transform: scale(1.4); opacity: 0; } +} + + +/* ============================================================ + * 响应式媒体查询 + * ============================================================ */ + +/* 移动端/平板(< 992px):显示移动端下载栏和FAB */ +@media (max-width: 991px) { + .resource-mobile-download-bar { + display: block; + } + + .resource-mobile-fab { + display: flex; + bottom: calc(72px + env(safe-area-inset-bottom, 0px)); + right: calc(20px + env(safe-area-inset-right, 0px)); + } + + /* 超小屏适配(<= 380px) */ + @media (max-width: 380px) { + .resource-mobile-download-bar .resource-download-box__header { + flex-wrap: wrap; + gap: 8px; + padding: 14px 12px 10px; + } + + .resource-mobile-download-bar .resource-download-box__list { + padding: 10px 12px 14px; + gap: 8px; + } + + .resource-mobile-download-bar .resource-download-box__btn { + min-height: 46px; + padding: 10px 14px; + font-size: 13px; + } + + .resource-mobile-download-bar .resource-download-box__title { + font-size: 14px; + } + + .resource-mobile-download-bar .resource-download-box__hint, + .resource-mobile-download-bar .resource-download-box__footer, + .resource-mobile-download-bar .resource-download-box__captcha { + margin-left: 12px; + margin-right: 12px; + } + } +} + +/* 桌面端(>= 992px):隐藏移动端元素,保持原侧栏布局 */ +@media (min-width: 992px) { + .resource-mobile-download-bar { + display: none !important; + } + + .resource-mobile-fab { + display: none !important; + } +} + +/* ============================================================ + * 云服务品牌按钮样式 + * ============================================================ */ +.resource-download-box__btn--service-baidu { + background: linear-gradient(135deg, #1578f8 0%, #0d65d9 100%); +} + +.resource-download-box__btn--service-lanzou { + background: linear-gradient(135deg, #f37526 0%, #e06318 100%); +} + +.resource-download-box__btn--service-aliyun { + background: linear-gradient(135deg, #6666ff 0%, #5050e0 100%); +} + +.resource-download-box__btn--service-weiyun { + background: linear-gradient(135deg, #4facfe 0%, #3a8fd4 100%); +} + +.resource-download-box__btn--service-onedrive { + background: linear-gradient(135deg, #0078d4 0%, #006abc 100%); +} + +.resource-download-box__btn--service-tianyi { + background: linear-gradient(135deg, #0099ff 0%, #0080e0 100%); +} + +.resource-download-box__btn--service-123pan { + background: linear-gradient(135deg, #2b7bff 0%, #1a65e0 100%); +} + +.resource-download-box__btn--service-quark { + background: linear-gradient(135deg, #6a5acd 0%, #5a4ab5 100%); +} + +.resource-download-box__btn--service-xunlei { + background: linear-gradient(135deg, #00a4ff 0%, #0090e0 100%); +} + +.resource-download-box__btn--service-mega { + background: linear-gradient(135deg, #d92323 0%, #c01a1a 100%); +} + +.resource-download-box__btn--service-github { + background: linear-gradient(135deg, #333333 0%, #1a1a1a 100%); +} + +/* 云服务徽章 */ +.resource-download-box__service-badge { + display: inline-block; + font-size: 10px; + font-weight: 600; + padding: 2px 6px; + border-radius: 4px; + color: #fff; + margin-left: 6px; + letter-spacing: 0.02em; + line-height: 1.3; +} + +/* ============================================================ + * 元信息卡片图标增强 + * ============================================================ */ +.resource-meta-box__key { + display: flex; + align-items: center; + gap: 8px; +} + +.resource-meta-box__key i { + width: 16px; + text-align: center; + color: var(--color-ink-4, #8A8F98); + font-size: 13px; + flex-shrink: 0; +} + +/* ============================================================ + * 渐变价格标签(模仿 zibll 渐变 pay-tag) + * ============================================================ */ +.resource-download-box__price--gradient { + background: linear-gradient(135deg, #EF4444 0%, #F97316 100%); + color: #fff; + font-weight: 700; + padding: 5px 12px; + border-radius: 20px; + font-size: 13px; +} + +.resource-download-box__price--gradient.is-free { + background: linear-gradient(135deg, #10B981 0%, #059669 100%); +} + +/* ============================================================ + * 销量/下载量徽章 + * ============================================================ */ +.resource-download-box__sales-badge { + position: absolute; + top: -8px; + right: -8px; + background: linear-gradient(135deg, #3B82F6 0%, #2563EB 100%); + color: #fff; + font-size: 11px; + font-weight: 600; + padding: 3px 8px; + border-radius: 12px; + box-shadow: 0 2px 6px rgba(59, 130, 246, 0.3); + white-space: nowrap; +} + +/* ============================================================ + * 下载框整体增强 — 模仿 zibll pay-box 视觉重量 + * ============================================================ */ +.resource-download-box { + position: relative; + overflow: visible; +} + +.resource-download-box::before { + content: ''; + position: absolute; + top: 0; + left: 0; + right: 0; + height: 3px; + background: linear-gradient(90deg, var(--color-primary), var(--color-accent)); + border-radius: var(--radius-lg) var(--radius-lg) 0 0; +} + +/* ============================================================ + * 付费类型徽章 — 模仿 zibll 渐变 pay-tag + * ============================================================ */ +.resource-pay-type-badge { + display: inline-flex; + align-items: center; + gap: 4px; + font-size: 11px; + font-weight: 600; + padding: 3px 8px; + border-radius: 4px; + color: #fff; + line-height: 1.3; + letter-spacing: 0.02em; +} + +.resource-pay-type-badge i { + font-size: 10px; +} + +/* 在归档卡片上的徽章位置 */ +.post-card .resource-pay-type-badge { + position: absolute; + top: 8px; + left: 8px; + z-index: 2; +} + +/* 在下载框内的徽章 */ +.resource-download-box__header .resource-pay-type-badge { + margin-left: 8px; +} + +/* ============================================================ + * 原价划线 — 模仿 zibll .original-price + * ============================================================ */ +.resource-original-price { + font-size: 13px; + color: var(--color-ink-4); + text-decoration: line-through; + margin-left: 6px; +} + +.resource-original-price::before { + content: ''; diff --git a/assets/css/frontend/resource-meta/part-5.css b/assets/css/frontend/resource-meta/part-5.css new file mode 100644 index 00000000..03274875 --- /dev/null +++ b/assets/css/frontend/resource-meta/part-5.css @@ -0,0 +1,55 @@ + position: absolute; + left: -2px; + right: -2px; + top: 50%; + height: 1px; + background: var(--color-ink-4); + transform: rotate(-8deg); +} + +/* ============================================================ + * 视频播放器容器 + * ============================================================ */ +.resource-video-container { + position: relative; + width: 100%; + padding-bottom: 56.25%; + margin: 16px 0; + border-radius: var(--radius-lg); + overflow: hidden; + background: #000; +} + +.resource-video-container iframe { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + border: none; +} + +/* ============================================================ + * 付费图库预览 + * ============================================================ */ +.resource-gallery-locked { + position: relative; + filter: blur(8px); + pointer-events: none; + user-select: none; +} + +.resource-gallery-locked::after { + content: '\f023'; + font-family: 'Font Awesome 5 Free'; + font-weight: 900; + position: absolute; + inset: 0; + display: flex; + align-items: center; + justify-content: center; + font-size: 32px; + color: rgba(255, 255, 255, 0.8); + background: rgba(0, 0, 0, 0.3); +} + diff --git a/assets/css/frontend/sidebar.css b/assets/css/frontend/sidebar.css new file mode 100644 index 00000000..04330043 --- /dev/null +++ b/assets/css/frontend/sidebar.css @@ -0,0 +1,167 @@ +/* ========== 侧边栏 — 对齐 zibll sidebar ========== */ +.sidebar { + width: var(--sidebar-width, 311px); + flex-shrink: 0; +} + +.sidebar-inner { + position: sticky; + top: calc(var(--nav-height, 60px) + 16px); +} + +/* Widget 通用 */ +.widget { + background: var(--surface-1, #fff); + border-radius: var(--radius, 8px); + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.04); + margin-bottom: 16px; + overflow: hidden; +} + +.widget-title { + font-size: 15px; + color: var(--color-ink, #333); + padding-bottom: 8px; + margin-bottom: 10px; + display: flex; + align-items: center; + gap: 6px; +} + +.widget-title i { + color: var(--color-primary, #f04494); + font-size: 14px; +} + +.widget-content { + padding: 15px; +} + +.widget-content--flush { + padding: 0; +} + +/* Widget 链接 */ +.widget a { + color: var(--color-ink-2, #4e5358); + text-decoration: none; + transition: color 0.2s; +} + +.widget a:hover { + color: var(--color-primary, #f04494); +} + +/* Widget 标签云 */ +.widget-tag-cloud .tagcloud { + display: flex; + flex-wrap: wrap; + gap: 6px; +} + +.widget-tag-cloud .tagcloud a { + display: inline-block; + padding: 3px 10px; + font-size: 12px !important; + background: var(--surface-2, #eee); + border-radius: 4px; + color: var(--color-ink-2, #4e5358); + transition: all 0.2s; +} + +.widget-tag-cloud .tagcloud a:hover { + background: var(--color-primary-soft, rgba(240, 68, 148, 0.1)); + color: var(--color-primary, #f04494); +} + +/* Widget 列表 */ +.widget ul { + list-style: none; + margin: 0; + padding: 0; +} + +.widget ul li { + padding: 8px 0; + font-size: 13px; + line-height: 1.6; +} + +.widget ul li:last-child { + border-bottom: none; +} + +/* 热门文章 widget */ +.widget-hot-posts .hot-post-item { + display: flex; + gap: 10px; + padding: 8px 0; + border-bottom: 1px solid var(--color-line-soft, rgba(0, 0, 0, 0.03)); +} + +.widget-hot-posts .hot-post-item:last-child { + border-bottom: none; +} + +.widget-hot-posts .hot-post-item__thumb { + width: 60px; + height: 45px; + border-radius: 4px; + object-fit: cover; + flex-shrink: 0; +} + +.widget-hot-posts .hot-post-item__title { + font-size: 13px; + color: var(--color-ink, #333); + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + overflow: hidden; +} + +.widget-hot-posts .hot-post-item__meta { + font-size: 11px; + color: var(--color-ink-4, #999); + margin-top: 2px; +} + +/* 用户卡片 widget */ +.widget-user-card { + text-align: center; + padding: 20px 16px; +} + +.widget-user-card__avatar { + width: 64px; + height: 64px; + border-radius: 50%; + object-fit: cover; + margin-bottom: 10px; +} + +.widget-user-card__name { + font-size: 15px; + font-weight: 600; + color: var(--color-ink, #333); + margin-bottom: 4px; +} + +.widget-user-card__desc { + font-size: 12px; + color: var(--color-ink-3, #777); + margin-bottom: 12px; +} + +/* 侧边栏响应式 */ +@media (max-width: 1200px) { + .sidebar { + width: 280px; + } +} + +@media (max-width: 991px) { + .sidebar { + display: none; + } +} diff --git a/assets/css/frontend/single-post.css b/assets/css/frontend/single-post.css new file mode 100644 index 00000000..fc82184b --- /dev/null +++ b/assets/css/frontend/single-post.css @@ -0,0 +1,7 @@ +@import url("single-post/content.css"); +@import url("single-post/code-blocks.css"); +@import url("single-post/navigation.css"); +@import url("single-post/cover.css"); +@import url("single-post/author-actions.css"); +@import url("single-post/related-toc.css"); +@import url("single-post/hidden-content.css"); diff --git a/assets/css/frontend/single-post/author-actions.css b/assets/css/frontend/single-post/author-actions.css new file mode 100644 index 00000000..1cf33304 --- /dev/null +++ b/assets/css/frontend/single-post/author-actions.css @@ -0,0 +1,441 @@ +/* ===== Author Bar (inside article card) ===== */ +.article-author-bar { + display: flex; + align-items: center; + gap: 10px; + margin-bottom: 16px; +} + +.article-author-bar__avatar { + width: 40px; + height: 40px; + border-radius: 50%; + object-fit: cover; + flex-shrink: 0; +} + +.article-author-bar__info { + flex: 1; + min-width: 0; +} + +.article-author-bar__name { + font-weight: 600; + font-size: 14px; + color: var(--color-ink); +} + +.article-author-bar__name:hover { + color: var(--color-primary); +} + +.article-author-bar__meta { + display: flex; + flex-wrap: wrap; + gap: 10px; + font-size: 12px; + color: var(--color-ink-4, var(--color-ink-4)); + margin-top: 2px; +} + +.article-author-bar__meta span { + display: inline-flex; + align-items: center; + gap: 3px; +} + +.article-author-bar__line { + height: 1px; + background: var(--color-line); + margin-bottom: 20px; +} + +/* ===== Content Footer ===== */ +.article-footer { + margin-top: 32px; + padding-top: 20px; + border-top: 1px solid var(--color-line); +} + +.article-copyright { + font-size: 13px; + color: var(--color-ink-4, var(--color-ink-4)); + margin-bottom: 16px; +} + +.article-end-separator { + text-align: center; + margin: 16px 0; + position: relative; +} + +.article-end-separator::before { + content: ''; + position: absolute; + top: 50%; + left: 0; + right: 0; + height: 1px; + background: var(--color-line); +} + +.article-end-separator span { + position: relative; + display: inline-block; + padding: 0 14px; + background: var(--surface-page); + font-size: 11px; + font-weight: 600; + color: var(--color-ink-4, var(--color-ink-4)); + letter-spacing: 2px; +} + +.article-tags { + display: flex; + flex-wrap: wrap; + gap: 6px; + margin-top: 12px; +} + +/* ===== Action Buttons Card ===== */ +.post-actions-card, +.post-actions { + position: relative; + text-align: center; + margin-bottom: 16px; +} + +.post-actions-card__hint { + font-size: 13px; + color: var(--color-ink-4, var(--color-ink-4)); + margin-bottom: 12px; +} + +.post-actions-card__buttons, +.post-actions { + display: flex; + justify-content: center; + gap: 10px; + margin-bottom: 12px; +} + +.action-btn, +.action { + display: inline-flex; + align-items: center; + gap: 6px; + padding: 0.3em 1em; + border-radius: 50px; + border: none; + background: rgba(136, 136, 136, 0.1); + color: #888; + cursor: pointer; + font-size: 14px; + transition: all 0.15s ease; +} + +.action-btn:hover, +.action:hover { + border-color: var(--color-primary); + color: var(--color-primary); +} + +.action-btn.is-active, +.action.is-active { + border-color: var(--color-primary); + color: var(--color-primary); + background: var(--color-primary-soft, rgba(240, 68, 148, 0.08)); +} + +.action-btn i, +.action i { font-size: 1.2em; } +.action-btn__count { font-weight: 600; } +.action-btn__label { font-size: 13px; } + +/* ===== 分享下拉面板 ===== */ + +/* 确保父容器作为定位参考 */ +.share-dropdown { + position: absolute; + left: 50%; + bottom: calc(100% + 8px); + transform: translateX(-50%); + z-index: 100; + /* 默认隐藏 — 最高优先级确保不被覆盖 */ + display: none !important; +} + +.share-dropdown[aria-hidden="false"] { + display: block !important; + animation: shareDropdownIn 0.2s ease-out forwards; +} + +@keyframes shareDropdownIn { + from { + opacity: 0; + transform: translateX(-50%) translateY(8px); + } + to { + opacity: 1; + transform: translateX(-50%) translateY(0); + } +} + +.share-dropdown__grid { + display: flex; + align-items: center; + gap: 8px; + padding: 12px 16px; + background: var(--surface-page); + border: 1px solid var(--color-line); + border-radius: var(--radius-lg, 8px); + box-shadow: var(--shadow-md, 0 4px 16px rgba(0,0,0,0.1)); +} + +.share-item { + display: inline-flex; + flex-direction: column; + align-items: center; + gap: 4px; + padding: 8px 12px; + border: none; + border-radius: var(--radius-btn, 6px); + background: transparent; + color: var(--color-ink-2, var(--color-ink-3)); + cursor: pointer; + font-size: 11px; + transition: background 0.15s, color 0.15s, transform 0.15s; + white-space: nowrap; +} + +.share-item:hover { + transform: none; +} + +.share-item i { + font-size: 18px; +} + +.share-item[data-platform="qq"]:hover { background: #e8f4fd; color: #12b7f5; } +.share-item[data-platform="weibo"]:hover { background: #fceae9; color: #ff6a00; } +.share-item[data-platform="twitter"]:hover { background: #f0f0f0; color: #000; } +.share-item[data-platform="wechat"]:hover { background: #e6f7ec; color: #07c160; } +.share-item[data-platform="copy"]:hover { background: #f0f2f5; color: #555; } + +/* 微信二维码浮层 */ +#share-qrcode-box { + position: absolute; + bottom: calc(100% + 10px); + left: 50%; + transform: translateX(-50%); + padding: 14px; + background: var(--surface-page); + border: 1px solid var(--color-line); + border-radius: var(--radius-lg, 8px); + box-shadow: var(--shadow-md, 0 4px 16px rgba(0,0,0,0.12)); + text-align: center; + z-index: 101; + pointer-events: none; + opacity: 0; + transition: opacity 0.2s ease, transform 0.2s ease; +} + +#share-qrcode-box.is-visible { + pointer-events: auto; + opacity: 1; +} + +#share-qrcode-image { + width: 140px; + height: 140px; + display: block; +} + +/* 暗色模式 */ +.theme-dark .share-dropdown__grid, +html.dark .share-dropdown__grid { + background: var(--surface-1); + border-color: var(--color-line); + box-shadow: 0 4px 16px rgba(0,0,0,0.35); +} + +.theme-dark #share-qrcode-box, +html.dark #share-qrcode-box { + background: var(--surface-1); + border-color: var(--color-line); +} + +.theme-dark .share-item, +html.dark .share-item { + color: var(--color-ink-2, #aaa); +} + +.theme-dark .share-item[data-platform="qq"]:hover { background: rgba(18,183,245,0.12); color: #12b7f5; } +.theme-dark .share-item[data-platform="weibo"]:hover { background: rgba(255,106,0,0.12); color: #ff6a00; } +.theme-dark .share-item[data-platform="twitter"]:hover { background: rgba(255,255,255,0.08); color: #fff; } +.theme-dark .share-item[data-platform="wechat"]:hover { background: rgba(7,193,96,0.12); color: #07c160; } +.theme-dark .share-item[data-platform="copy"]:hover { background: rgba(255,255,255,0.06); color: #ccc; } + +.theme-dark .post-drop-meta__menu, +html.dark .post-drop-meta__menu { + background: var(--surface-1, #323335); + border-color: var(--color-line); + box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35); +} + +.theme-dark .post-drop-meta__item, +html.dark .post-drop-meta__item { + color: var(--color-ink-2, #ccc); +} + +.theme-dark .post-drop-meta__item:hover, +html.dark .post-drop-meta__item:hover { + background: rgba(255,255,255,0.06); + color: #fff; +} + +/* ===== Author Card — 对齐 zibll 卡片容器 ===== */ +.author-box { + margin-bottom: 16px; + padding: 15px; + background: var(--main-bg-color, #fff); + border-radius: var(--main-radius, 8px); + box-shadow: 0 0 10px var(--main-shadow, rgba(116, 116, 116, 0.08)); +} + +.single-metabox { + display: flex; + align-items: center; + justify-content: flex-end; + gap: 8px; +} + +.post-drop-meta { + position: relative; +} + +.post-drop-meta__menu { + position: absolute; + top: calc(100% + 8px); + right: 0; + min-width: 150px; + padding: 8px; + border-radius: var(--radius, 8px); + border: 1px solid var(--color-line); + background: var(--surface-page, #fff); + box-shadow: var(--shadow-md, 0 8px 24px rgba(0, 0, 0, 0.12)); + display: none; + z-index: 20; +} + +.post-drop-meta.is-open .post-drop-meta__menu { + display: grid; + gap: 4px; +} + +.post-drop-meta__item { + width: 100%; + display: inline-flex; + align-items: center; + gap: 8px; + padding: 8px 10px; + border: 0; + border-radius: 6px; + background: transparent; + color: var(--color-ink-2, var(--color-ink)); + text-decoration: none; + font-size: 13px; + text-align: left; + cursor: pointer; +} + +.post-drop-meta__item:hover { + background: var(--color-line, rgba(50, 50, 50, 0.06)); + color: var(--color-primary); +} + +.post-drop-meta__item i { + width: 16px; + text-align: center; +} + +.author-box__header { + display: flex; + align-items: flex-start; + gap: 14px; +} + +.author-box__avatar { + width: 56px; + height: 56px; + border-radius: 50%; + object-fit: cover; + flex-shrink: 0; + border: 3px solid var(--color-primary-soft, rgba(240, 68, 148, 0.2)); +} + +.author-box__info { + flex: 1; + min-width: 0; +} + +.author-box__name { + font-size: 1rem; + font-weight: 700; + color: var(--color-ink); + display: block; + margin-bottom: 4px; +} + +.author-box__name:hover { color: var(--color-primary); } + +.author-box__bio { + font-size: 13px; + color: var(--color-ink-3, var(--color-ink-4)); + line-height: 1.5; + margin: 0 0 6px; +} + +.author-box__stats { + font-size: 12px; + color: var(--color-ink-4, var(--color-ink-4)); +} + +.author-box__stats strong { + color: var(--color-ink); + margin-right: 2px; +} + +.author-box__posts { + margin-top: 14px; + padding-top: 12px; + border-top: 1px solid var(--color-line); +} + +.author-box__posts-title { + font-size: 12px; + font-weight: 600; + color: var(--color-ink-3, var(--color-ink-4)); + margin: 0 0 8px; +} + +.author-box__posts ul { + list-style: none; + margin: 0; + padding: 0; +} + +.author-box__posts li { padding: 3px 0; } + +.author-box__posts a { + font-size: 13px; + color: var(--color-ink); + display: -webkit-box; + -webkit-line-clamp: 1; + -webkit-box-orient: vertical; + overflow: hidden; +} + +.author-box__posts a:hover { color: var(--color-primary); } +.author-box__posts a::before { content: '\2022'; color: var(--color-primary); } + diff --git a/assets/css/frontend/single-post/code-blocks.css b/assets/css/frontend/single-post/code-blocks.css new file mode 100644 index 00000000..22f97a57 --- /dev/null +++ b/assets/css/frontend/single-post/code-blocks.css @@ -0,0 +1,128 @@ +/* ========== 浠g爜鍧?GitHub 椋庢牸 ========== */ +.code-block { + border-radius: var(--radius-code); + border: 1px solid var(--color-line); + overflow: hidden; + margin: 1.5em 0; + background: var(--surface-3); +} + +.code-block__head { + display: flex; + align-items: center; + justify-content: space-between; + height: 36px; + padding: 0 12px; + background: var(--surface-3); + border-bottom: 1px solid var(--color-line); + font-size: 12px; + color: var(--color-ink-3); +} + +.code-block__copy { + display: inline-flex; + align-items: center; + gap: 6px; + padding: 6px 12px; + border-radius: 6px; + border: 1px solid var(--color-line); + background: var(--surface-page); + cursor: pointer; + font-size: 12px; + color: var(--color-ink-3); +} + +.code-block__copy:hover { + border-color: var(--color-primary); + color: var(--color-primary); +} + +.code-block__body { + overflow-x: auto; + padding: 16px 20px; + font-family: var(--font-mono); + font-size: 13.5px; + line-height: 1.6; +} + +@media (max-width: 767px) { + .code-block__body { + font-size: 12px; + padding: 12px 14px; + } +} + +.entry-content pre.wp-block-code, +.entry-content pre:not(.wp-block-preformatted) { + border-radius: var(--radius-code); + border: 1px solid var(--color-line); + background: var(--surface-3); + padding: 0; + overflow: hidden; +} + +.entry-content pre code { + display: block; + padding: 16px 20px; + overflow-x: auto; + background: transparent; + font-size: 13.5px; + line-height: 1.6; +} + +/* Syntax highlight utilities (plugin or wrapped markup) */ +.gh-keyword { + color: #cf222e; +} + +html.dark .gh-keyword, +html.dark .gh-keyword { + color: #ff7b72; +} + +.gh-string { + color: #0a3069; +} + +html.dark .gh-string, +html.dark .gh-string { + color: #a5d6ff; +} + +.gh-comment { + color: #6e7781; + font-style: italic; +} + +html.dark .gh-comment, +html.dark .gh-comment { + color: #8b949e; +} + +.gh-function { + color: #8250df; +} + +html.dark .gh-function, +html.dark .gh-function { + color: #d2a8ff; +} + +.gh-var { + color: #0550ae; +} + +html.dark .gh-var, +html.dark .gh-var { + color: #79c0ff; +} + +.gh-op { + color: #24292f; +} + +html.dark .gh-op, +html.dark .gh-op { + color: #c9d1d9; +} + diff --git a/assets/css/frontend/single-post/content.css b/assets/css/frontend/single-post/content.css new file mode 100644 index 00000000..780a879d --- /dev/null +++ b/assets/css/frontend/single-post/content.css @@ -0,0 +1,290 @@ +/* ========== Single Post ========== */ +.entry-header, +.article-header { + margin-bottom: 24px; +} + +/* 标题 — 对齐 zibll: 22px, bold, line-height 1.4 */ +.entry-title, +.article-title { + font-size: 22px; + font-weight: 700; + margin: 0 0 16px; + line-height: 1.4; +} + +.entry-meta { + display: flex; + flex-wrap: wrap; + gap: 10px 16px; + font-size: 0.875rem; + color: var(--color-ink-4); +} + +.entry-meta a { + color: var(--color-ink-3); +} + +.entry-meta a:hover { + color: var(--color-primary); +} + +.entry-thumb { + margin: 0 0 28px; + border-radius: var(--radius-btn); + overflow: hidden; +} + +/* 内容区 — 对齐 zibll: 16px, line-height 2 */ +.entry-content { + font-size: 16px; + line-height: 2; + color: var(--color-ink); + overflow-wrap: break-word; + word-wrap: break-word; + min-height: 90px; +} + +.entry-content > *:first-child { + margin-top: 0; +} + +.entry-content p { + margin: 0 0 1.5em; +} + +.entry-content h2 { + font-size: 20px; + font-weight: 700; + margin: 20px 0 10px; +} + +.entry-content h3 { + font-size: 18px; + font-weight: 700; + margin: 20px 0 10px; +} + +.entry-content blockquote { + margin: 0 0 20px; + padding: 15px 20px; + border-left: 4px solid var(--main-border-color, rgba(50, 50, 50, 0.06)); + background: var(--muted-border-color, rgba(0, 0, 0, 0.03)); + border-radius: 0; + color: var(--muted-color, #777); +} + +.entry-content img { + margin: 0 auto; + display: block; + max-width: 100%; + height: auto; +} + +/* ===== 图片灯箱 ===== */ +.lightbox-overlay { + position: fixed; + inset: 0; + z-index: 9999; + display: none; + align-items: center; + justify-content: center; + flex-direction: column; + gap: 12px; + padding: 24px; + background: rgba(0, 0, 0, 0.85); +} + +.lightbox-overlay.is-open { + display: flex; +} + +.lightbox-img { + max-width: 90vw; + max-height: 85vh; + width: auto; + height: auto; + border-radius: 4px; + object-fit: contain; +} + +.lightbox-caption { + max-width: min(96vw, 1200px); + color: #fff; + font-size: 14px; + line-height: 1.5; + text-align: center; + opacity: 0.92; +} + +.lightbox-close { + position: absolute; + top: 14px; + right: 14px; + width: 40px; + height: 40px; + border: none; + border-radius: 999px; + display: inline-flex; + align-items: center; + justify-content: center; + background: rgba(255, 255, 255, 0.12); + color: #fff; + cursor: pointer; + transition: background-color 0.2s ease; +} + +.lightbox-close:hover { + background: rgba(255, 255, 255, 0.22); +} + +.lightbox-close i { + pointer-events: none; +} + +.entry-content iframe, +.entry-content .wp-block-embed iframe, +.entry-content video { + max-width: 100%; + height: auto; +} + +.entry-content .wp-block-embed { + position: relative; + width: 100%; + max-width: 100%; + overflow: hidden; + margin: 1.5em 0; +} + +/* 行内代码 — 对齐 zibll: 粉色文字 + 粉色背景 */ +.entry-content code { + font-family: var(--font-mono); + font-size: 0.9em; + color: #ff3c98; + background: rgba(253, 153, 153, 0.2); + padding: 2px 6px; + border-radius: 4px; +} + +.entry-content ul, +.entry-content ol { + padding-left: 1.5em; + margin: 0 0 1.5em; +} + +.entry-content ul li::marker { + color: var(--color-primary); +} + +.entry-footer { + margin-top: 40px; + padding-top: 24px; + border-top: 1px solid var(--color-line); +} + +.post-tags { + display: flex; + flex-wrap: wrap; + gap: 8px; +} + +.post-tags a { + padding: 4px 10px; + border-radius: 50px; + background: var(--muted-bg-color, #eee); + border: 1px solid var(--main-border-color, rgba(50, 50, 50, 0.06)); + font-size: 13px; + color: var(--muted-color, #777); +} + +.post-tags a:hover { + border-color: var(--color-primary); + color: var(--color-primary); +} + +.related-posts { + margin-top: 48px; +} + +.related-posts__title { + font-size: 15px; + font-weight: 700; + margin: 0 0 10px; + color: var(--key-color, #333); +} + +.related-posts__title::before { + content: ''; + display: inline-block; + width: 40px; + height: 3px; + background: var(--theme-color, #f04494); + border-radius: 5px; + vertical-align: middle; + margin-right: 8px; +} + +.related-posts__grid { + display: flex; + flex-direction: column; + gap: 0; +} + +.related-card { + display: flex; + align-items: center; + gap: 12px; + padding: 10px 0; + border-bottom: 1px solid var(--main-border-color, rgba(50, 50, 50, 0.06)); + transition: 0.15s; +} + +.related-card:last-child { + border-bottom: none; +} + +.related-card a { + display: flex; + align-items: center; + gap: 12px; + color: var(--key-color, #333); + text-decoration: none; + width: 100%; +} + +.related-card:hover a { + color: var(--focus-color, #f04494); +} + +.related-card__thumb { + width: 96px; + min-width: 96px; + height: 64px; + border-radius: var(--main-radius, 8px); + overflow: hidden; + flex-shrink: 0; +} + +.related-card__thumb img { + width: 100%; + height: 100%; + object-fit: cover; + transition: transform 0.3s; +} + +.related-card:hover .related-card__thumb img { + transform: scale(1.05); +} + +.related-card h4 { + font-size: 14px; + font-weight: 600; + margin: 0; + line-height: 1.4; + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + overflow: hidden; +} + diff --git a/assets/css/frontend/single-post/cover.css b/assets/css/frontend/single-post/cover.css new file mode 100644 index 00000000..577e0a66 --- /dev/null +++ b/assets/css/frontend/single-post/cover.css @@ -0,0 +1,192 @@ +/* ============================================================ + * v4.3 cover, author bar, actions, author card, nav, and related posts + * The cover stays inside the content column with a fixed aspect ratio box. + * ============================================================ */ + +/* ===== Cover (in-column ratio box) ===== */ +.single-cover { + position: relative; + overflow: hidden; + border-radius: 8px; + margin-bottom: 16px; + padding-bottom: var(--single-cover-scale, 35%); +} + +.single-cover > .fit-cover, +.single-cover > img { + position: absolute; + inset: 0; + width: 100%; + height: 100%; + object-fit: cover; +} + +.single-cover__overlay { + position: absolute; + inset: 0; + background: linear-gradient( + to bottom, + rgba(0, 0, 0, 0) 30%, + rgba(0, 0, 0, 0.6) 100% + ); + pointer-events: none; +} + +.single-cover__content { + position: absolute; + bottom: 0; + left: 0; + right: 0; + padding: 20px; + color: #fff; + border-radius: 0 0 8px 8px; +} + +.single-cover__title, +.single-cover__content .article-title { + font-size: clamp(1.125rem, 2.5vw, 1.5rem); + font-weight: 700; + margin: 0 0 6px; + line-height: 1.35; + text-shadow: 0 1px 4px rgba(0, 0, 0, 0.4); + color: #fff; +} + +.single-cover__meta, +.single-cover__content .cover-meta { + display: flex; + flex-wrap: wrap; + gap: 12px; + font-size: 12px; + opacity: 0.85; +} + +.single-cover__meta span, +.single-cover__content .cover-meta .meta-view { + display: inline-flex; + align-items: center; + gap: 4px; +} + +/* ===== Video Cover ===== */ +.single-cover--video { + background: #000; +} + +.single-cover--video .single-cover__video { + position: absolute; + inset: 0; + width: 100%; + height: 100%; + object-fit: cover; +} + +/* ===== Slide Cover ===== */ +.single-cover--slide { + background: var(--color-bg-2, #f5f5f5); +} + +.single-cover__slides { + position: absolute; + inset: 0; + width: 100%; + height: 100%; +} + +.single-cover__slide { + position: absolute; + inset: 0; + opacity: 0; + transition: opacity 0.6s ease; +} + +.single-cover__slide.is-active { + opacity: 1; +} + +.single-cover__slide img { + width: 100%; + height: 100%; + object-fit: cover; +} + +.single-cover__dots { + position: absolute; + bottom: 12px; + right: 16px; + display: flex; + gap: 6px; + z-index: 2; +} + +.single-cover__dot { + width: 8px; + height: 8px; + border-radius: 50%; + background: rgba(255, 255, 255, 0.5); + transition: background 0.3s ease; + cursor: pointer; +} + +.single-cover__dot.is-active { + background: #fff; +} + +/* ===== 面包屑 ===== */ +.post-breadcrumbs { + margin-bottom: 12px; + font-size: 13px; + color: var(--color-ink-4, var(--color-ink-4)); +} + +.article-title + .img-badge, +.single-head-cover .img-badge.right, +.article-header .img-badge.right { + position: absolute; + top: 14px; + right: 14px; + z-index: 2; +} + +.article-avatar { + 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; +} + +/* ===== Article Card ===== */ +.article-card { + margin-bottom: 16px; +} + +.article-card__header { + margin-bottom: 16px; + padding-bottom: 12px; + border-bottom: 1px solid var(--color-line); +} + +.article-card__title { + font-size: clamp(1.25rem, 3vw, 1.75rem); + font-weight: 800; + margin: 0; + line-height: 1.35; + color: var(--color-ink); +} + diff --git a/assets/css/frontend/single-post/hidden-content.css b/assets/css/frontend/single-post/hidden-content.css new file mode 100644 index 00000000..fb2c3a17 --- /dev/null +++ b/assets/css/frontend/single-post/hidden-content.css @@ -0,0 +1,121 @@ +/* ---- Yiyan inline blocks (single post) ---- */ +.yiyan--header, +.yiyan--footer { + margin: 16px 0; + padding: 12px 16px; +} + +.yiyan--box { + margin: 24px 0; + padding: 20px; + border-radius: 8px; + background: var(--card-bg, #fff); + box-shadow: var(--card-shadow, 0 2px 8px rgba(0, 0, 0, .06)); +} + +/* ---- Front / After content insertion ---- */ +.article-front-content, +.article-after-content { + padding: 12px 0; + font-size: 14px; + line-height: 1.8; + color: var(--text-secondary, #666); + border-bottom: 1px dashed var(--border-color, #eee); + margin-bottom: 12px; +} + +.article-after-content { + border-bottom: none; + border-top: 1px dashed var(--border-color, #eee); + margin-bottom: 0; + margin-top: 12px; +} + +/* ---- Hidden Content Shortcodes ---- */ +.aksrt-hidden-content { + position: relative; + margin: 16px 0; + padding: 16px; + border-radius: var(--border-radius, 8px); + font-size: 14px; + line-height: 1.8; +} + +.aksrt-hidden-content--unlocked { + background: var(--bg-secondary, #f8f9fa); + border: 1px solid var(--border-color, #e5e7eb); +} + +.aksrt-hidden-content--locked { + background: linear-gradient(135deg, var(--bg-secondary, #f8f9fa) 0%, var(--bg-tertiary, #f1f3f5) 100%); + border: 1px dashed var(--border-color, #d1d5db); + text-align: center; + padding: 24px 16px; +} + +.aksrt-hidden-content__message { + display: flex; + align-items: center; + justify-content: center; + gap: 8px; + font-size: 15px; + color: var(--text-secondary, #6b7280); + margin-bottom: 12px; +} + +.aksrt-hidden-content__message i { + font-size: 18px; + color: var(--text-muted, #9ca3af); +} + +.aksrt-hidden-content--vip .aksrt-hidden-content__message i { + color: var(--vip-color, #f59e0b); +} + +.aksrt-hidden-content--payshow .aksrt-hidden-content__message i { + color: var(--primary-color, #3b82f6); +} + +.aksrt-hidden-content__form { + display: flex; + align-items: center; + justify-content: center; + gap: 8px; + margin-top: 8px; +} + +.aksrt-hidden-content__password-input { + width: 200px; + max-width: 60%; + padding: 6px 12px; + border: 1px solid var(--border-color, #d1d5db); + border-radius: var(--border-radius, 6px); + font-size: 14px; + background: var(--bg-primary, #fff); + color: var(--text-primary, #1f2937); + outline: none; + transition: border-color .2s; +} + +.aksrt-hidden-content__password-input:focus { + border-color: var(--primary-color, #3b82f6); +} + +.aksrt-hidden-content__submit-btn, +.aksrt-hidden-content__login-btn { + display: inline-flex; + align-items: center; + gap: 4px; + padding: 6px 16px; + font-size: 13px; + border-radius: var(--border-radius, 6px); + cursor: pointer; + text-decoration: none; + transition: opacity .2s; +} + +.aksrt-hidden-content__submit-btn:hover, +.aksrt-hidden-content__login-btn:hover { + opacity: .85; +} + diff --git a/assets/css/frontend/single-post/navigation.css b/assets/css/frontend/single-post/navigation.css new file mode 100644 index 00000000..6de42565 --- /dev/null +++ b/assets/css/frontend/single-post/navigation.css @@ -0,0 +1,79 @@ +/* ========== Post Navigation ========== */ +.post-nav-links { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 12px; + margin-top: 32px; +} + +@media (min-width: 768px) { + .post-nav-links { + gap: 16px; + margin-top: 40px; + } +} + +.post-nav-links a { + display: block; + padding: 16px; + border-radius: var(--radius-lg); + border: 1px solid var(--color-line); + background: var(--surface-2); + transition: border-color 0.2s; +} + +.post-nav-links a:hover { + border-color: var(--color-primary); +} + +.post-nav-links .nav-subtitle { + display: block; + font-size: 12px; + color: var(--color-ink-4); + margin-bottom: 4px; +} + +.post-nav-links .nav-title { + font-weight: 700; + color: var(--color-ink); +} + +.post-navigation, +.navigation.post-navigation { + margin-top: 40px; +} + +.post-navigation .nav-links, +.navigation.post-navigation .nav-links { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 12px; +} + +@media (min-width: 768px) { + .post-navigation .nav-links, + .navigation.post-navigation .nav-links { + gap: 16px; + } +} + +.post-navigation a, +.navigation.post-navigation a { + display: block; + padding: 16px; + border-radius: var(--radius-lg); + border: 1px solid var(--color-line); + background: var(--surface-2); + transition: border-color 0.2s; +} + +.post-navigation a:hover, +.navigation.post-navigation a:hover { + border-color: var(--color-primary); +} + + +/* ===== Utility card classes (unified in card-primitives.css) ===== */ +.mt-3 { + margin-top: 16px; +} diff --git a/assets/css/frontend/single-post/related-toc.css b/assets/css/frontend/single-post/related-toc.css new file mode 100644 index 00000000..d9485473 --- /dev/null +++ b/assets/css/frontend/single-post/related-toc.css @@ -0,0 +1,430 @@ +/* ===== Previous / Next Navigation ===== */ +.post-nav-box { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 12px; + margin-bottom: 16px; +} + +.post-nav-box__item { + display: block; + padding: 15px; + text-decoration: none; + transition: color 0.15s ease; + color: var(--key-color, #333); +} + +.post-nav-box__item:hover { + color: var(--focus-color, #f04494); + text-decoration: none; +} + +.post-nav-box__item--next { text-align: right; } + +.post-nav-box__label { + display: block; + font-size: 12px; + color: var(--color-ink-4, var(--color-ink-4)); + margin-bottom: 4px; +} + +.post-nav-box__title { + display: block; + font-size: 14px; + font-weight: 600; + color: var(--key-color, #333); + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + overflow: hidden; +} + +/* ===== Related Posts — 对齐 zibll 卡片容器 ===== */ +.related-box { + margin-bottom: 16px; + overflow: hidden; + background: var(--main-bg-color, #fff); + border-radius: var(--main-radius, 8px); + box-shadow: 0 0 10px var(--main-shadow, rgba(116, 116, 116, 0.08)); +} + +.related-box__header { padding-bottom: 0; } + +.related-box__title { + font-size: 14px; + font-weight: 700; + margin: 0; + display: flex; + align-items: center; + gap: 6px; +} + +.related-box__title i { color: var(--color-primary); font-size: 13px; } + +.related-box__list { + padding: 12px 16px 16px; + display: flex; + flex-direction: column; + gap: 0; +} + +.related-box__item { + display: flex; + align-items: center; + gap: 10px; + padding: 8px 0; + border-bottom: 1px solid var(--color-line); + text-decoration: none; + color: inherit; +} + +.related-box__item:last-child { border-bottom: none; } +.related-box__item:hover { color: var(--color-primary); } + +.related-box__thumb { + width: 96px; + min-width: 96px; + height: 64px; + border-radius: var(--main-radius, 8px); + overflow: hidden; + flex-shrink: 0; + background: var(--muted-bg-color, #eee); +} + +.related-box__thumb img { width: 100%; height: 100%; object-fit: cover; } + +.related-box__placeholder { + width: 100%; height: 100%; + display: flex; align-items: center; justify-content: center; + color: var(--color-ink-4); font-size: 14px; +} + +.related-box__item-title { + font-size: 14px; + font-weight: 600; + display: -webkit-box; + -webkit-line-clamp: 1; + -webkit-box-orient: vertical; + overflow: hidden; +} + +/* ===== Comment Card Spacing ===== */ +.comments-card { margin-bottom: 16px; } + +/* ===== Content Height Clamp ===== */ +.wp-posts-content.limit-height { + position: relative; + overflow: hidden; +} + +.wp-posts-content.limit-height::after { + content: ''; + position: absolute; + bottom: 0; left: 0; right: 0; + height: 100px; + background: linear-gradient(to bottom, transparent, var(--surface-page)); + pointer-events: none; +} + +.wp-posts-content.limit-height.is-expanded::after { display: none; } + +.entry-content.limit-height { + position: relative; + overflow: hidden; +} + +.entry-content.limit-height::after { + content: ''; + position: absolute; + bottom: 0; left: 0; right: 0; + height: 100px; + background: linear-gradient(to bottom, transparent, var(--surface-page)); + pointer-events: none; +} + +.entry-content.limit-height.is-expanded::after { display: none; } + +.content-expand-btn { + display: flex; + align-items: center; + justify-content: center; + gap: 6px; + width: 100%; + padding: 10px; + margin-top: -30px; + position: relative; + z-index: 2; + border: none; + background: var(--surface-page); + color: var(--color-primary); + font-size: 13px; + font-weight: 500; + cursor: pointer; + border-top: 1px solid var(--color-line); +} + +.content-expand-btn:hover { background: var(--color-primary-soft, rgba(240, 68, 148, 0.06)); } +.content-expand-btn.is-expanded i { transform: rotate(180deg); } + +/* ===== Mobile ===== */ +@media (max-width: 767px) { + .single-cover { padding-bottom: 55%; } + .single-cover__content { padding: 14px; } + .single-cover__title { font-size: 1rem; } + .post-nav-box { grid-template-columns: 1fr; } + .post-actions-card__buttons { gap: 8px; } + .action-btn { padding: 8px 14px; font-size: 13px; } +} + +/* ===== 鏆楄壊妯″紡 ===== */ +.theme-dark .article-end-separator span, +html.dark .article-end-separator span { + background: var(--surface-1); +} + +/* ============================================================ + * Phase 7 single/article controls + * ============================================================ */ +.reading-progress-bar { + position: fixed; + top: 0; + left: 0; + z-index: 120; + width: 0; + height: 3px; + background: linear-gradient(90deg, var(--color-primary), color-mix(in srgb, var(--color-primary) 55%, #fff)); + box-shadow: 0 2px 12px color-mix(in srgb, var(--color-primary) 24%, transparent); +} + +.author-info-bar.article-author-bar { + display: flex; + align-items: flex-start; + gap: 12px; + margin-bottom: 18px; +} + +.author-info-bar.article-author-bar .author-info-bar__avatar img, +.author-info-bar.article-author-bar .author-info-bar__avatar .avatar { + width: 44px; + height: 44px; + border-radius: 50%; + object-fit: cover; +} + +.author-info-bar.article-author-bar .author-info-bar__body { + min-width: 0; + flex: 1; +} + +.author-info-bar.article-author-bar .author-info-bar__name { + display: inline-flex; + align-items: center; + gap: 8px; + color: var(--color-ink); + font-weight: 600; + font-size: 15px; +} + +.author-info-bar.article-author-bar .author-info-bar__sub { + display: flex; + flex-wrap: wrap; + gap: 8px 10px; + margin-top: 4px; + color: var(--color-ink-4); + font-size: 12px; +} + +.author-info-bar.article-author-bar .author-info-bar__bio { + margin: 8px 0 0; + color: var(--color-ink-3); + font-size: 13px; + line-height: 1.6; +} + +.action-btn--ghost { + background: var(--surface-2); +} + +.toc-widget { + position: sticky; + top: 88px; + padding: 18px 18px 14px; + margin-bottom: 16px; +} + +.toc-widget .widget-title { + margin-bottom: 10px; +} + +.toc-list { + list-style: none; + margin: 0; + padding: 0; + display: grid; + gap: 8px; +} + +.toc-list li { + min-width: 0; +} + +.toc-list a { + display: block; + color: var(--color-ink-3); + font-size: 13px; + line-height: 1.55; + text-decoration: none; + transition: color 0.2s ease, transform 0.2s ease; +} + +.toc-list a:hover, +.toc-list a.is-active { + color: var(--color-primary); +} + +.toc-list .toc-h3 a { + padding-left: 12px; +} + +.toc-list .toc-h4 a { + padding-left: 24px; +} + +.toc-float-btn { + position: fixed; + right: 18px; + bottom: 86px; + z-index: 41; + width: 48px; + height: 48px; + border: none; + border-radius: 999px; + display: none; + align-items: center; + justify-content: center; + background: var(--color-primary); + color: #fff; + box-shadow: 0 10px 30px rgba(0, 0, 0, 0.18); +} + +.toc-drawer-overlay { + position: fixed; + inset: 0; + z-index: 79; + display: none; + background: rgba(15, 23, 42, 0.36); +} + +.toc-drawer-overlay.is-open { + display: block; +} + +.toc-drawer { + position: fixed; + right: 0; + top: 0; + bottom: 0; + z-index: 80; + width: min(86vw, 340px); + padding: 18px 18px 28px; + background: var(--surface-page); + border-left: 1px solid var(--color-line); + transform: translateX(100%); + transition: transform 0.25s ease; + overflow-y: auto; +} + +.toc-drawer.is-open { + transform: translateX(0); +} + +.toc-drawer__head { + display: flex; + align-items: center; + justify-content: space-between; + gap: 12px; + margin-bottom: 14px; +} + +.toc-drawer__head h3 { + margin: 0; + font-size: 16px; +} + +.toc-drawer__close { + width: 36px; + height: 36px; + border: none; + border-radius: 999px; + background: var(--surface-2); + color: var(--color-ink-3); +} + +.resource-mobile-fab { + position: fixed; + right: 18px; + bottom: 24px; + z-index: 42; + width: 52px; + height: 52px; + display: none; + align-items: center; + justify-content: center; + border-radius: 999px; + background: var(--color-primary); + color: #fff; + box-shadow: 0 10px 30px rgba(0, 0, 0, 0.18); +} + +.resource-mobile-download-bar { + display: none; + margin-bottom: 16px; +} + +.resource-related { + margin-bottom: 16px; +} + +.resource-related__header { + margin-bottom: 14px; +} + +.resource-related__title { + margin: 0; + font-size: 18px; + font-weight: 700; +} + +.resource-related__grid { + margin-top: 0; +} + +@media (max-width: 991px) { + .toc-widget { + display: none; + } + + .toc-float-btn { + display: inline-flex; + } + + .resource-mobile-download-bar { + display: block; + } + + .resource-mobile-fab { + display: inline-flex; + } +} + +@media (max-width: 767px) { + .author-info-bar.article-author-bar { + gap: 10px; + margin-bottom: 16px; + } + + .author-info-bar.article-author-bar .author-info-bar__sub { + gap: 6px 8px; + } +} + diff --git a/assets/css/frontend/site-notice.css b/assets/css/frontend/site-notice.css new file mode 100644 index 00000000..57a150e9 --- /dev/null +++ b/assets/css/frontend/site-notice.css @@ -0,0 +1,131 @@ +/** + * AKSRT Site Notice — Popup notice styles + */ + +.aksrt-site-notice { + position: fixed; + inset: 0; + z-index: 99998; + display: flex; + align-items: center; + justify-content: center; + padding: 20px; +} + +.aksrt-site-notice__overlay { + position: absolute; + inset: 0; + background: rgba(0, 0, 0, 0.5); +} + +.aksrt-site-notice__dialog { + position: relative; + background: var(--surface-1, #fff); + border-radius: var(--radius-lg, 12px); + box-shadow: 0 8px 40px rgba(0, 0, 0, 0.15); + width: 100%; + max-height: 80vh; + overflow-y: auto; +} + +.aksrt-site-notice__head { + display: flex; + align-items: center; + justify-content: space-between; + padding: 20px 24px 0; +} + +.aksrt-site-notice__title { + margin: 0; + font-size: 18px; + font-weight: 700; + color: var(--color-ink, #333); +} + +.aksrt-site-notice__close { + width: 32px; + height: 32px; + border: none; + border-radius: 50%; + background: var(--surface-2, #eee); + color: var(--color-ink-3, #777); + font-size: 16px; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + transition: background 0.15s; +} + +.aksrt-site-notice__close:hover { + background: var(--surface-3, #ddd); +} + +.aksrt-site-notice__body { + padding: 16px 24px; + font-size: 14px; + line-height: 1.7; + color: var(--color-ink-2, #4e5358); +} + +.aksrt-site-notice__body a { + color: var(--color-primary); +} + +.aksrt-site-notice__foot { + padding: 0 24px 20px; + text-align: center; + display: flex; + flex-wrap: wrap; + gap: 10px; + justify-content: center; +} + +/* Button base — shared by both