/* 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); }