gengxin
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,26 @@
|
||||
export type ArticleCategory = "班级记忆" | "毕业时刻" | "节日来信" | "考试升学" | "校园通知";
|
||||
|
||||
export interface WechatArticle {
|
||||
title: string;
|
||||
date: string;
|
||||
displayDate: string;
|
||||
sourceUrl: string;
|
||||
cover: string;
|
||||
excerpt: string;
|
||||
category: ArticleCategory;
|
||||
fileName: string;
|
||||
}
|
||||
|
||||
import articleData from "./articles.generated.json";
|
||||
|
||||
export const articles = articleData as WechatArticle[];
|
||||
|
||||
export const articleCategories: ArticleCategory[] = [
|
||||
"班级记忆",
|
||||
"毕业时刻",
|
||||
"节日来信",
|
||||
"考试升学",
|
||||
"校园通知"
|
||||
];
|
||||
|
||||
export const featuredArticles = articles.slice(0, 3);
|
||||
@@ -1,10 +1,11 @@
|
||||
import type { PhotoTopic } from "../photo-types";
|
||||
import { wechatPhoto } from "./wechat-photo";
|
||||
|
||||
export const candidTopic: PhotoTopic = {
|
||||
slug: "candid",
|
||||
title: "没被摆拍的瞬间",
|
||||
text: "走廊、食堂、晚霞和笑场。真正会让人停下来的,常常是不太整齐的照片。",
|
||||
cover: "",
|
||||
cover: "/assets/wechat-archive/wechat-499.webp",
|
||||
photos: [
|
||||
{
|
||||
title: "走廊偶遇",
|
||||
@@ -25,6 +26,8 @@ export const candidTopic: PhotoTopic = {
|
||||
title: "笑场",
|
||||
caption: "最不端正的照片,往往最像我们。",
|
||||
image: ""
|
||||
}
|
||||
},
|
||||
wechatPhoto(490, "恶魔角合照", "没有正式站姿,反而最像我们真实的青春。"),
|
||||
wechatPhoto(499, "草地上的伙伴", "坐下来聊聊天,晚风把时间吹得很慢。")
|
||||
]
|
||||
};
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import type { PhotoTopic } from "../photo-types";
|
||||
import { wechatPhoto } from "./wechat-photo";
|
||||
|
||||
export const classroomTopic: PhotoTopic = {
|
||||
slug: "classroom",
|
||||
title: "教室日常",
|
||||
text: "黑板、课桌、窗边、试卷,还有那些写在草稿纸边角的小情绪。",
|
||||
cover: "",
|
||||
cover: "/assets/wechat-archive/wechat-373.webp",
|
||||
photos: [
|
||||
{
|
||||
title: "窗边",
|
||||
@@ -30,6 +31,15 @@ export const classroomTopic: PhotoTopic = {
|
||||
title: "询问老师",
|
||||
caption: "课后向老师请教问题",
|
||||
image: "https://pic.biss.click/image/95c03bd4-d0d3-4c38-9855-3342fd582080.jpg"
|
||||
}
|
||||
},
|
||||
wechatPhoto(159, "清晨校园", "天还没完全亮,教学楼已经开始新的一天。"),
|
||||
wechatPhoto(160, "空走廊", "下课铃没有响起时,走廊安静得像一张旧照片。"),
|
||||
wechatPhoto(161, "教室一角", "寒冷的早晨、厚厚的毯子和靠窗的位置。"),
|
||||
wechatPhoto(162, "雪天课间", "楼下有人追着雪跑,楼上的人隔窗看热闹。"),
|
||||
wechatPhoto(193, "黑板前", "老师写下的每一行,都曾是我们共同的日常。"),
|
||||
wechatPhoto(196, "忙碌的教室", "有人整理桌面,有人继续写题,生活没有暂停。"),
|
||||
wechatPhoto(197, "围在桌边", "讲一道题的时间,也能成为多年后的回忆。"),
|
||||
wechatPhoto(373, "夕阳自习", "光从窗边落进来,照亮高中的普通一天。"),
|
||||
wechatPhoto(375, "教室合照", "镜头前挤成一团,是班级最真实的样子。")
|
||||
]
|
||||
};
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import type { PhotoTopic } from "../photo-types";
|
||||
import { wechatPhoto } from "./wechat-photo";
|
||||
|
||||
export const eventsTopic: PhotoTopic = {
|
||||
slug: "events",
|
||||
title: "班级活动",
|
||||
text: "运动会、晚会、春游、比赛,所有离开课桌之后还在一起发光的时刻。",
|
||||
cover: "",
|
||||
cover: "/assets/wechat-archive/wechat-455.webp",
|
||||
photos: [
|
||||
{
|
||||
title: "高一下学期表彰大会",
|
||||
@@ -20,6 +21,21 @@ export const eventsTopic: PhotoTopic = {
|
||||
title: "百日誓师大会",
|
||||
caption: "高三的第一次全体活动,大家都很随意地在听讲,虽然最后还是没能坚持到最后。",
|
||||
image: "https://pic.biss.click/image/45bfbe79-bd7b-40f3-9670-1b34cc0957b2.png"
|
||||
}
|
||||
},
|
||||
wechatPhoto(117, "考前舞台", "紧张的日子里,也需要一次大声唱出来。"),
|
||||
wechatPhoto(121, "看台上的我们", "一片红色校服,聚成高三最后的集体活动。"),
|
||||
wechatPhoto(129, "操场热身", "阳光很好,口号和动作都比平时更有力量。"),
|
||||
wechatPhoto(132, "坐在一起", "台上发生什么已经模糊,身边的人还记得。"),
|
||||
wechatPhoto(176, "元旦歌咏", "整齐站上舞台,是青春里难得的郑重。"),
|
||||
wechatPhoto(178, "领奖时刻", "证书会褪色,但被认可的那一刻不会。"),
|
||||
wechatPhoto(180, "操场挑战", "跨过栏架,也跨过一个个觉得做不到的瞬间。"),
|
||||
wechatPhoto(181, "百日倒计时", "数字揭开的那一刻,高考忽然变得很近。"),
|
||||
wechatPhoto(368, "军训合影", "刚认识不久的我们,第一次以班级的名字站在一起。"),
|
||||
wechatPhoto(370, "方阵出发", "步子未必完全整齐,方向却是一致的。"),
|
||||
wechatPhoto(446, "远足路上的笑脸", "路很长,但和同学一起走就没有那么累。"),
|
||||
wechatPhoto(455, "山脚合影", "走过很远的路,当然要认真留下一张合照。"),
|
||||
wechatPhoto(459, "班旗与伙伴", "把班级的名字举进镜头,也举进三年的记忆。"),
|
||||
wechatPhoto(470, "操场晚会", "天黑之后,灯光和欢呼把操场变成了舞台。"),
|
||||
wechatPhoto(480, "荧光人群", "挥动的光棒让普通夜晚有了节日的颜色。")
|
||||
]
|
||||
};
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import type { PhotoTopic } from "../photo-types";
|
||||
import { wechatPhoto } from "./wechat-photo";
|
||||
|
||||
export const graduationDayTopic: PhotoTopic = {
|
||||
slug: "graduation-day",
|
||||
title: "毕业那天",
|
||||
text: "合照、签名、花束、校门和没说完的话,都放在这个专题里。",
|
||||
cover: "https://pic.biss.click/image/c1528af5-62da-47c3-8309-cd809f779288.jpg",
|
||||
cover: "/assets/wechat-archive/wechat-145.webp",
|
||||
photos: [
|
||||
{
|
||||
title: "最后一张合照",
|
||||
@@ -30,6 +31,25 @@ export const graduationDayTopic: PhotoTopic = {
|
||||
title: "散场之前",
|
||||
caption: "那一刻大家都在笑,但心里都知道要分别了。",
|
||||
image: "https://pic.biss.click/image/f8d180c1-4827-4bfd-9550-4bfad4b97640.jpg"
|
||||
}
|
||||
},
|
||||
wechatPhoto(145, "壮行合影", "红色班服、彩色气球,和出发前最完整的一次站在一起。"),
|
||||
wechatPhoto(146, "气球升起之前", "所有人挤进镜头,等一个一起松手的瞬间。"),
|
||||
wechatPhoto(150, "飞向夏天", "气球越过教学楼,属于高中的倒计时也到了最后。"),
|
||||
wechatPhoto(151, "人群里的告别", "欢呼、拥抱和一句句被现场声音盖住的话。"),
|
||||
wechatPhoto(152, "穿过祝福", "从熟悉的人群中走过,前面就是新的路。"),
|
||||
wechatPhoto(153, "鲜花与笑脸", "最后一程依然有人在身旁鼓掌。"),
|
||||
wechatPhoto(81, "毕业典礼合影", "红色幕布前,老师和同学一起留下毕业的证据。"),
|
||||
wechatPhoto(84, "典礼现场", "从看台望向舞台,礼堂装下了整届人的夏天。"),
|
||||
wechatPhoto(85, "把花送给老师", "镜头拼在一起,也拼出那天的感谢。"),
|
||||
wechatPhoto(88, "走过红毯", "熟悉的老师站在两侧,目送这一届学生离开。"),
|
||||
wechatPhoto(89, "并肩入场", "毕业不是一个人的终点,是一群人的共同章节。"),
|
||||
wechatPhoto(382, "最后一天的教室", "书本还摊在桌上,离别已经悄悄开始。"),
|
||||
wechatPhoto(387, "签在衣服上", "名字、祝福和画得歪歪扭扭的小图案。"),
|
||||
wechatPhoto(388, "气球装点的教室", "最后一次把教室布置得像节日。"),
|
||||
wechatPhoto(391, "散场之后", "桌椅、书本和气球,保留着刚刚发生过的热闹。"),
|
||||
wechatPhoto(396, "捧着花出发", "校门口的人群里,每个人都有自己的告别方式。"),
|
||||
wechatPhoto(405, "校车旁的合照", "气球还在手里,下一段旅程已经在等候。"),
|
||||
wechatPhoto(408, "放飞之前", "大家抬头看向同一个方向。"),
|
||||
wechatPhoto(411, "毕业气球", "彩色气球升空,校门口只剩挥手的人群。")
|
||||
]
|
||||
};
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
import type { PhotoItem } from "../photo-types";
|
||||
|
||||
export const wechatPhoto = (id: number, title: string, caption: string): PhotoItem => ({
|
||||
title,
|
||||
caption,
|
||||
image: `/assets/wechat-archive/wechat-${String(id).padStart(3, "0")}.webp`
|
||||
});
|
||||
@@ -31,6 +31,7 @@ export const navItems = [
|
||||
{ label: "首页", href: "/" },
|
||||
{ label: "三年时间线", href: "/timeline/" },
|
||||
{ label: "照片墙", href: "/gallery/" },
|
||||
{ label: "青春刊物", href: "/articles/" },
|
||||
{ label: "如今的我们", href: "/people/" },
|
||||
{ label: "综合试卷", href: "/exam/" },
|
||||
{ label: "留言墙", href: "/messages/" }
|
||||
|
||||
@@ -25,6 +25,7 @@ const buildTime = new Intl.DateTimeFormat("zh-CN", {
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="referrer" content="no-referrer" />
|
||||
<title>{title}</title>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
---
|
||||
import BaseLayout from "../layouts/BaseLayout.astro";
|
||||
import { articleCategories, articles } from "../data/articles";
|
||||
|
||||
const categoryCounts = Object.fromEntries(
|
||||
articleCategories.map((category) => [category, articles.filter((article) => article.category === category).length])
|
||||
);
|
||||
---
|
||||
|
||||
<BaseLayout title="青春刊物 · 2024届612班">
|
||||
<main class="page-main publication-page">
|
||||
<section class="page-hero publication-hero">
|
||||
<div class="section-inner">
|
||||
<a class="back-link" href="/">返回首页</a>
|
||||
<p class="eyebrow">CLASS PUBLICATION · {articles.length} 篇</p>
|
||||
<h1>青春刊物</h1>
|
||||
<p>这里收录公众号里的班级日志、校园时刻与毕业后的来信。原文仍属于公众号,这里为它们做一份更容易寻找的目录。</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="article-archive">
|
||||
<div class="section-inner">
|
||||
<div class="archive-tools" aria-label="文章筛选工具">
|
||||
<label class="article-search">
|
||||
<i class="fa-solid fa-magnifying-glass" aria-hidden="true"></i>
|
||||
<span class="sr-only">搜索文章</span>
|
||||
<input id="article-search" type="search" placeholder="搜索标题或摘要…" autocomplete="off" />
|
||||
</label>
|
||||
<div class="category-filters" role="group" aria-label="按分类筛选">
|
||||
<button class="is-active" type="button" data-category="全部">全部 <span>{articles.length}</span></button>
|
||||
{
|
||||
articleCategories.map((category) => (
|
||||
<button type="button" data-category={category}>{category} <span>{categoryCounts[category]}</span></button>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p class="archive-status" aria-live="polite">正在展示 <strong>{articles.length}</strong> 篇文章</p>
|
||||
|
||||
<div class="article-list" id="article-list">
|
||||
{
|
||||
articles.map((article, index) => (
|
||||
<a
|
||||
class="archive-card"
|
||||
href={article.sourceUrl}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
data-category={article.category}
|
||||
data-search={`${article.title} ${article.excerpt}`.toLocaleLowerCase("zh-CN")}
|
||||
>
|
||||
<div
|
||||
class="archive-cover"
|
||||
style={article.cover ? `--article-cover: url("${article.cover}")` : ""}
|
||||
>
|
||||
{!article.cover && <span>{String(index + 1).padStart(3, "0")}</span>}
|
||||
</div>
|
||||
<div class="archive-copy">
|
||||
<div class="archive-meta">
|
||||
<span>{article.category}</span>
|
||||
<time datetime={article.date}>{article.displayDate}</time>
|
||||
</div>
|
||||
<h2>{article.title}</h2>
|
||||
<p>{article.excerpt}</p>
|
||||
<span class="archive-read">公众号原文 <i class="fa-solid fa-arrow-up-right-from-square"></i></span>
|
||||
</div>
|
||||
</a>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
|
||||
<div class="archive-empty" hidden>
|
||||
<span>没有找到相符的文章</span>
|
||||
<p>换一个关键词,或者查看其他分类吧。</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<script>
|
||||
const searchInput = document.querySelector<HTMLInputElement>("#article-search");
|
||||
const filterButtons = [...document.querySelectorAll<HTMLButtonElement>("[data-category]")];
|
||||
const cards = [...document.querySelectorAll<HTMLElement>(".archive-card")];
|
||||
const status = document.querySelector<HTMLElement>(".archive-status");
|
||||
const empty = document.querySelector<HTMLElement>(".archive-empty");
|
||||
let activeCategory = "全部";
|
||||
|
||||
const updateResults = () => {
|
||||
const query = searchInput?.value.trim().toLocaleLowerCase("zh-CN") ?? "";
|
||||
let visibleCount = 0;
|
||||
|
||||
cards.forEach((card) => {
|
||||
const categoryMatches = activeCategory === "全部" || card.dataset.category === activeCategory;
|
||||
const searchMatches = !query || card.dataset.search?.includes(query);
|
||||
const isVisible = Boolean(categoryMatches && searchMatches);
|
||||
card.hidden = !isVisible;
|
||||
if (isVisible) visibleCount += 1;
|
||||
});
|
||||
|
||||
if (status) status.innerHTML = `正在展示 <strong>${visibleCount}</strong> 篇文章`;
|
||||
if (empty) empty.hidden = visibleCount !== 0;
|
||||
};
|
||||
|
||||
filterButtons.forEach((button) => {
|
||||
button.addEventListener("click", () => {
|
||||
activeCategory = button.dataset.category ?? "全部";
|
||||
filterButtons.forEach((item) => item.classList.toggle("is-active", item === button));
|
||||
updateResults();
|
||||
});
|
||||
});
|
||||
|
||||
searchInput?.addEventListener("input", updateResults);
|
||||
</script>
|
||||
</BaseLayout>
|
||||
@@ -5,6 +5,7 @@ import { featuredMessage, messages, messagesIntro } from "../data/messages";
|
||||
import { people, peopleIntro } from "../data/people";
|
||||
import { site, stats } from "../data/site";
|
||||
import { timeline, timelineIntro } from "../data/timeline";
|
||||
import { articles, featuredArticles } from "../data/articles";
|
||||
|
||||
const previewTimeline = timeline.slice(0, 4);
|
||||
const previewPhotoTopics = photoTopics.slice(0, 4);
|
||||
@@ -136,6 +137,48 @@ const previewPeople = people.slice(0, 6);
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="articles" class="publication-band">
|
||||
<div class="section-inner">
|
||||
<div class="section-title publication-title">
|
||||
<div>
|
||||
<p class="eyebrow">FROM WECHAT · 青春刊物</p>
|
||||
<h2>散落在公众号里的故事,也该被好好收藏</h2>
|
||||
</div>
|
||||
<p>
|
||||
已整理 {articles.length} 篇公众号文章。从班级日志、毕业典礼到节日来信,按下时间的书签,重新读一遍当时的我们。
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="featured-articles">
|
||||
{
|
||||
featuredArticles.map((article, index) => (
|
||||
<a
|
||||
class:list={["article-card", index === 0 && "article-card-featured"]}
|
||||
href={article.sourceUrl}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
<div
|
||||
class="article-cover"
|
||||
style={article.cover ? `--article-cover: url("${article.cover}")` : ""}
|
||||
>
|
||||
<span>{article.category}</span>
|
||||
</div>
|
||||
<div class="article-copy">
|
||||
<time datetime={article.date}>{article.displayDate}</time>
|
||||
<h3>{article.title}</h3>
|
||||
<p>{article.excerpt}</p>
|
||||
<span class="read-more">阅读原文 <i class="fa-solid fa-arrow-up-right-from-square"></i></span>
|
||||
</div>
|
||||
</a>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
|
||||
<a class="section-link publication-link" href="/articles/">翻阅全部 {articles.length} 篇</a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="messages" class="gallery-band">
|
||||
<div class="section-inner">
|
||||
<div class="section-title">
|
||||
|
||||
@@ -1672,6 +1672,371 @@ h2 {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
/* WeChat publication archive */
|
||||
.publication-band {
|
||||
color: #fffdf7;
|
||||
background:
|
||||
radial-gradient(circle at 90% 10%, rgba(232, 168, 76, 0.18), transparent 28%),
|
||||
linear-gradient(145deg, #172522, #294a40);
|
||||
}
|
||||
|
||||
.publication-title {
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
.publication-title .eyebrow {
|
||||
margin: 0 0 14px;
|
||||
}
|
||||
|
||||
.publication-title > p {
|
||||
color: rgba(255, 253, 247, 0.7);
|
||||
}
|
||||
|
||||
.featured-articles {
|
||||
display: grid;
|
||||
grid-template-columns: 1.25fr 1fr;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.article-card {
|
||||
min-height: 210px;
|
||||
display: grid;
|
||||
grid-template-columns: 180px 1fr;
|
||||
overflow: hidden;
|
||||
border: 1px solid rgba(255, 253, 247, 0.15);
|
||||
border-radius: 10px;
|
||||
background: rgba(255, 253, 247, 0.08);
|
||||
transition: transform 180ms ease, background 180ms ease;
|
||||
}
|
||||
|
||||
.article-card:hover {
|
||||
transform: translateY(-4px);
|
||||
background: rgba(255, 253, 247, 0.12);
|
||||
}
|
||||
|
||||
.article-card-featured {
|
||||
grid-row: span 2;
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.article-cover,
|
||||
.archive-cover {
|
||||
position: relative;
|
||||
min-height: 170px;
|
||||
background:
|
||||
linear-gradient(0deg, rgba(20, 32, 29, 0.48), rgba(20, 32, 29, 0.06)),
|
||||
var(--article-cover, linear-gradient(135deg, #376d5a, #e8a84c));
|
||||
background-position: center;
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
.article-card-featured .article-cover {
|
||||
min-height: 300px;
|
||||
}
|
||||
|
||||
.article-cover > span {
|
||||
position: absolute;
|
||||
top: 16px;
|
||||
left: 16px;
|
||||
padding: 5px 10px;
|
||||
border-radius: 999px;
|
||||
background: rgba(23, 37, 34, 0.72);
|
||||
font-size: 12px;
|
||||
font-weight: 800;
|
||||
backdrop-filter: blur(8px);
|
||||
}
|
||||
|
||||
.article-copy {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
padding: 22px;
|
||||
}
|
||||
|
||||
.article-copy time {
|
||||
color: #f3cf8b;
|
||||
font-size: 12px;
|
||||
font-weight: 800;
|
||||
letter-spacing: 0.08em;
|
||||
}
|
||||
|
||||
.article-copy h3 {
|
||||
margin: 8px 0 10px;
|
||||
font-size: 21px;
|
||||
line-height: 1.35;
|
||||
}
|
||||
|
||||
.article-card-featured .article-copy h3 {
|
||||
font-size: clamp(24px, 3vw, 34px);
|
||||
}
|
||||
|
||||
.article-copy p {
|
||||
display: -webkit-box;
|
||||
overflow: hidden;
|
||||
margin: 0;
|
||||
color: rgba(255, 253, 247, 0.68);
|
||||
font-size: 14px;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
}
|
||||
|
||||
.read-more {
|
||||
margin-top: auto;
|
||||
padding-top: 18px;
|
||||
color: #f3cf8b;
|
||||
font-size: 13px;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.read-more i,
|
||||
.archive-read i {
|
||||
margin-left: 5px;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.publication-link {
|
||||
border-color: rgba(255, 253, 247, 0.2);
|
||||
color: #fffdf7;
|
||||
background: rgba(255, 253, 247, 0.08);
|
||||
}
|
||||
|
||||
.publication-hero {
|
||||
background:
|
||||
radial-gradient(circle at 82% 30%, rgba(232, 168, 76, 0.28), transparent 25%),
|
||||
linear-gradient(135deg, #172522, #376d5a);
|
||||
}
|
||||
|
||||
.article-archive {
|
||||
padding-top: clamp(36px, 5vw, 64px);
|
||||
}
|
||||
|
||||
.archive-tools {
|
||||
position: sticky;
|
||||
z-index: 5;
|
||||
top: 16px;
|
||||
display: grid;
|
||||
gap: 14px;
|
||||
margin-bottom: 22px;
|
||||
padding: 16px;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 12px;
|
||||
background: rgba(255, 253, 247, 0.92);
|
||||
box-shadow: 0 14px 40px rgba(39, 55, 52, 0.1);
|
||||
backdrop-filter: blur(16px);
|
||||
}
|
||||
|
||||
.article-search {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
min-height: 48px;
|
||||
padding: 0 16px;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 8px;
|
||||
background: #fff;
|
||||
color: var(--muted);
|
||||
}
|
||||
|
||||
.article-search:focus-within {
|
||||
border-color: var(--green);
|
||||
box-shadow: 0 0 0 3px rgba(55, 109, 90, 0.12);
|
||||
}
|
||||
|
||||
.article-search input {
|
||||
width: 100%;
|
||||
border: 0;
|
||||
outline: 0;
|
||||
background: transparent;
|
||||
color: var(--ink);
|
||||
font: inherit;
|
||||
}
|
||||
|
||||
.category-filters {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
overflow-x: auto;
|
||||
padding-bottom: 2px;
|
||||
}
|
||||
|
||||
.category-filters button {
|
||||
flex: 0 0 auto;
|
||||
min-height: 36px;
|
||||
padding: 7px 12px;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 999px;
|
||||
background: #fff;
|
||||
color: var(--muted);
|
||||
font: inherit;
|
||||
font-size: 13px;
|
||||
font-weight: 700;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.category-filters button span {
|
||||
margin-left: 4px;
|
||||
opacity: 0.65;
|
||||
}
|
||||
|
||||
.category-filters button.is-active {
|
||||
border-color: var(--green);
|
||||
background: var(--green);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.archive-status {
|
||||
margin: 0 0 18px;
|
||||
color: var(--muted);
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.article-list {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.archive-card {
|
||||
min-height: 220px;
|
||||
display: grid;
|
||||
grid-template-columns: 180px minmax(0, 1fr);
|
||||
overflow: hidden;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 10px;
|
||||
background: #fff;
|
||||
box-shadow: 0 8px 28px rgba(39, 55, 52, 0.06);
|
||||
transition: transform 180ms ease, border-color 180ms ease, box-shadow 180ms ease;
|
||||
}
|
||||
|
||||
.archive-card:hover {
|
||||
transform: translateY(-3px);
|
||||
border-color: rgba(55, 109, 90, 0.34);
|
||||
box-shadow: 0 16px 38px rgba(39, 55, 52, 0.12);
|
||||
}
|
||||
|
||||
.archive-card[hidden] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.archive-cover {
|
||||
display: grid;
|
||||
place-items: center;
|
||||
}
|
||||
|
||||
.archive-cover > span {
|
||||
color: rgba(255, 255, 255, 0.82);
|
||||
font-size: 30px;
|
||||
font-weight: 900;
|
||||
letter-spacing: 0.1em;
|
||||
}
|
||||
|
||||
.archive-copy {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
min-width: 0;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.archive-meta {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 10px;
|
||||
color: var(--muted);
|
||||
font-size: 12px;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.archive-meta span {
|
||||
color: var(--green);
|
||||
}
|
||||
|
||||
.archive-copy h2 {
|
||||
display: -webkit-box;
|
||||
overflow: hidden;
|
||||
margin: 10px 0 8px;
|
||||
font-size: 19px;
|
||||
line-height: 1.35;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
}
|
||||
|
||||
.archive-copy p {
|
||||
display: -webkit-box;
|
||||
overflow: hidden;
|
||||
margin: 0;
|
||||
color: var(--muted);
|
||||
font-size: 13px;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
}
|
||||
|
||||
.archive-read {
|
||||
margin-top: auto;
|
||||
padding-top: 14px;
|
||||
color: var(--green);
|
||||
font-size: 12px;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.archive-empty {
|
||||
padding: 80px 20px;
|
||||
text-align: center;
|
||||
color: var(--muted);
|
||||
}
|
||||
|
||||
.archive-empty span {
|
||||
color: var(--ink);
|
||||
font-size: 22px;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.archive-empty p {
|
||||
margin: 8px 0 0;
|
||||
}
|
||||
|
||||
.sr-only {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
overflow: hidden;
|
||||
clip: rect(0, 0, 0, 0);
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
@media (max-width: 920px) {
|
||||
.featured-articles,
|
||||
.article-list {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.article-card-featured {
|
||||
grid-row: auto;
|
||||
}
|
||||
|
||||
.article-card-featured .article-cover {
|
||||
min-height: 260px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 620px) {
|
||||
.article-card,
|
||||
.article-card-featured,
|
||||
.archive-card {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.article-card .article-cover,
|
||||
.article-card-featured .article-cover,
|
||||
.archive-cover {
|
||||
min-height: 210px;
|
||||
}
|
||||
|
||||
.archive-tools {
|
||||
top: 8px;
|
||||
margin-inline: -8px;
|
||||
}
|
||||
}
|
||||
|
||||
.site-footer p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user