dev #5

Merged
Latte merged 8 commits from dev into main 2026-01-01 14:04:36 +00:00
9 changed files with 622 additions and 351 deletions
Showing only changes of commit 6ed0eee514 - Show all commits
+51
View File
@@ -0,0 +1,51 @@
# Favicon Generation Instructions
The following favicon files are referenced in the site but need to be generated:
- `favicon-16x16.png` - 16x16px PNG favicon
- `favicon-32x32.png` - 32x32px PNG favicon
- `apple-touch-icon.png` - 180x180px PNG for Apple devices
- `og-image.png` - 1200x630px PNG for social media sharing (optional, currently using SVG)
## How to Generate
### Option 1: Use an Online Tool
Visit https://realfavicongenerator.net/ and upload your source image (coffee emoji or custom design).
### Option 2: Use ImageMagick (if available)
If you have a source PNG image:
```bash
# 16x16
convert source.png -resize 16x16 favicon-16x16.png
# 32x32
convert source.png -resize 32x32 favicon-32x32.png
# Apple touch icon
convert source.png -resize 180x180 apple-touch-icon.png
# OG image
convert source.png -resize 1200x630 og-image.png
```
### Option 3: Use the SVG favicon
The current `favicon.svg` (coffee emoji) works in modern browsers. The PNG variants are fallbacks for older browsers and specific platforms.
## Current Status
-`favicon.svg` - Exists (coffee emoji)
-`favicon-16x16.png` - Needs to be created
-`favicon-32x32.png` - Needs to be created
-`apple-touch-icon.png` - Needs to be created
-`og-image.svg` - Created (SVG placeholder)
- ⚠️ `og-image.png` - Optional (browsers support SVG, but PNG is more compatible)
## Design Recommendations
Use the cozy coffee theme colors:
- Background: `#1a1410` (dark coffee)
- Accent: `#e8bf8e` (light coffee/cream)
- Text: `#f4e9d8` (cream)
The favicon should be simple and recognizable at small sizes. The coffee emoji ☕ is perfect!
+30
View File
@@ -0,0 +1,30 @@
<svg width="1200" height="630" xmlns="http://www.w3.org/2000/svg">
<!-- Background gradient -->
<defs>
<linearGradient id="bgGradient" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#1a1410;stop-opacity:1" />
<stop offset="100%" style="stop-color:#2a1f18;stop-opacity:1" />
</linearGradient>
</defs>
<!-- Background -->
<rect width="1200" height="630" fill="url(#bgGradient)"/>
<!-- Coffee cup emoji (approximate) -->
<text x="600" y="250" font-size="120" text-anchor="middle"></text>
<!-- Title -->
<text x="600" y="380" font-family="system-ui, sans-serif" font-size="72" font-weight="bold" fill="#e8bf8e" text-anchor="middle">
Hidden Den Cafe
</text>
<!-- Subtitle -->
<text x="600" y="450" font-family="system-ui, sans-serif" font-size="36" fill="#c4b5a0" text-anchor="middle">
A cozy corner of the internet
</text>
<!-- Bottom text -->
<text x="600" y="550" font-family="system-ui, sans-serif" font-size="24" fill="#8b6f47" text-anchor="middle">
Self-hosted • Privacy-focused • Furry-friendly
</text>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

