Compare commits

...

10 Commits

10 changed files with 209 additions and 135 deletions

View File

@@ -16,9 +16,11 @@ jobs:
uses: actions/setup-node@v4 uses: actions/setup-node@v4
with: with:
node-version: '20' node-version: '20'
cache: 'pnpm'
- name: Install dependencies - name: Install dependencies
run: pnpm install run: pnpm install
- name: Create Ghost Config
run: |
echo "window.GhostConfig = { ghostApiKey: '${{ secrets.GHOST_CONTENT_API_KEY }}', ghostApiUrl: '${{ secrets.GHOST_ADMIN_API_URL }}' };" > assets/js/ghost-config.js
- name: Build theme - name: Build theme
run: pnpm build run: pnpm build
- name: Deploy Ghost Theme - name: Deploy Ghost Theme

51
README.md Normal file
View File

@@ -0,0 +1,51 @@
# Palina Theme: A Digital Shrine to Artistic Brilliance (and Palina)
Welcome, digital wanderer, to the "Palina" theme where every pixel is inspired by the radiant charisma of the one and only Palina Rojinski! ✨ This isn't just a Ghost CMS theme; it's a meticulously crafted digital gallery designed to showcase your most stunning AI-generated images with the elegance and flair that Palina herself embodies.
## Why "Palina," you ask?
Because ordinary themes are, well, *ordinary*. This theme captures the vibrant, sophisticated, and utterly captivating essence of Palina Rojinski, translating it into a clean, minimalistic, yet undeniably stylish aesthetic. Think modern art gallery meets exclusive digital showcase, all wrapped up in a package as delightful as Palina's latest dance move.
## Features that Dazzle (Like Palina's Smile):
* **Adaptive Brilliance:** Seamlessly switch between a chic **Dark Mode** and a vibrant **Light Mode** to match your mood (or Palina's outfit of the day). Your preference is remembered, naturally!
* **Mobile Grace:** A sleek, responsive design ensures your images look phenomenal on any device. Plus, a **hamburger menu** for mobile makes navigation as smooth as Palina's transitions on the dance floor.
* **Captivating Animations:** Subtle **CSS animations** bring your content to life, while a convenient **image lightbox** allows admirers to zoom into every exquisite detail.
* **Artistic Typography:** Featuring the elegant **Playfair Display** for headlines and the modern **Montserrat** for body text, ensuring your words are as captivating as your visuals.
* **Ghost CMS Power:** Full support for all Ghost features, because even artistic masterpieces need solid foundations.
## Getting Started (It's Easier Than Learning Palina's Choreography):
1. **Clone this repository.**
2. **Install dependencies:** Ensure you have `pnpm` installed, then run:
```bash
pnpm install
```
3. **Build the theme:**
* For development with live reloading:
```bash
pnpm dev
```
* For a production-ready, minified build:
```bash
pnpm build
```
## Deployment (Let Gitea Do the Heavy Lifting):
This theme comes with a built-in Gitea Actions workflow (`.gitea/workflows/deploy.yml`) to automate deployment to your live Ghost site.
**Before you push:**
1. Go to your Gitea repository settings.
2. Add the following secrets:
* `GHOST_ADMIN_API_URL`: Your Ghost site's URL (e.g., `https://your-domain.com`).
* `GHOST_ADMIN_API_KEY`: Your Admin API Key from Ghost (find it under **Settings > Integrations > Custom Integrations**).
Once configured, simply push your changes to the `main` branch, and watch the magic unfold! ✨
---
**A Note on the Images:** The AI-generated images of Palina Rojinski are purely for demonstrative and artistic purposes within the context of this theme. No actual endorsement or affiliation is implied, just immense admiration!
May your blog be as awesome, outstanding, and beautiful as its namesake!

View File

@@ -36,6 +36,8 @@ html[data-theme='light'] {
--text-tertiary: var(--color-gray-700); --text-tertiary: var(--color-gray-700);
} }
[x-cloak] { display: none !important; }
@layer base { @layer base {
body { body {
background-color: var(--bg-primary); background-color: var(--bg-primary);
@@ -48,6 +50,28 @@ html[data-theme='light'] {
} }
} }
@layer components {
/* Main navigation styling */
header nav ul {
@apply flex items-center space-x-4; /* Make li items inline with spacing */
}
header nav ul li a {
@apply text-[var(--text-primary)] hover:text-[var(--text-secondary)] transition-colors duration-200; /* Default link style */
}
/* Mobile navigation styling */
#mobile-menu nav ul {
@apply flex flex-col items-center space-y-8; /* Stack items vertically in mobile menu */
}
#mobile-menu nav ul li a {
@apply text-[var(--text-primary)] text-3xl font-bold hover:text-[var(--text-secondary)] transition-colors duration-200;
}
}
.kg-image-card img, .post-content img {
@apply cursor-pointer transition-opacity duration-200 hover:opacity-90;
}
@keyframes fadeInUp { @keyframes fadeInUp {
from { from {
opacity: 0; opacity: 0;

View File

@@ -1,93 +1,35 @@
// Main JavaScript file for Palina theme // Main JavaScript file for Palina theme
// Using HTMX and Alpine.js for enhanced functionality
document.addEventListener('DOMContentLoaded', () => { document.addEventListener('DOMContentLoaded', () => {
console.log('Palina theme loaded!'); console.log('Palina theme loaded!');
const htmlElement = document.documentElement;
// Remove 'hidden' class from html to prevent FOUC
htmlElement.classList.remove('hidden');
// Staggered fade-in animation for post grid // Staggered fade-in animation for post grid
const gridItems = document.querySelectorAll('.post-grid-item'); const animateGridItems = (container = document) => {
gridItems.forEach((item, index) => { const gridItems = container.querySelectorAll('.post-grid-item:not(.animated)');
item.style.animationDelay = `${index * 100}ms`; gridItems.forEach((item, index) => {
item.classList.add('animate-fadeInUp'); item.style.animationDelay = `${index * 100}ms`;
item.classList.add('animate-fadeInUp');
item.classList.add('animated');
});
};
// Initial animation
animateGridItems();
// Re-run animation and other setup when HTMX settles new content
document.body.addEventListener('htmx:afterSettle', (event) => {
// If the settled element is the posts-container or contains grid items
if (event.detail.target.id === 'posts-container' || event.detail.target.querySelector('.post-grid-item')) {
animateGridItems(event.detail.target);
}
// If it was a full page boost, we might need to reset some things
if (event.detail.boosted) {
animateGridItems();
}
}); });
// Lightbox for post images // Handle Lightbox for post images specifically (if needed beyond the global Alpine listener)
const lightbox = document.getElementById('lightbox'); // The global listener in default.hbs should handle most cases.
if (lightbox) {
const lightboxImage = document.getElementById('lightbox-image');
const lightboxClose = document.getElementById('lightbox-close');
const images = document.querySelectorAll('.kg-image-card img, .post-content img');
images.forEach(image => {
image.style.cursor = 'pointer';
image.addEventListener('click', () => {
lightbox.classList.remove('hidden');
lightbox.classList.add('show');
lightboxImage.src = image.src;
});
});
lightboxClose.addEventListener('click', () => {
lightbox.classList.add('hidden');
lightbox.classList.remove('show');
lightboxImage.src = '';
});
lightbox.addEventListener('click', (e) => {
if (e.target.id !== 'lightbox-image') {
lightbox.classList.add('hidden');
lightbox.classList.remove('show');
lightboxImage.src = '';
}
});
}
// Theme Switcher
const themeToggle = document.getElementById('theme-toggle');
// const htmlElement = document.documentElement; // Already defined above
const currentTheme = localStorage.getItem('theme');
if (currentTheme) {
htmlElement.setAttribute('data-theme', currentTheme);
} else if (window.matchMedia && window.matchMedia('(prefers-color-scheme: light)').matches) {
// Default to light theme if system preference is light
htmlElement.setAttribute('data-theme', 'light');
}
if (themeToggle) {
themeToggle.addEventListener('click', () => {
let newTheme = htmlElement.getAttribute('data-theme') === 'dark' ? 'light' : 'dark';
htmlElement.setAttribute('data-theme', newTheme);
localStorage.setItem('theme', newTheme);
});
}
// Mobile Menu
const mobileMenuToggle = document.getElementById('mobile-menu-toggle');
const mobileMenuClose = document.getElementById('mobile-menu-close');
const mobileMenu = document.getElementById('mobile-menu');
if (mobileMenuToggle && mobileMenu && mobileMenuClose) {
mobileMenuToggle.addEventListener('click', () => {
mobileMenu.classList.remove('-translate-x-full');
mobileMenu.classList.add('translate-x-0');
});
mobileMenuClose.addEventListener('click', () => {
mobileMenu.classList.remove('translate-x-0');
mobileMenu.classList.add('-translate-x-full');
});
// Close menu if a link is clicked
const mobileNavLinks = mobileMenu.querySelectorAll('a');
mobileNavLinks.forEach(link => {
link.addEventListener('click', () => {
mobileMenu.classList.remove('translate-x-0');
mobileMenu.classList.add('-translate-x-full');
});
});
}
}); });

View File

@@ -1,16 +1,39 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="{{@site.lang}}" data-theme="dark" class="hidden"> <html lang="{{@site.lang}}"
x-data="{
theme: localStorage.getItem('theme') || (window.matchMedia('(prefers-color-scheme: light)').matches ? 'light' : 'dark'),
init() {
$watch('theme', val => {
localStorage.setItem('theme', val);
document.documentElement.setAttribute('data-theme', val);
});
document.documentElement.setAttribute('data-theme', this.theme);
document.documentElement.classList.remove('hidden');
}
}"
:data-theme="theme"
class="hidden">
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<title>{{meta_title}}</title> <title>{{meta_title}}</title>
<link rel="stylesheet" href="{{asset "built/screen.css"}}"> <link rel="stylesheet" href="{{asset "built/screen.css"}}">
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;700&family=Playfair+Display:wght@700&display=swap" rel="stylesheet"> <link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;700&family=Playfair+Display:wght@700&display=swap" rel="stylesheet">
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
<script src="https://unpkg.com/htmx.org@2.0.0"></script>
{{ghost_head}} {{ghost_head}}
</head> </head>
<body class="{{body_class}} font-sans antialiased"> <body class="{{body_class}} font-sans antialiased" hx-boost="true">
<div class="min-h-screen flex flex-col"> <div class="min-h-screen flex flex-col"
x-data="{ mobileMenuOpen: false, lightboxOpen: false, lightboxImage: '' }"
@click="if ($event.target.closest('.kg-image-card img, .post-content img')) {
$event.preventDefault();
lightboxImage = $event.target.src;
lightboxOpen = true;
}">
{{> header}} {{> header}}
<main class="flex-grow"> <main class="flex-grow">
@@ -18,16 +41,22 @@
</main> </main>
{{> footer}} {{> footer}}
</div>
{{> mobile-menu}} {{> mobile-menu}}
<div id="lightbox" class="hidden fixed inset-0 bg-black bg-opacity-80 z-50 flex items-center justify-center"> <div id="lightbox"
<button id="lightbox-close" class="absolute top-4 right-4 text-white text-3xl">&times;</button> x-show="lightboxOpen"
<img id="lightbox-image" src="" alt="Lightbox image" class="max-w-full max-h-full"> x-transition
@click="lightboxOpen = false"
class="fixed inset-0 bg-black bg-opacity-80 z-50 flex items-center justify-center"
x-cloak>
<button @click="lightboxOpen = false" class="absolute top-4 right-4 text-white text-3xl">&times;</button>
<img :src="lightboxImage" alt="Lightbox image" class="max-w-full max-h-full" @click.stop>
</div>
</div> </div>
{{ghost_foot}} {{ghost_foot}}
<script src="{{asset "js/ghost-config.js"}}"></script>
<script src="{{asset "js/main.js"}}"></script> <script src="{{asset "js/main.js"}}"></script>
</body> </body>
</html> </html>

View File

@@ -1,40 +1,35 @@
{{!< default}} {{!< default}}
<header class="container mx-auto px-4 py-8 text-center"> <header class="container mx-auto px-4 py-8 text-center">
<h1 class="text-5xl font-bold tracking-tight text-[var(--text-primary)]">Palina Photo Blog</h1> <h1 class="text-5xl font-bold tracking-tight text-[var(--text-primary)]">{{@site.title}}</h1>
<p class="mt-2 text-xl text-[var(--text-secondary)]">{{@site.description}}</p> <p class="mt-2 text-xl text-[var(--text-secondary)]">{{@site.description}}</p>
</header> </header>
<div class="container mx-auto px-4"> <div class="container mx-auto px-4">
{{#if posts}} {{#if posts}}
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-6"> <div id="posts-container" class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-6">
{{#foreach posts}} {{#foreach posts}}
<article class="post-grid-item opacity-0 relative bg-[var(--bg-secondary)] rounded-lg shadow-lg overflow-hidden group"> {{> "post-card"}}
<a href="{{url}}" class="block">
{{#if feature_image}}
<img
class="w-full h-72 object-cover transition-transform duration-300 ease-in-out group-hover:scale-105"
src="{{img_url feature_image size="m"}}"
srcset="{{img_url feature_image size="s"}} 400w,
{{img_url feature_image size="m"}} 600w,
{{img_url feature_image size="l"}} 1000w,
{{img_url feature_image size="xl"}} 2000w"
sizes="(max-width: 800px) 400px, (max-width: 1200px) 600px, 1000px"
alt="{{title}}"
loading="lazy"
>
{{else}}
<div class="w-full h-72 flex items-center justify-center bg-[var(--bg-tertiary)] text-[var(--text-tertiary)] text-2xl">No Image</div>
{{/if}}
<div class="absolute inset-0 bg-black bg-opacity-50 flex items-end p-4 opacity-0 group-hover:opacity-100 transition-opacity duration-300 ease-in-out">
<h2 class="text-[var(--text-primary)] text-xl font-semibold leading-tight">{{title}}</h2>
</div>
</a>
</article>
{{/foreach}} {{/foreach}}
{{#if pagination.next}}
<div id="pagination-trigger"
hx-get="{{page_url pagination.next}}"
hx-trigger="revealed"
hx-select="#posts-container > *"
hx-target="this"
hx-swap="outerHTML"
hx-indicator="#loading-spinner"
class="col-span-full h-1">
</div>
{{/if}}
</div>
<div id="loading-spinner" class="htmx-indicator text-center py-8">
<div class="inline-block animate-spin rounded-full h-8 w-8 border-4 border-[var(--brand-primary)] border-t-transparent"></div>
<p class="text-[var(--text-secondary)] mt-2">Loading more posts...</p>
</div> </div>
{{pagination}}
{{else}} {{else}}
<p class="text-center text-[var(--text-secondary)] text-2xl py-20">No posts found.</p> <p class="text-center text-[var(--text-secondary)] text-2xl py-20">No posts found.</p>
{{/if}} {{/if}}

View File

@@ -5,17 +5,19 @@
</a> </a>
<div class="flex items-center"> <div class="flex items-center">
<nav class="hidden md:flex flex-wrap items-center text-base justify-center"> <nav class="hidden md:flex flex-wrap items-center justify-center">
{{navigation type="primary"}} {{navigation type="primary"}}
<button id="theme-toggle" class="ml-4 p-2 rounded-full bg-[var(--bg-secondary)] text-[var(--text-primary)] hover:bg-[var(--bg-tertiary)] transition-colors duration-200"> <button @click="theme = (theme === 'dark' ? 'light' : 'dark')" class="ml-4 p-2 rounded-full bg-[var(--bg-secondary)] stroke-[var(--text-primary)] hover:bg-[var(--bg-tertiary)] transition-colors duration-200">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="w-5 h-5"> <svg x-show="theme === 'dark'" class="theme-toggle-dark-icon w-5 h-5" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<path fill-rule="evenodd" d="M9.528 1.718a.75.75 0 01.178 1.043l-4.243 4.243a.75.75 0 01-1.061 0L.952 2.761a.75.75 0 011.06-1.06l3.52 3.52 3.712-3.712a.75.75 0 011.042-.178zM16.292 7.625a.75.75 0 01.132 1.056l-3.903 4.171c.466 1.102.615 2.373.13 3.673-.393 1.077-.665 2.164-.707 2.296-.135.347-.216.593-.216.593H12.75a.75.75 0 010-1.5h.084c.007-.022.036-.094.09-.253.307-.872.502-1.78.544-2.701.328-1.55-.145-2.915-.756-3.83A6.064 6.064 0 0015.6 9a.75.75 0 01.692-.375zM12.75 22.5c-2.935 0-5.696-1.07-7.795-2.997a.75.75 0 011.061-1.061 9 9 0 0013.868 0 .75.75 0 011.06-1.061C18.446 21.43 15.685 22.5 12.75 22.5z" clip-rule="evenodd" /> <path stroke-linecap="round" stroke-linejoin="round" d="M12 3v2.25m6.364.386-1.591 1.591M21 12h-2.25m-.386 6.364-1.591-1.591M12 18.75V21m-4.773-4.227-1.591 1.591M5.25 12H3m4.227-4.773L5.636 5.636M15.75 12a3.75 3.75 0 1 1-7.5 0 3.75 3.75 0 0 1 7.5 0Z" />
<path fill-rule="evenodd" d="M15.6 13.5a3.6 3.6 0 11-7.2 0 3.6 3.6 0 017.2 0z" clip-rule="evenodd" /> </svg>
<svg x-show="theme === 'light'" class="theme-toggle-light-icon w-5 h-5" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" x-cloak>
<path stroke-linecap="round" stroke-linejoin="round" d="M21.752 15.002A9.72 9.72 0 0 1 18 15.75c-5.385 0-9.75-4.365-9.75-9.75 0-1.33.266-2.597.748-3.752A9.753 9.753 0 0 0 3 11.25C3 16.635 7.365 21 12.75 21a9.753 9.753 0 0 0 9.002-5.998Z" />
</svg> </svg>
</button> </button>
</nav> </nav>
<button id="mobile-menu-toggle" class="md:hidden p-2 rounded-full bg-[var(--bg-secondary)] text-[var(--text-primary)] hover:bg-[var(--bg-tertiary)] transition-colors duration-200"> <button @click="mobileMenuOpen = true" class="md:hidden p-2 rounded-full bg-[var(--bg-secondary)] text-[var(--text-primary)] hover:bg-[var(--bg-tertiary)] transition-colors duration-200">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6"> <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
<path stroke-linecap="round" stroke-linejoin="round" d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5" /> <path stroke-linecap="round" stroke-linejoin="round" d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5" />
</svg> </svg>

View File

@@ -1,12 +1,21 @@
<div id="mobile-menu" class="fixed inset-0 z-40 bg-[var(--bg-primary)] transform -translate-x-full transition-transform duration-300 ease-in-out md:hidden"> <div id="mobile-menu"
x-show="mobileMenuOpen"
x-transition:enter="transition ease-out duration-300"
x-transition:enter-start="-translate-x-full"
x-transition:enter-end="translate-x-0"
x-transition:leave="transition ease-in duration-300"
x-transition:leave-start="translate-x-0"
x-transition:leave-end="-translate-x-full"
class="fixed inset-0 z-40 bg-[var(--bg-primary)] transform md:hidden"
x-cloak>
<div class="flex justify-end p-5"> <div class="flex justify-end p-5">
<button id="mobile-menu-close" class="p-2 rounded-full bg-[var(--bg-secondary)] text-[var(--text-primary)] hover:bg-[var(--bg-tertiary)] transition-colors duration-200"> <button @click="mobileMenuOpen = false" class="p-2 rounded-full bg-[var(--bg-secondary)] text-[var(--text-primary)] hover:bg-[var(--bg-tertiary)] transition-colors duration-200">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6"> <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" /> <path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />
</svg> </svg>
</button> </button>
</div> </div>
<nav class="flex flex-col items-center justify-center h-full space-y-8 text-2xl"> <nav class="flex flex-col items-center justify-center h-full space-y-8 text-2xl" @click="mobileMenuOpen = false">
{{navigation type="primary"}} {{navigation type="primary"}}
</nav> </nav>
</div> </div>

22
partials/post-card.hbs Normal file
View File

@@ -0,0 +1,22 @@
<article class="post-grid-item opacity-0 relative bg-[var(--bg-secondary)] rounded-lg shadow-lg overflow-hidden group">
<a href="{{url}}" class="block">
{{#if feature_image}}
<img
class="w-full h-72 object-cover transition-transform duration-300 ease-in-out group-hover:scale-105"
src="{{img_url feature_image size="m"}}"
srcset="{{img_url feature_image size="s"}} 400w,
{{img_url feature_image size="m"}} 600w,
{{img_url feature_image size="l"}} 1000w,
{{img_url feature_image size="xl"}} 2000w"
sizes="(max-width: 800px) 400px, (max-width: 1200px) 600px, 1000px"
alt="{{title}}"
loading="lazy"
>
{{else}}
<div class="w-full h-72 flex items-center justify-center bg-[var(--bg-tertiary)] text-[var(--text-tertiary)] text-2xl">No Image</div>
{{/if}}
<div class="absolute inset-0 bg-black bg-opacity-50 flex items-end p-4 opacity-0 group-hover:opacity-100 transition-opacity duration-300 ease-in-out">
<h2 class="text-[var(--text-primary)] text-xl font-semibold leading-tight">{{title}}</h2>
</div>
</a>
</article>

View File

@@ -1,8 +1,9 @@
{{!< default}} {{!< default}}
{{#post}}
<article class="container mx-auto px-4 py-12"> <article class="container mx-auto px-4 py-12">
<header class="text-center mb-8"> <header class="text-center mb-8">
<h1 class="text-6xl font-bold tracking-tight text-[var(--text-primary)] mb-4">{{title}}</h1> <h1 class="text-6xl font-bold tracking-tight text-[var(--text-primary)] mb-4">{{title fallback="No Title Provided"}}</h1>
<section class="post-meta text-[var(--text-secondary)] text-lg"> <section class="post-meta text-[var(--text-secondary)] text-lg">
<time datetime="{{date format="YYYY-MM-DD"}}">{{date format="MMMM DD, YYYY"}}</time> <time datetime="{{date format="YYYY-MM-DD"}}">{{date format="MMMM DD, YYYY"}}</time>
{{#if primary_tag}} {{#if primary_tag}}
@@ -20,17 +21,13 @@
srcset="{{img_url feature_image size="l"}} 1000w, srcset="{{img_url feature_image size="l"}} 1000w,
{{img_url feature_image size="xl"}} 2000w" {{img_url feature_image size="xl"}} 2000w"
sizes="(max-width: 1000px) 1000px, 2000px" sizes="(max-width: 1000px) 1000px, 2000px"
alt="{{title}}" alt="{{title fallback="No Title"}}"
> >
</figure> </figure>
{{else}}
<div class="mb-12 rounded-lg overflow-hidden shadow-xl w-full h-96 flex items-center justify-center bg-[var(--bg-tertiary)] text-[var(--text-tertiary)] text-3xl">
No Feature Image
</div>
{{/if}} {{/if}}
<section class="post-content max-w-3xl mx-auto text-[var(--text-primary)] leading-relaxed text-lg prose prose-invert"> <section class="post-content max-w-3xl mx-auto text-[var(--text-primary)] leading-relaxed text-lg prose prose-invert">
{{content}} {{content fallback="<p>No content provided for this post.</p>"}}
</section> </section>
<footer class="mt-12 pt-8 border-t border-[var(--bg-tertiary)] text-center"> <footer class="mt-12 pt-8 border-t border-[var(--bg-tertiary)] text-center">
@@ -39,3 +36,4 @@
</a> </a>
</footer> </footer>
</article> </article>
{{/post}}