Initial website — Astro + Tailwind + Sanity schema, 9 pages

This commit is contained in:
2026-06-04 15:53:52 +00:00
commit 1d1492e611
33 changed files with 7472 additions and 0 deletions

5
.env.example Normal file
View File

@@ -0,0 +1,5 @@
# Sanity-Projekt-ID — aus sanity.io/manage
PUBLIC_SANITY_PROJECT_ID=xxxxxxxx
# Dataset — in der Regel "production"
PUBLIC_SANITY_DATASET=production

24
.gitignore vendored Normal file
View File

@@ -0,0 +1,24 @@
# build output
dist/
# generated types
.astro/
# dependencies
node_modules/
# logs
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# environment variables
.env
.env.production
# macOS-specific files
.DS_Store
# jetbrains setting folder
.idea/

4
.vscode/extensions.json vendored Normal file
View File

@@ -0,0 +1,4 @@
{
"recommendations": ["astro-build.astro-vscode"],
"unwantedRecommendations": []
}

11
.vscode/launch.json vendored Normal file
View File

@@ -0,0 +1,11 @@
{
"version": "0.2.0",
"configurations": [
{
"command": "./node_modules/.bin/astro dev",
"name": "Development server",
"request": "launch",
"type": "node-terminal"
}
]
}

43
README.md Normal file
View File