+32
View File
@@ -0,0 +1,32 @@
{
"name": "Hidden Den Cafe",
"short_name": "Hidden Den",
"description": "A cozy, self-hosted corner of the internet",
"icons": [
{
"src": "/favicon.svg",
"sizes": "any",
"type": "image/svg+xml"
},
{
"src": "/favicon-16x16.png",
"sizes": "16x16",
"type": "image/png"
},
{
"src": "/favicon-32x32.png",
"sizes": "32x32",
"type": "image/png"
},
{
"src": "/apple-touch-icon.png",
"sizes": "180x180",
"type": "image/png"
}
],
"theme_color": "#d4a574",
"background_color": "#1a1410",
"display": "standalone",
"start_url": "/",
"orientation": "portrait"
}
+74
View File
@@ -0,0 +1,74 @@
---
interface Props {
class?: string;
}
const { class: className } = Astro.props;
---
<div class:list={["card", "scroll-animate", className]}>
<slot />
</div>
<style>
.card {
background: var(--color-bg-light);
border-radius: 12px;
padding: var(--space-lg);
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.3);
border: 1px solid rgba(212, 165, 116, 0.1);
transition: box-shadow 0.3s ease;
}
.card:hover {
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.4);
}
.card :global(h2) {
font-size: 2rem;
margin-bottom: var(--space-md);
}
.card :global(p) {
margin-bottom: var(--space-md);
color: var(--color-text);
}
.card :global(p:last-child) {
margin-bottom: 0;
}
/* Scroll animation states */
.scroll-animate {
opacity: 0;
transform: translateY(30px);
transition: opacity 0.6s ease-out, transform 0.6s ease-out;
}
.scroll-animate.visible {
opacity: 1;
transform: translateY(0);
}
@media (prefers-reduced-motion: reduce) {
.card {
transition: none;
}
.card:hover {
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.3);
}
.scroll-animate {
opacity: 1;
transform: none;
transition: none;
}
}
@media (max-width: 768px) {
.card :global(h2) {
font-size: 1.5rem;
}
}
</style>
+27
View File
@@ -0,0 +1,27 @@
---
interface Props {
class?: string;
ariaLabelledby?: string;
}
const { class: className, ariaLabelledby } = Astro.props;
---
<section class:list={["section", className]} aria-labelledby={ariaLabelledby}>
<div class="container">
<slot />
</div>
</section>
<style>
.section {
padding: var(--space-lg) 0;
}
.container {
max-width: 800px;
margin: 0 auto;
padding: 0 var(--space-md);
width: 100%;
}
</style>
+68
View File
@@ -0,0 +1,68 @@
---
interface Props {
title: string;
description: string;
url?: string;
comingSoon?: boolean;
}
const { title, description, url, comingSoon = false } = Astro.props;
---
<div class="service-item" class:list={{ "coming-soon": comingSoon }} role="listitem">
<h3>
{url ? (
<a
href={url}
target="_blank"
rel="noopener noreferrer"
aria-label={`Visit ${title}`}
>
{title}
</a>
) : (
title
)}
</h3>
<p>{description}</p>
</div>
<style>
.service-item {
background: var(--color-bg);
padding: var(--space-md);
border-radius: 8px;
border-left: 4px solid var(--color-accent);
transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.service-item:hover {
transform: translateX(4px);
box-shadow: 0 4px 8px rgba(212, 165, 116, 0.2);
}
.service-item.coming-soon {
border-left-color: var(--color-warm);
opacity: 0.8;
}
.service-item h3 {
margin-bottom: var(--space-xs);
font-size: 1.25rem;
}
.service-item p {
color: var(--color-text-dim);
margin: 0;
}
@media (prefers-reduced-motion: reduce) {
.service-item {
transition: none;
}
.service-item:hover {
transform: none;
}
}
</style>
+58
View File
@@ -0,0 +1,58 @@
---
interface Props {
title: string;
description: string;
comingSoonNote?: string;
}
const { title, description, comingSoonNote } = Astro.props;
---
<div class="support-item" role="listitem">
<h3>{title}</h3>
<p>
{description}
{comingSoonNote && (
<span class="coming-soon-text">({comingSoonNote})</span>
)}
</p>
</div>
<style>
.support-item {
background: var(--color-bg);
padding: var(--space-md);
border-radius: 8px;
transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.support-item:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(212, 165, 116, 0.15);
}
.support-item h3 {
margin-bottom: var(--space-xs);
font-size: 1.25rem;
}
.support-item p {
color: var(--color-text-dim);
margin: 0;
}
.coming-soon-text {
font-style: italic;
color: var(--color-warm);
}
@media (prefers-reduced-motion: reduce) {
.support-item {
transition: none;
}
.support-item:hover {
transform: none;
}
}
</style>
+170 -143
View File
@@ -1,16 +1,16 @@
--- ---
interface Props { interface Props {
title: string; title: string;
description?: string; description?: string;
ogImage?: string; ogImage?: string;
canonicalURL?: string; canonicalURL?: string;
} }
const { const {
title, title,
description = "Hidden Den Cafe - A cozy, self-hosted corner of the internet. Privacy-focused, furry-friendly, and built with love.", description = "Hidden Den Cafe - A cozy, self-hosted corner of the internet. Privacy-focused, furry-friendly, and built with love.",
ogImage = "/og-image.png", ogImage = "/og-image.png",
canonicalURL = Astro.url.pathname canonicalURL = Astro.url.pathname,
} = Astro.props; } = Astro.props;
const fullCanonicalURL = new URL(canonicalURL, Astro.site).href; const fullCanonicalURL = new URL(canonicalURL, Astro.site).href;
@@ -19,156 +19,183 @@ const fullOgImage = new URL(ogImage, Astro.site).href;
<!doctype html> <!doctype html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="generator" content={Astro.generator} /> <meta name="generator" content={Astro.generator} />
<!-- Primary Meta Tags --> <!-- Primary Meta Tags -->
<title>{title}</title> <title>{title}</title>
<meta name="title" content={title} /> <meta name="title" content={title} />
<meta name="description" content={description} /> <meta name="description" content={description} />
<link rel="canonical" href={fullCanonicalURL} /> <link rel="canonical" href={fullCanonicalURL} />
<!-- Open Graph / Facebook --> <!-- Open Graph / Facebook -->
<meta property="og:type" content="website" /> <meta property="og:type" content="website" />
<meta property="og:url" content={fullCanonicalURL} /> <meta property="og:url" content={fullCanonicalURL} />
<meta property="og:title" content={title} /> <meta property="og:title" content={title} />
<meta property="og:description" content={description} /> <meta property="og:description" content={description} />
<meta property="og:image" content={fullOgImage} /> <meta property="og:image" content={fullOgImage} />
<meta property="og:site_name" content="Hidden Den Cafe" /> <meta property="og:site_name" content="Hidden Den Cafe" />
<meta property="og:locale" content="en_US" /> <meta property="og:locale" content="en_US" />
<!-- Twitter Card --> <!-- Twitter Card -->
<meta name="twitter:card" content="summary_large_image" /> <meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:url" content={fullCanonicalURL} /> <meta name="twitter:url" content={fullCanonicalURL} />
<meta name="twitter:title" content={title} /> <meta name="twitter:title" content={title} />
<meta name="twitter:description" content={description} /> <meta name="twitter:description" content={description} />
<meta name="twitter:image" content={fullOgImage} /> <meta name="twitter:image" content={fullOgImage} />
<!-- Additional Meta Tags --> <!-- Additional Meta Tags -->
<meta name="author" content="Latte" /> <meta name="author" content="Latte" />
<meta name="keywords" content="self-hosted, privacy, open-source, furry, developer, cozy, hidden den" /> <meta
<meta name="theme-color" content="#d4a574" /> name="keywords"
<meta name="color-scheme" content="dark" /> content="self-hosted, privacy, open-source, furry, developer, cozy, hidden den"
/>
<meta name="theme-color" content="#d4a574" />
<meta name="color-scheme" content="dark" />
<!-- Favicon --> <!-- Favicons -->
<link rel="icon" type="image/svg+xml" href="/favicon.svg" /> <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<link rel="apple-touch-icon" href="/favicon.svg" /> <link
rel="icon"
type="image/png"
sizes="32x32"
href="/favicon-32x32.png"
/>
<link
rel="icon"
type="image/png"
sizes="16x16"
href="/favicon-16x16.png"
/>
<link
rel="apple-touch-icon"
sizes="180x180"
href="/apple-touch-icon.png"
/>
<link rel="manifest" href="/site.webmanifest" />
<!-- Preconnect for performance (if needed for future external resources) --> <!-- Preconnect for performance (if needed for future external resources) -->
<!-- <link rel="preconnect" href="https://example.com" crossorigin /> --> <!-- <link rel="preconnect" href="https://example.com" crossorigin /> -->
</head> </head>
<body> <body>
<slot /> <slot />
</body> </body>
</html> </html>
<style is:global> <style is:global>
:root { :root {
/* Cozy Den Color Palette */ /* Cozy Den Color Palette */
--color-bg: #1a1410; --color-bg: #1a1410;
--color-bg-light: #2a1f18; --color-bg-light: #2a1f18;
--color-text: #f4e9d8; --color-text: #f4e9d8;
--color-text-dim: #c4b5a0; --color-text-dim: #c4b5a0;
--color-accent: #d4a574; --color-accent: #d4a574;
--color-accent-bright: #e8bf8e; --color-accent-bright: #e8bf8e;
--color-warm: #8b6f47; --color-warm: #8b6f47;
/* Spacing */ /* Spacing */
--space-xs: 0.5rem; --space-xs: 0.5rem;
--space-sm: 1rem; --space-sm: 1rem;
--space-md: 1.5rem; --space-md: 1.5rem;
--space-lg: 2rem; --space-lg: 2rem;
--space-xl: 3rem; --space-xl: 3rem;
/* Typography */ /* Typography */
--font-body: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; --font-body:
} system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
sans-serif;
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html {
font-family: var(--font-body);
background: var(--color-bg);
color: var(--color-text);
scroll-behavior: smooth;
}
body {
min-height: 100vh;
line-height: 1.6;
}
h1, h2, h3, h4, h5, h6 {
color: var(--color-accent-bright);
line-height: 1.2;
}
a {
color: var(--color-accent-bright);
text-decoration: none;
transition: color 0.2s ease;
}
a:hover {
color: var(--color-accent);
}
a:focus-visible {
outline: 2px solid var(--color-accent);
outline-offset: 2px;
border-radius: 2px;
}
/* Smooth animations */
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(20px);
} }
to {
opacity: 1; * {
transform: translateY(0); margin: 0;
padding: 0;
box-sizing: border-box;
} }
}
.fade-in { html {
animation: fadeIn 0.6s ease-out; font-family: var(--font-body);
} background: var(--color-bg);
color: var(--color-text);
/* Respect user's motion preferences */ scroll-behavior: smooth;
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
scroll-behavior: auto !important;
} }
}
/* Improve focus visibility for keyboard navigation */ body {
*:focus-visible { min-height: 100vh;
outline: 2px solid var(--color-accent); line-height: 1.6;
outline-offset: 2px; }
}
/* Screen reader only content */ h1,
.sr-only { h2,
position: absolute; h3,
width: 1px; h4,
height: 1px; h5,
padding: 0; h6 {
margin: -1px; color: var(--color-accent-bright);
overflow: hidden; line-height: 1.2;
clip: rect(0, 0, 0, 0); }
white-space: nowrap;
border-width: 0; a {
} color: var(--color-accent-bright);
text-decoration: none;
transition: color 0.2s ease;
}
a:hover {
color: var(--color-accent);
}
a:focus-visible {
outline: 2px solid var(--color-accent);
outline-offset: 2px;
border-radius: 2px;
}
/* Smooth animations */
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.fade-in {
animation: fadeIn 0.6s ease-out;
}
/* Respect user's motion preferences */
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
scroll-behavior: auto !important;
}
}
/* Improve focus visibility for keyboard navigation */
*:focus-visible {
outline: 2px solid var(--color-accent);
outline-offset: 2px;
}
/* Screen reader only content */
.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border-width: 0;
}
</style> </style>
+112 -208
View File
@@ -1,5 +1,9 @@
--- ---
import BaseLayout from "../layouts/BaseLayout.astro"; import BaseLayout from "../layouts/BaseLayout.astro";
import Card from "../components/Card.astro";
import Section from "../components/Section.astro";
import ServiceItem from "../components/ServiceItem.astro";
import SupportItem from "../components/SupportItem.astro";
--- ---
<BaseLayout <BaseLayout
@@ -18,137 +22,95 @@ import BaseLayout from "../layouts/BaseLayout.astro";
</section> </section>
<!-- About Hidden Den Section --> <!-- About Hidden Den Section -->
<section class="section about-den" aria-labelledby="about-den-heading"> <Section class="about-den" ariaLabelledby="about-den-heading">
<div class="container"> <Card>
<div class="card fade-in"> <h2 id="about-den-heading">About Hidden Den</h2>
<h2 id="about-den-heading">About Hidden Den</h2> <p>
<p> Welcome to Hidden Den Cafe - a warm, self-hosted space where
Welcome to Hidden Den Cafe - a warm, self-hosted space technology meets comfort. This is a personal corner of the
where technology meets comfort. This is a personal internet built with love, care, and a strong belief in
corner of the internet built with love, care, and a privacy and open-source values.
strong belief in privacy and open-source values. </p>
</p> <p>
<p> Everything here runs on self-hosted infrastructure, giving
Everything here runs on self-hosted infrastructure, complete control over data and services. No cloud
giving complete control over data and services. No cloud dependencies, no tracking, just a cozy digital home.
dependencies, no tracking, just a cozy digital home. </p>
</p> </Card>
</div> </Section>
</div>
</section>
<!-- About Latte Section --> <!-- About Latte Section -->
<section class="section about-me" aria-labelledby="about-me-heading"> <Section class="about-me" ariaLabelledby="about-me-heading">
<div class="container"> <Card>
<div class="card fade-in"> <h2 id="about-me-heading">About Me</h2>
<h2 id="about-me-heading">About Me</h2> <p>
<p> Hey there! I'm Latte, a gay furry developer who loves
Hey there! I'm Latte, a gay furry developer who loves building things and being part of the warm, welcoming furry
building things and being part of the warm, welcoming community. I'm passionate about self-hosting, open-source
furry community. I'm passionate about self-hosting, software, and creating cozy spaces both online and off.
open-source software, and creating cozy spaces both </p>
online and off. <p>
</p> I work primarily with Python and Flask, though I'm always
<p> learning new things (currently exploring JavaScript and the
I work primarily with Python and Flask, though I'm C stack). When I get those surges of creative energy, I love
always learning new things (currently exploring diving into new projects - from Reddit downloaders to
JavaScript and the C stack). When I get those surges of Telegram sticker tools, and everything in between.
creative energy, I love diving into new projects - from </p>
Reddit downloaders to Telegram sticker tools, and <p>Coffee enthusiast • Linux lover • Self-hosting advocate</p>
everything in between. </Card>
</p> </Section>
<p>
Coffee enthusiast • Linux lover • Self-hosting advocate
</p>
</div>
</div>
</section>
<!-- Services Section --> <!-- Services Section -->
<section class="section services" aria-labelledby="services-heading"> <Section class="services" ariaLabelledby="services-heading">
<div class="container"> <Card>
<div class="card fade-in"> <h2 id="services-heading">Services</h2>
<h2 id="services-heading">Services</h2> <p>Here are the services currently running in the den:</p>
<p>Here are the services currently running in the den:</p>
<div class="service-list" role="list"> <div class="service-list" role="list">
<div class="service-item" role="listitem"> <ServiceItem
<h3> title="Gitea"
<a description="Self-hosted Git service for all my projects and code repositories."
href="https://git.hiddenden.cafe" url="https://git.hiddenden.cafe"
target="_blank" />
rel="noopener noreferrer" <ServiceItem
aria-label="Visit Gitea - Self-hosted Git service" title="More Coming Soon"
> description="The den is always growing! More services will be added as they're developed and deployed."
Gitea comingSoon={true}
</a> />
</h3>
<p>
Self-hosted Git service for all my projects and
code repositories.
</p>
</div>
<div class="service-item coming-soon" role="listitem">
<h3>More Coming Soon</h3>
<p>
The den is always growing! More services will be
added as they're developed and deployed.
</p>
</div>
</div>
</div> </div>
</div> </Card>
</section> </Section>
<!-- Support Section --> <!-- Support Section -->
<section class="section support" aria-labelledby="support-heading"> <Section class="support" ariaLabelledby="support-heading">
<div class="container"> <Card>
<div class="card fade-in"> <h2 id="support-heading">How to Help Out</h2>
<h2 id="support-heading">How to Help Out</h2> <p>
<p> If you'd like to support the Hidden Den and help keep the
If you'd like to support the Hidden Den and help keep lights on, here are some ways you can contribute:
the lights on, here are some ways you can contribute: </p>
</p>
<div class="support-list" role="list"> <div class="support-list" role="list">
<div class="support-item" role="listitem"> <SupportItem
<h3>Share & Spread the Word</h3> title="Share & Spread the Word"
<p> description="Tell others about the projects and services hosted here!"
Tell others about the projects and services />
hosted here! <SupportItem
</p> title="Report Issues"
</div> description="Found a bug or have a suggestion? Let me know!"
/>
<div class="support-item" role="listitem"> <SupportItem
<h3>Report Issues</h3> title="Buy Me a Coffee"
<p> description="Donations help cover server costs and keep the den cozy."
Found a bug or have a suggestion? Let me know! comingSoonNote="Payment links coming soon!"
</p> />
</div> <SupportItem
title="Contribute"
<div class="support-item" role="listitem"> description="Check out the projects on Gitea - contributions are always welcome!"
<h3>Buy Me a Coffee</h3> />
<p>
Donations help cover server costs and keep the
den cozy.
<span class="coming-soon-text"
>(Payment links coming soon!)</span
>
</p>
</div>
<div class="support-item" role="listitem">
<h3>Contribute</h3>
<p>
Check out the projects on Gitea - contributions
are always welcome!
</p>
</div>
</div>
</div> </div>
</div> </Card>
</section> </Section>
<!-- Footer --> <!-- Footer -->
<footer class="footer" role="contentinfo"> <footer class="footer" role="contentinfo">
@@ -166,6 +128,32 @@ import BaseLayout from "../layouts/BaseLayout.astro";
</div> </div>
</footer> </footer>
</main> </main>
<!-- Scroll Animation Script -->
<script>
// Intersection Observer for scroll animations
const observerOptions = {
threshold: 0.1,
rootMargin: "0px 0px -50px 0px",
};
const observer = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
entry.target.classList.add("visible");
// Optionally unobserve after animation
observer.unobserve(entry.target);
}
});
}, observerOptions);
// Observe all elements with scroll-animate class
document.addEventListener("DOMContentLoaded", () => {
const animateElements =
document.querySelectorAll(".scroll-animate");
animateElements.forEach((el) => observer.observe(el));
});
</script>
</BaseLayout> </BaseLayout>
<style> <style>
@@ -204,91 +192,15 @@ import BaseLayout from "../layouts/BaseLayout.astro";
color: var(--color-text-dim); color: var(--color-text-dim);
} }
/* Sections */ /* Service and Support Lists */
.section { .service-list,
padding: var(--space-lg) 0; .support-list {
}
.card {
background: var(--color-bg-light);
border-radius: 12px;
padding: var(--space-lg);
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.3);
border: 1px solid rgba(212, 165, 116, 0.1);
}
.card h2 {
font-size: 2rem;
margin-bottom: var(--space-md);
}
.card p {
margin-bottom: var(--space-md);
color: var(--color-text);
}
.card p:last-child {
margin-bottom: 0;
}
/* Services Section */
.service-list {
margin-top: var(--space-md); margin-top: var(--space-md);
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: var(--space-md); gap: var(--space-md);
} }
.service-item {
background: var(--color-bg);
padding: var(--space-md);
border-radius: 8px;
border-left: 4px solid var(--color-accent);
}
.service-item h3 {
margin-bottom: var(--space-xs);
font-size: 1.25rem;
}
.service-item p {
color: var(--color-text-dim);
margin: 0;
}
.service-item.coming-soon {
border-left-color: var(--color-warm);
opacity: 0.8;
}
/* Support Section */
.support-list {
margin-top: var(--space-md);
display: grid;
gap: var(--space-md);
}
.support-item {
background: var(--color-bg);
padding: var(--space-md);
border-radius: 8px;
}
.support-item h3 {
margin-bottom: var(--space-xs);
font-size: 1.25rem;
}
.support-item p {
color: var(--color-text-dim);
margin: 0;
}
.coming-soon-text {
font-style: italic;
color: var(--color-warm);
}
/* Footer */ /* Footer */
.footer { .footer {
margin-top: auto; margin-top: auto;
@@ -310,10 +222,6 @@ import BaseLayout from "../layouts/BaseLayout.astro";
gap: var(--space-sm); gap: var(--space-sm);
} }
.separator {
color: var(--color-warm);
}
/* Responsive */ /* Responsive */
@media (max-width: 768px) { @media (max-width: 768px) {
.hero-title { .hero-title {
@@ -323,9 +231,5 @@ import BaseLayout from "../layouts/BaseLayout.astro";
.hero-subtitle { .hero-subtitle {
font-size: 1rem; font-size: 1rem;
} }
.card h2 {
font-size: 1.5rem;
}
} }
</style> </style>