dev #5
@@ -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!
|
||||||
@@ -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 |
@@ -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"
|
||||||
|
}
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -10,7 +10,7 @@ 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;
|
||||||
@@ -48,13 +48,33 @@ const fullOgImage = new URL(ogImage, Astro.site).href;
|
|||||||
|
|
||||||
<!-- 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
|
||||||
|
name="keywords"
|
||||||
|
content="self-hosted, privacy, open-source, furry, developer, cozy, hidden den"
|
||||||
|
/>
|
||||||
<meta name="theme-color" content="#d4a574" />
|
<meta name="theme-color" content="#d4a574" />
|
||||||
<meta name="color-scheme" content="dark" />
|
<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 /> -->
|
||||||
@@ -83,7 +103,9 @@ const fullOgImage = new URL(ogImage, Astro.site).href;
|
|||||||
--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;
|
||||||
}
|
}
|
||||||
|
|
||||||
* {
|
* {
|
||||||
@@ -104,7 +126,12 @@ const fullOgImage = new URL(ogImage, Astro.site).href;
|
|||||||
line-height: 1.6;
|
line-height: 1.6;
|
||||||
}
|
}
|
||||||
|
|
||||||
h1, h2, h3, h4, h5, h6 {
|
h1,
|
||||||
|
h2,
|
||||||
|
h3,
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
color: var(--color-accent-bright);
|
color: var(--color-accent-bright);
|
||||||
line-height: 1.2;
|
line-height: 1.2;
|
||||||
}
|
}
|
||||||
|
|||||||
+93
-189
@@ -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
|
Welcome to Hidden Den Cafe - a warm, self-hosted space where
|
||||||
where technology meets comfort. This is a personal
|
technology meets comfort. This is a personal corner of the
|
||||||
corner of the internet built with love, care, and a
|
internet built with love, care, and a strong belief in
|
||||||
strong belief in privacy and open-source values.
|
privacy and open-source values.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Everything here runs on self-hosted infrastructure,
|
Everything here runs on self-hosted infrastructure, giving
|
||||||
giving complete control over data and services. No cloud
|
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>
|
||||||
</div>
|
</Card>
|
||||||
</div>
|
</Section>
|
||||||
</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
|
building things and being part of the warm, welcoming furry
|
||||||
furry community. I'm passionate about self-hosting,
|
community. I'm passionate about self-hosting, open-source
|
||||||
open-source software, and creating cozy spaces both
|
software, and creating cozy spaces both online and off.
|
||||||
online and off.
|
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
I work primarily with Python and Flask, though I'm
|
I work primarily with Python and Flask, though I'm always
|
||||||
always learning new things (currently exploring
|
learning new things (currently exploring JavaScript and the
|
||||||
JavaScript and the C stack). When I get those surges of
|
C stack). When I get those surges of creative energy, I love
|
||||||
creative energy, I love diving into new projects - from
|
diving into new projects - from Reddit downloaders to
|
||||||
Reddit downloaders to Telegram sticker tools, and
|
Telegram sticker tools, and everything in between.
|
||||||
everything in between.
|
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>Coffee enthusiast • Linux lover • Self-hosting advocate</p>
|
||||||
Coffee enthusiast • Linux lover • Self-hosting advocate
|
</Card>
|
||||||
</p>
|
</Section>
|
||||||
</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>
|
||||||
|
</Card>
|
||||||
<div class="service-item coming-soon" role="listitem">
|
</Section>
|
||||||
<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>
|
|
||||||
</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
|
If you'd like to support the Hidden Den and help keep the
|
||||||
the lights on, here are some ways you can contribute:
|
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"
|
||||||
|
description="Found a bug or have a suggestion? Let me know!"
|
||||||
|
/>
|
||||||
|
<SupportItem
|
||||||
|
title="Buy Me a Coffee"
|
||||||
|
description="Donations help cover server costs and keep the den cozy."
|
||||||
|
comingSoonNote="Payment links coming soon!"
|
||||||
|
/>
|
||||||
|
<SupportItem
|
||||||
|
title="Contribute"
|
||||||
|
description="Check out the projects on Gitea - contributions are always welcome!"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
</Card>
|
||||||
<div class="support-item" role="listitem">
|
</Section>
|
||||||
<h3>Report Issues</h3>
|
|
||||||
<p>
|
|
||||||
Found a bug or have a suggestion? Let me know!
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="support-item" role="listitem">
|
|
||||||
<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>
|
|
||||||
</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>
|
||||||
|
|||||||
Reference in New Issue
Block a user