@@ -0,0 +1,43 @@
# Astro Starter Kit: Minimal
```sh
npm create astro@latest -- --template minimal
```
> 🧑‍🚀 **Seasoned astronaut?** Delete this file. Have fun!
## 🚀 Project Structure
Inside of your Astro project, you'll see the following folders and files:
```text
/
├── public/
├── src/
│ └── pages/
│ └── index.astro
└── package.json
```
Astro looks for `.astro` or `.md` files in the `src/pages/` directory. Each page is exposed as a route based on its file name.
There's nothing special about `src/components/`, but that's where we like to put any Astro/React/Vue/Svelte/Preact components.
Any static assets, like images, can be placed in the `public/` directory.
## 🧞 Commands
All commands are run from the root of the project, from a terminal:
| Command | Action |
| :------------------------ | :----------------------------------------------- |
| `npm install` | Installs dependencies |
| `npm run dev` | Starts local dev server at `localhost:4321` |
| `npm run build` | Build your production site to `./dist/` |
| `npm run preview` | Preview your build locally, before deploying |
| `npm run astro ...` | Run CLI commands like `astro add`, `astro check` |
| `npm run astro -- --help` | Get help using the Astro CLI |
## 👀 Want to learn more?
Feel free to check [our documentation](https://docs.astro.build) or jump into our [Discord server](https://astro.build/chat).

13
astro.config.mjs Normal file
View File

@@ -0,0 +1,13 @@
// @ts-check
import { defineConfig } from "astro/config";
import tailwindcss from "@tailwindcss/vite";
export default defineConfig({
site: "https://kitafreunde-regenbogen.de",
vite: {
plugins: [tailwindcss()],
},
// Für Cloudflare Pages: output auf "static" (default)
// Wenn Server-Features gewünscht: output: "server", adapter: cloudflare()
output: "static",
});

5694
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

21
package.json Normal file
View File

@@ -0,0 +1,21 @@
{
"name": "kitafreunde-regenbogen",
"type": "module",
"version": "0.0.1",
"engines": {
"node": ">=22.12.0"
},
"scripts": {
"dev": "astro dev",
"build": "astro build",
"preview": "astro preview",
"astro": "astro"
},
"dependencies": {
"@portabletext/to-html": "^5.0.2",
"@sanity/client": "^7.22.1",
"@tailwindcss/vite": "^4.3.0",
"astro": "^6.4.4",
"tailwindcss": "^4.3.0"
}
}

BIN
public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 655 B

9
public/favicon.svg Normal file
View File

@@ -0,0 +1,9 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 128 128">
<path d="M50.4 78.5a75.1 75.1 0 0 0-28.5 6.9l24.2-65.7c.7-2 1.9-3.2 3.4-3.2h29c1.5 0 2.7 1.2 3.4 3.2l24.2 65.7s-11.6-7-28.5-7L67 45.5c-.4-1.7-1.6-2.8-2.9-2.8-1.3 0-2.5 1.1-2.9 2.7L50.4 78.5Zm-1.1 28.2Zm-4.2-20.2c-2 6.6-.6 15.8 4.2 20.2a17.5 17.5 0 0 1 .2-.7 5.5 5.5 0 0 1 5.7-4.5c2.8.1 4.3 1.5 4.7 4.7.2 1.1.2 2.3.2 3.5v.4c0 2.7.7 5.2 2.2 7.4a13 13 0 0 0 5.7 4.9v-.3l-.2-.3c-1.8-5.6-.5-9.5 4.4-12.8l1.5-1a73 73 0 0 0 3.2-2.2 16 16 0 0 0 6.8-11.4c.3-2 .1-4-.6-6l-.8.6-1.6 1a37 37 0 0 1-22.4 2.7c-5-.7-9.7-2-13.2-6.2Z" />
<style>
path { fill: #000; }
@media (prefers-color-scheme: dark) {
path { fill: #FFF; }
}
</style>
</svg>

After

Width:  |  Height:  |  Size: 749 B

30
sanity/sanity.config.ts Normal file
View File

@@ -0,0 +1,30 @@
import { defineConfig } from "sanity";
import { structureTool } from "sanity/structure";
import { visionTool } from "@sanity/vision";
import { schemaTypes } from "./schemas";
export default defineConfig({
name: "kitafreunde-regenbogen",
title: "Kitafreunde Regenbogen",
projectId: process.env.SANITY_STUDIO_PROJECT_ID!,
dataset: process.env.SANITY_STUDIO_DATASET ?? "production",
plugins: [
structureTool({
structure: (S) =>
S.list()
.title("Inhalt")
.items([
S.documentTypeListItem("post").title("Aktuelles / Blog"),
S.documentTypeListItem("project").title("Projekte"),
S.documentTypeListItem("teamMember").title("Vorstand"),
S.divider(),
S.documentTypeListItem("siteSettings").title("Website-Einstellungen"),
]),
}),
visionTool(),
],
schema: { types: schemaTypes },
});

6
sanity/schemas/index.ts Normal file
View File

@@ -0,0 +1,6 @@
import post from "./post";
import project from "./project";
import teamMember from "./teamMember";
import siteSettings from "./siteSettings";
export const schemaTypes = [post, project, teamMember, siteSettings];

39
sanity/schemas/post.ts Normal file
View File

@@ -0,0 +1,39 @@
import { defineType, defineField } from "sanity";
export default defineType({
name: "post",
title: "Aktuelles / Blog",
type: "document",
fields: [
defineField({ name: "title", title: "Titel", type: "string", validation: (r) => r.required() }),
defineField({ name: "slug", title: "URL-Slug", type: "slug", options: { source: "title" }, validation: (r) => r.required() }),
defineField({ name: "publishedAt", title: "Veröffentlicht am", type: "datetime", validation: (r) => r.required() }),
defineField({ name: "excerpt", title: "Kurzbeschreibung", type: "text", rows: 3 }),
defineField({ name: "coverImage", title: "Titelbild", type: "image", options: { hotspot: true } }),
defineField({
name: "body",
title: "Inhalt",
type: "array",
of: [
{ type: "block" },
{ type: "image", options: { hotspot: true } },
],
}),
defineField({
name: "category",
title: "Kategorie",
type: "string",
options: {
list: [
{ title: "Vereinsnews", value: "news" },
{ title: "Projekte", value: "projects" },
{ title: "Veranstaltungen", value: "events" },
{ title: "Presse", value: "press" },
],
},
}),
],
preview: {
select: { title: "title", subtitle: "publishedAt", media: "coverImage" },
},
});

38
sanity/schemas/project.ts Normal file
View File

@@ -0,0 +1,38 @@
import { defineType, defineField } from "sanity";
export default defineType({
name: "project",
title: "Projekte",
type: "document",
fields: [
defineField({ name: "title", title: "Projektname", type: "string", validation: (r) => r.required() }),
defineField({ name: "slug", title: "URL-Slug", type: "slug", options: { source: "title" }, validation: (r) => r.required() }),
defineField({ name: "date", title: "Zeitraum", type: "string", description: 'z.B. "Sommer 2024" oder "MärzMai 2024"' }),
defineField({ name: "summary", title: "Kurzbeschreibung", type: "text", rows: 3, validation: (r) => r.required() }),
defineField({
name: "body",
title: "Ausführliche Beschreibung",
type: "array",
of: [{ type: "block" }, { type: "image", options: { hotspot: true } }],
}),
defineField({ name: "image", title: "Hauptbild", type: "image", options: { hotspot: true } }),
defineField({ name: "targetGroup", title: "Für wen", type: "string", description: 'z.B. "Alle Kinder" oder "Gruppe Schmetterlinge"' }),
defineField({ name: "featured", title: "Auf Startseite hervorheben?", type: "boolean", initialValue: false }),
defineField({
name: "status",
title: "Status",
type: "string",
options: {
list: [
{ title: "Geplant", value: "planned" },
{ title: "Laufend", value: "active" },
{ title: "Abgeschlossen", value: "done" },
],
},
initialValue: "done",
}),
],
preview: {
select: { title: "title", subtitle: "date", media: "image" },
},
});

View File

@@ -0,0 +1,62 @@
import { defineType, defineField } from "sanity";
export default defineType({
name: "siteSettings",
title: "Website-Einstellungen",
type: "document",
// Singleton — nur ein Dokument
__experimental_actions: ["update", "publish"],
fields: [
defineField({
name: "contact",
title: "Kontakt",
type: "object",
fields: [
{ name: "email", title: "E-Mail", type: "string" },
{ name: "phone", title: "Telefon (optional)", type: "string" },
{ name: "address", title: "Adresse", type: "string", initialValue: "Keilerstraße 23, 13503 Berlin" },
],
}),
defineField({
name: "bank",
title: "Bankverbindung",
type: "object",
fields: [
{ name: "iban", title: "IBAN", type: "string" },
{ name: "bic", title: "BIC", type: "string" },
{ name: "bank", title: "Bankname", type: "string" },
{ name: "accountHolder", title: "Kontoinhaber", type: "string", initialValue: "Kitafreunde Regenbogen e.V." },
],
}),
defineField({
name: "social",
title: "Social Media",
type: "object",
fields: [
{ name: "instagram", title: "Instagram-URL", type: "url" },
{ name: "facebook", title: "Facebook-URL", type: "url" },
],
}),
defineField({
name: "memberFees",
title: "Mitgliedsbeiträge",
type: "object",
fields: [
{ name: "active", title: "Aktives Mitglied (Mindestbeitrag €/Jahr)", type: "number", initialValue: 12 },
{ name: "supporting", title: "Fördermitglied (Mindestbeitrag €/Jahr)", type: "number", initialValue: 6 },
{ name: "admissionFee", title: "Aufnahmegebühr €", type: "number", initialValue: 5 },
],
}),
defineField({
name: "stats",
title: "Zahlen für die Startseite",
type: "object",
fields: [
{ name: "members", title: "Mitgliederzahl", type: "number" },
{ name: "fundsPerYear", title: "Fördersumme €/Jahr", type: "number" },
{ name: "projectsTotal", title: "Projekte gesamt", type: "number" },
],
}),
],
preview: { select: { title: "contact.email" } },
});

View File

@@ -0,0 +1,31 @@
import { defineType, defineField } from "sanity";
export default defineType({
name: "teamMember",
title: "Vorstandsmitglieder",
type: "document",
fields: [
defineField({ name: "name", title: "Name", type: "string", validation: (r) => r.required() }),
defineField({
name: "role",
title: "Funktion",
type: "string",
options: {
list: [
{ title: "Vorsitzende/r", value: "chair" },
{ title: "Stellvertretung", value: "deputy" },
{ title: "Kassenwart/in", value: "treasurer" },
{ title: "Beisitz", value: "board" },
],
},
validation: (r) => r.required(),
}),
defineField({ name: "bio", title: "Kurz-Bio", type: "text", rows: 2 }),
defineField({ name: "photo", title: "Foto", type: "image", options: { hotspot: true } }),
defineField({ name: "order", title: "Reihenfolge", type: "number", initialValue: 99 }),
],
orderings: [{ title: "Reihenfolge", name: "orderAsc", by: [{ field: "order", direction: "asc" }] }],
preview: {
select: { title: "name", subtitle: "role", media: "photo" },
},
});

View File

@@ -0,0 +1,48 @@
---
const year = new Date().getFullYear();
---
<footer class="mt-24 border-t border-[var(--color-border)] bg-[var(--color-surface-alt)]">
<div class="rainbow-bar"></div>
<div class="max-w-6xl mx-auto px-4 py-12 grid grid-cols-1 md:grid-cols-3 gap-8">
<div>
<p class="font-brand text-xl text-[var(--color-primary)] mb-3">🌈 Kitafreunde Regenbogen</p>
<p class="text-sm text-[var(--color-text-muted)] leading-relaxed">
Förderverein der Integrationskindertagesstätte Regenbogen<br>
Keilerstraße 23 · 13503 Berlin
</p>
</div>
<div>
<p class="font-semibold text-sm mb-3">Navigation</p>
<ul class="text-sm text-[var(--color-text-muted)] space-y-2">
<li><a href="/ueber-uns" class="hover:text-[var(--color-primary)]">Über uns</a></li>
<li><a href="/was-wir-tun" class="hover:text-[var(--color-primary)]">Was wir tun</a></li>
<li><a href="/projekte" class="hover:text-[var(--color-primary)]">Projekte</a></li>
<li><a href="/aktuelles" class="hover:text-[var(--color-primary)]">Aktuelles</a></li>
<li><a href="/presse" class="hover:text-[var(--color-primary)]">Presse</a></li>
</ul>
</div>
<div>
<p class="font-semibold text-sm mb-3">Mitmachen</p>
<ul class="text-sm text-[var(--color-text-muted)] space-y-2">
<li><a href="/mitglied-werden" class="hover:text-[var(--color-primary)]">Mitglied werden</a></li>
<li><a href="/unterstuetzen" class="hover:text-[var(--color-primary)]">Spenden</a></li>
<li><a href="/kontakt" class="hover:text-[var(--color-primary)]">Kontakt</a></li>
</ul>
<p class="text-xs text-[var(--color-text-muted)] mt-4">
Gemeinnützig anerkannt · Spenden steuerlich absetzbar
</p>
</div>
</div>
<div class="border-t border-[var(--color-border)] max-w-6xl mx-auto px-4 py-4 flex flex-col md:flex-row justify-between text-xs text-[var(--color-text-muted)]">
<span>© {year} Kitafreunde Regenbogen e.V.</span>
<div class="flex gap-4 mt-2 md:mt-0">
<a href="/impressum" class="hover:text-[var(--color-primary)]">Impressum</a>
<a href="/datenschutz" class="hover:text-[var(--color-primary)]">Datenschutz</a>
</div>
</div>
</footer>

View File

@@ -0,0 +1,68 @@
---
const nav = [
{ href: "/ueber-uns", label: "Über uns" },
{ href: "/was-wir-tun", label: "Was wir tun" },
{ href: "/projekte", label: "Projekte" },
{ href: "/aktuelles", label: "Aktuelles" },
{ href: "/unterstuetzen", label: "Unterstützen" },
];
const pathname = Astro.url.pathname;
---
<header class="sticky top-0 z-50 bg-white/95 backdrop-blur border-b border-[var(--color-border)]">
<div class="rainbow-bar"></div>
<div class="max-w-6xl mx-auto px-4 flex items-center justify-between h-16">
<a href="/" class="flex items-center gap-2 font-brand text-xl text-[var(--color-primary)]">
🌈 Kitafreunde Regenbogen
</a>
<!-- Desktop Nav -->
<nav class="hidden md:flex items-center gap-6 text-sm font-medium">
{nav.map(({ href, label }) => (
<a
href={href}
class:list={[
"transition-colors hover:text-[var(--color-primary)]",
pathname.startsWith(href)
? "text-[var(--color-primary)] font-semibold"
: "text-[var(--color-text-muted)]"
]}
>
{label}
</a>
))}
</nav>
<a href="/mitglied-werden" class="btn-primary text-sm hidden md:inline-flex">
Mitglied werden
</a>
<!-- Mobile Menu Button -->
<button
id="mobile-menu-btn"
class="md:hidden p-2 rounded-lg text-[var(--color-text-muted)]"
aria-label="Menü öffnen"
>
<svg xmlns="http://www.w3.org/2000/svg" class="w-6 h-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"/>
</svg>
</button>
</div>
<!-- Mobile Nav -->
<div id="mobile-menu" class="hidden md:hidden border-t border-[var(--color-border)] bg-white">
<div class="px-4 py-4 flex flex-col gap-4 text-sm font-medium">
{nav.map(({ href, label }) => (
<a href={href} class="text-[var(--color-text)] hover:text-[var(--color-primary)]">{label}</a>
))}
<a href="/mitglied-werden" class="btn-primary text-center">Mitglied werden</a>
</div>
</div>
</header>
<script>
const btn = document.getElementById("mobile-menu-btn");
const menu = document.getElementById("mobile-menu");
btn?.addEventListener("click", () => menu?.classList.toggle("hidden"));
</script>

52
src/layouts/Layout.astro Normal file
View File

@@ -0,0 +1,52 @@
---
import Header from "../components/Header.astro";
import Footer from "../components/Footer.astro";
import "../styles/global.css";
interface Props {
title: string;
description?: string;
ogImage?: string;
}
const {
title,
description = "Der Förderverein der Integrationskita Regenbogen in Berlin-Tegel. Für das Besondere. Für alle Kinder.",
ogImage = "/og-default.jpg",
} = Astro.props;
const canonicalURL = new URL(Astro.url.pathname, "https://kitafreunde-regenbogen.de");
---
<!doctype html>
<html lang="de">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<link rel="canonical" href={canonicalURL} />
<title>{title} | Kitafreunde Regenbogen e.V.</title>
<meta name="description" content={description} />
<!-- Open Graph -->
<meta property="og:title" content={`${title} | Kitafreunde Regenbogen e.V.`} />
<meta property="og:description" content={description} />
<meta property="og:url" content={canonicalURL} />
<meta property="og:image" content={ogImage} />
<meta property="og:type" content="website" />
<meta property="og:locale" content="de_DE" />
<!-- Google Fonts fallback (bis Apex Brush eingebettet ist) -->
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Pacifico&family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet" />
</head>
<body>
<Header />
<main>
<slot />
</main>
<Footer />
</body>
</html>

88
src/lib/sanity.ts Normal file
View File

@@ -0,0 +1,88 @@
import { createClient } from "@sanity/client";
export const client = createClient({
projectId: import.meta.env.PUBLIC_SANITY_PROJECT_ID ?? "placeholder",
dataset: import.meta.env.PUBLIC_SANITY_DATASET ?? "production",
apiVersion: "2024-01-01",
useCdn: true,
});
// Bildurl aus Sanity-Asset
export function imageUrl(asset: any, width = 800): string {
if (!asset?.asset?._ref) return "";
const [, id, dimensions, format] = asset.asset._ref.split("-");
return `https://cdn.sanity.io/images/${import.meta.env.PUBLIC_SANITY_PROJECT_ID}/production/${id}-${dimensions}.${format}?w=${width}&auto=format`;
}
// --- Queries ---
export async function getSettings() {
try {
return await client.fetch(`*[_type == "siteSettings"][0]{
contact, bank, social, memberFees, stats
}`);
} catch { return null; }
}
export async function getFeaturedProjects() {
try {
return await client.fetch(`*[_type == "project" && featured == true] | order(_createdAt desc)[0..5]{
title, slug, date, summary, status,
image{ asset->{ url } }
}`);
} catch { return []; }
}
export async function getAllProjects() {
try {
return await client.fetch(`*[_type == "project"] | order(_createdAt desc){
title, slug, date, summary, status, targetGroup,
image{ asset->{ url } }
}`);
} catch { return []; }
}
export async function getProject(slug: string) {
try {
return await client.fetch(`*[_type == "project" && slug.current == $slug][0]{
title, slug, date, summary, body, status, targetGroup,
image{ asset->{ url } }
}`, { slug });
} catch { return null; }
}
export async function getLatestPosts(limit = 6) {
try {
return await client.fetch(`*[_type == "post"] | order(publishedAt desc)[0..${limit - 1}]{
title, slug, publishedAt, excerpt, category,
coverImage{ asset->{ url } }
}`);
} catch { return []; }
}
export async function getAllPosts() {
try {
return await client.fetch(`*[_type == "post"] | order(publishedAt desc){
title, slug, publishedAt, excerpt, category,
coverImage{ asset->{ url } }
}`);
} catch { return []; }
}
export async function getPost(slug: string) {
try {
return await client.fetch(`*[_type == "post" && slug.current == $slug][0]{
title, slug, publishedAt, excerpt, body, category,
coverImage{ asset->{ url } }
}`, { slug });
} catch { return null; }
}
export async function getTeam() {
try {
return await client.fetch(`*[_type == "teamMember"] | order(order asc){
name, role, bio,
photo{ asset->{ url } }
}`);
} catch { return []; }
}

View File

@@ -0,0 +1,55 @@
---
import Layout from "../../layouts/Layout.astro";
import { getAllPosts, getPost } from "../../lib/sanity";
import { toHTML } from "@portabletext/to-html";
export async function getStaticPaths() {
const posts = await getAllPosts();
return posts.map((p: any) => ({ params: { slug: p.slug.current } }));
}
const { slug } = Astro.params;
const post = await getPost(slug!);
if (!post) return Astro.redirect("/aktuelles");
const bodyHtml = post.body ? toHTML(post.body) : "";
const dateFormatted = new Date(post.publishedAt).toLocaleDateString("de-DE", {
day: "numeric", month: "long", year: "numeric",
});
---
<Layout
title={post.title}
description={post.excerpt}
ogImage={post.coverImage?.asset?.url}
>
<div class="max-w-6xl mx-auto px-4 pt-6">
<a href="/aktuelles" class="text-sm text-[var(--color-text-muted)] hover:text-[var(--color-primary)]">← Alle Beiträge</a>
</div>
{post.coverImage?.asset?.url && (
<div class="max-w-6xl mx-auto px-4 mt-6">
<div class="aspect-video rounded-3xl overflow-hidden">
<img src={`${post.coverImage.asset.url}?w=1200&auto=format`} alt={post.title} class="w-full h-full object-cover" />
</div>
</div>
)}
<article class="section max-w-3xl">
<time class="text-sm text-[var(--color-text-muted)]" datetime={post.publishedAt}>{dateFormatted}</time>
<h1 class="font-brand text-4xl md:text-5xl text-[var(--color-text)] mt-3 mb-6 leading-tight">{post.title}</h1>
{post.excerpt && <p class="text-xl text-[var(--color-text-muted)] mb-8 leading-relaxed">{post.excerpt}</p>}
{bodyHtml && (
<div class="prose prose-lg max-w-none text-[var(--color-text-muted)]" set:html={bodyHtml} />
)}
</article>
<div class="max-w-3xl mx-auto px-4 pb-16">
<div class="rainbow-bar rounded-full mb-8"></div>
<div class="flex flex-col sm:flex-row gap-4">
<a href="/mitglied-werden" class="btn-primary">Mitglied werden</a>
<a href="/aktuelles" class="btn-secondary">Mehr Beiträge</a>
</div>
</div>
</Layout>

View File

@@ -0,0 +1,57 @@
---
import Layout from "../../layouts/Layout.astro";
import { getAllPosts } from "../../lib/sanity";
const posts = await getAllPosts();
const categoryLabel: Record<string, string> = {
news: "Vereinsnews",
projects: "Projekte",
events: "Veranstaltungen",
press: "Presse",
};
---
<Layout title="Aktuelles" description="Neuigkeiten vom Kitafreunde Regenbogen e.V. — Projekte, Veranstaltungen, Vereinsleben.">
<section class="section pt-16 pb-0">
<p class="text-sm font-semibold tracking-widest uppercase text-[var(--color-primary)] mb-3">Aktuelles</p>
<h1 class="font-brand text-5xl text-[var(--color-text)] mb-4">Was gerade<br><span class="rainbow-text">bei uns passiert.</span></h1>
</section>
<div class="rainbow-bar max-w-6xl mx-auto px-4 my-10"></div>
<section class="section pt-0">
{posts.length === 0 ? (
<div class="card text-center py-16 bg-[var(--color-surface-alt)]">
<p class="text-4xl mb-4">✍️</p>
<h2 class="text-xl font-bold mb-2">Bald mehr hier</h2>
<p class="text-[var(--color-text-muted)]">Wir befüllen den Blog gerade. Schau bald wieder rein!</p>
</div>
) : (
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{posts.map((post: any) => (
<a href={`/aktuelles/${post.slug.current}`} class="card group">
{post.coverImage?.asset?.url ? (
<div class="aspect-video rounded-xl overflow-hidden mb-4 bg-[var(--color-surface-alt)]">
<img src={`${post.coverImage.asset.url}?w=600&auto=format`} alt={post.title} class="w-full h-full object-cover group-hover:scale-105 transition-transform duration-300" />
</div>
) : (
<div class="aspect-video rounded-xl mb-4 bg-[var(--color-surface-alt)] flex items-center justify-center text-4xl">📰</div>
)}
<div class="flex items-center gap-2 mb-2">
{post.category && (
<span class="text-xs font-semibold text-[var(--color-primary)] bg-[var(--color-surface-alt)] px-2 py-0.5 rounded-full">
{categoryLabel[post.category] ?? post.category}
</span>
)}
<time class="text-xs text-[var(--color-text-muted)]" datetime={post.publishedAt}>
{new Date(post.publishedAt).toLocaleDateString("de-DE", { day: "numeric", month: "long", year: "numeric" })}
</time>
</div>
<h3 class="font-bold leading-snug group-hover:text-[var(--color-primary)] transition-colors">{post.title}</h3>
{post.excerpt && <p class="text-sm text-[var(--color-text-muted)] mt-2 line-clamp-3">{post.excerpt}</p>}
</a>
))}
</div>
)}
</section>
</Layout>

172
src/pages/index.astro Normal file
View File

@@ -0,0 +1,172 @@
---
import Layout from "../layouts/Layout.astro";
import { getSettings, getFeaturedProjects, getLatestPosts } from "../lib/sanity";
const settings = await getSettings();
const featuredProjects = await getFeaturedProjects();
const latestPosts = await getLatestPosts(3);
const stats = settings?.stats;
---
<Layout
title="Mehr als Kita. Mehr als genug."
description="Der Kitafreunde Regenbogen e.V. ist der Förderverein der Integrationskita Regenbogen in Berlin-Tegel. Für das Besondere. Für alle Kinder."
>
<!-- Hero -->
<section class="relative overflow-hidden bg-gradient-to-br from-[var(--color-surface-alt)] to-white">
<div class="section py-24 md:py-32 text-center">
<p class="text-sm font-semibold tracking-widest uppercase text-[var(--color-primary)] mb-4">
Berlin-Tegel · Integrationskita Regenbogen
</p>
<h1 class="font-brand text-5xl md:text-7xl text-[var(--color-text)] mb-6 leading-tight">
Mehr als Kita.<br>
<span class="rainbow-text">Mehr als genug.</span>
</h1>
<p class="text-xl text-[var(--color-text-muted)] max-w-2xl mx-auto mb-10 leading-relaxed">
Wir schaffen die Momente, die Kinder ihr Leben lang mit sich tragen —
Kulturprojekte, Naturerfahrungen, Gemeinschaft. Und dafür, dass kein Kind
außen vor bleibt.
</p>
<div class="flex flex-col sm:flex-row gap-4 justify-center">
<a href="/mitglied-werden" class="btn-primary text-base">Jetzt Mitglied werden</a>
<a href="/was-wir-tun" class="btn-secondary text-base">Was wir tun</a>
</div>
</div>
<!-- Decorative rainbow -->
<div class="rainbow-bar absolute bottom-0 left-0 right-0"></div>
</section>
<!-- Drei-Sätze -->
<section class="section-sm text-center">
<p class="text-2xl md:text-3xl font-semibold text-[var(--color-text)] max-w-3xl mx-auto leading-snug">
Die Kita stellt die Grundversorgung sicher. Das Land zahlt das Nötige.
<span class="text-[var(--color-primary)]">Wir bezahlen das Besondere.</span>
</p>
</section>
<!-- Drei Säulen -->
<section class="section">
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
{[
{
icon: "🎭",
color: "var(--color-rb-violet)",
title: "Erleben",
text: "Theater, Musik, Natur, Kunst. Erlebnisse, die keine Lehrplan-Vorgabe anordnet — und die man nicht vergisst.",
href: "/was-wir-tun#erleben",
},
{
icon: "🤝",
color: "var(--color-rb-green)",
title: "Teilhabe",
text: "Kein Kind bleibt beim Ausflug zuhause, weil die Familie sich den Beitrag nicht leisten kann. Punkt.",
href: "/was-wir-tun#teilhabe",
},
{
icon: "🌍",
color: "var(--color-rb-orange)",
title: "Gemeinschaft",
text: "Eltern, Erzieher*innen, Nachbarschaft, lokale Unternehmen. Der Verein verbindet, wer die Kita trägt.",
href: "/was-wir-tun#gemeinschaft",
},
].map(({ icon, color, title, text, href }) => (
<a href={href} class="card group cursor-pointer">
<div class="text-4xl mb-4">{icon}</div>
<h3 class="text-xl font-bold mb-2 group-hover:text-[var(--color-primary)] transition-colors"
style={`color: ${color}`}>{title}</h3>
<p class="text-[var(--color-text-muted)] leading-relaxed text-sm">{text}</p>
<p class="mt-4 text-sm font-semibold text-[var(--color-primary)]">Mehr erfahren →</p>
</a>
))}
</div>
</section>
<!-- Zahlen -->
{stats && (stats.members || stats.fundsPerYear || stats.projectsTotal) && (
<section class="bg-[var(--color-primary)] text-white">
<div class="max-w-6xl mx-auto px-4 py-16 grid grid-cols-1 md:grid-cols-3 gap-8 text-center">
{stats.members && (
<div>
<p class="font-brand text-5xl mb-2">{stats.members}</p>
<p class="text-white/80">Mitglieder unterstützen den Verein</p>
</div>
)}
{stats.fundsPerYear && (
<div>
<p class="font-brand text-5xl mb-2">{stats.fundsPerYear.toLocaleString("de")} €</p>
<p class="text-white/80">jährlich für die Kinder</p>
</div>
)}
{stats.projectsTotal && (
<div>
<p class="font-brand text-5xl mb-2">{stats.projectsTotal}</p>
<p class="text-white/80">Projekte seit Vereinsgründung</p>
</div>
)}
</div>
</section>
)}
<!-- Aktuelle Projekte -->
{featuredProjects.length > 0 && (
<section class="section">
<h2 class="text-3xl font-bold mb-2">Aktuelle Projekte</h2>
<p class="text-[var(--color-text-muted)] mb-8">Was wir gerade machen und was geplant ist.</p>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{featuredProjects.map((p: any) => (
<a href={`/projekte/${p.slug.current}`} class="card group">
{p.image?.asset && (
<div class="aspect-video bg-[var(--color-surface-alt)] rounded-xl mb-4 overflow-hidden">
<img src={p.image.asset.url} alt={p.title} class="w-full h-full object-cover group-hover:scale-105 transition-transform duration-300" />
</div>
)}
<p class="text-xs text-[var(--color-text-muted)] mb-1">{p.date}</p>
<h3 class="font-bold text-lg group-hover:text-[var(--color-primary)] transition-colors">{p.title}</h3>
<p class="text-sm text-[var(--color-text-muted)] mt-2 line-clamp-2">{p.summary}</p>
</a>
))}
</div>
<div class="mt-8 text-center">
<a href="/projekte" class="btn-secondary">Alle Projekte →</a>
</div>
</section>
)}
<!-- Aktuelles -->
{latestPosts.length > 0 && (
<section class="section bg-[var(--color-surface-alt)] rounded-3xl">
<h2 class="text-3xl font-bold mb-8">Aktuelles</h2>
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
{latestPosts.map((post: any) => (
<a href={`/aktuelles/${post.slug.current}`} class="card group">
<p class="text-xs text-[var(--color-text-muted)] mb-2">
{new Date(post.publishedAt).toLocaleDateString("de-DE", { day: "numeric", month: "long", year: "numeric" })}
</p>
<h3 class="font-bold leading-snug group-hover:text-[var(--color-primary)] transition-colors">{post.title}</h3>
{post.excerpt && <p class="text-sm text-[var(--color-text-muted)] mt-2 line-clamp-3">{post.excerpt}</p>}
</a>
))}
</div>
<div class="mt-8">
<a href="/aktuelles" class="btn-secondary">Alle Beiträge →</a>
</div>
</section>
)}
<!-- CTA -->
<section class="section text-center">
<div class="max-w-2xl mx-auto">
<div class="rainbow-bar w-24 mx-auto mb-8 rounded-full" style="height: 4px;"></div>
<h2 class="font-brand text-4xl md:text-5xl text-[var(--color-text)] mb-4">Ab 1 € im Monat.</h2>
<p class="text-lg text-[var(--color-text-muted)] mb-8">
Kein Aufwand. Kein Ehrenamt verpflichtend.<br>
Nur Kinder, die mehr bekommen.
</p>
<a href="/mitglied-werden" class="btn-primary text-lg px-8 py-4">Jetzt Mitglied werden</a>
<p class="text-sm text-[var(--color-text-muted)] mt-4">
Gemeinnützig anerkannt · Beiträge steuerlich absetzbar
</p>
</div>
</section>
</Layout>

91
src/pages/kontakt.astro Normal file
View File

@@ -0,0 +1,91 @@
---
import Layout from "../layouts/Layout.astro";
import { getSettings } from "../lib/sanity";
const settings = await getSettings();
const contact = settings?.contact;
const social = settings?.social;
---
<Layout title="Kontakt" description="Kontakt zum Kitafreunde Regenbogen e.V. — schreib uns, werde Mitglied oder bring eine Idee ein.">
<section class="section pt-16">
<p class="text-sm font-semibold tracking-widest uppercase text-[var(--color-primary)] mb-3">Kontakt</p>
<h1 class="font-brand text-5xl text-[var(--color-text)] mb-6">Schreib uns.</h1>
<div class="grid grid-cols-1 md:grid-cols-2 gap-12 mt-8">
<!-- Kontaktinfos -->
<div class="space-y-6">
<div class="card">
<h2 class="font-bold mb-3">Kitafreunde Regenbogen e.V.</h2>
<p class="text-sm text-[var(--color-text-muted)] leading-relaxed">
c/o Integrationskita Regenbogen<br>
Keilerstraße 23<br>
13503 Berlin
</p>
</div>
{contact?.email && (
<div class="card">
<h3 class="font-bold mb-2 text-sm uppercase tracking-wide text-[var(--color-text-muted)]">E-Mail</h3>
<a href={`mailto:${contact.email}`} class="text-[var(--color-primary)] font-medium text-lg">
{contact.email}
</a>
</div>
)}
<div class="card">
<h3 class="font-bold mb-3">Mitglied werden?</h3>
<p class="text-sm text-[var(--color-text-muted)] mb-3">
Beitrittserklärung herunterladen und ausgefüllt im Kitabüro abgeben oder per Mail schicken.
</p>
<a href="/mitglied-werden" class="btn-primary text-sm">Zur Mitgliedschaftsseite →</a>
</div>
{(social?.instagram || social?.facebook) && (
<div class="card">
<h3 class="font-bold mb-3">Social Media</h3>
<div class="flex gap-3">
{social.instagram && (
<a href={social.instagram} target="_blank" rel="noopener" class="btn-secondary text-sm">Instagram</a>
)}
{social.facebook && (
<a href={social.facebook} target="_blank" rel="noopener" class="btn-secondary text-sm">Facebook</a>
)}
</div>
</div>
)}
</div>
<!-- Formular (statisches HTML, ohne Backend) -->
<div class="card">
<h2 class="font-bold mb-4">Direkte Nachricht</h2>
<p class="text-sm text-[var(--color-text-muted)] mb-6">
Dieses Formular öffnet deinen E-Mail-Client.
</p>
<form
action={`mailto:${contact?.email ?? "info@kitafreunde-regenbogen.de"}`}
method="get"
enctype="text/plain"
class="space-y-4"
>
<div>
<label for="subject" class="block text-sm font-medium mb-1">Betreff</label>
<select id="subject" name="subject" class="w-full border border-[var(--color-border)] rounded-xl px-4 py-2.5 text-sm focus:outline-none focus:border-[var(--color-primary)]">
<option value="Mitgliedschaft">Mitgliedschaft</option>
<option value="Projektidee">Projektidee einbringen</option>
<option value="Spende/Kooperation">Spende / Kooperation</option>
<option value="Presseanfrage">Presseanfrage</option>
<option value="Allgemeine Anfrage">Allgemeine Anfrage</option>
</select>
</div>
<div>
<label for="body" class="block text-sm font-medium mb-1">Nachricht</label>
<textarea id="body" name="body" rows="5"
class="w-full border border-[var(--color-border)] rounded-xl px-4 py-2.5 text-sm focus:outline-none focus:border-[var(--color-primary)] resize-none"
placeholder="Deine Nachricht..."></textarea>
</div>
<button type="submit" class="btn-primary w-full justify-center">
E-Mail öffnen →
</button>
</form>
</div>
</div>
</section>
</Layout>

View File

@@ -0,0 +1,122 @@
---
import Layout from "../layouts/Layout.astro";
import { getSettings } from "../lib/sanity";
const settings = await getSettings();
const fees = settings?.memberFees;
const bank = settings?.bank;
---
<Layout
title="Mitglied werden"
description="Mitglied beim Kitafreunde Regenbogen e.V. werden. Steuerlich absetzbar. Keine Verpflichtungen. Direkte Wirkung für Kinder in Berlin-Tegel."
>
<section class="section pt-16 pb-0">
<p class="text-sm font-semibold tracking-widest uppercase text-[var(--color-primary)] mb-3">Mitglied werden</p>
<h1 class="font-brand text-5xl md:text-6xl text-[var(--color-text)] mb-6 leading-tight">
Dabei sein.<br><span class="rainbow-text">So einfach wie möglich.</span>
</h1>
</section>
<div class="rainbow-bar max-w-6xl mx-auto px-4 mb-12"></div>
<!-- Warum -->
<section class="section pt-0">
<div class="max-w-2xl">
<p class="text-2xl text-[var(--color-text)] leading-relaxed mb-2">Du musst keine Zeit haben.</p>
<p class="text-2xl text-[var(--color-text)] leading-relaxed mb-2">Du musst nicht auf Sitzungen kommen.</p>
<p class="text-2xl text-[var(--color-text)] leading-relaxed mb-8">Du musst nicht tischlern, backen oder organisieren können.</p>
<p class="text-2xl font-bold text-[var(--color-primary)] leading-relaxed">
Du musst nur wollen, dass die Kita in deiner Nachbarschaft ein bisschen mehr kann als ohne dich.
</p>
<p class="text-3xl font-brand text-[var(--color-text)] mt-6">Das ist alles.</p>
</div>
</section>
<!-- Mitgliedschaftstypen -->
<section class="section">
<h2 class="text-3xl font-bold mb-8">Drei Wege mitzumachen</h2>
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
<div class="card border-2 border-[var(--color-primary)]">
<p class="text-sm font-semibold text-[var(--color-primary)] uppercase tracking-wide mb-2">Aktives Mitglied</p>
<p class="font-brand text-4xl text-[var(--color-text)] mb-1">
ab {fees?.active ?? 12} €<span class="text-lg font-normal">/Jahr</span>
</p>
<p class="text-sm text-[var(--color-text-muted)] mb-4">zzgl. einmalig {fees?.admissionFee ?? 5} € Aufnahmegebühr</p>
<ul class="text-sm text-[var(--color-text-muted)] space-y-2 mb-6">
<li class="flex gap-2"><span class="text-[var(--color-rb-green)] font-bold">✓</span> Stimmrecht auf der Mitgliederversammlung</li>
<li class="flex gap-2"><span class="text-[var(--color-rb-green)] font-bold">✓</span> Mitgestaltung von Projekten und Zielen</li>
<li class="flex gap-2"><span class="text-[var(--color-rb-green)] font-bold">✓</span> Voller Überblick über Vereinsgeschehen</li>
</ul>
<p class="text-xs text-[var(--color-text-muted)]">Für alle, die mitentscheiden wollen.</p>
</div>
<div class="card">
<p class="text-sm font-semibold text-[var(--color-accent)] uppercase tracking-wide mb-2">Fördermitglied</p>
<p class="font-brand text-4xl text-[var(--color-text)] mb-1">
ab {fees?.supporting ?? 6} €<span class="text-lg font-normal">/Jahr</span>
</p>
<p class="text-sm text-[var(--color-text-muted)] mb-4">keine Aufnahmegebühr</p>
<ul class="text-sm text-[var(--color-text-muted)] space-y-2 mb-6">
<li class="flex gap-2"><span class="text-[var(--color-rb-green)] font-bold">✓</span> Beitrag geht direkt an die Projekte</li>
<li class="flex gap-2"><span class="text-[var(--color-rb-green)] font-bold">✓</span> Kein Aufwand, keine Verpflichtung</li>
<li class="flex gap-2"><span class="text-[var(--color-rb-green)] font-bold">✓</span> Volle Wirkung, null Bürokratie</li>
</ul>
<p class="text-xs text-[var(--color-text-muted)]">Für alle, die einfach dabei sein wollen.</p>
</div>
<div class="card bg-[var(--color-surface-alt)]">
<p class="text-sm font-semibold text-[var(--color-rb-blue)] uppercase tracking-wide mb-2">Unternehmen</p>
<p class="font-brand text-4xl text-[var(--color-text)] mb-4">Auf Anfrage</p>
<ul class="text-sm text-[var(--color-text-muted)] space-y-2 mb-6">
<li class="flex gap-2"><span class="text-[var(--color-rb-green)] font-bold">✓</span> Sichtbare lokale Verantwortung</li>
<li class="flex gap-2"><span class="text-[var(--color-rb-green)] font-bold">✓</span> Projektpatenschaften möglich</li>
<li class="flex gap-2"><span class="text-[var(--color-rb-green)] font-bold">✓</span> Erwähnung in Kommunikation</li>
</ul>
<a href="/kontakt" class="btn-secondary text-sm w-full justify-center">Gespräch anfragen →</a>
</div>
</div>
</section>
<!-- So geht's -->
<section class="section bg-[var(--color-surface-alt)] rounded-3xl">
<h2 class="text-3xl font-bold mb-8">So wirst du Mitglied</h2>
<div class="grid grid-cols-1 md:grid-cols-3 gap-8">
{[
{ step: "1", title: "Beitrittserklärung ausfüllen", text: "Als PDF ausdrucken und unterschreiben — oder im Kitabüro abholen." },
{ step: "2", title: "Beitrag überweisen", text: `Jahresbeitrag + einmalige Aufnahmegebühr (${fees?.admissionFee ?? 5} €) auf unser Vereinskonto.` },
{ step: "3", title: "Fertig — du bist dabei.", text: "Willkommen bei den Kitafreunden. Wir freuen uns." },
].map(({ step, title, text }) => (
<div class="text-center">
<div class="w-14 h-14 rounded-full bg-[var(--color-primary)] text-white font-brand text-2xl flex items-center justify-center mx-auto mb-4">{step}</div>
<h3 class="font-bold mb-2">{title}</h3>
<p class="text-sm text-[var(--color-text-muted)]">{text}</p>
</div>
))}
</div>
<div class="mt-10 text-center">
<a href="/Beitrittserklarung-Kitafreunde-Regenbogen.pdf" class="btn-primary" download>
Beitrittserklärung als PDF
</a>
</div>
</section>
<!-- Bank -->
{bank?.iban && (
<section class="section">
<div class="card max-w-xl">
<h3 class="font-bold mb-4">Bankverbindung</h3>
<dl class="text-sm space-y-2 text-[var(--color-text-muted)]">
<div class="flex gap-2"><dt class="font-medium text-[var(--color-text)] w-32">Empfänger</dt><dd>{bank.accountHolder}</dd></div>
<div class="flex gap-2"><dt class="font-medium text-[var(--color-text)] w-32">IBAN</dt><dd class="font-mono">{bank.iban}</dd></div>
{bank.bic && <div class="flex gap-2"><dt class="font-medium text-[var(--color-text)] w-32">BIC</dt><dd class="font-mono">{bank.bic}</dd></div>}
{bank.bank && <div class="flex gap-2"><dt class="font-medium text-[var(--color-text)] w-32">Bank</dt><dd>{bank.bank}</dd></div>}
<div class="flex gap-2"><dt class="font-medium text-[var(--color-text)] w-32">Verwendung</dt><dd>Mitgliedsbeitrag [Dein Name]</dd></div>
</dl>
</div>
<p class="text-sm text-[var(--color-text-muted)] mt-4">
Mitgliedsbeiträge und Spenden sind steuerlich absetzbar (gemeinnützig anerkannt).
Spendenquittung auf Anfrage.
</p>
</section>
)}
</Layout>

66
src/pages/presse.astro Normal file
View File

@@ -0,0 +1,66 @@
---
import Layout from "../layouts/Layout.astro";
import { getSettings } from "../lib/sanity";
const settings = await getSettings();
const contact = settings?.contact;
---
<Layout title="Presse" description="Pressekontakt und Informationen zum Kitafreunde Regenbogen e.V., Förderverein der Integrationskita Regenbogen in Berlin-Tegel.">
<section class="section pt-16">
<p class="text-sm font-semibold tracking-widest uppercase text-[var(--color-primary)] mb-3">Presse</p>
<h1 class="font-brand text-5xl text-[var(--color-text)] mb-6">Kontakt für Presse<br>und Medien.</h1>
<div class="grid grid-cols-1 md:grid-cols-2 gap-12 mt-12">
<div>
<h2 class="text-xl font-bold mb-4">Pressekontakt</h2>
{contact?.email ? (
<div class="card">
<p class="font-semibold mb-1">Kitafreunde Regenbogen e.V.</p>
<p class="text-sm text-[var(--color-text-muted)] mb-3">Keilerstraße 23 · 13503 Berlin</p>
<a href={`mailto:${contact.email}?subject=Presseanfrage`} class="text-[var(--color-primary)] font-medium">
{contact.email}
</a>
</div>
) : (
<div class="card">
<p class="text-sm text-[var(--color-text-muted)] italic">Pressekontakt folgt</p>
</div>
)}
<div class="mt-8">
<h3 class="font-bold mb-3">Pressekit (Download)</h3>
<ul class="text-sm text-[var(--color-text-muted)] space-y-2">
<li>🖼️ Logo in PNG und SVG (alle Varianten)</li>
<li>📄 Kurzbeschreibung (150 Wörter)</li>
<li>📄 Langprofil</li>
<li>📷 Projektfotos (DSGVO-konform)</li>
</ul>
<a href="/presse-kit.zip" class="btn-secondary text-sm mt-4 inline-flex">Pressekit anfragen</a>
</div>
</div>
<!-- Boilerplate -->
<div>
<h2 class="text-xl font-bold mb-4">Über den Verein</h2>
<div class="card bg-[var(--color-surface-alt)] prose prose-sm max-w-none text-[var(--color-text-muted)]">
<p>
Der Kitafreunde Regenbogen e.V. ist der gemeinnützige Förderverein der
Integrationskindertagesstätte „Regenbogen" in Berlin-Tegel (Keilerstraße 23,
13503 Berlin). Der Verein ermöglicht Projekte, Erlebnisse und Teilhabe, die über
die staatlich finanzierte Grundversorgung hinausgehen.
</p>
<p>
Schwerpunkte sind kulturelle Bildung, Naturerfahrung und die finanzielle Unterstützung
von Kindern aus einkommensschwachen Familien. Als Förderverein einer Integrationskita
setzt sich der Kitafreunde Regenbogen e.V. dafür ein, dass ein Ort, an dem Kinder mit
und ohne Behinderung gemeinsam aufwachsen, mehr kann als das Minimum.
</p>
<p class="text-xs">
Vereinssitz: Berlin &middot; Gemeinnützig anerkannt
</p>
</div>
</div>
</div>
</section>
</Layout>

View File

@@ -0,0 +1,58 @@
---
import Layout from "../../layouts/Layout.astro";
import { getAllProjects, getProject } from "../../lib/sanity";
import { toHTML } from "@portabletext/to-html";
export async function getStaticPaths() {
const projects = await getAllProjects();
return projects.map((p: any) => ({ params: { slug: p.slug.current } }));
}
const { slug } = Astro.params;
const project = await getProject(slug!);
if (!project) return Astro.redirect("/projekte");
const bodyHtml = project.body ? toHTML(project.body) : "";
---
<Layout
title={project.title}
description={project.summary}
ogImage={project.image?.asset?.url}
>
<!-- Breadcrumb -->
<div class="max-w-6xl mx-auto px-4 pt-6">
<a href="/projekte" class="text-sm text-[var(--color-text-muted)] hover:text-[var(--color-primary)]">← Alle Projekte</a>
</div>
{project.image?.asset?.url && (
<div class="max-w-6xl mx-auto px-4 mt-6">
<div class="aspect-video rounded-3xl overflow-hidden">
<img src={`${project.image.asset.url}?w=1200&auto=format`} alt={project.title} class="w-full h-full object-cover" />
</div>
</div>
)}
<section class="section">
<div class="max-w-3xl">
<div class="flex items-center gap-3 mb-4 text-sm text-[var(--color-text-muted)]">
{project.date && <span>📅 {project.date}</span>}
{project.targetGroup && <span>👥 {project.targetGroup}</span>}
</div>
<h1 class="font-brand text-4xl md:text-5xl text-[var(--color-text)] mb-6">{project.title}</h1>
<p class="text-xl text-[var(--color-text-muted)] leading-relaxed mb-8">{project.summary}</p>
{bodyHtml && (
<div class="prose prose-lg max-w-none text-[var(--color-text-muted)]" set:html={bodyHtml} />
)}
</div>
</section>
<section class="section text-center border-t border-[var(--color-border)] pt-12">
<p class="text-[var(--color-text-muted)] mb-4">Solche Projekte werden durch Mitgliedsbeiträge und Spenden möglich.</p>
<div class="flex flex-col sm:flex-row gap-4 justify-center">
<a href="/mitglied-werden" class="btn-primary">Mitglied werden</a>
<a href="/unterstuetzen" class="btn-secondary">Spenden</a>
</div>
</section>
</Layout>

View File

@@ -0,0 +1,79 @@
---
import Layout from "../../layouts/Layout.astro";
import { getAllProjects } from "../../lib/sanity";
const projects = await getAllProjects();
const statusLabel: Record<string, string> = {
planned: "Geplant",
active: "Laufend",
done: "Abgeschlossen",
};
const statusColor: Record<string, string> = {
planned: "var(--color-rb-blue)",
active: "var(--color-rb-green)",
done: "var(--color-text-muted)",
};
---
<Layout
title="Projekte"
description="Aktuelle und vergangene Projekte des Kitafreunde Regenbogen e.V.: Theater, Natur, Musik, Ausflüge — für alle Kinder der Integrationskita Regenbogen Berlin."
>
<section class="section pt-16 pb-0">
<p class="text-sm font-semibold tracking-widest uppercase text-[var(--color-primary)] mb-3">Projekte</p>
<h1 class="font-brand text-5xl text-[var(--color-text)] mb-4">Was wir schon gemacht haben.<br><span class="rainbow-text">Was als nächstes kommt.</span></h1>
<p class="text-xl text-[var(--color-text-muted)] max-w-2xl leading-relaxed">
Jedes Projekt erzählt, warum der Verein existiert. Konkret, sichtbar, für alle.
</p>
</section>
<div class="rainbow-bar max-w-6xl mx-auto px-4 my-10"></div>
{projects.length === 0 ? (
<section class="section pt-0">
<div class="card text-center py-16 bg-[var(--color-surface-alt)]">
<p class="text-4xl mb-4">🚀</p>
<h2 class="text-xl font-bold mb-2">Projekte folgen</h2>
<p class="text-[var(--color-text-muted)]">Wir befüllen den Bereich gerade. Schau bald wieder vorbei!</p>
</div>
</section>
) : (
<section class="section pt-0">
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{projects.map((p: any) => (
<a href={`/projekte/${p.slug.current}`} class="card group">
{p.image?.asset?.url ? (
<div class="aspect-video rounded-xl overflow-hidden mb-4 bg-[var(--color-surface-alt)]">
<img src={`${p.image.asset.url}?w=600&auto=format`} alt={p.title} class="w-full h-full object-cover group-hover:scale-105 transition-transform duration-300" />
</div>
) : (
<div class="aspect-video rounded-xl mb-4 bg-[var(--color-surface-alt)] flex items-center justify-center text-4xl">🎭</div>
)}
<div class="flex items-center gap-2 mb-2">
<span class="text-xs font-semibold px-2 py-0.5 rounded-full bg-current/10"
style={`color: ${statusColor[p.status ?? "done"]}`}>
{statusLabel[p.status ?? "done"]}
</span>
{p.date && <span class="text-xs text-[var(--color-text-muted)]">{p.date}</span>}
</div>
<h3 class="font-bold text-lg mb-2 group-hover:text-[var(--color-primary)] transition-colors">{p.title}</h3>
<p class="text-sm text-[var(--color-text-muted)] line-clamp-3">{p.summary}</p>
{p.targetGroup && (
<p class="text-xs text-[var(--color-text-muted)] mt-3">👥 {p.targetGroup}</p>
)}
</a>
))}
</div>
</section>
)}
<!-- Idee einbringen -->
<section class="section text-center">
<div class="card max-w-lg mx-auto bg-[var(--color-surface-alt)] border-0 py-10">
<p class="text-2xl mb-3">💡</p>
<h2 class="font-bold text-xl mb-2">Du hast eine Idee?</h2>
<p class="text-[var(--color-text-muted)] text-sm mb-4">Neue Projektvorschläge sind immer willkommen.</p>
<a href="/kontakt" class="btn-primary text-sm">Idee einbringen →</a>
</div>
</section>
</Layout>

148
src/pages/ueber-uns.astro Normal file
View File

@@ -0,0 +1,148 @@
---
import Layout from "../layouts/Layout.astro";
import { getTeam } from "../lib/sanity";
const team = await getTeam();
const roleLabel: Record<string, string> = {
chair: "Vorsitzende/r",
deputy: "Stellvertretung",
treasurer: "Kassenwart/in",
board: "Beisitz",
};
---
<Layout
title="Über uns"
description="Wer sind die Kitafreunde Regenbogen? Der Förderverein der Integrationskita Regenbogen Berlin — gegründet von Eltern, getragen von einer Gemeinschaft."
>
<!-- Hero -->
<section class="section pt-16 pb-0">
<div class="max-w-3xl">
<p class="text-sm font-semibold tracking-widest uppercase text-[var(--color-primary)] mb-3">Über uns</p>
<h1 class="font-brand text-5xl md:text-6xl text-[var(--color-text)] mb-6 leading-tight">
Wir sind die<br><span class="rainbow-text">Kitafreunde.</span>
</h1>
</div>
</section>
<div class="rainbow-bar max-w-6xl mx-auto px-4 my-8"></div>
<!-- Geschichte -->
<section class="section pt-0">
<div class="grid grid-cols-1 md:grid-cols-2 gap-16 items-start">
<div class="prose prose-lg max-w-none text-[var(--color-text-muted)] leading-relaxed space-y-5">
<p>
Irgendwann haben Eltern angefangen zu fragen: Was bräuchte die Kita, wenn sie dürfte?
Was würde den Kindern gut tun, wenn das Budget keine Rolle spielt?
</p>
<p>
Die Antworten waren überraschend konkret. Ein Theaterstück. Eine Woche Garten und Kompost.
Trommelkurse. Ein Ausflug zum See für alle — wirklich für alle. Und dafür, dass kein Kind
fehlt, weil zuhause gerade kein Geld da ist.
</p>
<p>
Der Kitafreunde Regenbogen e.V. wurde gegründet, weil diese Antworten umsetzbar sind.
Nicht durch das Land. Nicht durch den Träger. Durch uns.
</p>
<p>
Die Kita Regenbogen ist eine Integrationskita — Kinder mit und ohne Behinderung lernen,
spielen und wachsen gemeinsam. Das ist keine Besonderheit, die man erklärt. Das ist einfach,
wie es richtig ist. Und der Förderverein trägt diese Haltung nach außen:
Alle sind dabei. Alle zählen. Kein Abstrich, kein Sonderfall.
</p>
<p>
Zwischenzeitlich war der Verein ruhiger geworden. Jetzt erwacht er neu — mit frischen
Mitgliedern, klaren Zielen und dem Willen, der Kita Regenbogen den Rücken zu stärken,
den sie verdient.
</p>
</div>
<!-- Leitbild -->
<div class="space-y-6">
<div class="card bg-[var(--color-surface-alt)]">
<h2 class="text-xl font-bold mb-4 text-[var(--color-primary)]">Unser Leitbild</h2>
<p class="font-semibold text-[var(--color-text)] mb-3">
Wir sind nicht für das Alltägliche zuständig. Das ist Aufgabe des Landes.
</p>
<p class="text-[var(--color-text-muted)] text-sm leading-relaxed">
Wir sind für das, was darüber hinausgeht. Das i-Tüpfelchen. Die Erinnerung.
Die Chance, die sonst keine Chance hätte.
</p>
</div>
<div class="space-y-4">
{[
{ icon: "🌈", text: "Jedes Kind zählt — unabhängig von Herkunft, Behinderung oder dem Kontostand der Eltern" },
{ icon: "🎯", text: "Wirkung vor Verwaltung — jeder Euro geht an die Kinder, nicht in den Apparat" },
{ icon: "🤝", text: "Gemeinschaft ist kein Ziel, sie ist das Mittel" },
].map(({ icon, text }) => (
<div class="flex gap-3 items-start">
<span class="text-2xl mt-0.5">{icon}</span>
<p class="text-[var(--color-text)] leading-relaxed">{text}</p>
</div>
))}
</div>
</div>
</div>
</section>
<!-- Team -->
{team.length > 0 && (
<section class="section bg-[var(--color-surface-alt)] rounded-3xl">
<h2 class="text-3xl font-bold mb-2">Der Vorstand</h2>
<p class="text-[var(--color-text-muted)] mb-8">
Wir sind Eltern. Wir haben Kinder in der Kita. Wir kennen den Unterschied zwischen dem, was ist, und dem, was sein könnte.
</p>
<div class="grid grid-cols-2 md:grid-cols-4 gap-6">
{team.map((member: any) => (
<div class="text-center">
<div class="w-20 h-20 mx-auto mb-3 rounded-full bg-[var(--color-primary-light)] flex items-center justify-center text-white text-2xl overflow-hidden">
{member.photo?.asset
? <img src={member.photo.asset.url} alt={member.name} class="w-full h-full object-cover" />
: "👤"}
</div>
<p class="font-semibold">{member.name}</p>
<p class="text-sm text-[var(--color-primary)]">{roleLabel[member.role] ?? member.role}</p>
{member.bio && <p class="text-xs text-[var(--color-text-muted)] mt-1">{member.bio}</p>}
</div>
))}
</div>
</section>
)}
<!-- FAQ -->
<section class="section">
<h2 class="text-3xl font-bold mb-8">Häufige Fragen</h2>
<div class="space-y-4 max-w-3xl">
{[
{
q: "Was ist ein Förderverein eigentlich?",
a: "Ein eingetragener, gemeinnütziger Verein, der eine Einrichtung unterstützt — nicht als Ersatz für staatliche Leistungen, sondern als Ergänzung für das, was darüber hinaus geht.",
},
{
q: "Wer kann Mitglied werden?",
a: "Alle. Eltern, Großeltern, Nachbar*innen, ehemalige Kitafamilien, Menschen ohne jeden Kita-Bezug. Natürliche und juristische Personen.",
},
{
q: "Muss ich aktiv mitarbeiten?",
a: "Nein. Wer möchte, kann — wer nicht möchte oder kann, zahlt einfach den Beitrag. Beides hilft.",
},
{
q: "Wofür wird mein Beitrag verwendet?",
a: "Ausschließlich für Vereinszwecke: Projekte, Veranstaltungen, Materialien und die finanzielle Unterstützung von Kindern, die es brauchen. Kein Vorstandsmitglied erhält eine Vergütung.",
},
].map(({ q, a }) => (
<div class="card">
<h3 class="font-bold mb-2">{q}</h3>
<p class="text-[var(--color-text-muted)] text-sm leading-relaxed">{a}</p>
</div>
))}
</div>
</section>
<!-- CTA -->
<section class="section text-center">
<a href="/mitglied-werden" class="btn-primary text-lg">Jetzt Mitglied werden</a>
<span class="mx-4 text-[var(--color-text-muted)]">oder</span>
<a href="/kontakt" class="btn-secondary text-lg">Schreib uns</a>
</section>
</Layout>

View File

@@ -0,0 +1,103 @@
---
import Layout from "../layouts/Layout.astro";
import { getSettings } from "../lib/sanity";
const settings = await getSettings();
const bank = settings?.bank;
const contact = settings?.contact;
---
<Layout
title="Unterstützen & Spenden"
description="Einmalspende, Projektpatenschaft oder Unternehmenspartnerschaft — jede Unterstützung kommt direkt bei den Kindern der Kita Regenbogen an."
>
<section class="section pt-16 pb-0">
<p class="text-sm font-semibold tracking-widest uppercase text-[var(--color-primary)] mb-3">Unterstützen</p>
<h1 class="font-brand text-5xl md:text-6xl text-[var(--color-text)] mb-6 leading-tight">
Du musst kein Mitglied sein,<br>
<span class="rainbow-text">um zu helfen.</span>
</h1>
<p class="text-xl text-[var(--color-text-muted)] max-w-2xl leading-relaxed">
Einmalspenden, Sachspenden, Projektpatenschaften — jede Form der Unterstützung
landet direkt bei den Kindern.
</p>
</section>
<div class="rainbow-bar max-w-6xl mx-auto px-4 my-12"></div>
<section class="section pt-0">
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<!-- Einmalspende -->
<div class="card">
<div class="text-4xl mb-4">💸</div>
<h2 class="text-xl font-bold mb-3">Einmalspende</h2>
<p class="text-[var(--color-text-muted)] text-sm leading-relaxed mb-4">
Überweise direkt auf unser Vereinskonto. Kein Formular, kein Aufwand.
Spendenquittung auf Wunsch.
</p>
{bank?.iban ? (
<div class="bg-[var(--color-surface-alt)] rounded-xl p-4 text-sm space-y-1">
<p><span class="font-medium">Empfänger:</span> {bank.accountHolder}</p>
<p><span class="font-medium">IBAN:</span> <span class="font-mono">{bank.iban}</span></p>
{bank.bic && <p><span class="font-medium">BIC:</span> <span class="font-mono">{bank.bic}</span></p>}
<p><span class="font-medium">Verwendung:</span> Spende Kitafreunde Regenbogen</p>
</div>
) : (
<p class="text-sm text-[var(--color-text-muted)] italic">Bankverbindung folgt</p>
)}
</div>
<!-- Projektpatenschaft -->
<div class="card">
<div class="text-4xl mb-4">🎯</div>
<h2 class="text-xl font-bold mb-3">Projektpatenschaft</h2>
<p class="text-[var(--color-text-muted)] text-sm leading-relaxed mb-4">
Du willst, dass ein konkretes Projekt stattfindet? Finanziere es gezielt.
Wir dokumentieren die Wirkung und berichten dir zurück — mit echten Fotos
und echter Geschichte.
</p>
<a href="/kontakt" class="btn-primary text-sm">Projekt anfragen →</a>
</div>
<!-- Sachspenden -->
<div class="card">
<div class="text-4xl mb-4">🎁</div>
<h2 class="text-xl font-bold mb-3">Sachspenden</h2>
<p class="text-[var(--color-text-muted)] text-sm leading-relaxed mb-4">
Spielzeug, Bücher, Materialien, Werkzeug, Pflanzen für den Garten —
frag uns, was gerade gebraucht wird. Wir stimmen mit der Kita ab.
</p>
{contact?.email && (
<a href={`mailto:${contact.email}?subject=Sachspende`} class="btn-secondary text-sm">
{contact.email}
</a>
)}
</div>
<!-- Unternehmenspartnerschaft -->
<div class="card bg-[var(--color-surface-alt)]">
<div class="text-4xl mb-4">🏢</div>
<h2 class="text-xl font-bold mb-3">Unternehmenspartnerschaft</h2>
<p class="text-[var(--color-text-muted)] text-sm leading-relaxed mb-4">
Lokale Verantwortung, sichtbare Wirkung. Als Vereinspartner oder Sponsor
unterstützt du konkrete Projekte — und wir machen das sichtbar: auf der Website,
bei Veranstaltungen und in unserer Kommunikation.
</p>
<a href="/kontakt" class="btn-secondary text-sm">Gespräch anfragen →</a>
</div>
</div>
</section>
<!-- Transparenz -->
<section class="section">
<div class="card bg-[var(--color-primary)] text-white border-0 text-center py-12">
<h2 class="font-brand text-3xl mb-4">Wo dein Geld landet.</h2>
<p class="text-white/80 max-w-xl mx-auto leading-relaxed">
Jeder Euro geht an die Kinder — für Projekte, Ausflüge und Teilhabe.
Kein Vorstandsmitglied erhält eine Vergütung. Wir veröffentlichen regelmäßig,
was wir mit den Mitteln gemacht haben.
</p>
<p class="text-white/60 text-sm mt-4">Gemeinnützig anerkannt · Spenden steuerlich absetzbar</p>
</div>
</section>
</Layout>

148
src/pages/was-wir-tun.astro Normal file
View File

@@ -0,0 +1,148 @@
---
import Layout from "../layouts/Layout.astro";
---
<Layout
title="Was wir tun"
description="Nicht das Pflichtprogramm — das Besondere. Kulturelle Bildung, Naturerfahrungen, Chancengleichheit für alle Kinder der Kita Regenbogen."
>
<section class="section pt-16 pb-0">
<p class="text-sm font-semibold tracking-widest uppercase text-[var(--color-primary)] mb-3">Was wir tun</p>
<h1 class="font-brand text-5xl md:text-6xl text-[var(--color-text)] mb-4 leading-tight">
Nicht das Pflichtprogramm.<br>
<span class="rainbow-text">Das Besondere.</span>
</h1>
<p class="text-xl text-[var(--color-text-muted)] max-w-2xl leading-relaxed mb-8">
Der Staat finanziert die Grundversorgung. Der Träger stellt den Rahmen.
Der Förderverein füllt den Raum, der danach kommt.
</p>
</section>
<div class="rainbow-bar max-w-6xl mx-auto px-4 mb-16"></div>
<!-- Erleben -->
<section id="erleben" class="section pt-0">
<div class="grid grid-cols-1 md:grid-cols-2 gap-12 items-center">
<div>
<div class="text-5xl mb-4">🎭</div>
<h2 class="text-3xl font-bold mb-4" style="color: var(--color-rb-violet)">Erleben</h2>
<p class="text-[var(--color-text-muted)] leading-relaxed mb-4">
Kinder brauchen mehr als Struktur. Sie brauchen Staunen.
</p>
<p class="text-[var(--color-text-muted)] leading-relaxed mb-4">
Der Verein ermöglicht Projekte, die im normalen Kitaalltag keinen Platz finden:
Theaterprojekte, bei denen Kinder selbst auf der Bühne stehen. Musikworkshops ohne
Vorkenntnisse. Naturerfahrungen, die zeigen, dass Erde nicht nur Schmutz ist, sondern
Leben. Ausflüge in Museen, Theater, Parks und Orte, die Berliner Kinder kennen sollten.
</p>
<p class="font-semibold text-[var(--color-text)]">
Das sind keine Extras für besondere Kinder. Das ist das, was alle Kinder brauchen.
</p>
</div>
<div class="grid grid-cols-2 gap-4">
{[
{ icon: "🎪", label: "Theaterprojekte & Besuche" },
{ icon: "🎵", label: "Musik, Tanz & Kreativworkshops" },
{ icon: "🌱", label: "Garten- & Naturprojekte" },
{ icon: "🚌", label: "Ausflüge & Tagesreisen" },
{ icon: "🤸", label: "Zirkus & Bewegung" },
{ icon: "📚", label: "Lesungen & Kunst" },
].map(({ icon, label }) => (
<div class="card text-center py-4">
<div class="text-3xl mb-2">{icon}</div>
<p class="text-sm font-medium">{label}</p>
</div>
))}
</div>
</div>
</section>
<div class="rainbow-bar max-w-6xl mx-auto px-4 my-12"></div>
<!-- Teilhabe -->
<section id="teilhabe" class="section py-0">
<div class="grid grid-cols-1 md:grid-cols-2 gap-12 items-center">
<div class="order-2 md:order-1 bg-[var(--color-surface-alt)] rounded-3xl p-8">
<blockquote class="text-2xl font-semibold text-[var(--color-text)] leading-snug mb-6">
„Kein Kind fragt. Kein Kind wird gefragt."
</blockquote>
<div class="space-y-4">
{[
"Übernahme von Beiträgen für Ausflüge und Veranstaltungen",
"Unterstützung bei Materialien und Bedarf",
"Diskret, unbürokratisch, selbstverständlich",
].map((item) => (
<div class="flex gap-3 items-start">
<span class="text-[var(--color-rb-green)] text-xl font-bold mt-0.5">✓</span>
<p class="text-[var(--color-text-muted)]">{item}</p>
</div>
))}
</div>
</div>
<div class="order-1 md:order-2">
<div class="text-5xl mb-4">🤝</div>
<h2 class="text-3xl font-bold mb-4" style="color: var(--color-rb-green)">Teilhabe</h2>
<p class="text-[var(--color-text-muted)] leading-relaxed mb-4">
Manche Familien können sich den Ausflugsbeitrag nicht leisten. Manche können das
Kostüm fürs Theaterstück nicht kaufen. Manche möchten nicht, dass ihr Kind angefragt
wird, ob das Budget reicht.
</p>
<p class="text-[var(--color-text-muted)] leading-relaxed mb-4">
Der Förderverein schließt diese Lücken — diskret, unbürokratisch und ohne dass ein
Kind erklären muss, warum.
</p>
<p class="font-semibold text-[var(--color-text)]">
Das ist kein Sozialprogramm. Das ist Selbstverständlichkeit.
</p>
</div>
</div>
</section>
<div class="rainbow-bar max-w-6xl mx-auto px-4 my-12"></div>
<!-- Gemeinschaft -->
<section id="gemeinschaft" class="section py-0">
<div class="grid grid-cols-1 md:grid-cols-2 gap-12 items-center">
<div>
<div class="text-5xl mb-4">🌍</div>
<h2 class="text-3xl font-bold mb-4" style="color: var(--color-rb-orange)">Gemeinschaft</h2>
<p class="text-[var(--color-text-muted)] leading-relaxed mb-4">
Eine Kita ist stärker, wenn das Umfeld sie trägt. Der Förderverein baut diese
Verbindung: zwischen Eltern, Erzieher*innen, Nachbarschaft und lokalen Unternehmen.
</p>
<p class="text-[var(--color-text-muted)] leading-relaxed mb-6">
Das bedeutet: gemeinsame Feste, die Menschen zusammenbringen. Kooperationen mit
lokalen Partnern. Eine Öffentlichkeit, die weiß, was hier passiert und warum es sich
lohnt, dabei zu sein.
</p>
<div class="space-y-3">
{[
"🎉 Sommer- und Frühlingsfeste",
"🛍️ Basare und Gemeinschaftsevents",
"🏢 Kooperationen mit lokalen Unternehmen",
"📣 Öffentlichkeitsarbeit für die Kita",
].map((item) => (
<p class="text-[var(--color-text-muted)]">{item}</p>
))}
</div>
</div>
<div class="card bg-[var(--color-accent-light)] border-0 p-8 text-center">
<p class="font-brand text-6xl text-[var(--color-accent)] mb-4">+</p>
<p class="text-lg font-semibold text-[var(--color-text)] mb-2">Du hast eine Idee?</p>
<p class="text-[var(--color-text-muted)] mb-6">
Der Verein ist offen für neue Projekte, Kooperationsideen und Initiativen.
</p>
<a href="/kontakt" class="btn-primary" style="background: var(--color-accent)">Idee einbringen</a>
</div>
</div>
</section>
<!-- CTA -->
<section class="section text-center">
<h2 class="font-brand text-4xl mb-4">Dabei sein.</h2>
<p class="text-[var(--color-text-muted)] mb-8">Ab 1 € im Monat. Keine Verpflichtungen.</p>
<div class="flex flex-col sm:flex-row gap-4 justify-center">
<a href="/mitglied-werden" class="btn-primary">Mitglied werden</a>
<a href="/unterstuetzen" class="btn-secondary">Einmalig spenden</a>
</div>
</section>
</Layout>

82
src/styles/global.css Normal file
View File

@@ -0,0 +1,82 @@
@import "tailwindcss";
@theme {
/* Regenbogen CI — aus dem Logoguide */
--color-rb-red: #E8192C;
--color-rb-orange: #F5820D;
--color-rb-yellow: #F9C80E;
--color-rb-green: #00A651;
--color-rb-cyan: #00AEEF;
--color-rb-blue: #3B4FA8;
--color-rb-violet: #6B3FA0;
--color-primary: #6B3FA0;
--color-primary-dark: #4D2C78;
--color-primary-light: #9B6FC8;
--color-accent: #F5820D;
--color-accent-light: #FEF3E8;
--color-surface: #FAFAFA;
--color-surface-alt: #F4EFF9;
--color-text: #1A1A2E;
--color-text-muted: #6B7280;
--color-border: #E5E7EB;
--font-brand: "Apex Brush", "Pacifico", cursive;
--font-body: "Inter", system-ui, sans-serif;
}
@font-face {
font-family: "Apex Brush";
src: url("/fonts/ApexBrush-Regular.woff2") format("woff2"),
url("/fonts/ApexBrush-Regular.woff") format("woff");
font-weight: normal;
font-display: swap;
}
html { scroll-behavior: smooth; }
body {
font-family: var(--font-body);
color: var(--color-text);
background: var(--color-surface);
}
.font-brand { font-family: var(--font-brand); }
.rainbow-bar {
height: 4px;
background: linear-gradient(
to right,
#E8192C, #F5820D, #F9C80E, #00A651, #00AEEF, #3B4FA8, #6B3FA0
);
}
.rainbow-text {
background: linear-gradient(135deg, #6B3FA0, #3B4FA8, #00A651);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.btn-primary {
@apply inline-flex items-center gap-2 px-6 py-3 rounded-full font-semibold text-white transition-all duration-200;
background: var(--color-primary);
}
.btn-primary:hover { background: var(--color-primary-dark); transform: translateY(-1px); }
.btn-secondary {
@apply inline-flex items-center gap-2 px-6 py-3 rounded-full font-semibold transition-all duration-200;
border: 2px solid var(--color-primary);
color: var(--color-primary);
}
.btn-secondary:hover { background: var(--color-surface-alt); }
.card {
@apply rounded-2xl bg-white border p-6 transition-shadow duration-200;
border-color: var(--color-border);
}
.card:hover { box-shadow: 0 8px 30px rgba(107,63,160,0.12); }
.section { @apply py-16 px-4 max-w-6xl mx-auto; }
.section-sm { @apply py-10 px-4 max-w-6xl mx-auto; }

5
tsconfig.json Normal file
View File

@@ -0,0 +1,5 @@
{
"extends": "astro/tsconfigs/strict",
"include": [".astro/types.d.ts", "**/*"],
"exclude": ["dist"]
}