Merge pull request 'Add blog post and support pubDate/tags' (#46) from feat/after-the-silence-post into dev
CI / ci (push) Successful in 29s

Reviewed-on: #46
This commit was merged in pull request #46.
This commit is contained in:
2026-03-07 11:56:15 +00:00
7 changed files with 580 additions and 150 deletions
+133
View File
@@ -0,0 +1,133 @@
---
title: "After the Silence"
description: "Reflections on what remains after a meaningful relationship ends, and how love can transform without disappearing."
pubDate: 2026-03-04
tags: ["love", "reflection", "healing", "relationships", "personal"]
---
When a relationship ends, the world does not become quiet immediately.
At first there is noise.
Questions that circle endlessly.
Memories that appear without warning.
Moments where the absence of someone feels louder than their presence ever was.
But eventually something changes.
The storm that once lived inside your mind slowly settles.
And what remains is something different.
A silence that is not empty - but reflective.
---
## The Quiet After Love
The silence that follows a meaningful relationship is unlike any other.
It is not the silence of indifference.
Nor the silence of forgetting.
It is the quiet that appears when two lives that once moved together begin to move separately.
Routines shift.
Spaces feel different.
The future you once imagined slowly dissolves into something undefined.
At first, that silence can feel unsettling.
But over time it becomes something else.
A place where reflection becomes possible.
---
## Love Does Not Always Disappear
One of the more confusing realizations after a relationship ends is that love does not always vanish with it.
Even when distance becomes necessary, care can remain.
This can feel contradictory at first.
We often expect emotional closure to mean the disappearance of feeling.
But meaningful connections rarely dissolve that neatly.
Sometimes love simply changes form.
It moves from something shared into something carried quietly.
And that does not make it less real.
---
## The Quiet Transformation
Time has a way of reshaping emotional intensity.
What once felt overwhelming slowly becomes more understandable.
Moments that once caused pain begin to look different when viewed from a distance.
Not because the past changes.
But because you do.
Perspective grows.
The urgency fades.
And what once felt like chaos becomes something you can hold with calm understanding.
This transformation rarely happens suddenly.
It arrives slowly, through reflection, distance, and the quiet work of healing.
---
## Carrying Without Clinging
There is a difference between remembering someone and remaining attached to them.
Clinging keeps you in the past.
Carrying allows you to move forward.
When you carry something, you acknowledge its importance without letting it control your direction.
You recognize the place it had in your life.
You respect the impact it left.
But you also accept that some chapters belong where they ended.
In that sense, remembering can become an act of peace rather than longing.
---
## What Remains
When the emotional storm has passed, something meaningful remains.
Not the loss.
Not the confusion.
But the understanding.
You understand more about the kind of connection that matters to you.
You understand more about your own capacity to care deeply.
And perhaps most importantly, you understand that love itself was never the mistake.
Even when relationships end, the love that existed still shapes who we become.
It leaves behind lessons, perspective, and a deeper awareness of what it means to connect with another human being.
And sometimes, what remains after the silence is not emptiness.
But growth.
+4 -3
View File
@@ -1,7 +1,8 @@
---
---
title: "Welcome to the Den"
date: 2026-03-01
description: "First proper post. Why I built this site, what it runs on, and what to expect."
pubDate: 2026-03-01
tags: ["self-hosting", "privacy", "personal-web", "infrastructure"]
draft: false
---
@@ -11,7 +12,7 @@ So I finally got around to setting up a proper blog. Welcome.
I wanted a place to write that wasn't owned by a corporation. No Medium, no Substack, no algorithm deciding who sees what. Just markdown files on my own server, served by nginx from a Docker container I control.
That's the whole point of the den owning your own space on the internet.
That's the whole point of the den - owning your own space on the internet.
## What It Runs On
+14 -13
View File
@@ -1,7 +1,8 @@
---
---
title: "Love Without Access"
date: 2026-03-01
description: "A reflection on a first love — what it meant, what it cost, and why distance was the most loving thing left."
description: "A reflection on a first love - what it meant, what it cost, and why distance was the most loving thing left."
pubDate: 2026-03-01
tags: ["love", "reflection", "healing", "relationships", "personal"]
---
*by LATTE*
@@ -16,7 +17,7 @@ Power and surrender that were, underneath it all, just different shapes of trust
This isn't a story about blame.
And it's not a story about anger.
It's a story about something that stayed real
It's a story about something that stayed real...
even after it stopped being reachable.
---
@@ -25,7 +26,7 @@ even after it stopped being reachable.
We were friends first.
Maybe that's what made it so deep. It didn't explode into existence it grew. Slowly. Safely.
Maybe that's what made it so deep. It didn't explode into existence - it grew. Slowly. Safely.
From gaming together to talking for hours.
From talking to tension.
From tension to touch.
@@ -75,7 +76,7 @@ Silence.
"I don't feel it anymore."
And something in me went very quiet and very loud at the same time.
And something in me went very quiet - and very loud - at the same time.
Because I could still feel myself holding on.
And carrying someone who no longer carries back
@@ -98,7 +99,7 @@ But no longer together.
A body that says yes.
Words that say no.
That contradiction doesn't just hurt emotionally it destabilizes you.
That contradiction doesn't just hurt emotionally - it destabilizes you.
Hope becomes a reflex.
And every time hope collapses, you fracture a little with it.
@@ -199,7 +200,7 @@ That's architecture.
## On Being Replaced
Yes he found someone new quickly.
Yes - he found someone new quickly.
That hurt.
@@ -222,7 +223,7 @@ Something ending does not mean it was nothing.
## For You
If you ever read this
If you ever read this -
I want you to know that what we had was real to me.
Not experimental. Not temporary. Not a placeholder.
@@ -243,7 +244,7 @@ Trying. Failing. Adjusting.
Discovering what intimacy meant.
Discovering what we meant.
You weren't just someone who entered my life
You weren't just someone who entered my life -
you were part of my becoming.
That matters.
@@ -262,7 +263,7 @@ I was trying to hold something I didn't yet know how to let go of.
But even then, I wasn't against you.
I saw you as someone struggling not someone malicious.
I saw you as someone struggling - not someone malicious.
There were moments when you softened completely with me.
Moments where you rested your full weight without guarding yourself.
@@ -295,7 +296,7 @@ It changes shape.
It becomes quieter.
It becomes something I carry instead of something I reach for.
And yes I'm going to be a little playful about it:
And yes - I'm going to be a little playful about it:
You're on my website. Do you get that?
@@ -333,4 +334,4 @@ to be worthy of being held.
The wolf in me was never meant to become smaller.
Only to find the right pack.
LATTE
- LATTE
+9 -8
View File
@@ -1,13 +1,14 @@
import { z, defineCollection } from 'astro:content';
import { z, defineCollection } from "astro:content";
const blog = defineCollection({
type: 'content',
schema: z.object({
title: z.string(),
date: z.coerce.date(),
description: z.string(),
draft: z.boolean().optional().default(false),
}),
type: "content",
schema: z.object({
title: z.string(),
description: z.string(),
pubDate: z.coerce.date(),
tags: z.array(z.string()).default([]),
draft: z.boolean().optional().default(false),
}),
});
export const collections = { blog };
+202 -12
View File
@@ -1,16 +1,43 @@
---
import BaseLayout from "../../layouts/BaseLayout.astro";
import { getCollection } from "astro:content";
import { getCollection, type CollectionEntry } from "astro:content";
type BlogPost = CollectionEntry<"blog">;
export async function getStaticPaths() {
const posts = await getCollection("blog", ({ data }) => !data.draft);
return posts.map((post) => ({
params: { slug: post.slug },
props: { post },
props: {
post,
relatedPosts: posts
.filter((candidate) => candidate.slug !== post.slug)
.map((candidate) => ({
post: candidate,
score: candidate.data.tags.filter((tag) =>
post.data.tags.includes(tag),
).length,
}))
.sort((a, b) => {
if (b.score !== a.score) return b.score - a.score;
return (
b.post.data.pubDate.valueOf() -
a.post.data.pubDate.valueOf()
);
})
.filter((candidate) => candidate.score > 0)
.slice(0, 2)
.map((candidate) => candidate.post),
},
}));
}
const { post } = Astro.props;
const { post, relatedPosts = [] } = Astro.props as {
post: BlogPost;
relatedPosts: BlogPost[];
};
const { Content } = await post.render();
function formatDate(date: Date) {
@@ -19,7 +46,7 @@ function formatDate(date: Date) {
---
<BaseLayout
title={`${post.data.title} Hidden Den Cafe`}
title={`${post.data.title} - Hidden Den Cafe`}
description={post.data.description}
>
<div class="matrix-bg" aria-hidden="true"></div>
@@ -28,14 +55,60 @@ function formatDate(date: Date) {
<div class="container">
<header class="header fade-in">
<h1 class="title">{post.data.title}</h1>
<p class="date">{formatDate(post.data.date)}</p>
<div class="divider">══════════════════════════════</div>
<p class="date">{formatDate(post.data.pubDate)}</p>
{
post.data.tags.length > 0 && (
<div
class="tag-list"
aria-label={`${post.data.title} tags`}
>
{post.data.tags.map((tag) => (
<span class="tag">{tag}</span>
))}
</div>
)
}
<div class="divider">==============================</div>
</header>
<article class="content fade-in">
<Content />
</article>
{
relatedPosts.length > 0 && (
<section
class="related fade-in"
aria-labelledby="related-posts"
>
<div class="related-head">
<h2 id="related-posts">Related Reading</h2>
<a href="/blog" class="related-link">
Back to blog
</a>
</div>
<ul class="related-list">
{relatedPosts.map((relatedPost) => (
<li class="related-item">
<a
href={`/blog/${relatedPost.slug}`}
class="related-card"
>
<span class="related-date">
{formatDate(
relatedPost.data.pubDate,
)}
</span>
<h3>{relatedPost.data.title}</h3>
<p>{relatedPost.data.description}</p>
</a>
</li>
))}
</ul>
</section>
)
}
<footer class="footer fade-in">
<p>Made with love by Latte</p>
</footer>
@@ -60,8 +133,12 @@ function formatDate(date: Date) {
}
@keyframes grid-move {
0% { transform: translate(0, 0); }
100% { transform: translate(50px, 50px); }
0% {
transform: translate(0, 0);
}
100% {
transform: translate(50px, 50px);
}
}
.main {
@@ -107,7 +184,21 @@ function formatDate(date: Date) {
font-size: 0.85rem;
}
/* Prose styles for markdown content */
.tag-list {
display: flex;
flex-wrap: wrap;
gap: var(--space-xs);
margin-top: var(--space-sm);
}
.tag {
font-size: 0.72rem;
color: var(--color-accent);
border: 1px solid var(--color-surface);
padding: 1px 6px;
border-radius: 999px;
}
.content {
color: var(--color-text);
line-height: 1.8;
@@ -208,6 +299,82 @@ function formatDate(date: Date) {
margin-top: var(--space-xs);
}
.related {
margin-top: var(--space-xl);
padding-top: var(--space-lg);
border-top: 1px solid var(--color-surface);
}
.related-head {
display: flex;
align-items: baseline;
justify-content: space-between;
gap: var(--space-sm);
margin-bottom: var(--space-md);
}
.related-head h2 {
font-size: 1rem;
text-transform: uppercase;
letter-spacing: 2px;
color: var(--color-accent);
}
.related-link {
color: var(--color-blue);
font-size: 0.85rem;
white-space: nowrap;
}
.related-link:hover {
color: var(--color-accent-bright);
}
.related-list {
list-style: none;
display: flex;
flex-direction: column;
gap: var(--space-md);
}
.related-card {
display: block;
padding: var(--space-md);
border-radius: 8px;
background: color-mix(in srgb, var(--color-bg-light) 88%, transparent);
border: 1px solid
color-mix(in srgb, var(--color-surface) 70%, transparent);
transition:
border-color 0.2s ease,
transform 0.2s ease,
box-shadow 0.2s ease;
}
.related-card:hover {
border-color: color-mix(in srgb, var(--color-accent) 55%, transparent);
transform: translateY(-2px);
box-shadow: 0 0 0 1px
color-mix(in srgb, var(--color-accent) 35%, transparent);
}
.related-date {
display: inline-block;
color: var(--color-text-dim);
font-size: 0.8rem;
margin-bottom: var(--space-xs);
}
.related-card h3 {
font-size: 1rem;
color: var(--color-accent-bright);
margin-bottom: var(--space-xs);
}
.related-card p {
color: var(--color-text-dim);
line-height: 1.7;
}
.footer {
margin-top: var(--space-xl);
text-align: center;
@@ -223,9 +390,18 @@ function formatDate(date: Date) {
opacity: 0;
}
.fade-in:nth-child(1) { animation-delay: 0.1s; }
.fade-in:nth-child(2) { animation-delay: 0.2s; }
.fade-in:nth-child(3) { animation-delay: 0.3s; }
.fade-in:nth-child(1) {
animation-delay: 0.1s;
}
.fade-in:nth-child(2) {
animation-delay: 0.2s;
}
.fade-in:nth-child(3) {
animation-delay: 0.3s;
}
.fade-in:nth-child(4) {
animation-delay: 0.4s;
}
@keyframes fadeIn {
from {
@@ -250,6 +426,11 @@ function formatDate(date: Date) {
.divider {
font-size: 0.6rem;
}
.related-head {
flex-direction: column;
align-items: flex-start;
}
}
@media (prefers-reduced-motion: reduce) {
@@ -261,5 +442,14 @@ function formatDate(date: Date) {
animation: none;
opacity: 1;
}
.related-card {
transition: none;
}
.related-card:hover {
transform: none;
box-shadow: none;
}
}
</style>
+76 -26
View File
@@ -2,8 +2,9 @@
import BaseLayout from "../../layouts/BaseLayout.astro";
import { getCollection } from "astro:content";
const posts = (await getCollection("blog", ({ data }) => !data.draft))
.sort((a, b) => b.data.date.valueOf() - a.data.date.valueOf());
const posts = (await getCollection("blog", ({ data }) => !data.draft)).sort(
(a, b) => b.data.pubDate.valueOf() - a.data.pubDate.valueOf(),
);
function formatDate(date: Date) {
return date.toISOString().split("T")[0];
@@ -23,25 +24,50 @@ function formatDate(date: Date) {
<div class="divider">══════════════════════════════</div>
</header>
{posts.length === 0 ? (
<section class="section fade-in">
<p class="empty">No posts yet. Will get around to it.</p>
</section>
) : (
<section class="section fade-in">
<ul class="post-list">
{posts.map((post) => (
<li class="post-item">
<span class="post-date">{formatDate(post.data.date)}</span>
<div class="post-info">
<a href={`/blog/${post.slug}`} class="post-title">{post.data.title}</a>
<p class="post-desc">{post.data.description}</p>
</div>
</li>
))}
</ul>
</section>
)}
{
posts.length === 0 ? (
<section class="section fade-in">
<p class="empty">
No posts yet. Will get around to it.
</p>
</section>
) : (
<section class="section fade-in">
<ul class="post-list">
{posts.map((post) => (
<li class="post-item">
<span class="post-date">
{formatDate(post.data.pubDate)}
</span>
<div class="post-info">
<a
href={`/blog/${post.slug}`}
class="post-title"
>
{post.data.title}
</a>
<p class="post-desc">
{post.data.description}
</p>
{post.data.tags.length > 0 && (
<div
class="tag-list"
aria-label={`${post.data.title} tags`}
>
{post.data.tags.map((tag) => (
<span class="tag">
{tag}
</span>
))}
</div>
)}
</div>
</li>
))}
</ul>
</section>
)
}
<footer class="footer fade-in">
<p>Made with love by Latte</p>
@@ -67,8 +93,12 @@ function formatDate(date: Date) {
}
@keyframes grid-move {
0% { transform: translate(0, 0); }
100% { transform: translate(50px, 50px); }
0% {
transform: translate(0, 0);
}
100% {
transform: translate(50px, 50px);
}
}
.main {
@@ -156,6 +186,20 @@ function formatDate(date: Date) {
line-height: 1.6;
}
.tag-list {
display: flex;
flex-wrap: wrap;
gap: var(--space-xs);
}
.tag {
font-size: 0.72rem;
color: var(--color-accent);
border: 1px solid var(--color-surface);
padding: 1px 6px;
border-radius: 999px;
}
.empty {
color: var(--color-text-dim);
font-style: italic;
@@ -176,9 +220,15 @@ function formatDate(date: Date) {
opacity: 0;
}
.fade-in:nth-child(1) { animation-delay: 0.1s; }
.fade-in:nth-child(2) { animation-delay: 0.2s; }
.fade-in:nth-child(3) { animation-delay: 0.3s; }
.fade-in:nth-child(1) {
animation-delay: 0.1s;
}
.fade-in:nth-child(2) {
animation-delay: 0.2s;
}
.fade-in:nth-child(3) {
animation-delay: 0.3s;
}
@keyframes fadeIn {
from {
+142 -88
View File
@@ -16,7 +16,7 @@ type Project = {
};
const posts = (await getCollection("blog", ({ data }) => !data.draft)).sort(
(a, b) => b.data.date.valueOf() - a.data.date.valueOf(),
(a, b) => b.data.pubDate.valueOf() - a.data.pubDate.valueOf(),
);
const recommendedPosts = posts.slice(0, 3);
@@ -28,12 +28,17 @@ const highlightedProjects = highlightedProjectNames
.map((name) => typedProjects.find((project) => project.name === name))
.filter((project): project is Project => Boolean(project));
function formatDate(date: CollectionEntry<"blog">["data"]["date"]) {
function formatDate(date: CollectionEntry<"blog">["data"]["pubDate"]) {
return date.toISOString().split("T")[0];
}
function getProjectLink(project: Project) {
return project.links.site || project.links.gitea || project.links.github || "/projects";
return (
project.links.site ||
project.links.gitea ||
project.links.github ||
"/projects"
);
}
function getProjectLinkLabel(project: Project) {
@@ -57,75 +62,95 @@ function getProjectLinkLabel(project: Project) {
<h1 class="title">Start Here</h1>
<div class="divider">==============================</div>
<p class="lead">
This page is a small orientation point for first-time visitors. If
you have just found Hidden Den, this is the quickest way to get a
feel for what kind of place it is and where you might want to wander
next.
This page is a small orientation point for first-time
visitors. If you have just found Hidden Den, this is the
quickest way to get a feel for what kind of place it is and
where you might want to wander next.
</p>
</header>
<section class="section fade-in" aria-labelledby="what-this-place-is">
<section
class="section fade-in"
aria-labelledby="what-this-place-is"
>
<h2 id="what-this-place-is">What Hidden Den Is</h2>
<p class="desc">
Hidden Den is Latte&apos;s personal corner of the internet: part
writing space, part workshop, part quiet place to think out loud. It
holds projects, experiments, infrastructure-minded notes, and the
kind of personal web presence that does not need to behave like a
brand.
Hidden Den is Latte&apos;s personal corner of the internet:
part writing space, part workshop, part quiet place to think
out loud. It holds projects, experiments,
infrastructure-minded notes, and the kind of personal web
presence that does not need to behave like a brand.
</p>
<p class="desc">
The site leans toward privacy, ownership, and human-scale spaces
online. It is built to feel warm and readable rather than optimized,
noisy, or extractive. More cozy tech wizard than cyberpunk hacker.
The site leans toward privacy, ownership, and human-scale
spaces online. It is built to feel warm and readable rather
than optimized, noisy, or extractive. More cozy tech wizard
than cyberpunk hacker.
</p>
<div class="note">
<p>
If you want the short version: this is a personal site for
writing, building, self-hosting, and keeping a small piece of the
web genuinely personal.
If you want the short version: this is a personal site
for writing, building, self-hosting, and keeping a small
piece of the web genuinely personal.
</p>
</div>
</section>
<section class="section fade-in" aria-labelledby="recommended-reading">
<section
class="section fade-in"
aria-labelledby="recommended-reading"
>
<div class="section-head">
<h2 id="recommended-reading">Recommended Reading</h2>
<a class="section-link" href="/blog">See all posts</a>
</div>
<p class="desc section-intro">
A few good starting points from the blog. These give a feel for the
den so far without asking you to dig through everything first.
A few good starting points from the blog. These give a feel
for the den so far without asking you to dig through
everything first.
</p>
{recommendedPosts.length === 0 ? (
<p class="empty">The den is still quiet on the writing front.</p>
) : (
<ul class="reading-list">
{recommendedPosts.map((post) => (
<li class="reading-item">
<article class="content-card">
<div class="meta-row">
<span class="meta-label">posted</span>
<time datetime={formatDate(post.data.date)}>
{formatDate(post.data.date)}
</time>
</div>
<h3>
<a href={`/blog/${post.slug}`}>{post.data.title}</a>
</h3>
<p>{post.data.description}</p>
</article>
</li>
))}
</ul>
)}
{
recommendedPosts.length === 0 ? (
<p class="empty">
The den is still quiet on the writing front.
</p>
) : (
<ul class="reading-list">
{recommendedPosts.map((post) => (
<li class="reading-item">
<article class="content-card">
<div class="meta-row">
<span class="meta-label">
posted
</span>
<time
datetime={formatDate(
post.data.pubDate,
)}
>
{formatDate(post.data.pubDate)}
</time>
</div>
<h3>
<a href={`/blog/${post.slug}`}>
{post.data.title}
</a>
</h3>
<p>{post.data.description}</p>
</article>
</li>
))}
</ul>
)
}
</section>
<section class="section fade-in" aria-labelledby="explore-the-site">
<h2 id="explore-the-site">Explore The Site</h2>
<p class="desc section-intro">
If you would rather browse by section, these are the best places to
continue.
If you would rather browse by section, these are the best
places to continue.
</p>
<div class="explore-grid">
@@ -133,9 +158,9 @@ function getProjectLinkLabel(project: Project) {
<span class="card-kicker">About</span>
<h3>Meet the person behind the den</h3>
<p>
A fuller introduction to Latte, the philosophy behind the
site, and the kind of internet this place is trying to make
room for.
A fuller introduction to Latte, the philosophy
behind the site, and the kind of internet this place
is trying to make room for.
</p>
</a>
@@ -143,8 +168,9 @@ function getProjectLinkLabel(project: Project) {
<span class="card-kicker">Blog</span>
<h3>Read the writing</h3>
<p>
Thoughts, personal pieces, and technical reflections gathered
in one place without feeds, tracking, or platform noise.
Thoughts, personal pieces, and technical reflections
gathered in one place without feeds, tracking, or
platform noise.
</p>
</a>
@@ -152,52 +178,76 @@ function getProjectLinkLabel(project: Project) {
<span class="card-kicker">Projects</span>
<h3>See what is being built</h3>
<p>
Bots, tools, experiments, and den-adjacent systems that show
the practical side of the site.
Bots, tools, experiments, and den-adjacent systems
that show the practical side of the site.
</p>
</a>
</div>
</section>
<section class="section fade-in" aria-labelledby="project-highlights">
<section
class="section fade-in"
aria-labelledby="project-highlights"
>
<div class="section-head">
<h2 id="project-highlights">Projects Worth Seeing</h2>
<a class="section-link" href="/projects">Browse all projects</a>
<a class="section-link" href="/projects"
>Browse all projects</a
>
</div>
<p class="desc section-intro">
A small curated subset, just enough to sketch the shape of the work
without turning this page into a full catalog.
A small curated subset, just enough to sketch the shape of
the work without turning this page into a full catalog.
</p>
<ul class="project-list">
{highlightedProjects.map((project) => (
<li class="project-item">
<article class="content-card project-card">
<div class="project-topline">
<h3>{project.name}</h3>
<span class={`status status-${project.status}`}>
{project.status}
</span>
</div>
<p>{project.description}</p>
<div class="project-footer">
<div class="tag-list" aria-label={`${project.name} tags`}>
{project.tags.map((tag) => (
<span class="tag">{tag}</span>
))}
{
highlightedProjects.map((project) => (
<li class="project-item">
<article class="content-card project-card">
<div class="project-topline">
<h3>{project.name}</h3>
<span
class={`status status-${project.status}`}
>
{project.status}
</span>
</div>
<a
class="project-link"
href={getProjectLink(project)}
target={getProjectLink(project).startsWith("http") ? "_blank" : undefined}
rel={getProjectLink(project).startsWith("http") ? "noopener noreferrer" : undefined}
>
{getProjectLinkLabel(project)}
</a>
</div>
</article>
</li>
))}
<p>{project.description}</p>
<div class="project-footer">
<div
class="tag-list"
aria-label={`${project.name} tags`}
>
{project.tags.map((tag) => (
<span class="tag">{tag}</span>
))}
</div>
<a
class="project-link"
href={getProjectLink(project)}
target={
getProjectLink(
project,
).startsWith("http")
? "_blank"
: undefined
}
rel={
getProjectLink(
project,
).startsWith("http")
? "noopener noreferrer"
: undefined
}
>
{getProjectLinkLabel(project)}
</a>
</div>
</article>
</li>
))
}
</ul>
</section>
@@ -337,7 +387,8 @@ function getProjectLinkLabel(project: Project) {
.note {
margin-top: var(--space-md);
padding: var(--space-md);
border: 1px solid color-mix(in srgb, var(--color-accent) 30%, transparent);
border: 1px solid
color-mix(in srgb, var(--color-accent) 30%, transparent);
background:
linear-gradient(
135deg,
@@ -365,7 +416,8 @@ function getProjectLinkLabel(project: Project) {
padding: var(--space-md);
border-radius: 8px;
background: color-mix(in srgb, var(--color-bg-light) 88%, transparent);
border: 1px solid color-mix(in srgb, var(--color-surface) 70%, transparent);
border: 1px solid
color-mix(in srgb, var(--color-surface) 70%, transparent);
}
.content-card h3 {
@@ -405,7 +457,8 @@ function getProjectLinkLabel(project: Project) {
display: block;
padding: var(--space-md);
border-radius: 8px;
border: 1px solid color-mix(in srgb, var(--color-surface) 70%, transparent);
border: 1px solid
color-mix(in srgb, var(--color-surface) 70%, transparent);
background: color-mix(in srgb, var(--color-bg-light) 88%, transparent);
transition:
border-color 0.2s ease,
@@ -416,7 +469,8 @@ function getProjectLinkLabel(project: Project) {
.explore-card:hover {
border-color: color-mix(in srgb, var(--color-accent) 55%, transparent);
transform: translateY(-2px);
box-shadow: 0 0 0 1px color-mix(in srgb, var(--color-accent) 35%, transparent);
box-shadow: 0 0 0 1px
color-mix(in srgb, var(--color-accent) 35%, transparent);
}
.card-kicker {