往年今日
This commit is contained in:
@@ -0,0 +1,133 @@
|
|||||||
|
<section class="on-this-day-band" aria-labelledby="on-this-day-title">
|
||||||
|
<div class="section-inner on-this-day-shell" data-on-this-day>
|
||||||
|
<div class="memory-date-card" aria-hidden="true">
|
||||||
|
<span data-memory-month>今日</span>
|
||||||
|
<strong data-memory-day>--</strong>
|
||||||
|
<small>北京时间</small>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="on-this-day-content">
|
||||||
|
<div class="on-this-day-heading">
|
||||||
|
<div>
|
||||||
|
<p class="eyebrow">ON THIS DAY · 那年今日</p>
|
||||||
|
<h2 id="on-this-day-title">今天,记忆翻到了这一页</h2>
|
||||||
|
</div>
|
||||||
|
<p data-memory-summary aria-live="polite">正在寻找同月同日的班级记忆……</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="memory-grid" data-memory-grid aria-live="polite" aria-busy="true"></div>
|
||||||
|
|
||||||
|
<div class="memory-empty" data-memory-empty hidden>
|
||||||
|
<span class="memory-empty-mark" aria-hidden="true">✦</span>
|
||||||
|
<div>
|
||||||
|
<h3>这一天还没有被写进纪念册</h3>
|
||||||
|
<p>也许只是故事还没整理好。先从其他日期里随手翻一页吧。</p>
|
||||||
|
<nav class="memory-empty-links" aria-label="浏览其他班级记忆">
|
||||||
|
<a href="/timeline/">班级时间线</a>
|
||||||
|
<a href="/gallery/">照片墙</a>
|
||||||
|
<a href="/articles/">文章归档</a>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<noscript>
|
||||||
|
<p class="memory-noscript">启用 JavaScript 后,这里会根据北京时间自动展示当天的班级记忆。</p>
|
||||||
|
</noscript>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { onThisDayMemories } from "../data/on-this-day";
|
||||||
|
|
||||||
|
const root = document.querySelector<HTMLElement>("[data-on-this-day]");
|
||||||
|
|
||||||
|
if (root) {
|
||||||
|
const dateParts = new Intl.DateTimeFormat("zh-CN", {
|
||||||
|
timeZone: "Asia/Shanghai",
|
||||||
|
year: "numeric",
|
||||||
|
month: "numeric",
|
||||||
|
day: "numeric"
|
||||||
|
}).formatToParts(new Date());
|
||||||
|
const dateValues = Object.fromEntries(dateParts.map((part) => [part.type, part.value]));
|
||||||
|
const month = Number(dateValues.month);
|
||||||
|
const day = Number(dateValues.day);
|
||||||
|
const currentYear = Number(dateValues.year);
|
||||||
|
const monthDay = `${String(month).padStart(2, "0")}-${String(day).padStart(2, "0")}`;
|
||||||
|
const matches = onThisDayMemories.filter((memory) => memory.monthDay === monthDay);
|
||||||
|
const visibleMatches = matches.slice(0, 6);
|
||||||
|
|
||||||
|
const monthLabel = root.querySelector<HTMLElement>("[data-memory-month]");
|
||||||
|
const dayLabel = root.querySelector<HTMLElement>("[data-memory-day]");
|
||||||
|
const summary = root.querySelector<HTMLElement>("[data-memory-summary]");
|
||||||
|
const grid = root.querySelector<HTMLElement>("[data-memory-grid]");
|
||||||
|
const empty = root.querySelector<HTMLElement>("[data-memory-empty]");
|
||||||
|
|
||||||
|
if (monthLabel) monthLabel.textContent = `${month}月`;
|
||||||
|
if (dayLabel) dayLabel.textContent = String(day).padStart(2, "0");
|
||||||
|
|
||||||
|
if (summary) {
|
||||||
|
summary.textContent = matches.length
|
||||||
|
? `${month}月${day}日,找到了 ${matches.length} 条跨越不同年份的班级记忆。`
|
||||||
|
: `${month}月${day}日,今天暂时没有同月同日的记录。`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (grid) {
|
||||||
|
const fragment = document.createDocumentFragment();
|
||||||
|
|
||||||
|
visibleMatches.forEach((memory) => {
|
||||||
|
const card = document.createElement("a");
|
||||||
|
card.className = `memory-card memory-card-${memory.kind}`;
|
||||||
|
card.href = memory.href;
|
||||||
|
card.setAttribute("aria-label", `${memory.year}年${memory.kindLabel}:${memory.title}`);
|
||||||
|
if (memory.external) {
|
||||||
|
card.target = "_blank";
|
||||||
|
card.rel = "noreferrer";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (memory.image) {
|
||||||
|
const image = document.createElement("img");
|
||||||
|
image.src = memory.image;
|
||||||
|
image.alt = "";
|
||||||
|
image.loading = "lazy";
|
||||||
|
card.append(image);
|
||||||
|
} else {
|
||||||
|
const visual = document.createElement("span");
|
||||||
|
visual.className = "memory-card-visual";
|
||||||
|
visual.setAttribute("aria-hidden", "true");
|
||||||
|
visual.textContent = "记";
|
||||||
|
card.append(visual);
|
||||||
|
}
|
||||||
|
|
||||||
|
const copy = document.createElement("span");
|
||||||
|
copy.className = "memory-card-copy";
|
||||||
|
|
||||||
|
const meta = document.createElement("span");
|
||||||
|
meta.className = "memory-card-meta";
|
||||||
|
const yearsAgo = currentYear - memory.year;
|
||||||
|
meta.textContent = `${memory.year}年 · ${yearsAgo > 0 ? `${yearsAgo}年前 · ` : ""}${memory.kindLabel}`;
|
||||||
|
|
||||||
|
const title = document.createElement("strong");
|
||||||
|
title.textContent = memory.title;
|
||||||
|
|
||||||
|
const text = document.createElement("span");
|
||||||
|
text.className = "memory-card-text";
|
||||||
|
text.textContent = memory.text;
|
||||||
|
|
||||||
|
const action = document.createElement("span");
|
||||||
|
action.className = "memory-card-action";
|
||||||
|
action.textContent = memory.external ? "阅读旧文章 ↗" : "翻开这段记忆 →";
|
||||||
|
|
||||||
|
copy.append(meta, title, text, action);
|
||||||
|
card.append(copy);
|
||||||
|
fragment.append(card);
|
||||||
|
});
|
||||||
|
|
||||||
|
grid.replaceChildren(fragment);
|
||||||
|
grid.hidden = matches.length === 0;
|
||||||
|
grid.setAttribute("aria-busy", "false");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty) empty.hidden = matches.length > 0;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@@ -0,0 +1,103 @@
|
|||||||
|
import { articles } from "./articles";
|
||||||
|
import { photoTopics } from "./photos";
|
||||||
|
import { timeline } from "./timeline";
|
||||||
|
|
||||||
|
export type MemoryKind = "event" | "photo" | "article";
|
||||||
|
|
||||||
|
export interface OnThisDayMemory {
|
||||||
|
id: string;
|
||||||
|
date: string;
|
||||||
|
monthDay: string;
|
||||||
|
year: number;
|
||||||
|
kind: MemoryKind;
|
||||||
|
kindLabel: string;
|
||||||
|
title: string;
|
||||||
|
text: string;
|
||||||
|
href: string;
|
||||||
|
image?: string;
|
||||||
|
external?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const kindLabels: Record<MemoryKind, string> = {
|
||||||
|
event: "班级事件",
|
||||||
|
photo: "旧照片",
|
||||||
|
article: "旧文章"
|
||||||
|
};
|
||||||
|
|
||||||
|
const toIsoDate = (year: number, month: number, day: number) =>
|
||||||
|
`${year}-${String(month).padStart(2, "0")}-${String(day).padStart(2, "0")}`;
|
||||||
|
|
||||||
|
const getTimelineDates = (label: string) => {
|
||||||
|
const match = label.match(/(\d{4})年(\d{1,2})月([^日]+)日/);
|
||||||
|
if (!match) return [];
|
||||||
|
|
||||||
|
const [, yearText, monthText, dayText] = match;
|
||||||
|
return dayText
|
||||||
|
.split(/[、,,]/)
|
||||||
|
.map((value) => Number(value.match(/\d+/)?.[0]))
|
||||||
|
.filter((value) => Number.isInteger(value) && value >= 1 && value <= 31)
|
||||||
|
.map((day) => toIsoDate(Number(yearText), Number(monthText), day));
|
||||||
|
};
|
||||||
|
|
||||||
|
const createMemory = (
|
||||||
|
memory: Omit<OnThisDayMemory, "monthDay" | "year" | "kindLabel">
|
||||||
|
): OnThisDayMemory => ({
|
||||||
|
...memory,
|
||||||
|
monthDay: memory.date.slice(5),
|
||||||
|
year: Number(memory.date.slice(0, 4)),
|
||||||
|
kindLabel: kindLabels[memory.kind]
|
||||||
|
});
|
||||||
|
|
||||||
|
const eventMemories = timeline.flatMap((moment, momentIndex) =>
|
||||||
|
getTimelineDates(moment.date).map((date) =>
|
||||||
|
createMemory({
|
||||||
|
id: `event-${momentIndex}-${date}`,
|
||||||
|
date,
|
||||||
|
kind: "event",
|
||||||
|
title: moment.title,
|
||||||
|
text: moment.text,
|
||||||
|
href: "href" in moment && typeof moment.href === "string" ? moment.href : "/timeline/"
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
const photoMemories = photoTopics.flatMap((topic) =>
|
||||||
|
topic.photos.flatMap((photo, photoIndex) =>
|
||||||
|
photo.date
|
||||||
|
? [
|
||||||
|
createMemory({
|
||||||
|
id: `photo-${topic.slug}-${photoIndex}-${photo.date}`,
|
||||||
|
date: photo.date,
|
||||||
|
kind: "photo",
|
||||||
|
title: photo.title,
|
||||||
|
text: photo.caption,
|
||||||
|
href: `/gallery/${topic.slug}/`,
|
||||||
|
image: photo.image
|
||||||
|
})
|
||||||
|
]
|
||||||
|
: []
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
const articleMemories = articles.map((article, articleIndex) =>
|
||||||
|
createMemory({
|
||||||
|
id: `article-${articleIndex}-${article.date}`,
|
||||||
|
date: article.date,
|
||||||
|
kind: "article",
|
||||||
|
title: article.title,
|
||||||
|
text: article.excerpt,
|
||||||
|
href: article.sourceUrl,
|
||||||
|
image: article.cover,
|
||||||
|
external: true
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
const kindOrder: Record<MemoryKind, number> = {
|
||||||
|
event: 0,
|
||||||
|
photo: 1,
|
||||||
|
article: 2
|
||||||
|
};
|
||||||
|
|
||||||
|
export const onThisDayMemories = [...eventMemories, ...photoMemories, ...articleMemories].sort(
|
||||||
|
(left, right) => right.year - left.year || kindOrder[left.kind] - kindOrder[right.kind]
|
||||||
|
);
|
||||||
@@ -10,7 +10,8 @@ export const eventsTopic: PhotoTopic = {
|
|||||||
{
|
{
|
||||||
title: "高一下学期表彰大会",
|
title: "高一下学期表彰大会",
|
||||||
caption: "排练时觉得麻烦,回头看全是可爱。",
|
caption: "排练时觉得麻烦,回头看全是可爱。",
|
||||||
image: "https://pic.biss.click/image/50e233d6-dd88-4a10-bb2d-a42ace27cdec.jpg"
|
image: "https://pic.biss.click/image/50e233d6-dd88-4a10-bb2d-a42ace27cdec.jpg",
|
||||||
|
date: "2022-07-08"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "集体出游",
|
title: "集体出游",
|
||||||
@@ -20,13 +21,17 @@ export const eventsTopic: PhotoTopic = {
|
|||||||
{
|
{
|
||||||
title: "百日誓师大会",
|
title: "百日誓师大会",
|
||||||
caption: "高三的第一次全体活动,大家都很随意地在听讲,虽然最后还是没能坚持到最后。",
|
caption: "高三的第一次全体活动,大家都很随意地在听讲,虽然最后还是没能坚持到最后。",
|
||||||
image: "https://pic.biss.click/image/45bfbe79-bd7b-40f3-9670-1b34cc0957b2.png"
|
image: "https://pic.biss.click/image/45bfbe79-bd7b-40f3-9670-1b34cc0957b2.png",
|
||||||
|
date: "2024-02-28"
|
||||||
},
|
},
|
||||||
wechatPhoto(117, "考前舞台", "紧张的日子里,也需要一次大声唱出来。"),
|
wechatPhoto(117, "考前舞台", "紧张的日子里,也需要一次大声唱出来。"),
|
||||||
wechatPhoto(121, "看台上的我们", "一片红色校服,聚成高三最后的集体活动。"),
|
wechatPhoto(121, "看台上的我们", "一片红色校服,聚成高三最后的集体活动。"),
|
||||||
wechatPhoto(129, "操场热身", "阳光很好,口号和动作都比平时更有力量。"),
|
wechatPhoto(129, "操场热身", "阳光很好,口号和动作都比平时更有力量。"),
|
||||||
wechatPhoto(132, "坐在一起", "台上发生什么已经模糊,身边的人还记得。"),
|
wechatPhoto(132, "坐在一起", "台上发生什么已经模糊,身边的人还记得。"),
|
||||||
wechatPhoto(176, "元旦歌咏", "整齐站上舞台,是青春里难得的郑重。"),
|
{
|
||||||
|
...wechatPhoto(176, "元旦歌咏", "整齐站上舞台,是青春里难得的郑重。"),
|
||||||
|
date: "2021-12-31"
|
||||||
|
},
|
||||||
wechatPhoto(178, "领奖时刻", "证书会褪色,但被认可的那一刻不会。"),
|
wechatPhoto(178, "领奖时刻", "证书会褪色,但被认可的那一刻不会。"),
|
||||||
wechatPhoto(180, "操场挑战", "跨过栏架,也跨过一个个觉得做不到的瞬间。"),
|
wechatPhoto(180, "操场挑战", "跨过栏架,也跨过一个个觉得做不到的瞬间。"),
|
||||||
wechatPhoto(181, "百日倒计时", "数字揭开的那一刻,高考忽然变得很近。"),
|
wechatPhoto(181, "百日倒计时", "数字揭开的那一刻,高考忽然变得很近。"),
|
||||||
|
|||||||
@@ -32,13 +32,19 @@ export const graduationDayTopic: PhotoTopic = {
|
|||||||
caption: "那一刻大家都在笑,但心里都知道要分别了。",
|
caption: "那一刻大家都在笑,但心里都知道要分别了。",
|
||||||
image: "https://pic.biss.click/image/f8d180c1-4827-4bfd-9550-4bfad4b97640.jpg"
|
image: "https://pic.biss.click/image/f8d180c1-4827-4bfd-9550-4bfad4b97640.jpg"
|
||||||
},
|
},
|
||||||
wechatPhoto(145, "壮行合影", "红色班服、彩色气球,和出发前最完整的一次站在一起。"),
|
{
|
||||||
|
...wechatPhoto(145, "壮行合影", "红色班服、彩色气球,和出发前最完整的一次站在一起。"),
|
||||||
|
date: "2024-06-06"
|
||||||
|
},
|
||||||
wechatPhoto(146, "气球升起之前", "所有人挤进镜头,等一个一起松手的瞬间。"),
|
wechatPhoto(146, "气球升起之前", "所有人挤进镜头,等一个一起松手的瞬间。"),
|
||||||
wechatPhoto(150, "飞向夏天", "气球越过教学楼,属于高中的倒计时也到了最后。"),
|
wechatPhoto(150, "飞向夏天", "气球越过教学楼,属于高中的倒计时也到了最后。"),
|
||||||
wechatPhoto(151, "人群里的告别", "欢呼、拥抱和一句句被现场声音盖住的话。"),
|
wechatPhoto(151, "人群里的告别", "欢呼、拥抱和一句句被现场声音盖住的话。"),
|
||||||
wechatPhoto(152, "穿过祝福", "从熟悉的人群中走过,前面就是新的路。"),
|
wechatPhoto(152, "穿过祝福", "从熟悉的人群中走过,前面就是新的路。"),
|
||||||
wechatPhoto(153, "鲜花与笑脸", "最后一程依然有人在身旁鼓掌。"),
|
wechatPhoto(153, "鲜花与笑脸", "最后一程依然有人在身旁鼓掌。"),
|
||||||
wechatPhoto(81, "毕业典礼合影", "红色幕布前,老师和同学一起留下毕业的证据。"),
|
{
|
||||||
|
...wechatPhoto(81, "毕业典礼合影", "红色幕布前,老师和同学一起留下毕业的证据。"),
|
||||||
|
date: "2024-06-09"
|
||||||
|
},
|
||||||
wechatPhoto(84, "典礼现场", "从看台望向舞台,礼堂装下了整届人的夏天。"),
|
wechatPhoto(84, "典礼现场", "从看台望向舞台,礼堂装下了整届人的夏天。"),
|
||||||
wechatPhoto(85, "把花送给老师", "镜头拼在一起,也拼出那天的感谢。"),
|
wechatPhoto(85, "把花送给老师", "镜头拼在一起,也拼出那天的感谢。"),
|
||||||
wechatPhoto(88, "走过红毯", "熟悉的老师站在两侧,目送这一届学生离开。"),
|
wechatPhoto(88, "走过红毯", "熟悉的老师站在两侧,目送这一届学生离开。"),
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ export interface PhotoItem {
|
|||||||
title: string;
|
title: string;
|
||||||
caption: string;
|
caption: string;
|
||||||
image: string;
|
image: string;
|
||||||
|
date?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PhotoTopic {
|
export interface PhotoTopic {
|
||||||
|
|||||||
@@ -3,7 +3,14 @@ export const timelineIntro = {
|
|||||||
text: "把三年里的班级大事按时间放在这里。军训、分班、网课、百日誓师、高考和毕业,都成为了后来回头看时很亮的节点。"
|
text: "把三年里的班级大事按时间放在这里。军训、分班、网课、百日誓师、高考和毕业,都成为了后来回头看时很亮的节点。"
|
||||||
};
|
};
|
||||||
|
|
||||||
export const timeline = [
|
export interface TimelineMoment {
|
||||||
|
date: string;
|
||||||
|
title: string;
|
||||||
|
text: string;
|
||||||
|
href?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const timeline: TimelineMoment[] = [
|
||||||
{
|
{
|
||||||
date: "2021年8月",
|
date: "2021年8月",
|
||||||
title: "进入高中",
|
title: "进入高中",
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
---
|
---
|
||||||
import BaseLayout from "../layouts/BaseLayout.astro";
|
import BaseLayout from "../layouts/BaseLayout.astro";
|
||||||
|
import OnThisDay from "../components/OnThisDay.astro";
|
||||||
import { galleryIntro, photoTopics } from "../data/photos";
|
import { galleryIntro, photoTopics } from "../data/photos";
|
||||||
import { featuredMessage, messages, messagesIntro } from "../data/messages";
|
import { featuredMessage, messages, messagesIntro } from "../data/messages";
|
||||||
import { people, peopleIntro } from "../data/people";
|
import { people, peopleIntro } from "../data/people";
|
||||||
@@ -41,6 +42,8 @@ const previewPeople = people.slice(0, 6);
|
|||||||
</aside>
|
</aside>
|
||||||
|
|
||||||
<main>
|
<main>
|
||||||
|
<OnThisDay />
|
||||||
|
|
||||||
<section id="timeline">
|
<section id="timeline">
|
||||||
<div class="section-inner">
|
<div class="section-inner">
|
||||||
<div class="section-title">
|
<div class="section-title">
|
||||||
|
|||||||
@@ -198,6 +198,225 @@ h1 {
|
|||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.on-this-day-band {
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
background:
|
||||||
|
radial-gradient(circle at 8% 14%, rgba(232, 168, 76, 0.2), transparent 24%),
|
||||||
|
linear-gradient(135deg, #f6f0df, #fffdf7 48%, #eef4e9);
|
||||||
|
}
|
||||||
|
|
||||||
|
.on-this-day-band::after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
right: -80px;
|
||||||
|
bottom: -110px;
|
||||||
|
width: 280px;
|
||||||
|
height: 280px;
|
||||||
|
border: 1px solid rgba(55, 109, 90, 0.12);
|
||||||
|
border-radius: 50%;
|
||||||
|
box-shadow:
|
||||||
|
0 0 0 34px rgba(55, 109, 90, 0.035),
|
||||||
|
0 0 0 68px rgba(55, 109, 90, 0.025);
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.on-this-day-shell {
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 150px minmax(0, 1fr);
|
||||||
|
gap: clamp(28px, 5vw, 64px);
|
||||||
|
align-items: start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.memory-date-card {
|
||||||
|
position: sticky;
|
||||||
|
top: 26px;
|
||||||
|
overflow: hidden;
|
||||||
|
border: 1px solid rgba(55, 109, 90, 0.2);
|
||||||
|
border-radius: 14px;
|
||||||
|
background: #fffdf7;
|
||||||
|
box-shadow: 0 18px 42px rgba(39, 55, 52, 0.11);
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.memory-date-card span,
|
||||||
|
.memory-date-card small {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.memory-date-card span {
|
||||||
|
padding: 8px 12px;
|
||||||
|
background: var(--green);
|
||||||
|
color: #fffdf7;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 800;
|
||||||
|
}
|
||||||
|
|
||||||
|
.memory-date-card strong {
|
||||||
|
display: block;
|
||||||
|
padding: 12px 12px 2px;
|
||||||
|
color: var(--ink);
|
||||||
|
font-family: Georgia, "Times New Roman", serif;
|
||||||
|
font-size: 62px;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.memory-date-card small {
|
||||||
|
padding: 8px 12px 13px;
|
||||||
|
color: var(--muted);
|
||||||
|
font-size: 11px;
|
||||||
|
letter-spacing: 0.08em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.on-this-day-heading {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: minmax(0, 1fr) minmax(240px, 0.8fr);
|
||||||
|
gap: clamp(20px, 4vw, 52px);
|
||||||
|
align-items: end;
|
||||||
|
margin-bottom: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.on-this-day-heading .eyebrow {
|
||||||
|
color: var(--coral);
|
||||||
|
}
|
||||||
|
|
||||||
|
.on-this-day-heading p:last-child {
|
||||||
|
margin: 0;
|
||||||
|
color: var(--muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
.memory-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||||
|
gap: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.memory-card {
|
||||||
|
min-height: 190px;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 150px minmax(0, 1fr);
|
||||||
|
overflow: hidden;
|
||||||
|
border: 1px solid rgba(31, 43, 42, 0.12);
|
||||||
|
border-radius: 12px;
|
||||||
|
background: rgba(255, 255, 255, 0.82);
|
||||||
|
box-shadow: 0 8px 28px rgba(39, 55, 52, 0.06);
|
||||||
|
transition: transform 180ms ease, border-color 180ms ease, box-shadow 180ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.memory-card:hover {
|
||||||
|
transform: translateY(-3px);
|
||||||
|
border-color: rgba(55, 109, 90, 0.34);
|
||||||
|
box-shadow: 0 16px 38px rgba(39, 55, 52, 0.12);
|
||||||
|
}
|
||||||
|
|
||||||
|
.memory-card > img,
|
||||||
|
.memory-card-visual {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
min-height: 190px;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
.memory-card-visual {
|
||||||
|
display: grid;
|
||||||
|
place-items: center;
|
||||||
|
color: rgba(255, 253, 247, 0.9);
|
||||||
|
background: linear-gradient(135deg, rgba(55, 109, 90, 0.94), rgba(69, 111, 148, 0.88));
|
||||||
|
font-family: STKaiti, KaiTi, serif;
|
||||||
|
font-size: 48px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.memory-card-copy {
|
||||||
|
min-width: 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.memory-card-meta {
|
||||||
|
color: var(--coral);
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 800;
|
||||||
|
letter-spacing: 0.04em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.memory-card-copy > strong {
|
||||||
|
margin-top: 7px;
|
||||||
|
font-size: 19px;
|
||||||
|
line-height: 1.35;
|
||||||
|
}
|
||||||
|
|
||||||
|
.memory-card-text {
|
||||||
|
display: -webkit-box;
|
||||||
|
overflow: hidden;
|
||||||
|
margin-top: 8px;
|
||||||
|
color: var(--muted);
|
||||||
|
font-size: 13px;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
-webkit-line-clamp: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.memory-card-action {
|
||||||
|
margin-top: auto;
|
||||||
|
padding-top: 14px;
|
||||||
|
color: var(--green);
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 800;
|
||||||
|
}
|
||||||
|
|
||||||
|
.memory-empty {
|
||||||
|
min-height: 190px;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: auto minmax(0, 1fr);
|
||||||
|
gap: 22px;
|
||||||
|
align-items: center;
|
||||||
|
padding: clamp(24px, 4vw, 38px);
|
||||||
|
border: 1px dashed rgba(55, 109, 90, 0.3);
|
||||||
|
border-radius: 14px;
|
||||||
|
background: rgba(255, 255, 255, 0.56);
|
||||||
|
}
|
||||||
|
|
||||||
|
.memory-empty[hidden],
|
||||||
|
.memory-grid[hidden] {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.memory-empty-mark {
|
||||||
|
color: var(--sun);
|
||||||
|
font-size: 48px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.memory-empty h3 {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.memory-empty p,
|
||||||
|
.memory-noscript {
|
||||||
|
margin: 6px 0 0;
|
||||||
|
color: var(--muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
.memory-empty-links {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 9px;
|
||||||
|
margin-top: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.memory-empty-links a {
|
||||||
|
padding: 7px 12px;
|
||||||
|
border: 1px solid var(--line);
|
||||||
|
border-radius: 999px;
|
||||||
|
background: #fff;
|
||||||
|
color: var(--green);
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 800;
|
||||||
|
}
|
||||||
|
|
||||||
main {
|
main {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
@@ -2227,6 +2446,8 @@ h2 {
|
|||||||
|
|
||||||
.stats,
|
.stats,
|
||||||
.section-title,
|
.section-title,
|
||||||
|
.on-this-day-shell,
|
||||||
|
.on-this-day-heading,
|
||||||
.message-wall,
|
.message-wall,
|
||||||
.twikoo-sticky-wall .tk-comments,
|
.twikoo-sticky-wall .tk-comments,
|
||||||
.twikoo-sticky-wall .tk-comments-container,
|
.twikoo-sticky-wall .tk-comments-container,
|
||||||
@@ -2428,6 +2649,16 @@ h2 {
|
|||||||
padding-inline: 14px;
|
padding-inline: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.memory-card {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
.memory-card > img,
|
||||||
|
.memory-card-visual {
|
||||||
|
height: 190px;
|
||||||
|
min-height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.hero-actions {
|
.hero-actions {
|
||||||
display: grid;
|
display: grid;
|
||||||
}
|
}
|
||||||
@@ -2442,6 +2673,19 @@ h2 {
|
|||||||
min-height: auto;
|
min-height: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.memory-date-card {
|
||||||
|
position: static;
|
||||||
|
width: 104px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.memory-date-card strong {
|
||||||
|
font-size: 48px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.memory-grid {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
.photo-card,
|
.photo-card,
|
||||||
.photo-card:nth-child(2),
|
.photo-card:nth-child(2),
|
||||||
.photo-card:nth-child(4) {
|
.photo-card:nth-child(4) {
|
||||||
|
|||||||
Reference in New Issue
Block a user