820 lines
22 KiB
Plaintext
820 lines
22 KiB
Plaintext
---
|
|
import Layout from "../layouts/Layout.astro";
|
|
import HeroSection from "../components/HeroSection.astro";
|
|
---
|
|
|
|
<Layout home>
|
|
<Fragment slot="head">
|
|
<title th:text="${site.title}"></title>
|
|
</Fragment>
|
|
|
|
<HeroSection />
|
|
|
|
<div
|
|
class="wi-home-content"
|
|
th:classappend="${theme.config?.hero?.hero_enabled != false} ? 'wi-home-content--with-hero'"
|
|
th:attr="data-i18n-all-loaded=#{common.allLoaded},data-i18n-loading=#{common.loading},data-i18n-words=#{common.words},data-i18n-read-time=#{common.readTime},data-i18n-views=#{common.views}"
|
|
>
|
|
<section
|
|
class="wi-home-pinned"
|
|
th:if="${posts != null and !#lists.isEmpty(posts.items)}"
|
|
>
|
|
<div class="wi-container">
|
|
<div class="wi-section__header">
|
|
<h2 class="wi-section__title" th:text="${theme.config?.home?.home_pinned_title ?: #messages.msg('hero.pinned')}">置顶</h2>
|
|
</div>
|
|
<div class="wi-pinned">
|
|
<a
|
|
th:each="post : ${posts.items}"
|
|
th:if="${post.spec.pinned}"
|
|
th:href="@{${post.status.permalink}}"
|
|
class="wi-pinned__card"
|
|
>
|
|
<div
|
|
class="wi-pinned__cover"
|
|
th:if="${!#strings.isEmpty(post.spec.cover)}"
|
|
>
|
|
<img th:src="${post.spec.cover}" th:alt="${post.spec.title}" class="wi-pinned__image" loading="lazy" decoding="async" />
|
|
</div>
|
|
<div class="wi-pinned__body">
|
|
<div class="wi-pinned__meta">
|
|
<span
|
|
class="wi-pinned__category"
|
|
th:if="${!#lists.isEmpty(post.categories)}"
|
|
th:text="${post.categories[0].spec.displayName}"
|
|
></span>
|
|
<time
|
|
class="wi-pinned__date"
|
|
th:text="${#dates.format(post.spec.publishTime, 'yyyy-MM-dd')}"
|
|
></time>
|
|
</div>
|
|
<h3
|
|
class="wi-pinned__title"
|
|
th:text="${post.spec.title}"
|
|
></h3>
|
|
<p
|
|
class="wi-pinned__excerpt"
|
|
th:if="${post.status.excerpt}"
|
|
th:text="${post.status.excerpt}"
|
|
></p>
|
|
</div>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<section class="wi-home-posts" id="wi-home-posts">
|
|
<div class="wi-container">
|
|
<div class="wi-section__header">
|
|
<h2 class="wi-section__title" th:text="${theme.config?.home?.home_posts_title ?: #messages.msg('hero.posts')}">文章</h2>
|
|
</div>
|
|
<div class="wi-flow" id="wi-post-grid">
|
|
<article
|
|
th:each="post : ${posts.items}"
|
|
th:if="${!post.spec.pinned}"
|
|
class="wi-flow__card"
|
|
th:classappend="${!#strings.isEmpty(post.spec.cover)} ? 'wi-flow__card--with-cover' : ''"
|
|
>
|
|
<a
|
|
class="wi-flow__stretched-link"
|
|
th:href="@{${post.status.permalink}}"
|
|
tabindex="-1"
|
|
aria-hidden="true"
|
|
></a>
|
|
<div class="wi-flow__body">
|
|
<div class="wi-flow__meta">
|
|
<th:block th:if="${(theme.config?.home?.home_card_show_category ?: true) and !#lists.isEmpty(post.categories)}">
|
|
<span class="wi-flow__categories">
|
|
<a
|
|
th:each="cat : ${post.categories}"
|
|
th:href="@{${cat.status.permalink}}"
|
|
th:text="${cat.spec.displayName}"
|
|
class="wi-flow__category-link"
|
|
></a>
|
|
</span>
|
|
</th:block>
|
|
<time
|
|
class="wi-flow__date"
|
|
th:text="${#dates.format(post.spec.publishTime, 'yyyy-MM-dd')}"
|
|
></time>
|
|
</div>
|
|
<a
|
|
th:href="@{${post.status.permalink}}"
|
|
class="wi-flow__title-link"
|
|
>
|
|
<h3
|
|
class="wi-flow__title"
|
|
th:text="${post.spec.title}"
|
|
></h3>
|
|
</a>
|
|
<p
|
|
class="wi-flow__excerpt"
|
|
th:if="${post.status.excerpt}"
|
|
th:text="${post.status.excerpt}"
|
|
th:style="'-webkit-line-clamp:' + (${theme.config?.home?.home_excerpt_lines ?: 3})"
|
|
></p>
|
|
<div class="wi-flow__footer">
|
|
<th:block th:if="${(theme.config?.home?.home_card_show_tags ?: true) and post.tags != null and !#lists.isEmpty(post.tags)}">
|
|
<div class="wi-flow__tags">
|
|
<a
|
|
th:each="tag : ${post.tags}"
|
|
th:href="@{${tag.status.permalink}}"
|
|
th:text="${tag.spec.displayName}"
|
|
class="wi-flow__tag-link"
|
|
></a>
|
|
</div>
|
|
</th:block>
|
|
<div class="wi-flow__stats">
|
|
<span
|
|
class="wi-flow__stat"
|
|
th:if="${theme.config?.home?.home_card_show_visit ?: true}"
|
|
>
|
|
<th:block th:text="${post.stats?.visit ?: 0}"></th:block> <th:block th:text="#{common.views}">阅读</th:block>
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div
|
|
class="wi-flow__cover"
|
|
th:if="${!#strings.isEmpty(post.spec.cover)}"
|
|
>
|
|
<img th:src="${post.spec.cover}" th:alt="${post.spec.title}" class="wi-flow__image" loading="lazy" decoding="async" />
|
|
</div>
|
|
</article>
|
|
</div>
|
|
|
|
<nav
|
|
th:if="${posts.totalPages gt 1 and theme.config?.home?.home_post_loading != 'infinite_scroll'}"
|
|
class="wi-pagination"
|
|
id="wi-post-pagination"
|
|
aria-label="Pagination"
|
|
>
|
|
<a
|
|
th:if="${posts.hasPrevious()}"
|
|
th:href="@{${posts.prevUrl}}"
|
|
class="wi-pagination__prev"
|
|
th:text="${theme.config?.home?.home_label_newer ?: #messages.msg('common.newer')}"
|
|
>← 较新</a>
|
|
<span
|
|
class="wi-pagination__info"
|
|
th:text="|${posts.page} / ${posts.totalPages}|"
|
|
></span>
|
|
<a
|
|
th:if="${posts.hasNext()}"
|
|
th:href="@{${posts.nextUrl}}"
|
|
class="wi-pagination__next"
|
|
th:text="${theme.config?.home?.home_label_older ?: #messages.msg('common.older')}"
|
|
>较旧 →</a>
|
|
</nav>
|
|
|
|
<div
|
|
th:if="${posts.hasNext() and theme.config?.home?.home_post_loading == 'infinite_scroll'}"
|
|
id="wi-infinite-scroll-sentinel"
|
|
th:attr="data-next-url=${posts.nextUrl}, data-all-loaded-text=${theme.config?.home?.home_label_all_loaded ?: #messages.msg('common.allLoaded')}"
|
|
>
|
|
<div class="wi-infinite-scroll__loader">
|
|
<div class="wi-infinite-scroll__spinner"></div>
|
|
<span th:text="${theme.config?.home?.home_label_loading ?: #messages.msg('common.loading')}">加载中...</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div
|
|
th:if="${!posts.hasNext() and posts.totalPages gt 1 and theme.config?.home?.home_post_loading == 'infinite_scroll'}"
|
|
class="wi-infinite-scroll__end"
|
|
>
|
|
<span th:text="${theme.config?.home?.home_label_all_loaded ?: #messages.msg('common.allLoaded')}">已加载全部文章</span>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
</div>
|
|
</Layout>
|
|
|
|
<script is:inline>
|
|
(function () {
|
|
var sentinel = document.getElementById("wi-infinite-scroll-sentinel");
|
|
if (!sentinel) return;
|
|
|
|
var grid = document.getElementById("wi-post-grid");
|
|
var i18nEl = document.querySelector(".wi-home-content");
|
|
var loading = false;
|
|
var nextUrl = sentinel.getAttribute("data-next-url");
|
|
var allLoadedText = sentinel.getAttribute("data-all-loaded-text") || (i18nEl && i18nEl.getAttribute("data-i18n-all-loaded")) || "All posts loaded";
|
|
|
|
var observer = new IntersectionObserver(
|
|
function (entries) {
|
|
if (entries[0].isIntersecting && !loading && nextUrl) {
|
|
loading = true;
|
|
var loader = sentinel.querySelector(".wi-infinite-scroll__loader");
|
|
if (loader) loader.style.display = "flex";
|
|
|
|
fetch(nextUrl)
|
|
.then(function (res) {
|
|
if (!res.ok) throw new Error("Fetch failed");
|
|
return res.text();
|
|
})
|
|
.then(function (html) {
|
|
var parser = new DOMParser();
|
|
var doc = parser.parseFromString(html, "text/html");
|
|
|
|
var newCards = doc.querySelectorAll("#wi-post-grid .wi-flow__card");
|
|
for (var i = 0; i < newCards.length; i++) {
|
|
var card = newCards[i];
|
|
card.style.opacity = "0";
|
|
card.style.transform = "translateY(20px)";
|
|
grid.appendChild(card);
|
|
(function (c) {
|
|
requestAnimationFrame(function () {
|
|
c.style.transition = "opacity 0.4s ease, transform 0.4s ease";
|
|
c.style.opacity = "1";
|
|
c.style.transform = "translateY(0)";
|
|
});
|
|
})(card);
|
|
}
|
|
|
|
var newSentinel = doc.getElementById("wi-infinite-scroll-sentinel");
|
|
if (newSentinel && newSentinel.getAttribute("data-next-url")) {
|
|
nextUrl = newSentinel.getAttribute("data-next-url");
|
|
} else {
|
|
nextUrl = null;
|
|
observer.disconnect();
|
|
sentinel.style.display = "none";
|
|
var endMsg = document.createElement("div");
|
|
endMsg.className = "wi-infinite-scroll__end";
|
|
endMsg.innerHTML = "<span>" + allLoadedText + "</span>";
|
|
sentinel.parentNode.appendChild(endMsg);
|
|
}
|
|
|
|
loading = false;
|
|
if (loader) loader.style.display = "none";
|
|
})
|
|
.catch(function () {
|
|
loading = false;
|
|
if (loader) loader.style.display = "none";
|
|
});
|
|
}
|
|
},
|
|
{ rootMargin: "300px" }
|
|
);
|
|
|
|
observer.observe(sentinel);
|
|
})();
|
|
</script>
|
|
|
|
<script is:inline>
|
|
(function () {
|
|
var hero = document.getElementById("wi-hero");
|
|
var blurOverlay = document.getElementById("wi-hero-blur-overlay");
|
|
var heroContent = document.getElementById("wi-hero-content");
|
|
var scrollIndicator = document.getElementById("wi-hero-scroll-indicator");
|
|
|
|
if (!hero || !blurOverlay) return;
|
|
|
|
var maxBlur = 20;
|
|
var triggerDistance = 300;
|
|
var fadeStart = 200;
|
|
var fadeEnd = 500;
|
|
var ticking = false;
|
|
|
|
function onScroll() {
|
|
if (ticking) return;
|
|
ticking = true;
|
|
requestAnimationFrame(function () {
|
|
ticking = false;
|
|
var scrollY = window.scrollY || window.pageYOffset;
|
|
|
|
var currentBlur = Math.min(scrollY / triggerDistance * maxBlur, maxBlur);
|
|
blurOverlay.style.backdropFilter = "blur(" + currentBlur + "px)";
|
|
blurOverlay.style.webkitBackdropFilter = "blur(" + currentBlur + "px)";
|
|
|
|
if (heroContent) {
|
|
var progress = Math.max(0, Math.min(1, (scrollY - fadeStart) / (fadeEnd - fadeStart)));
|
|
heroContent.style.opacity = String(1 - progress);
|
|
heroContent.style.transform = "translateY(" + (-20 * progress) + "px)";
|
|
}
|
|
|
|
if (scrollIndicator) {
|
|
var indicatorProgress = Math.max(0, Math.min(1, (scrollY - fadeStart) / (fadeEnd - fadeStart)));
|
|
scrollIndicator.style.opacity = String(1 - indicatorProgress);
|
|
}
|
|
});
|
|
}
|
|
|
|
window.addEventListener("scroll", onScroll, { passive: true });
|
|
onScroll();
|
|
})();
|
|
</script>
|
|
|
|
<script is:inline>
|
|
(function () {
|
|
var hero = document.getElementById("wi-hero");
|
|
var content = document.querySelector(".wi-home-content--with-hero");
|
|
if (!hero || !content) return;
|
|
|
|
var isSnapping = false;
|
|
var heroHeight = window.innerHeight;
|
|
|
|
window.addEventListener("resize", function () {
|
|
heroHeight = window.innerHeight;
|
|
}, { passive: true });
|
|
|
|
function snapTo(targetY) {
|
|
if (isSnapping) return;
|
|
isSnapping = true;
|
|
window.scrollTo({ top: targetY, behavior: "smooth" });
|
|
var timer = setTimeout(function () {
|
|
isSnapping = false;
|
|
}, 800);
|
|
if ("onscrollend" in window) {
|
|
window.addEventListener(
|
|
"scrollend",
|
|
function () {
|
|
clearTimeout(timer);
|
|
isSnapping = false;
|
|
},
|
|
{ once: true }
|
|
);
|
|
}
|
|
}
|
|
|
|
window.addEventListener("wheel", function (e) {
|
|
if (isSnapping) {
|
|
e.preventDefault();
|
|
return;
|
|
}
|
|
var y = window.scrollY;
|
|
if (y < heroHeight && e.deltaY > 0) {
|
|
e.preventDefault();
|
|
snapTo(heroHeight);
|
|
} else if (y > 0 && y <= heroHeight && e.deltaY < 0) {
|
|
e.preventDefault();
|
|
snapTo(0);
|
|
}
|
|
}, { passive: false });
|
|
|
|
var touchStartY = 0;
|
|
window.addEventListener("touchstart", function (e) {
|
|
touchStartY = e.touches[0].clientY;
|
|
}, { passive: true });
|
|
|
|
window.addEventListener("touchend", function (e) {
|
|
if (isSnapping) return;
|
|
var diff = touchStartY - e.changedTouches[0].clientY;
|
|
var y = window.scrollY;
|
|
if (y < heroHeight && diff > 30) {
|
|
snapTo(heroHeight);
|
|
} else if (y > 0 && y <= heroHeight && diff < -30) {
|
|
snapTo(0);
|
|
}
|
|
}, { passive: true });
|
|
})();
|
|
</script>
|
|
|
|
<style>
|
|
.wi-home-content {
|
|
position: relative;
|
|
z-index: 1;
|
|
background: var(--bg);
|
|
min-height: 100vh;
|
|
padding-bottom: 2rem;
|
|
}
|
|
|
|
.wi-home-content--with-hero {
|
|
margin-top: 100vh;
|
|
margin-top: 100dvh;
|
|
}
|
|
|
|
.wi-home-pinned {
|
|
padding-block: 2rem;
|
|
background: var(--bg);
|
|
}
|
|
|
|
.wi-home-pinned:not(:has(.wi-pinned__card)) {
|
|
display: none;
|
|
}
|
|
|
|
.wi-section__header {
|
|
margin-bottom: var(--space-xl);
|
|
}
|
|
|
|
.wi-section__title {
|
|
font-family: var(--font-sans);
|
|
font-size: var(--text-2xl);
|
|
font-weight: 700;
|
|
color: var(--ink);
|
|
letter-spacing: var(--tracking-tight);
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.5rem;
|
|
}
|
|
|
|
.wi-section__title::before {
|
|
content: '';
|
|
display: inline-block;
|
|
width: 8px;
|
|
height: 8px;
|
|
border-radius: 50%;
|
|
background: var(--accent);
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.wi-pinned {
|
|
display: grid;
|
|
grid-template-columns: repeat(2, 1fr);
|
|
gap: var(--space-lg);
|
|
}
|
|
|
|
.wi-pinned__card {
|
|
display: flex;
|
|
flex-direction: column;
|
|
border-radius: 16px;
|
|
overflow: hidden;
|
|
background: var(--bg-raised);
|
|
box-shadow: var(--shadow-sm);
|
|
text-decoration: none;
|
|
color: inherit;
|
|
transition:
|
|
transform var(--duration-normal) var(--ease-out-expo),
|
|
box-shadow var(--duration-normal) var(--ease-out-expo);
|
|
}
|
|
|
|
.wi-pinned__card:hover {
|
|
transform: translateY(-4px);
|
|
box-shadow: var(--shadow-lg);
|
|
}
|
|
|
|
.wi-pinned__card:first-child:nth-last-child(1) {
|
|
grid-column: 1 / -1;
|
|
}
|
|
|
|
.wi-pinned__card:first-child:nth-last-child(1) .wi-pinned__cover {
|
|
aspect-ratio: 21 / 9;
|
|
}
|
|
|
|
.wi-pinned__card:first-child:nth-last-child(1) .wi-pinned__title {
|
|
font-size: var(--text-2xl);
|
|
}
|
|
|
|
.wi-pinned__cover {
|
|
aspect-ratio: 16 / 10;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.wi-pinned__image {
|
|
width: 100%;
|
|
height: 100%;
|
|
object-fit: cover;
|
|
transition: transform var(--duration-normal) var(--ease-out-expo);
|
|
border-radius: 0;
|
|
}
|
|
|
|
.wi-pinned__card:hover .wi-pinned__image {
|
|
transform: scale(1.03);
|
|
}
|
|
|
|
.wi-pinned__body {
|
|
padding: var(--space-lg);
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: var(--space-sm);
|
|
flex: 1;
|
|
}
|
|
|
|
.wi-pinned__meta {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: var(--space-sm);
|
|
flex-wrap: wrap;
|
|
}
|
|
|
|
.wi-pinned__category {
|
|
font-size: var(--text-xs);
|
|
color: var(--accent);
|
|
letter-spacing: var(--tracking-wide);
|
|
text-transform: uppercase;
|
|
font-weight: 600;
|
|
}
|
|
|
|
.wi-pinned__category::after {
|
|
content: '·';
|
|
margin-left: var(--space-sm);
|
|
color: var(--ink-3);
|
|
}
|
|
|
|
.wi-pinned__date {
|
|
font-size: var(--text-xs);
|
|
color: var(--ink-3);
|
|
letter-spacing: var(--tracking-wide);
|
|
text-transform: uppercase;
|
|
}
|
|
|
|
.wi-pinned__title {
|
|
font-family: var(--font-sans);
|
|
font-size: var(--text-xl);
|
|
font-weight: 700;
|
|
color: var(--ink);
|
|
line-height: var(--leading-tight);
|
|
letter-spacing: var(--tracking-tight);
|
|
transition: color var(--duration-fast) var(--ease-out-quart);
|
|
}
|
|
|
|
.wi-pinned__card:hover .wi-pinned__title {
|
|
color: var(--accent);
|
|
}
|
|
|
|
.wi-pinned__excerpt {
|
|
font-size: var(--text-sm);
|
|
color: var(--ink-2);
|
|
line-height: var(--leading-relaxed);
|
|
display: -webkit-box;
|
|
-webkit-line-clamp: 3;
|
|
-webkit-box-orient: vertical;
|
|
overflow: hidden;
|
|
}
|
|
|
|
@media (max-width: 768px) {
|
|
.wi-pinned {
|
|
grid-template-columns: 1fr;
|
|
}
|
|
|
|
.wi-pinned__card:first-child:nth-last-child(1) .wi-pinned__cover {
|
|
aspect-ratio: 16 / 9;
|
|
}
|
|
|
|
.wi-pinned__card:first-child:nth-last-child(1) .wi-pinned__title {
|
|
font-size: var(--text-xl);
|
|
}
|
|
}
|
|
|
|
.wi-home-posts {
|
|
padding-block: 2rem;
|
|
background: var(--bg);
|
|
}
|
|
|
|
.wi-flow {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: var(--space-lg);
|
|
}
|
|
|
|
.wi-flow__card {
|
|
display: flex;
|
|
flex-direction: row;
|
|
align-items: stretch;
|
|
border-radius: 16px;
|
|
overflow: hidden;
|
|
background: var(--bg-raised);
|
|
box-shadow: var(--shadow-sm);
|
|
color: inherit;
|
|
position: relative;
|
|
transition:
|
|
transform var(--duration-normal) var(--ease-out-expo),
|
|
box-shadow var(--duration-normal) var(--ease-out-expo);
|
|
}
|
|
|
|
.wi-flow__stretched-link {
|
|
position: absolute;
|
|
inset: 0;
|
|
z-index: 1;
|
|
}
|
|
|
|
.wi-flow__card:hover {
|
|
transform: translateY(-4px);
|
|
box-shadow: var(--shadow-lg);
|
|
}
|
|
|
|
.wi-flow__card--with-cover .wi-flow__body {
|
|
flex: 1;
|
|
min-width: 0;
|
|
}
|
|
|
|
.wi-flow__cover {
|
|
width: 240px;
|
|
flex-shrink: 0;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.wi-flow__image {
|
|
width: 100%;
|
|
height: 100%;
|
|
display: block;
|
|
object-fit: cover;
|
|
transition: transform var(--duration-normal) var(--ease-out-expo);
|
|
border-radius: 0;
|
|
}
|
|
|
|
.wi-flow__card:hover .wi-flow__image {
|
|
transform: scale(1.03);
|
|
}
|
|
|
|
.wi-flow__body {
|
|
padding: var(--space-lg);
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: var(--space-sm);
|
|
flex: 1;
|
|
justify-content: center;
|
|
}
|
|
|
|
.wi-flow__meta {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: var(--space-sm);
|
|
flex-wrap: wrap;
|
|
}
|
|
|
|
.wi-flow__categories {
|
|
font-size: var(--text-xs);
|
|
letter-spacing: var(--tracking-wide);
|
|
font-weight: 600;
|
|
}
|
|
|
|
.wi-flow__categories::after {
|
|
content: '·';
|
|
margin-left: var(--space-sm);
|
|
margin-right: var(--space-sm);
|
|
color: var(--ink-3);
|
|
}
|
|
|
|
.wi-flow__category-link {
|
|
color: var(--accent);
|
|
text-decoration: none;
|
|
position: relative;
|
|
z-index: 2;
|
|
transition: color var(--duration-fast) var(--ease-out-quart);
|
|
}
|
|
|
|
.wi-flow__category-link:hover {
|
|
color: var(--accent-hover);
|
|
text-decoration: underline;
|
|
}
|
|
|
|
.wi-flow__category-link + .wi-flow__category-link::before {
|
|
content: '、';
|
|
color: var(--accent);
|
|
}
|
|
|
|
.wi-flow__date {
|
|
font-size: var(--text-xs);
|
|
color: var(--ink-3);
|
|
letter-spacing: var(--tracking-wide);
|
|
text-transform: uppercase;
|
|
}
|
|
|
|
.wi-flow__title-link {
|
|
text-decoration: none;
|
|
position: relative;
|
|
z-index: 2;
|
|
}
|
|
|
|
.wi-flow__title {
|
|
font-family: var(--font-sans);
|
|
font-size: var(--text-lg);
|
|
font-weight: 700;
|
|
color: var(--ink);
|
|
line-height: var(--leading-tight);
|
|
letter-spacing: var(--tracking-tight);
|
|
transition: color var(--duration-fast) var(--ease-out-quart);
|
|
}
|
|
|
|
.wi-flow__card:hover .wi-flow__title {
|
|
color: var(--accent);
|
|
}
|
|
|
|
.wi-flow__excerpt {
|
|
font-size: var(--text-sm);
|
|
color: var(--ink-2);
|
|
line-height: var(--leading-relaxed);
|
|
display: -webkit-box;
|
|
-webkit-box-orient: vertical;
|
|
overflow: hidden;
|
|
margin-block-end: 0;
|
|
}
|
|
|
|
.wi-flow__footer {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
gap: 0.5rem;
|
|
flex-wrap: wrap;
|
|
margin-top: auto;
|
|
padding-top: var(--space-xs);
|
|
}
|
|
|
|
.wi-flow__tags {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 4px;
|
|
}
|
|
|
|
.wi-flow__tag-link {
|
|
font-size: 11px;
|
|
color: var(--ink-3);
|
|
text-decoration: none;
|
|
padding: 2px 8px;
|
|
border-radius: 4px;
|
|
background: var(--bg);
|
|
border: 1px solid var(--rule);
|
|
position: relative;
|
|
z-index: 2;
|
|
transition: color var(--duration-fast) var(--ease-out-quart), border-color var(--duration-fast) var(--ease-out-quart), background var(--duration-fast) var(--ease-out-quart);
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.wi-flow__tag-link:hover {
|
|
color: var(--accent);
|
|
border-color: var(--accent);
|
|
background: color-mix(in srgb, var(--accent) 6%, var(--bg));
|
|
}
|
|
|
|
.wi-flow__stats {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.5rem;
|
|
font-size: var(--text-xs);
|
|
color: var(--ink-3);
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.wi-flow__stat + .wi-flow__stat::before {
|
|
content: '·';
|
|
margin-right: 0.5rem;
|
|
color: var(--ink-3);
|
|
}
|
|
|
|
.wi-pagination {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
gap: 1rem;
|
|
padding-top: var(--space-xl);
|
|
margin-top: var(--space-xl);
|
|
border-top: 1px solid var(--rule);
|
|
font-size: var(--text-sm);
|
|
}
|
|
|
|
.wi-pagination__prev,
|
|
.wi-pagination__next {
|
|
color: var(--ink-2);
|
|
text-decoration: none;
|
|
transition: color var(--duration-fast) var(--ease-out-quart);
|
|
}
|
|
|
|
.wi-pagination__prev:hover,
|
|
.wi-pagination__next:hover {
|
|
color: var(--accent);
|
|
}
|
|
|
|
.wi-pagination__info {
|
|
color: var(--ink-3);
|
|
}
|
|
|
|
.wi-infinite-scroll__loader {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
gap: var(--space-sm);
|
|
padding: var(--space-xl) 0;
|
|
color: var(--ink-3);
|
|
font-size: var(--text-sm);
|
|
}
|
|
|
|
.wi-infinite-scroll__spinner {
|
|
width: 18px;
|
|
height: 18px;
|
|
border: 2px solid var(--rule);
|
|
border-top-color: var(--accent);
|
|
border-radius: 50%;
|
|
animation: wi-spin 0.6s linear infinite;
|
|
}
|
|
|
|
@keyframes wi-spin {
|
|
to {
|
|
transform: rotate(360deg);
|
|
}
|
|
}
|
|
|
|
.wi-infinite-scroll__end {
|
|
text-align: center;
|
|
padding: var(--space-xl) 0;
|
|
color: var(--ink-3);
|
|
font-size: var(--text-sm);
|
|
}
|
|
|
|
@media (max-width: 640px) {
|
|
.wi-flow__card {
|
|
flex-direction: column;
|
|
}
|
|
|
|
.wi-flow__cover {
|
|
width: 100%;
|
|
aspect-ratio: 16 / 9;
|
|
}
|
|
|
|
.wi-flow__footer {
|
|
flex-direction: column;
|
|
align-items: flex-start;
|
|
gap: 0.4rem;
|
|
}
|
|
}
|
|
</style>
|