Merge 'design/playful-paper': Warm Paper redesign, real logo + webfont, polished pages

This commit is contained in:
2026-06-06 14:19:33 +02:00
32 changed files with 817 additions and 465 deletions

3
.gitignore vendored
View File

@@ -22,3 +22,6 @@ pnpm-debug.log*
# jetbrains setting folder # jetbrains setting folder
.idea/ .idea/
# editor / tooling
.claude/

111
package-lock.json generated
View File

@@ -698,9 +698,6 @@
"cpu": [ "cpu": [
"arm" "arm"
], ],
"libc": [
"glibc"
],
"license": "LGPL-3.0-or-later", "license": "LGPL-3.0-or-later",
"optional": true, "optional": true,
"os": [ "os": [
@@ -717,9 +714,6 @@
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
"libc": [
"glibc"
],
"license": "LGPL-3.0-or-later", "license": "LGPL-3.0-or-later",
"optional": true, "optional": true,
"os": [ "os": [
@@ -736,9 +730,6 @@
"cpu": [ "cpu": [
"ppc64" "ppc64"
], ],
"libc": [
"glibc"
],
"license": "LGPL-3.0-or-later", "license": "LGPL-3.0-or-later",
"optional": true, "optional": true,
"os": [ "os": [
@@ -755,9 +746,6 @@
"cpu": [ "cpu": [
"riscv64" "riscv64"
], ],
"libc": [
"glibc"
],
"license": "LGPL-3.0-or-later", "license": "LGPL-3.0-or-later",
"optional": true, "optional": true,
"os": [ "os": [
@@ -774,9 +762,6 @@
"cpu": [ "cpu": [
"s390x" "s390x"
], ],
"libc": [
"glibc"
],
"license": "LGPL-3.0-or-later", "license": "LGPL-3.0-or-later",
"optional": true, "optional": true,
"os": [ "os": [
@@ -793,9 +778,6 @@
"cpu": [ "cpu": [
"x64" "x64"
], ],
"libc": [
"glibc"
],
"license": "LGPL-3.0-or-later", "license": "LGPL-3.0-or-later",
"optional": true, "optional": true,
"os": [ "os": [
@@ -812,9 +794,6 @@
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
"libc": [
"musl"
],
"license": "LGPL-3.0-or-later", "license": "LGPL-3.0-or-later",
"optional": true, "optional": true,
"os": [ "os": [
@@ -831,9 +810,6 @@
"cpu": [ "cpu": [
"x64" "x64"
], ],
"libc": [
"musl"
],
"license": "LGPL-3.0-or-later", "license": "LGPL-3.0-or-later",
"optional": true, "optional": true,
"os": [ "os": [
@@ -850,9 +826,6 @@
"cpu": [ "cpu": [
"arm" "arm"
], ],
"libc": [
"glibc"
],
"license": "Apache-2.0", "license": "Apache-2.0",
"optional": true, "optional": true,
"os": [ "os": [
@@ -875,9 +848,6 @@
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
"libc": [
"glibc"
],
"license": "Apache-2.0", "license": "Apache-2.0",
"optional": true, "optional": true,
"os": [ "os": [
@@ -900,9 +870,6 @@
"cpu": [ "cpu": [
"ppc64" "ppc64"
], ],
"libc": [
"glibc"
],
"license": "Apache-2.0", "license": "Apache-2.0",
"optional": true, "optional": true,
"os": [ "os": [
@@ -925,9 +892,6 @@
"cpu": [ "cpu": [
"riscv64" "riscv64"
], ],
"libc": [
"glibc"
],
"license": "Apache-2.0", "license": "Apache-2.0",
"optional": true, "optional": true,
"os": [ "os": [
@@ -950,9 +914,6 @@
"cpu": [ "cpu": [
"s390x" "s390x"
], ],
"libc": [
"glibc"
],
"license": "Apache-2.0", "license": "Apache-2.0",
"optional": true, "optional": true,
"os": [ "os": [
@@ -975,9 +936,6 @@
"cpu": [ "cpu": [
"x64" "x64"
], ],
"libc": [
"glibc"
],
"license": "Apache-2.0", "license": "Apache-2.0",
"optional": true, "optional": true,
"os": [ "os": [
@@ -1000,9 +958,6 @@
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
"libc": [
"musl"
],
"license": "Apache-2.0", "license": "Apache-2.0",
"optional": true, "optional": true,
"os": [ "os": [
@@ -1025,9 +980,6 @@
"cpu": [ "cpu": [
"x64" "x64"
], ],
"libc": [
"musl"
],
"license": "Apache-2.0", "license": "Apache-2.0",
"optional": true, "optional": true,
"os": [ "os": [
@@ -1311,9 +1263,6 @@
"cpu": [ "cpu": [
"arm" "arm"
], ],
"libc": [
"glibc"
],
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
@@ -1327,9 +1276,6 @@
"cpu": [ "cpu": [
"arm" "arm"
], ],
"libc": [
"musl"
],
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
@@ -1343,9 +1289,6 @@
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
"libc": [
"glibc"
],
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
@@ -1359,9 +1302,6 @@
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
"libc": [
"musl"
],
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
@@ -1375,9 +1315,6 @@
"cpu": [ "cpu": [
"loong64" "loong64"
], ],
"libc": [
"glibc"
],
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
@@ -1391,9 +1328,6 @@
"cpu": [ "cpu": [
"loong64" "loong64"
], ],
"libc": [
"musl"
],
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
@@ -1407,9 +1341,6 @@
"cpu": [ "cpu": [
"ppc64" "ppc64"
], ],
"libc": [
"glibc"
],
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
@@ -1423,9 +1354,6 @@
"cpu": [ "cpu": [
"ppc64" "ppc64"
], ],
"libc": [
"musl"
],
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
@@ -1439,9 +1367,6 @@
"cpu": [ "cpu": [
"riscv64" "riscv64"
], ],
"libc": [
"glibc"
],
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
@@ -1455,9 +1380,6 @@
"cpu": [ "cpu": [
"riscv64" "riscv64"
], ],
"libc": [
"musl"
],
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
@@ -1471,9 +1393,6 @@
"cpu": [ "cpu": [
"s390x" "s390x"
], ],
"libc": [
"glibc"
],
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
@@ -1487,9 +1406,6 @@
"cpu": [ "cpu": [
"x64" "x64"
], ],
"libc": [
"glibc"
],
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
@@ -1503,9 +1419,6 @@
"cpu": [ "cpu": [
"x64" "x64"
], ],
"libc": [
"musl"
],
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
@@ -1842,9 +1755,6 @@
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
"libc": [
"glibc"
],
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
@@ -1861,9 +1771,6 @@
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
"libc": [
"musl"
],
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
@@ -1880,9 +1787,6 @@
"cpu": [ "cpu": [
"x64" "x64"
], ],
"libc": [
"glibc"
],
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
@@ -1899,9 +1803,6 @@
"cpu": [ "cpu": [
"x64" "x64"
], ],
"libc": [
"musl"
],
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
@@ -3334,9 +3235,6 @@
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
"libc": [
"glibc"
],
"license": "MPL-2.0", "license": "MPL-2.0",
"optional": true, "optional": true,
"os": [ "os": [
@@ -3357,9 +3255,6 @@
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
"libc": [
"musl"
],
"license": "MPL-2.0", "license": "MPL-2.0",
"optional": true, "optional": true,
"os": [ "os": [
@@ -3380,9 +3275,6 @@
"cpu": [ "cpu": [
"x64" "x64"
], ],
"libc": [
"glibc"
],
"license": "MPL-2.0", "license": "MPL-2.0",
"optional": true, "optional": true,
"os": [ "os": [
@@ -3403,9 +3295,6 @@
"cpu": [ "cpu": [
"x64" "x64"
], ],
"libc": [
"musl"
],
"license": "MPL-2.0", "license": "MPL-2.0",
"optional": true, "optional": true,
"os": [ "os": [

Binary file not shown.

Binary file not shown.

BIN
public/img/momente/m1.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

BIN
public/img/momente/m2.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

BIN
public/img/momente/m3.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

BIN
public/img/momente/m4.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

BIN
public/img/momente/m5.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

BIN
public/img/momente/m6.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

BIN
public/logo/logo-v1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 210 KiB

BIN
public/logo/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 206 KiB

View File

@@ -0,0 +1,82 @@
---
/**
* Handgezeichnete Deko-Kritzeleien im Stil des Logos.
* <Decor type="sun" class="w-16 anim-spin-slow" />
*/
interface Props {
type: "sun" | "cloud" | "sparkle" | "heart" | "rainbow" | "leaf" | "loop" | "petals";
class?: string;
}
const { type, class: cls = "" } = Astro.props;
const sw = 7; // stroke width, kindlich-dick
---
{type === "sun" && (
<svg class={cls} viewBox="0 0 100 100" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
<circle cx="50" cy="50" r="20" stroke="var(--color-rb-yellow)" stroke-width={sw} fill="var(--color-rb-yellow)" fill-opacity="0.25" />
{Array.from({ length: 12 }).map((_, i) => {
const a = (i / 12) * Math.PI * 2;
const x1 = 50 + Math.cos(a) * 28, y1 = 50 + Math.sin(a) * 28;
const x2 = 50 + Math.cos(a) * 40, y2 = 50 + Math.sin(a) * 40;
return <line x1={x1} y1={y1} x2={x2} y2={y2} stroke="var(--color-rb-orange)" stroke-width={sw} stroke-linecap="round" />;
})}
</svg>
)}
{type === "cloud" && (
<svg class={cls} viewBox="0 0 120 70" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
<path d="M30 55 Q10 55 12 40 Q14 28 28 30 Q30 12 48 14 Q62 8 70 22 Q90 18 92 36 Q108 36 104 52 Q102 56 92 55 Z"
fill="#fff" stroke="var(--color-rb-cyan)" stroke-width={sw} stroke-linejoin="round" />
</svg>
)}
{type === "sparkle" && (
<svg class={cls} viewBox="0 0 100 100" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
<path d="M50 8 C 54 38, 62 46, 92 50 C 62 54, 54 62, 50 92 C 46 62, 38 54, 8 50 C 38 46, 46 38, 50 8 Z"
fill="var(--color-rb-yellow)" stroke="var(--color-rb-orange)" stroke-width="5" stroke-linejoin="round" />
</svg>
)}
{type === "heart" && (
<svg class={cls} viewBox="0 0 100 90" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
<path d="M50 82 C 10 54, 8 24, 30 18 C 42 15, 50 26, 50 32 C 50 26, 58 15, 70 18 C 92 24, 90 54, 50 82 Z"
fill="var(--color-rb-red)" fill-opacity="0.18" stroke="var(--color-rb-red)" stroke-width={sw} stroke-linejoin="round" />
</svg>
)}
{type === "rainbow" && (
<svg class={cls} viewBox="0 0 120 70" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
<path d="M10 65 A50 50 0 0 1 110 65" stroke="var(--color-rb-red)" stroke-width="8" stroke-linecap="round" />
<path d="M22 65 A38 38 0 0 1 98 65" stroke="var(--color-rb-yellow)" stroke-width="8" stroke-linecap="round" />
<path d="M34 65 A26 26 0 0 1 86 65" stroke="var(--color-rb-green)" stroke-width="8" stroke-linecap="round" />
<path d="M46 65 A14 14 0 0 1 74 65" stroke="var(--color-rb-violet)" stroke-width="8" stroke-linecap="round" />
</svg>
)}
{type === "leaf" && (
<svg class={cls} viewBox="0 0 80 100" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
<path d="M40 96 C 40 60, 8 50, 14 14 C 50 18, 72 44, 40 96 Z" fill="var(--color-rb-green)" fill-opacity="0.22" stroke="var(--color-rb-green)" stroke-width={sw} stroke-linejoin="round" />
<path d="M40 90 C 36 60, 28 42, 22 26" stroke="var(--color-rb-green)" stroke-width="4" stroke-linecap="round" />
</svg>
)}
{type === "loop" && (
<svg class={cls} viewBox="0 0 160 40" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
<path d="M4 24 C 24 4, 36 4, 40 20 C 44 36, 56 36, 60 20 C 64 4, 76 4, 80 20 C 84 36, 96 36, 100 20 C 104 4, 116 4, 120 20 C 124 36, 136 36, 156 16"
stroke="var(--color-rb-cyan)" stroke-width="5" stroke-linecap="round" />
</svg>
)}
{type === "petals" && (
<svg class={cls} viewBox="0 0 100 100" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
{[
"var(--color-rb-red)","var(--color-rb-orange)","var(--color-rb-yellow)",
"var(--color-rb-green)","var(--color-rb-cyan)","var(--color-rb-blue)","var(--color-rb-violet)"
].map((c, i, arr) => {
const a = (i / arr.length) * Math.PI * 2 - Math.PI / 2;
const cx = 50 + Math.cos(a) * 24, cy = 50 + Math.sin(a) * 24;
return <ellipse cx={cx} cy={cy} rx="9" ry="16" fill={c} fill-opacity="0.9" transform={`rotate(${(i / arr.length) * 360} ${cx} ${cy})`} />;
})}
<circle cx="50" cy="50" r="11" fill="#fff" stroke="var(--color-rb-violet)" stroke-width="4" />
</svg>
)}

View File

@@ -1,22 +1,28 @@
--- ---
import Decor from "./Decor.astro";
const year = new Date().getFullYear(); const year = new Date().getFullYear();
--- ---
<footer class="mt-24 border-t border-[var(--color-border)] bg-[var(--color-surface-alt)]"> <footer class="relative mt-28 overflow-hidden bg-[var(--color-paper-2)]">
<div class="rainbow-bar"></div> <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> <!-- Deko -->
<p class="font-brand text-xl text-[var(--color-primary)] mb-3">🌈 Kitafreunde Regenbogen</p> <Decor type="cloud" class="hidden md:block w-28 absolute top-10 right-[8%] opacity-70 anim-float" />
<Decor type="sun" class="w-24 absolute -bottom-6 -left-6 opacity-50" />
<div class="relative max-w-6xl mx-auto px-4 py-16 grid grid-cols-1 md:grid-cols-3 gap-10">
<div class="md:col-span-1">
<img src="/logo/logo.png" alt="Kitafreunde Regenbogen" class="h-24 w-auto mb-4" width="744" height="745" />
<p class="text-sm text-[var(--color-text-muted)] leading-relaxed"> <p class="text-sm text-[var(--color-text-muted)] leading-relaxed">
Förderverein der Integrationskindertagesstätte Regenbogen<br> Förderverein der Integrationskita Regenbogen<br>
Keilerstraße 23 · 13503 Berlin Keilerstraße 23 · 13503 Berlin-Tegel
</p> </p>
<p class="eyebrow mt-5 !text-[var(--color-rb-violet)]">Mit Herz für alle Kinder</p>
</div> </div>
<div> <div>
<p class="font-semibold text-sm mb-3">Navigation</p> <p class="font-display font-semibold text-lg mb-4">Verein</p>
<ul class="text-sm text-[var(--color-text-muted)] space-y-2"> <ul class="text-[15px] text-[var(--color-text-muted)] space-y-2.5">
<li><a href="/ueber-uns" class="hover:text-[var(--color-primary)]">Über uns</a></li> <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="/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="/projekte" class="hover:text-[var(--color-primary)]">Projekte</a></li>
@@ -26,23 +32,23 @@ const year = new Date().getFullYear();
</div> </div>
<div> <div>
<p class="font-semibold text-sm mb-3">Mitmachen</p> <p class="font-display font-semibold text-lg mb-4">Mitmachen</p>
<ul class="text-sm text-[var(--color-text-muted)] space-y-2"> <ul class="text-[15px] text-[var(--color-text-muted)] space-y-2.5">
<li><a href="/mitglied-werden" class="hover:text-[var(--color-primary)]">Mitglied werden</a></li> <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="/unterstuetzen" class="hover:text-[var(--color-primary)]">Spenden</a></li>
<li><a href="/kontakt" class="hover:text-[var(--color-primary)]">Kontakt</a></li> <li><a href="/kontakt" class="hover:text-[var(--color-primary)]">Kontakt</a></li>
</ul> </ul>
<p class="text-xs text-[var(--color-text-muted)] mt-4"> <a href="/mitglied-werden" class="btn-primary text-sm mt-6"><span aria-hidden="true">♥</span> Jetzt unterstützen</a>
Gemeinnützig anerkannt · Spenden steuerlich absetzbar
</p>
</div> </div>
</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)]"> <div class="relative border-t border-[var(--color-border)]">
<span>© {year} Kitafreunde Regenbogen e.V.</span> <div class="max-w-6xl mx-auto px-4 py-5 flex flex-col md:flex-row justify-between gap-2 text-xs text-[var(--color-text-muted)]">
<div class="flex gap-4 mt-2 md:mt-0"> <span>© {year} Kitafreunde Regenbogen e.V. · Gemeinnützig anerkannt</span>
<a href="/impressum" class="hover:text-[var(--color-primary)]">Impressum</a> <div class="flex gap-5">
<a href="/datenschutz" class="hover:text-[var(--color-primary)]">Datenschutz</a> <a href="/impressum" class="hover:text-[var(--color-primary)]">Impressum</a>
<a href="/datenschutz" class="hover:text-[var(--color-primary)]">Datenschutz</a>
</div>
</div> </div>
</div> </div>
</footer> </footer>

View File

@@ -6,57 +6,66 @@ const nav = [
{ href: "/aktuelles", label: "Aktuelles" }, { href: "/aktuelles", label: "Aktuelles" },
{ href: "/unterstuetzen", label: "Unterstützen" }, { href: "/unterstuetzen", label: "Unterstützen" },
]; ];
const pathname = Astro.url.pathname; const pathname = Astro.url.pathname;
const isActive = (href: string) => pathname === href || pathname.startsWith(href + "/");
--- ---
<header class="sticky top-0 z-50 bg-white/95 backdrop-blur border-b border-[var(--color-border)]"> <header class="sticky top-0 z-50">
<div class="rainbow-bar"></div> <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 --> <div class="bg-[var(--color-paper)]/85 backdrop-blur-md border-b border-[var(--color-border)]">
<nav class="hidden md:flex items-center gap-6 text-sm font-medium"> <div class="max-w-6xl mx-auto px-4 flex items-center justify-between gap-4 py-3">
{nav.map(({ href, label }) => ( <!-- Logo: jetzt mit Präsenz -->
<a <a href="/" class="shrink-0 transition-transform duration-200 hover:-rotate-2 hover:scale-[1.03]" aria-label="Kitafreunde Regenbogen — Startseite">
href={href} <img src="/logo/logo.png" alt="Kitafreunde Regenbogen" class="h-14 sm:h-16 w-auto" width="744" height="745" />
class:list={[ </a>
"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"> <!-- Desktop Nav -->
Mitglied werden <nav class="hidden md:flex items-center gap-7 text-[15px] font-semibold">
</a> {nav.map(({ href, label }) => (
<a
href={href}
class:list={[
"relative py-1 transition-colors hover:text-[var(--color-primary)]",
isActive(href) ? "text-[var(--color-primary)]" : "text-[var(--color-text-muted)]",
]}
>
{label}
{isActive(href) && (
<span class="absolute -bottom-0.5 left-0 right-0 h-[3px] rounded-full bg-[var(--color-accent)]"></span>
)}
</a>
))}
</nav>
<!-- Mobile Menu Button --> <a href="/mitglied-werden" class="btn-primary text-sm hidden md:inline-flex">
<button <span aria-hidden="true">♥</span> Mitglied werden
id="mobile-menu-btn" </a>
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 --> <!-- Mobile Button -->
<div id="mobile-menu" class="hidden md:hidden border-t border-[var(--color-border)] bg-white"> <button
<div class="px-4 py-4 flex flex-col gap-4 text-sm font-medium"> id="mobile-menu-btn"
{nav.map(({ href, label }) => ( class="md:hidden p-2 rounded-xl text-[var(--color-primary)] hover:bg-[var(--color-surface-alt)]"
<a href={href} class="text-[var(--color-text)] hover:text-[var(--color-primary)]">{label}</a> aria-label="Menü öffnen" aria-expanded="false"
))} >
<a href="/mitglied-werden" class="btn-primary text-center">Mitglied werden</a> <svg xmlns="http://www.w3.org/2000/svg" class="w-7 h-7" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2.2" d="M4 7h16M4 12h16M4 17h16"/>
</svg>
</button>
</div>
<!-- Mobile Nav -->
<div id="mobile-menu" class="hidden md:hidden border-t border-[var(--color-border)] bg-[var(--color-paper)]">
<div class="px-4 py-5 flex flex-col gap-1 text-base font-semibold">
{nav.map(({ href, label }) => (
<a href={href}
class:list={[
"py-2.5 px-3 rounded-xl transition-colors",
isActive(href) ? "text-[var(--color-primary)] bg-[var(--color-surface-alt)]" : "text-[var(--color-text)] hover:bg-[var(--color-surface-alt)]",
]}>{label}</a>
))}
<a href="/mitglied-werden" class="btn-primary mt-3"><span aria-hidden="true">♥</span> Mitglied werden</a>
</div>
</div> </div>
</div> </div>
</header> </header>
@@ -64,5 +73,8 @@ const pathname = Astro.url.pathname;
<script> <script>
const btn = document.getElementById("mobile-menu-btn"); const btn = document.getElementById("mobile-menu-btn");
const menu = document.getElementById("mobile-menu"); const menu = document.getElementById("mobile-menu");
btn?.addEventListener("click", () => menu?.classList.toggle("hidden")); btn?.addEventListener("click", () => {
const open = menu?.classList.toggle("hidden");
btn.setAttribute("aria-expanded", String(open === false));
});
</script> </script>

View File

@@ -0,0 +1,35 @@
---
import Decor from "./Decor.astro";
/**
* Einheitlicher Seitenkopf: Apex-Brush-Eyebrow + Fraunces-H1 (+ optionaler Lead).
* Titel kommt als Default-Slot (mit eigenem rainbow-text/squiggle-Akzent),
* Lead optional als <Fragment slot="lead">.
*/
interface Props {
eyebrow: string;
center?: boolean;
decor?: boolean;
}
const { eyebrow, center = false, decor = true } = Astro.props;
const hasLead = Astro.slots.has("lead");
---
<section class={`relative overflow-hidden ${center ? "text-center" : ""}`}>
{decor && (
<Fragment>
<Decor type="sparkle" class="w-9 absolute top-12 right-[7%] opacity-70 anim-float" />
<Decor type="loop" class="hidden md:block w-24 absolute bottom-4 left-[2%] opacity-40 anim-wiggle" />
</Fragment>
)}
<div class={`section pt-14 pb-8 md:pt-16 ${center ? "" : "max-w-3xl"}`}>
<p class="eyebrow">{eyebrow}</p>
<h1 class="mt-3 text-[clamp(2.3rem,6vw,4rem)] font-black leading-[1.02] text-[var(--color-text)]">
<slot />
</h1>
{hasLead && (
<p class={`mt-5 text-lg md:text-xl text-[var(--color-text-muted)] leading-relaxed max-w-2xl ${center ? "mx-auto" : ""}`}>
<slot name="lead" />
</p>
)}
</div>
</section>

27
src/components/Wave.astro Normal file
View File

@@ -0,0 +1,27 @@
---
/**
* Weicher, handgezeichneter Sektions-Übergang.
* `color` = Farbe der FOLGENDEN Sektion (die Welle "gehört" der nächsten Fläche).
* `flip` = Welle nach unten zeigen lassen.
*/
interface Props {
color?: string;
flip?: boolean;
class?: string;
}
const { color = "var(--color-paper-2)", flip = false, class: cls = "" } = Astro.props;
---
<div class={`wave ${cls}`} style={`--wave: ${color}; ${flip ? "transform: rotate(180deg);" : ""}`} aria-hidden="true">
<svg viewBox="0 0 1440 80" preserveAspectRatio="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M0,40 C 180,90 360,0 540,28 C 740,60 900,12 1080,34 C 1260,56 1380,30 1440,42 L1440,80 L0,80 Z"
fill="var(--wave)"
/>
</svg>
</div>
<style>
.wave { line-height: 0; }
.wave svg { display: block; width: 100%; height: clamp(40px, 6vw, 80px); }
</style>

View File

@@ -37,10 +37,13 @@ const canonicalURL = new URL(Astro.url.pathname, "https://kitafreunde-regenbogen
<meta property="og:type" content="website" /> <meta property="og:type" content="website" />
<meta property="og:locale" content="de_DE" /> <meta property="og:locale" content="de_DE" />
<!-- Google Fonts fallback (bis Apex Brush eingebettet ist) --> <!-- Schriften: Fraunces (Display) + Hanken Grotesk (Body). Apex Brush = lokal eingebettet. -->
<link rel="preconnect" href="https://fonts.googleapis.com" /> <link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin /> <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" /> <link
href="https://fonts.googleapis.com/css2?family=Fraunces:ital,opsz,wght@0,9..144,400..900;1,9..144,400..600&family=Hanken+Grotesk:wght@400..800&display=swap"
rel="stylesheet"
/>
</head> </head>
<body> <body>
<Header /> <Header />

View File

@@ -36,8 +36,8 @@ const dateFormatted = new Date(post.published_at).toLocaleDateString("de-DE", {
)} )}
<article class="section max-w-3xl"> <article class="section max-w-3xl">
<time class="text-sm text-[var(--color-text-muted)]" datetime={post.published_at}>{dateFormatted}</time> <time class="chip" datetime={post.published_at}>📅 {dateFormatted}</time>
<h1 class="font-brand text-4xl md:text-5xl text-[var(--color-text)] mt-3 mb-6 leading-tight">{post.title}</h1> <h1 class="text-4xl md:text-5xl font-black text-[var(--color-text)] mt-4 mb-6 leading-[1.05]">{post.title}</h1>
{post.excerpt && <p class="text-xl text-[var(--color-text-muted)] mb-8 leading-relaxed">{post.excerpt}</p>} {post.excerpt && <p class="text-xl text-[var(--color-text-muted)] mb-8 leading-relaxed">{post.excerpt}</p>}
{bodyHtml && ( {bodyHtml && (
<div class="prose prose-lg max-w-none text-[var(--color-text-muted)]" set:html={bodyHtml} /> <div class="prose prose-lg max-w-none text-[var(--color-text-muted)]" set:html={bodyHtml} />

View File

@@ -1,5 +1,6 @@
--- ---
import Layout from "../../layouts/Layout.astro"; import Layout from "../../layouts/Layout.astro";
import PageHeader from "../../components/PageHeader.astro";
import { getAllPosts, imageUrl } from "../../lib/directus"; import { getAllPosts, imageUrl } from "../../lib/directus";
const posts = await getAllPosts(); const posts = await getAllPosts();
@@ -12,13 +13,14 @@ const categoryLabel: Record<string, string> = {
--- ---
<Layout title="Aktuelles" description="Neuigkeiten vom Kitafreunde Regenbogen e.V. — Projekte, Veranstaltungen, Vereinsleben."> <Layout title="Aktuelles" description="Neuigkeiten vom Kitafreunde Regenbogen e.V. — Projekte, Veranstaltungen, Vereinsleben.">
<section class="section pt-16 pb-0"> <PageHeader eyebrow="Aktuelles">
<p class="text-sm font-semibold tracking-widest uppercase text-[var(--color-primary)] mb-3">Aktuelles</p> Was gerade<br><span class="squiggle rainbow-text">bei uns passiert.</span>
<h1 class="font-brand text-5xl text-[var(--color-text)] mb-4">Was gerade<br><span class="rainbow-text">bei uns passiert.</span></h1> <Fragment slot="lead">
</section> Projekte, Veranstaltungen, Vereinsleben — Neuigkeiten von den Kitafreunden.
<div class="rainbow-bar max-w-6xl mx-auto px-4 my-10"></div> </Fragment>
</PageHeader>
<section class="section pt-0"> <section class="section pt-6">
{posts.length === 0 ? ( {posts.length === 0 ? (
<div class="card text-center py-16 bg-[var(--color-surface-alt)]"> <div class="card text-center py-16 bg-[var(--color-surface-alt)]">
<p class="text-4xl mb-4">✍️</p> <p class="text-4xl mb-4">✍️</p>

View File

@@ -1,5 +1,6 @@
--- ---
import Layout from "../layouts/Layout.astro"; import Layout from "../layouts/Layout.astro";
import PageHeader from "../components/PageHeader.astro";
import { getSettings } from "../lib/directus"; import { getSettings } from "../lib/directus";
const settings = await getSettings(); const settings = await getSettings();
@@ -9,10 +10,9 @@ const settings = await getSettings();
title="Datenschutz" title="Datenschutz"
description="Datenschutzerklärung des Kitafreunde Regenbogen e.V. gemäß DSGVO." description="Datenschutzerklärung des Kitafreunde Regenbogen e.V. gemäß DSGVO."
> >
<section class="section pt-16 max-w-3xl"> <PageHeader eyebrow="Rechtliches" decor={false}>Datenschutz</PageHeader>
<p class="text-sm font-semibold tracking-widest uppercase text-[var(--color-primary)] mb-3">Rechtliches</p>
<h1 class="font-brand text-5xl text-[var(--color-text)] mb-10">Datenschutz</h1>
<section class="section pt-2 max-w-3xl">
<div class="space-y-8 text-[var(--color-text-muted)] text-sm leading-relaxed"> <div class="space-y-8 text-[var(--color-text-muted)] text-sm leading-relaxed">
<div class="card"> <div class="card">
@@ -72,7 +72,7 @@ const settings = await getSettings();
<div class="card"> <div class="card">
<h2 class="font-bold text-[var(--color-text)] mb-3">4. Google Fonts</h2> <h2 class="font-bold text-[var(--color-text)] mb-3">4. Google Fonts</h2>
<p> <p>
Diese Website lädt Schriftarten (Pacifico, Inter) von Google Fonts Diese Website lädt Schriftarten (Fraunces, Hanken Grotesk) von Google Fonts
(<code class="text-xs bg-[var(--color-surface)] px-1 rounded">fonts.googleapis.com</code>). (<code class="text-xs bg-[var(--color-surface)] px-1 rounded">fonts.googleapis.com</code>).
Dabei wird deine IP-Adresse an Server von Google LLC in den USA übermittelt. Dabei wird deine IP-Adresse an Server von Google LLC in den USA übermittelt.
Rechtsgrundlage ist Art. 6 Abs. 1 lit. f DSGVO; unser berechtigtes Interesse Rechtsgrundlage ist Art. 6 Abs. 1 lit. f DSGVO; unser berechtigtes Interesse

View File

@@ -1,5 +1,6 @@
--- ---
import Layout from "../layouts/Layout.astro"; import Layout from "../layouts/Layout.astro";
import PageHeader from "../components/PageHeader.astro";
import { getSettings } from "../lib/directus"; import { getSettings } from "../lib/directus";
const settings = await getSettings(); const settings = await getSettings();
@@ -9,10 +10,9 @@ const settings = await getSettings();
title="Impressum" title="Impressum"
description="Impressum des Kitafreunde Regenbogen e.V. — Angaben gemäß § 5 TMG." description="Impressum des Kitafreunde Regenbogen e.V. — Angaben gemäß § 5 TMG."
> >
<section class="section pt-16 max-w-3xl"> <PageHeader eyebrow="Rechtliches" decor={false}>Impressum</PageHeader>
<p class="text-sm font-semibold tracking-widest uppercase text-[var(--color-primary)] mb-3">Rechtliches</p>
<h1 class="font-brand text-5xl text-[var(--color-text)] mb-10">Impressum</h1>
<section class="section pt-2 max-w-3xl">
<div class="space-y-8 text-[var(--color-text-muted)] text-sm leading-relaxed"> <div class="space-y-8 text-[var(--color-text-muted)] text-sm leading-relaxed">
<div class="card"> <div class="card">

View File

@@ -1,164 +1,236 @@
--- ---
import Layout from "../layouts/Layout.astro"; import Layout from "../layouts/Layout.astro";
import { getSettings, getFeaturedProjects, getLatestPosts, imageUrl } from "../lib/directus"; import Wave from "../components/Wave.astro";
import Decor from "../components/Decor.astro";
import { getSettings, getFeaturedProjects, imageUrl } from "../lib/directus";
const settings = await getSettings(); const settings = await getSettings();
const featuredProjects = await getFeaturedProjects(); const featuredProjects = await getFeaturedProjects();
const latestPosts = await getLatestPosts(3);
// --- Platzhalter, damit die Seite auch ohne CMS lebendig wirkt ---
const stats = {
members: settings?.stats_members ?? 120,
funded: settings?.stats_funded ?? 14500,
};
const momente = [
{ src: "/img/momente/m1.jpg", cap: "Sommerfest", tone: "var(--color-rb-red)" },
{ src: "/img/momente/m2.jpg", cap: "Malwerkstatt", tone: "var(--color-rb-orange)" },
{ src: "/img/momente/m3.jpg", cap: "Naturtag", tone: "var(--color-rb-green)" },
{ src: "/img/momente/m4.jpg", cap: "Freispiel", tone: "var(--color-rb-cyan)" },
{ src: "/img/momente/m5.jpg", cap: "Musikstunde", tone: "var(--color-rb-violet)" },
{ src: "/img/momente/m6.jpg", cap: "Gartenprojekt",tone: "var(--color-rb-blue)" },
];
const fallbackProjects = [
{ title: "Theaterwoche für alle Gruppen", slug: "#", date: "Frühjahr 2026", img: "/img/momente/m5.jpg", chip: "Kultur", summary: "Eine Woche Bühne, Kostüme und Mut — ein Theaterpädagoge zu Gast in der Kita." },
{ title: "Naschgarten im Hof", slug: "#", date: "Laufend", img: "/img/momente/m6.jpg", chip: "Natur", summary: "Hochbeete, Beeren und Kräuter. Die Kinder säen, pflegen und ernten selbst." },
{ title: "Inklusions-Ausflüge", slug: "#", date: "Ganzjährig", img: "/img/momente/m3.jpg", chip: "Teilhabe", summary: "Damit wirklich jedes Kind mitkommt — wir übernehmen Eintritt und Fahrt." },
];
const projectsToShow = featuredProjects.length > 0 ? null : fallbackProjects;
--- ---
<Layout <Layout
title="Mehr als Kita. Mehr als genug." 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." 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 --> <!-- ===================== HERO ===================== -->
<section class="relative overflow-hidden bg-gradient-to-br from-[var(--color-surface-alt)] to-white"> <section class="relative overflow-hidden">
<div class="section py-24 md:py-32 text-center"> <!-- schwebende Deko -->
<p class="text-sm font-semibold tracking-widest uppercase text-[var(--color-primary)] mb-4"> <Decor type="sparkle" class="w-10 absolute top-24 left-[6%] anim-float opacity-80" />
Berlin-Tegel · Integrationskita Regenbogen <Decor type="cloud" class="w-24 absolute top-16 right-[10%] anim-float-slow opacity-80" />
</p> <Decor type="loop" class="w-28 absolute bottom-24 left-[4%] opacity-60 anim-wiggle" />
<h1 class="font-brand text-5xl md:text-7xl text-[var(--color-text)] mb-6 leading-tight">
Mehr als Kita.<br> <div class="section grid lg:grid-cols-2 gap-12 items-center pt-14 pb-24 md:pt-20">
<span class="rainbow-text">Mehr als genug.</span> <!-- Text -->
</h1> <div class="text-center lg:text-left">
<p class="text-xl text-[var(--color-text-muted)] max-w-2xl mx-auto mb-10 leading-relaxed"> <p class="eyebrow reveal d1">Berlin-Tegel · seit 2019</p>
Wir schaffen die Momente, die Kinder ihr Leben lang mit sich tragen — <h1 class="reveal d2 mt-3 text-[clamp(2.6rem,7vw,4.7rem)] text-[var(--color-text)] font-black leading-[0.98]">
Kulturprojekte, Naturerfahrungen, Gemeinschaft. Und dafür, dass kein Kind Mehr als Kita.<br>
außen vor bleibt. <span class="squiggle rainbow-text">Mehr als genug.</span>
</p> </h1>
<div class="flex flex-col sm:flex-row gap-4 justify-center"> <p class="reveal d3 mt-6 text-lg md:text-xl text-[var(--color-text-muted)] max-w-xl mx-auto lg:mx-0 leading-relaxed">
<a href="/mitglied-werden" class="btn-primary text-base">Jetzt Mitglied werden</a> Wir schaffen die Momente, die Kinder ihr Leben lang mit sich tragen —
<a href="/was-wir-tun" class="btn-secondary text-base">Was wir tun</a> Kultur, Natur, Gemeinschaft. Und dafür, dass <strong class="text-[var(--color-text)] font-semibold">kein Kind außen vor bleibt</strong>.
</p>
<div class="reveal d4 mt-9 flex flex-col sm:flex-row gap-4 justify-center lg:justify-start">
<a href="/mitglied-werden" class="btn-primary text-base"><span aria-hidden="true">♥</span> Jetzt Mitglied werden</a>
<a href="/was-wir-tun" class="btn-secondary text-base">Was wir tun</a>
</div>
<div class="reveal d5 mt-7 flex flex-wrap gap-x-6 gap-y-2 justify-center lg:justify-start text-sm text-[var(--color-text-muted)]">
<span class="inline-flex items-center gap-2"><span class="text-[var(--color-rb-green)]">✓</span> Ab 1 € im Monat</span>
<span class="inline-flex items-center gap-2"><span class="text-[var(--color-rb-green)]">✓</span> Steuerlich absetzbar</span>
<span class="inline-flex items-center gap-2"><span class="text-[var(--color-rb-green)]">✓</span> Kein Ehrenamt nötig</span>
</div>
</div>
<!-- Logo-Bühne -->
<div class="reveal d3 relative mx-auto w-full max-w-md aspect-square">
<!-- weicher Farb-Halo -->
<div class="absolute inset-6 rounded-[42%_58%_63%_37%/41%_44%_56%_59%] bg-white/70 backdrop-blur-sm shadow-[0_40px_80px_-30px_rgba(42,36,51,0.4)]"></div>
<div class="absolute inset-0 rounded-[42%_58%_63%_37%/41%_44%_56%_59%] bg-gradient-to-br from-[var(--color-accent-light)] via-transparent to-[rgba(0,174,239,0.15)]"></div>
<Decor type="sun" class="w-28 absolute -top-2 -right-2 anim-spin-slow" />
<Decor type="rainbow" class="w-32 absolute bottom-4 -left-4 opacity-90 anim-float" />
<Decor type="sparkle" class="w-8 absolute top-10 left-6 anim-wiggle" />
<!-- DAS Logo, groß und schön -->
<img src="/logo/logo.png" alt="Kitafreunde Regenbogen Logo"
class="relative z-10 w-[78%] h-[78%] object-contain mx-auto mt-[11%] drop-shadow-[0_18px_30px_rgba(42,36,51,0.18)] anim-float" />
</div> </div>
</div> </div>
<!-- Decorative rainbow -->
<div class="rainbow-bar absolute bottom-0 left-0 right-0"></div> <Wave color="var(--color-paper-2)" />
</section> </section>
<!-- Drei-Sätze --> <!-- ===================== MANIFEST ===================== -->
<section class="section-sm text-center"> <section class="bg-[var(--color-paper-2)]">
<p class="text-2xl md:text-3xl font-semibold text-[var(--color-text)] max-w-3xl mx-auto leading-snug"> <div class="section-sm text-center max-w-3xl">
Die Kita stellt die Grundversorgung sicher. Das Land zahlt das Nötige. <Decor type="heart" class="w-12 mx-auto mb-5 anim-float" />
<span class="text-[var(--color-primary)]">Wir bezahlen das Besondere.</span> <p class="font-display text-2xl md:text-4xl font-semibold text-[var(--color-text)] leading-snug">
</p> Die Kita sichert die Grundversorgung. Das Land zahlt das Nötige.
<span class="squiggle text-[var(--color-primary)]">Wir bezahlen das Besondere.</span>
</p>
</div>
</section> </section>
<Wave color="var(--color-paper)" flip={true} />
<!-- Drei Säulen --> <!-- ===================== DREI SÄULEN ===================== -->
<section class="section"> <section class="section">
<div class="grid grid-cols-1 md:grid-cols-3 gap-6"> <div class="text-center mb-12">
<p class="eyebrow">Wofür wir da sind</p>
<h2 class="mt-2 text-4xl md:text-5xl font-bold">Drei Versprechen.</h2>
</div>
<div class="grid grid-cols-1 md:grid-cols-3 gap-7">
{[ {[
{ { emoji: "🎭", color: "var(--color-rb-violet)", title: "Erleben", text: "Theater, Musik, Natur, Kunst. Erlebnisse, die kein Lehrplan vorschreibt — und die man nie vergisst.", href: "/was-wir-tun#erleben", tilt: "tilt-l" },
icon: "🎭", { emoji: "🤝", color: "var(--color-rb-green)", title: "Teilhabe", text: "Kein Kind bleibt beim Ausflug zuhause, weil die Familie den Beitrag nicht stemmen kann. Punkt.", href: "/was-wir-tun#teilhabe", tilt: "" },
color: "var(--color-rb-violet)", { emoji: "🌍", color: "var(--color-rb-orange)", title: "Gemeinschaft", text: "Eltern, Erzieher*innen, Nachbarschaft, lokale Betriebe. Der Verein verbindet, wer die Kita trägt.", href: "/was-wir-tun#gemeinschaft", tilt: "tilt-r" },
title: "Erleben", ].map(({ emoji, color, title, text, href, tilt }) => (
text: "Theater, Musik, Natur, Kunst. Erlebnisse, die keine Lehrplan-Vorgabe anordnet — und die man nicht vergisst.", <a href={href} class={`sticker group ${tilt}`}>
href: "/was-wir-tun#erleben", <div class="blob w-16 h-16 grid place-items-center text-3xl mb-5"
}, style={`background:${color}20; box-shadow: inset 0 0 0 2px ${color}40;`}>
{ <span>{emoji}</span>
icon: "🤝", </div>
color: "var(--color-rb-green)", <h3 class="font-display text-2xl font-bold mb-2 transition-colors" style={`color:${color}`}>{title}</h3>
title: "Teilhabe", <p class="text-[var(--color-text-muted)] leading-relaxed">{text}</p>
text: "Kein Kind bleibt beim Ausflug zuhause, weil die Familie sich den Beitrag nicht leisten kann. Punkt.", <p class="mt-5 text-sm font-semibold text-[var(--color-primary)] group-hover:gap-2 inline-flex items-center gap-1 transition-all">
href: "/was-wir-tun#teilhabe", Mehr erfahren <span aria-hidden="true">→</span>
}, </p>
{
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> </a>
))} ))}
</div> </div>
</section> </section>
<!-- Zahlen --> <!-- ===================== MOMENTE (Galerie) ===================== -->
{settings && (settings.stats_members || settings.stats_funded) && ( <Wave color="var(--color-paper-2)" />
<section class="bg-[var(--color-primary)] text-white"> <section class="bg-[var(--color-paper-2)]">
<div class="max-w-6xl mx-auto px-4 py-16 grid grid-cols-1 md:grid-cols-2 gap-8 text-center"> <div class="section">
{settings.stats_members && ( <div class="flex flex-wrap items-end justify-between gap-4 mb-10">
<div> <div>
<p class="font-brand text-5xl mb-2">{settings.stats_members}</p> <p class="eyebrow">Aus dem Alltag</p>
<p class="text-white/80">Mitglieder unterstützen den Verein</p> <h2 class="mt-2 text-4xl md:text-5xl font-bold">Momente, die zählen.</h2>
</div> </div>
)} <span class="chip" title="Platzhalterbilder">📷 Beispielbilder</span>
{settings.stats_funded && (
<div>
<p class="font-brand text-5xl mb-2">{settings.stats_funded.toLocaleString("de")} €</p>
<p class="text-white/80">geförderte Projekte</p>
</div>
)}
</div> </div>
</section> <div class="grid grid-cols-2 md:grid-cols-3 gap-5">
)} {momente.map((m, i) => (
<figure class={`photo-frame relative ${i % 3 === 0 ? "tilt-l" : i % 3 === 2 ? "tilt-r" : ""} transition-transform duration-300 hover:rotate-0 hover:-translate-y-1 ${i === 0 || i === 4 ? "md:row-span-2" : ""}`}>
<div class={`relative overflow-hidden rounded-[0.6rem] ${i === 0 || i === 4 ? "aspect-[3/4]" : "aspect-[4/3]"}`}>
<img src={m.src} alt={m.cap} loading="lazy" style="filter: saturate(0.9) contrast(1.03);" />
<!-- Markenfärbung, damit Platzhalter on-brand wirken -->
<div class="absolute inset-0" style={`background:${m.tone}; mix-blend-mode: soft-light; opacity:.6;`}></div>
<div class="absolute inset-0 bg-gradient-to-t from-black/35 via-transparent to-transparent"></div>
</div>
<figcaption class="absolute bottom-3 left-3">
<span class="chip" style={`background:${m.tone}; color:#fff;`}>{m.cap}</span>
</figcaption>
</figure>
))}
</div>
</div>
</section>
<Wave color="var(--color-paper-3)" />
<!-- Aktuelle Projekte --> <!-- ===================== ZAHLEN ===================== -->
{featuredProjects.length > 0 && ( <section class="relative overflow-hidden bg-[var(--color-paper-3)] text-white">
<section class="section"> <Decor type="sparkle" class="w-12 absolute top-8 right-[12%] opacity-70 anim-wiggle" />
<h2 class="text-3xl font-bold mb-2">Aktuelle Projekte</h2> <Decor type="sparkle" class="w-7 absolute bottom-10 left-[14%] opacity-60 anim-float" />
<p class="text-[var(--color-text-muted)] mb-8">Was wir gerade machen und was geplant ist.</p> <div class="max-w-5xl mx-auto px-4 py-20 grid grid-cols-1 sm:grid-cols-3 gap-10 text-center">
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6"> <div>
{featuredProjects.map((p: any) => ( <p class="font-display text-6xl font-black rainbow-text">{stats.members}</p>
<a href={`/projekte/${p.slug}`} class="card group"> <p class="text-white/70 mt-2">Mitglieder tragen den Verein</p>
{p.image && ( </div>
<div class="aspect-video bg-[var(--color-surface-alt)] rounded-xl mb-4 overflow-hidden"> <div>
<img src={imageUrl(p.image, 600)} alt={p.title} class="w-full h-full object-cover group-hover:scale-105 transition-transform duration-300" /> <p class="font-display text-6xl font-black rainbow-text">{stats.funded.toLocaleString("de")}&nbsp;€</p>
<p class="text-white/70 mt-2">in Projekte geflossen</p>
</div>
<div>
<p class="font-display text-6xl font-black rainbow-text">100%</p>
<p class="text-white/70 mt-2">der Mittel kommen bei den Kindern an</p>
</div>
</div>
</section>
<Wave color="var(--color-paper)" />
<!-- ===================== PROJEKTE ===================== -->
<section class="section">
<div class="flex flex-wrap items-end justify-between gap-4 mb-10">
<div>
<p class="eyebrow">Was gerade läuft</p>
<h2 class="mt-2 text-4xl md:text-5xl font-bold">Aktuelle Projekte</h2>
</div>
<a href="/projekte" class="btn-secondary text-sm">Alle Projekte →</a>
</div>
<div class="grid grid-cols-1 md:grid-cols-3 gap-7">
{featuredProjects.length > 0
? featuredProjects.map((p: any) => (
<a href={`/projekte/${p.slug}`} class="sticker group !p-0 overflow-hidden">
{p.image && (
<div class="aspect-video overflow-hidden">
<img src={imageUrl(p.image, 600)} alt={p.title} class="w-full h-full object-cover group-hover:scale-105 transition-transform duration-500" />
</div>
)}
<div class="p-6">
<p class="text-xs text-[var(--color-text-muted)] mb-1">{p.date}</p>
<h3 class="font-display font-bold text-xl 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>
</div> </div>
)} </a>
<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> : projectsToShow!.map((p) => (
<p class="text-sm text-[var(--color-text-muted)] mt-2 line-clamp-2">{p.summary}</p> <a href={p.slug} class="sticker group !p-0 overflow-hidden">
</a> <div class="aspect-video overflow-hidden relative">
))} <img src={p.img} alt={p.title} loading="lazy" class="w-full h-full object-cover group-hover:scale-105 transition-transform duration-500" />
</div> <span class="chip absolute top-3 left-3 bg-white/90">{p.chip}</span>
<div class="mt-8 text-center"> </div>
<a href="/projekte" class="btn-secondary">Alle Projekte →</a> <div class="p-6">
</div> <p class="text-xs text-[var(--color-text-muted)] mb-1">{p.date}</p>
</section> <h3 class="font-display font-bold text-xl group-hover:text-[var(--color-primary)] transition-colors">{p.title}</h3>
)} <p class="text-sm text-[var(--color-text-muted)] mt-2">{p.summary}</p>
</div>
</a>
))}
</div>
</section>
<!-- Aktuelles --> <!-- ===================== CTA ===================== -->
{latestPosts.length > 0 && ( <section class="section">
<section class="section bg-[var(--color-surface-alt)] rounded-3xl"> <div class="relative overflow-hidden rounded-[2.5rem] bg-[var(--color-primary)] text-white text-center px-6 py-16 md:py-20">
<h2 class="text-3xl font-bold mb-8">Aktuelles</h2> <div class="absolute inset-0 opacity-30 bg-gradient-to-br from-[var(--color-rb-violet)] via-[var(--color-rb-blue)] to-[var(--color-rb-cyan)]"></div>
<div class="grid grid-cols-1 md:grid-cols-3 gap-6"> <Decor type="sun" class="w-24 absolute -top-4 -left-4 opacity-80 anim-spin-slow" />
{latestPosts.map((post: any) => ( <Decor type="rainbow" class="w-28 absolute -bottom-2 right-6 opacity-90 anim-float" />
<a href={`/aktuelles/${post.slug}`} class="card group"> <div class="relative max-w-2xl mx-auto">
<p class="text-xs text-[var(--color-text-muted)] mb-2"> <p class="eyebrow !text-[var(--color-rb-yellow)]">Schon ab 1 € im Monat</p>
{new Date(post.published_at).toLocaleDateString("de-DE", { day: "numeric", month: "long", year: "numeric" })} <h2 class="mt-3 text-4xl md:text-6xl font-black">Werde Kitafreund*in.</h2>
</p> <p class="mt-5 text-lg text-white/85">
<h3 class="font-bold leading-snug group-hover:text-[var(--color-primary)] transition-colors">{post.title}</h3> Kein Aufwand. Kein verpflichtendes Ehrenamt.<br class="hidden sm:block">
{post.excerpt && <p class="text-sm text-[var(--color-text-muted)] mt-2 line-clamp-3">{post.excerpt}</p>} Nur Kinder, die mehr bekommen.
</a> </p>
))} <a href="/mitglied-werden" class="btn-primary text-lg mt-9 !bg-white !text-[var(--color-primary)] !shadow-[0_6px_0_0_rgba(0,0,0,0.25)]">
<span aria-hidden="true">♥</span> Jetzt Mitglied werden
</a>
<p class="text-sm text-white/70 mt-4">Gemeinnützig anerkannt · Beiträge steuerlich absetzbar</p>
</div> </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> </div>
</section> </section>
</Layout> </Layout>

View File

@@ -1,16 +1,19 @@
--- ---
import Layout from "../layouts/Layout.astro"; import Layout from "../layouts/Layout.astro";
import PageHeader from "../components/PageHeader.astro";
import { getSettings } from "../lib/directus"; import { getSettings } from "../lib/directus";
const settings = await getSettings(); const settings = await getSettings();
--- ---
<Layout title="Kontakt" description="Kontakt zum Kitafreunde Regenbogen e.V. — schreib uns, werde Mitglied oder bring eine Idee ein."> <Layout title="Kontakt" description="Kontakt zum Kitafreunde Regenbogen e.V. — schreib uns, werde Mitglied oder bring eine Idee ein.">
<section class="section pt-16"> <PageHeader eyebrow="Kontakt">
<p class="text-sm font-semibold tracking-widest uppercase text-[var(--color-primary)] mb-3">Kontakt</p> Schreib <span class="squiggle rainbow-text">uns.</span>
<h1 class="font-brand text-5xl text-[var(--color-text)] mb-6">Schreib uns.</h1> <Fragment slot="lead">Fragen, Ideen, Mitmachen — wir freuen uns über jede Nachricht.</Fragment>
</PageHeader>
<div class="grid grid-cols-1 md:grid-cols-2 gap-12 mt-8"> <section class="section pt-6">
<div class="grid grid-cols-1 md:grid-cols-2 gap-12">
<!-- Kontaktinfos --> <!-- Kontaktinfos -->
<div class="space-y-6"> <div class="space-y-6">
<div class="card"> <div class="card">

View File

@@ -1,5 +1,7 @@
--- ---
import Layout from "../layouts/Layout.astro"; import Layout from "../layouts/Layout.astro";
import PageHeader from "../components/PageHeader.astro";
import { getSettings } from "../lib/directus"; import { getSettings } from "../lib/directus";
const settings = await getSettings(); const settings = await getSettings();
@@ -9,16 +11,15 @@ const settings = await getSettings();
title="Mitglied werden" title="Mitglied werden"
description="Mitglied beim Kitafreunde Regenbogen e.V. werden. Steuerlich absetzbar. Keine Verpflichtungen. Direkte Wirkung für Kinder in Berlin-Tegel." 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"> <PageHeader eyebrow="Mitglied werden">
<p class="text-sm font-semibold tracking-widest uppercase text-[var(--color-primary)] mb-3">Mitglied werden</p> Dabei sein.<br><span class="squiggle rainbow-text">So einfach wie möglich.</span>
<h1 class="font-brand text-5xl md:text-6xl text-[var(--color-text)] mb-6 leading-tight"> <Fragment slot="lead">
Dabei sein.<br><span class="rainbow-text">So einfach wie möglich.</span> Steuerlich absetzbar, keine Verpflichtungen — und direkte Wirkung für Kinder in deiner Nachbarschaft.
</h1> </Fragment>
</section> </PageHeader>
<div class="rainbow-bar max-w-6xl mx-auto px-4 mb-12"></div>
<!-- Warum --> <!-- Warum -->
<section class="section pt-0"> <section class="section pt-6">
<div class="max-w-2xl"> <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 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-2">Du musst nicht auf Sitzungen kommen.</p>

View File

@@ -1,16 +1,19 @@
--- ---
import Layout from "../layouts/Layout.astro"; import Layout from "../layouts/Layout.astro";
import PageHeader from "../components/PageHeader.astro";
import { getSettings } from "../lib/directus"; import { getSettings } from "../lib/directus";
const settings = await getSettings(); const settings = await getSettings();
--- ---
<Layout title="Presse" description="Pressekontakt und Informationen zum Kitafreunde Regenbogen e.V., Förderverein der Integrationskita Regenbogen in Berlin-Tegel."> <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"> <PageHeader eyebrow="Presse">
<p class="text-sm font-semibold tracking-widest uppercase text-[var(--color-primary)] mb-3">Presse</p> Kontakt für Presse<br>und <span class="squiggle rainbow-text">Medien.</span>
<h1 class="font-brand text-5xl text-[var(--color-text)] mb-6">Kontakt für Presse<br>und Medien.</h1> <Fragment slot="lead">Pressekontakt, Boilerplate und Pressekit zum Verein.</Fragment>
</PageHeader>
<div class="grid grid-cols-1 md:grid-cols-2 gap-12 mt-12"> <section class="section pt-6">
<div class="grid grid-cols-1 md:grid-cols-2 gap-12">
<div> <div>
<h2 class="text-xl font-bold mb-4">Pressekontakt</h2> <h2 class="text-xl font-bold mb-4">Pressekontakt</h2>
{settings?.contact_email ? ( {settings?.contact_email ? (

View File

@@ -35,11 +35,11 @@ const bodyHtml = project.body ?? "";
<section class="section"> <section class="section">
<div class="max-w-3xl"> <div class="max-w-3xl">
<div class="flex items-center gap-3 mb-4 text-sm text-[var(--color-text-muted)]"> <div class="flex flex-wrap items-center gap-2 mb-5">
{project.date && <span>📅 {project.date}</span>} {project.date && <span class="chip">📅 {project.date}</span>}
{project.target_group && <span>👥 {project.target_group}</span>} {project.target_group && <span class="chip">👥 {project.target_group}</span>}
</div> </div>
<h1 class="font-brand text-4xl md:text-5xl text-[var(--color-text)] mb-6">{project.title}</h1> <h1 class="text-4xl md:text-5xl font-black text-[var(--color-text)] mb-6 leading-[1.05]">{project.title}</h1>
<p class="text-xl text-[var(--color-text-muted)] leading-relaxed mb-8">{project.summary}</p> <p class="text-xl text-[var(--color-text-muted)] leading-relaxed mb-8">{project.summary}</p>
{bodyHtml && ( {bodyHtml && (
<div class="prose prose-lg max-w-none text-[var(--color-text-muted)]" set:html={bodyHtml} /> <div class="prose prose-lg max-w-none text-[var(--color-text-muted)]" set:html={bodyHtml} />

View File

@@ -1,5 +1,6 @@
--- ---
import Layout from "../../layouts/Layout.astro"; import Layout from "../../layouts/Layout.astro";
import PageHeader from "../../components/PageHeader.astro";
import { getAllProjects, imageUrl } from "../../lib/directus"; import { getAllProjects, imageUrl } from "../../lib/directus";
const projects = await getAllProjects(); const projects = await getAllProjects();
@@ -20,17 +21,15 @@ const statusColor: Record<string, string> = {
title="Projekte" 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." 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"> <PageHeader eyebrow="Projekte">
<p class="text-sm font-semibold tracking-widest uppercase text-[var(--color-primary)] mb-3">Projekte</p> Was wir schon gemacht haben.<br><span class="squiggle rainbow-text">Was als nächstes kommt.</span>
<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> <Fragment slot="lead">
<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. Jedes Projekt erzählt, warum der Verein existiert. Konkret, sichtbar, für alle.
</p> </Fragment>
</section> </PageHeader>
<div class="rainbow-bar max-w-6xl mx-auto px-4 my-10"></div>
{projects.length === 0 ? ( {projects.length === 0 ? (
<section class="section pt-0"> <section class="section pt-6">
<div class="card text-center py-16 bg-[var(--color-surface-alt)]"> <div class="card text-center py-16 bg-[var(--color-surface-alt)]">
<p class="text-4xl mb-4">🚀</p> <p class="text-4xl mb-4">🚀</p>
<h2 class="text-xl font-bold mb-2">Projekte folgen</h2> <h2 class="text-xl font-bold mb-2">Projekte folgen</h2>

View File

@@ -1,5 +1,8 @@
--- ---
import Layout from "../layouts/Layout.astro"; import Layout from "../layouts/Layout.astro";
import PageHeader from "../components/PageHeader.astro";
import Wave from "../components/Wave.astro";
import Decor from "../components/Decor.astro";
import { getTeam, imageUrl } from "../lib/directus"; import { getTeam, imageUrl } from "../lib/directus";
const team = await getTeam(); const team = await getTeam();
@@ -17,18 +20,16 @@ const roleLabel: Record<string, string> = {
description="Wer sind die Kitafreunde Regenbogen? Der Förderverein der Integrationskita Regenbogen Berlin — gegründet von Eltern, getragen von einer Gemeinschaft." description="Wer sind die Kitafreunde Regenbogen? Der Förderverein der Integrationskita Regenbogen Berlin — gegründet von Eltern, getragen von einer Gemeinschaft."
> >
<!-- Hero --> <!-- Hero -->
<section class="section pt-16 pb-0"> <PageHeader eyebrow="Über uns">
<div class="max-w-3xl"> Wir sind die <span class="squiggle rainbow-text">Kitafreunde.</span>
<p class="text-sm font-semibold tracking-widest uppercase text-[var(--color-primary)] mb-3">Über uns</p> <Fragment slot="lead">
<h1 class="font-brand text-5xl md:text-6xl text-[var(--color-text)] mb-6 leading-tight"> Gegründet von Eltern, getragen von einer Gemeinschaft — für eine Kita,
Wir sind die<br><span class="rainbow-text">Kitafreunde.</span> die mehr kann als das Minimum.
</h1> </Fragment>
</div> </PageHeader>
</section>
<div class="rainbow-bar max-w-6xl mx-auto px-4 my-8"></div>
<!-- Geschichte --> <!-- Geschichte -->
<section class="section pt-0"> <section class="section pt-6">
<div class="grid grid-cols-1 md:grid-cols-2 gap-16 items-start"> <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"> <div class="prose prose-lg max-w-none text-[var(--color-text-muted)] leading-relaxed space-y-5">
<p> <p>
@@ -75,9 +76,9 @@ const roleLabel: Record<string, string> = {
{ icon: "🎯", text: "Wirkung vor Verwaltung — jeder Euro geht an die Kinder, nicht in den Apparat" }, { 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" }, { icon: "🤝", text: "Gemeinschaft ist kein Ziel, sie ist das Mittel" },
].map(({ icon, text }) => ( ].map(({ icon, text }) => (
<div class="flex gap-3 items-start"> <div class="flex gap-4 items-start">
<span class="text-2xl mt-0.5">{icon}</span> <span class="blob shrink-0 w-11 h-11 grid place-items-center text-xl" style="background: var(--color-accent-light); box-shadow: inset 0 0 0 2px rgba(245,130,13,0.25);">{icon}</span>
<p class="text-[var(--color-text)] leading-relaxed">{text}</p> <p class="text-[var(--color-text)] leading-relaxed pt-1.5">{text}</p>
</div> </div>
))} ))}
</div> </div>
@@ -87,31 +88,39 @@ const roleLabel: Record<string, string> = {
<!-- Team --> <!-- Team -->
{team.length > 0 && ( {team.length > 0 && (
<section class="section bg-[var(--color-surface-alt)] rounded-3xl"> <Fragment>
<h2 class="text-3xl font-bold mb-2">Der Vorstand</h2> <Wave color="var(--color-paper-2)" />
<p class="text-[var(--color-text-muted)] mb-8"> <section class="bg-[var(--color-paper-2)]">
Wir sind Eltern. Wir haben Kinder in der Kita. Wir kennen den Unterschied zwischen dem, was ist, und dem, was sein könnte. <div class="section">
</p> <p class="eyebrow">Wer dahintersteckt</p>
<div class="grid grid-cols-2 md:grid-cols-4 gap-6"> <h2 class="mt-2 text-3xl md:text-4xl font-bold mb-3">Der Vorstand</h2>
{team.map((member: any) => ( <p class="text-[var(--color-text-muted)] mb-10 max-w-2xl">
<div class="text-center"> Wir sind Eltern. Wir haben Kinder in der Kita. Wir kennen den Unterschied zwischen dem, was ist, und dem, was sein könnte.
<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"> </p>
{member.photo <div class="grid grid-cols-2 md:grid-cols-4 gap-8">
? <img src={imageUrl(member.photo, 80)} alt={member.name} class="w-full h-full object-cover" /> {team.map((member: any) => (
: "👤"} <div class="text-center">
</div> <div class="w-24 h-24 mx-auto mb-3 blob bg-[var(--color-primary-light)] flex items-center justify-center text-white text-2xl overflow-hidden ring-4 ring-white shadow-[0_14px_30px_-16px_rgba(42,36,51,0.5)]">
<p class="font-semibold">{member.name}</p> {member.photo
<p class="text-sm text-[var(--color-primary)]">{roleLabel[member.role] ?? member.role}</p> ? <img src={imageUrl(member.photo, 96)} alt={member.name} class="w-full h-full object-cover" />
{member.bio && <p class="text-xs text-[var(--color-text-muted)] mt-1">{member.bio}</p>} : "👤"}
</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> </div>
))} </div>
</div> </section>
</section> <Wave color="var(--color-paper)" flip={true} />
</Fragment>
)} )}
<!-- FAQ --> <!-- FAQ -->
<section class="section"> <section class="section">
<h2 class="text-3xl font-bold mb-8">Häufige Fragen</h2> <p class="eyebrow">Gut zu wissen</p>
<h2 class="mt-2 text-3xl md:text-4xl font-bold mb-8">Häufige Fragen</h2>
<div class="space-y-4 max-w-3xl"> <div class="space-y-4 max-w-3xl">
{[ {[
{ {
@@ -140,9 +149,15 @@ const roleLabel: Record<string, string> = {
</section> </section>
<!-- CTA --> <!-- CTA -->
<section class="section text-center"> <section class="section">
<a href="/mitglied-werden" class="btn-primary text-lg">Jetzt Mitglied werden</a> <div class="relative overflow-hidden rounded-[2.5rem] bg-[var(--color-paper-2)] text-center px-6 py-14">
<span class="mx-4 text-[var(--color-text-muted)]">oder</span> <Decor type="heart" class="w-12 mx-auto mb-4 anim-float" />
<a href="/kontakt" class="btn-secondary text-lg">Schreib uns</a> <h2 class="text-3xl md:text-4xl font-bold mb-2">Werd Teil davon.</h2>
<p class="text-[var(--color-text-muted)] mb-8">Ab 1 € im Monat. Kein Aufwand, große Wirkung.</p>
<div class="flex flex-col sm:flex-row gap-4 justify-center">
<a href="/mitglied-werden" class="btn-primary text-base"><span aria-hidden="true">♥</span> Jetzt Mitglied werden</a>
<a href="/kontakt" class="btn-secondary text-base">Schreib uns</a>
</div>
</div>
</section> </section>
</Layout> </Layout>

View File

@@ -1,5 +1,6 @@
--- ---
import Layout from "../layouts/Layout.astro"; import Layout from "../layouts/Layout.astro";
import PageHeader from "../components/PageHeader.astro";
import { getSettings } from "../lib/directus"; import { getSettings } from "../lib/directus";
const settings = await getSettings(); const settings = await getSettings();
@@ -9,20 +10,16 @@ const settings = await getSettings();
title="Unterstützen & Spenden" title="Unterstützen & Spenden"
description="Einmalspende, Projektpatenschaft oder Unternehmenspartnerschaft — jede Unterstützung kommt direkt bei den Kindern der Kita Regenbogen an." description="Einmalspende, Projektpatenschaft oder Unternehmenspartnerschaft — jede Unterstützung kommt direkt bei den Kindern der Kita Regenbogen an."
> >
<section class="section pt-16 pb-0"> <PageHeader eyebrow="Unterstützen">
<p class="text-sm font-semibold tracking-widest uppercase text-[var(--color-primary)] mb-3">Unterstützen</p> Du musst kein Mitglied sein,<br>
<h1 class="font-brand text-5xl md:text-6xl text-[var(--color-text)] mb-6 leading-tight"> <span class="squiggle rainbow-text">um zu helfen.</span>
Du musst kein Mitglied sein,<br> <Fragment slot="lead">
<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 Einmalspenden, Sachspenden, Projektpatenschaften — jede Form der Unterstützung
landet direkt bei den Kindern. landet direkt bei den Kindern.
</p> </Fragment>
</section> </PageHeader>
<div class="rainbow-bar max-w-6xl mx-auto px-4 my-12"></div>
<section class="section pt-0"> <section class="section pt-6">
<div class="grid grid-cols-1 md:grid-cols-2 gap-6"> <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<!-- Einmalspende --> <!-- Einmalspende -->

View File

@@ -1,30 +1,29 @@
--- ---
import Layout from "../layouts/Layout.astro"; import Layout from "../layouts/Layout.astro";
import PageHeader from "../components/PageHeader.astro";
import Decor from "../components/Decor.astro";
--- ---
<Layout <Layout
title="Was wir tun" title="Was wir tun"
description="Nicht das Pflichtprogramm — das Besondere. Kulturelle Bildung, Naturerfahrungen, Chancengleichheit für alle Kinder der Kita Regenbogen." description="Nicht das Pflichtprogramm — das Besondere. Kulturelle Bildung, Naturerfahrungen, Chancengleichheit für alle Kinder der Kita Regenbogen."
> >
<section class="section pt-16 pb-0"> <PageHeader eyebrow="Was wir tun">
<p class="text-sm font-semibold tracking-widest uppercase text-[var(--color-primary)] mb-3">Was wir tun</p> Nicht das Pflichtprogramm.<br>
<h1 class="font-brand text-5xl md:text-6xl text-[var(--color-text)] mb-4 leading-tight"> <span class="squiggle rainbow-text">Das Besondere.</span>
Nicht das Pflichtprogramm.<br> <Fragment slot="lead">
<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 Staat finanziert die Grundversorgung. Der Träger stellt den Rahmen.
Der Förderverein füllt den Raum, der danach kommt. Der Förderverein füllt den Raum, der danach kommt.
</p> </Fragment>
</section> </PageHeader>
<div class="rainbow-bar max-w-6xl mx-auto px-4 mb-16"></div>
<!-- Erleben --> <!-- Erleben -->
<section id="erleben" class="section pt-0"> <section id="erleben" class="section pt-6 scroll-mt-24">
<div class="grid grid-cols-1 md:grid-cols-2 gap-12 items-center"> <div class="grid grid-cols-1 md:grid-cols-2 gap-12 items-center">
<div> <div>
<div class="text-5xl mb-4">🎭</div> <div class="blob w-16 h-16 grid place-items-center text-3xl mb-5" style="background: rgba(107,63,160,0.12); box-shadow: inset 0 0 0 2px rgba(107,63,160,0.25);">🎭</div>
<h2 class="text-3xl font-bold mb-4" style="color: var(--color-rb-violet)">Erleben</h2> <p class="eyebrow !text-[var(--color-rb-violet)]">Staunen</p>
<h2 class="mt-1 text-3xl md:text-4xl font-bold mb-4" style="color: var(--color-rb-violet)">Erleben</h2>
<p class="text-[var(--color-text-muted)] leading-relaxed mb-4"> <p class="text-[var(--color-text-muted)] leading-relaxed mb-4">
Kinder brauchen mehr als Struktur. Sie brauchen Staunen. Kinder brauchen mehr als Struktur. Sie brauchen Staunen.
</p> </p>
@@ -56,7 +55,7 @@ import Layout from "../layouts/Layout.astro";
</div> </div>
</section> </section>
<div class="rainbow-bar max-w-6xl mx-auto px-4 my-12"></div> <div class="rainbow-bar w-20 mx-auto rounded-full my-6"></div>
<!-- Teilhabe --> <!-- Teilhabe -->
<section id="teilhabe" class="section py-0"> <section id="teilhabe" class="section py-0">
@@ -79,8 +78,9 @@ import Layout from "../layouts/Layout.astro";
</div> </div>
</div> </div>
<div class="order-1 md:order-2"> <div class="order-1 md:order-2">
<div class="text-5xl mb-4">🤝</div> <div class="blob w-16 h-16 grid place-items-center text-3xl mb-5" style="background: rgba(0,166,81,0.12); box-shadow: inset 0 0 0 2px rgba(0,166,81,0.25);">🤝</div>
<h2 class="text-3xl font-bold mb-4" style="color: var(--color-rb-green)">Teilhabe</h2> <p class="eyebrow !text-[var(--color-rb-green)]">Für alle</p>
<h2 class="mt-1 text-3xl md:text-4xl font-bold mb-4" style="color: var(--color-rb-green)">Teilhabe</h2>
<p class="text-[var(--color-text-muted)] leading-relaxed mb-4"> <p class="text-[var(--color-text-muted)] leading-relaxed mb-4">
Manche Familien können sich den Ausflugsbeitrag nicht leisten. Manche können das 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 Kostüm fürs Theaterstück nicht kaufen. Manche möchten nicht, dass ihr Kind angefragt
@@ -97,14 +97,15 @@ import Layout from "../layouts/Layout.astro";
</div> </div>
</section> </section>
<div class="rainbow-bar max-w-6xl mx-auto px-4 my-12"></div> <div class="rainbow-bar w-20 mx-auto rounded-full my-6"></div>
<!-- Gemeinschaft --> <!-- Gemeinschaft -->
<section id="gemeinschaft" class="section py-0"> <section id="gemeinschaft" class="section py-0">
<div class="grid grid-cols-1 md:grid-cols-2 gap-12 items-center"> <div class="grid grid-cols-1 md:grid-cols-2 gap-12 items-center">
<div> <div>
<div class="text-5xl mb-4">🌍</div> <div class="blob w-16 h-16 grid place-items-center text-3xl mb-5" style="background: rgba(245,130,13,0.12); box-shadow: inset 0 0 0 2px rgba(245,130,13,0.25);">🌍</div>
<h2 class="text-3xl font-bold mb-4" style="color: var(--color-rb-orange)">Gemeinschaft</h2> <p class="eyebrow">Zusammen</p>
<h2 class="mt-1 text-3xl md:text-4xl font-bold mb-4" style="color: var(--color-rb-orange)">Gemeinschaft</h2>
<p class="text-[var(--color-text-muted)] leading-relaxed mb-4"> <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 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. Verbindung: zwischen Eltern, Erzieher*innen, Nachbarschaft und lokalen Unternehmen.
@@ -137,12 +138,20 @@ import Layout from "../layouts/Layout.astro";
</section> </section>
<!-- CTA --> <!-- CTA -->
<section class="section text-center"> <section class="section">
<h2 class="font-brand text-4xl mb-4">Dabei sein.</h2> <div class="relative overflow-hidden rounded-[2.5rem] bg-[var(--color-primary)] text-white text-center px-6 py-16">
<p class="text-[var(--color-text-muted)] mb-8">Ab 1 € im Monat. Keine Verpflichtungen.</p> <div class="absolute inset-0 opacity-30 bg-gradient-to-br from-[var(--color-rb-violet)] via-[var(--color-rb-blue)] to-[var(--color-rb-cyan)]"></div>
<div class="flex flex-col sm:flex-row gap-4 justify-center"> <Decor type="sun" class="w-20 absolute -top-3 -left-3 opacity-80 anim-spin-slow" />
<a href="/mitglied-werden" class="btn-primary">Mitglied werden</a> <Decor type="rainbow" class="w-24 absolute -bottom-1 right-6 opacity-90 anim-float" />
<a href="/unterstuetzen" class="btn-secondary">Einmalig spenden</a> <div class="relative max-w-2xl mx-auto">
<p class="eyebrow !text-[var(--color-rb-yellow)]">Schon ab 1 € im Monat</p>
<h2 class="mt-2 text-4xl md:text-5xl font-black">Dabei sein.</h2>
<p class="mt-4 text-white/85 mb-8">Keine Verpflichtungen. Nur Kinder, die mehr bekommen.</p>
<div class="flex flex-col sm:flex-row gap-4 justify-center">
<a href="/mitglied-werden" class="btn-primary !bg-white !text-[var(--color-primary)] !shadow-[0_6px_0_0_rgba(0,0,0,0.25)]"><span aria-hidden="true">♥</span> Mitglied werden</a>
<a href="/unterstuetzen" class="btn-secondary !bg-transparent !text-white !border-white !shadow-[0_6px_0_0_rgba(0,0,0,0.25)]">Einmalig spenden</a>
</div>
</div>
</div> </div>
</section> </section>
</Layout> </Layout>

View File

@@ -1,31 +1,50 @@
@import "tailwindcss"; @import "tailwindcss";
/* ============================================================
Kitafreunde Regenbogen — "Warm Paper" Design System
Picture-book warmth · rainbow as punctuation · hand-drawn soul
============================================================ */
@theme { @theme {
/* Regenbogen CI — aus dem Logoguide */ /* --- Rainbow CI (exact aus dem Logoguide) --- */
--color-rb-red: #E8192C; --color-rb-red: #E8192C;
--color-rb-orange: #F5820D; --color-rb-orange: #F5820D;
--color-rb-yellow: #F9C80E; --color-rb-yellow: #F9C80E;
--color-rb-green: #00A651; --color-rb-green: #00A651;
--color-rb-cyan: #00AEEF; --color-rb-cyan: #00AEEF;
--color-rb-blue: #3B4FA8; --color-rb-blue: #3B4FA8;
--color-rb-violet: #6B3FA0; --color-rb-violet: #6B3FA0;
--color-primary: #6B3FA0; /* --- Brand roles --- */
--color-primary-dark: #4D2C78; --color-primary: #6B3FA0; /* violet — Marke, Text-Akzente, Links */
--color-primary-light: #9B6FC8; --color-primary-dark: #4D2C78;
--color-accent: #F5820D; --color-primary-light: #9B6FC8;
--color-accent-light: #FEF3E8; --color-accent: #F5820D; /* orange — Aktionen, Wärme */
--color-accent-dark: #D96E00;
--color-accent-light: #FDEBD3;
--color-surface: #FAFAFA; /* --- Paper surfaces --- */
--color-surface-alt: #F4EFF9; --color-paper: #FBF4E6; /* warmes Recyclingpapier — Haupt-BG */
--color-text: #1A1A2E; --color-paper-2: #F4E9D4; /* getönt — alternierende Sektionen */
--color-text-muted: #6B7280; --color-paper-3: #2A2433; /* tiefe Tinten-Sektion */
--color-border: #E5E7EB;
--font-brand: "Apex Brush", "Pacifico", cursive; /* --- Back-compat Aliase (bestehende Seiten nutzen diese) --- */
--font-body: "Inter", system-ui, sans-serif; --color-surface: #FBF4E6;
--color-surface-alt: #F4E9D4;
--color-text: #2A2433; /* warme Tinte mit Violett-Unterton */
--color-text-muted: #6E6679;
--color-border: #E7DAC2; /* warmer Papierrand */
/* --- Typografie --- */
--font-brand: "Apex Brush", "Pacifico", cursive; /* Signatur, sparsam */
--font-display: "Fraunces", "Georgia", serif; /* Headlines */
--font-body: "Hanken Grotesk", system-ui, sans-serif; /* Fließtext, UI */
/* --- Radii: organisch, weich --- */
--radius-blob: 42% 58% 63% 37% / 41% 44% 56% 59%;
} }
/* --- Marken-Webfont (lokal eingebettet) --- */
@font-face { @font-face {
font-family: "Apex Brush"; font-family: "Apex Brush";
src: url("/fonts/ApexBrush-Regular.woff2") format("woff2"), src: url("/fonts/ApexBrush-Regular.woff2") format("woff2"),
@@ -34,49 +53,224 @@
font-display: swap; font-display: swap;
} }
/* ============================================================
Base
============================================================ */
@layer base {
html { scroll-behavior: smooth; } html { scroll-behavior: smooth; }
body { body {
font-family: var(--font-body); font-family: var(--font-body);
color: var(--color-text); color: var(--color-text);
background: var(--color-surface); background-color: var(--color-paper);
/* subtile, warme Lichtwäsche in Regenbogenfarben */
background-image:
radial-gradient(60rem 40rem at 110% -10%, rgba(245,130,13,0.10), transparent 60%),
radial-gradient(50rem 40rem at -10% 0%, rgba(107,63,160,0.10), transparent 55%),
radial-gradient(45rem 40rem at 50% 120%, rgba(0,174,239,0.08), transparent 60%);
background-attachment: fixed;
-webkit-font-smoothing: antialiased;
text-rendering: optimizeLegibility;
} }
.font-brand { font-family: var(--font-brand); } /* Papier-Korn — extrem subtil, über allem, ohne Interaktion */
body::before {
content: "";
position: fixed;
inset: 0;
z-index: 1;
pointer-events: none;
opacity: 0.5;
mix-blend-mode: multiply;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.05'/%3E%3C/svg%3E");
}
/* Inhalt liegt über dem Korn */
body > * { position: relative; z-index: 2; }
.rainbow-bar { ::selection { background: var(--color-rb-yellow); color: var(--color-text); }
height: 4px;
background: linear-gradient( h1, h2, h3, h4 {
to right, font-family: var(--font-display);
#E8192C, #F5820D, #F9C80E, #00A651, #00AEEF, #3B4FA8, #6B3FA0 font-weight: 600;
); font-optical-sizing: auto;
letter-spacing: -0.015em;
line-height: 1.05;
text-wrap: balance;
} }
.rainbow-text { a { text-underline-offset: 3px; }
background: linear-gradient(135deg, #6B3FA0, #3B4FA8, #00A651);
-webkit-background-clip: text; :focus-visible {
-webkit-text-fill-color: transparent; outline: 3px solid var(--color-accent);
background-clip: text; outline-offset: 2px;
border-radius: 4px;
} }
} /* @layer base */
/* ============================================================
Components
============================================================ */
@layer components {
/* Signatur-Eyebrow im Pinsel-Font */
.eyebrow {
font-family: var(--font-brand);
color: var(--color-accent);
font-size: 1.35rem;
line-height: 1;
transform: rotate(-2deg);
display: inline-block;
}
/* Buttons — Sticker-Pillen mit Tiefe */
.btn-primary { .btn-primary {
@apply inline-flex items-center gap-2 px-6 py-3 rounded-full font-semibold text-white transition-all duration-200; @apply inline-flex items-center justify-center gap-2 px-7 py-3.5 rounded-full font-semibold text-white;
background: var(--color-primary); background: var(--color-accent);
box-shadow: 0 6px 0 0 var(--color-accent-dark), 0 14px 24px -10px rgba(217,110,0,0.6);
transition: transform .15s ease, box-shadow .15s ease, background .2s ease;
} }
.btn-primary:hover { background: var(--color-primary-dark); transform: translateY(-1px); } .btn-primary:hover {
background: #ff8f1f;
transform: translateY(-2px);
box-shadow: 0 8px 0 0 var(--color-accent-dark), 0 20px 30px -10px rgba(217,110,0,0.6);
}
.btn-primary:active { transform: translateY(3px); box-shadow: 0 2px 0 0 var(--color-accent-dark); }
.btn-secondary { .btn-secondary {
@apply inline-flex items-center gap-2 px-6 py-3 rounded-full font-semibold transition-all duration-200; @apply inline-flex items-center justify-center gap-2 px-7 py-3.5 rounded-full font-semibold;
border: 2px solid var(--color-primary);
color: var(--color-primary); color: var(--color-primary);
background: #fff;
border: 2px solid var(--color-primary);
box-shadow: 0 6px 0 0 var(--color-primary);
transition: transform .15s ease, box-shadow .15s ease, background .2s ease;
} }
.btn-secondary:hover { background: var(--color-surface-alt); } .btn-secondary:hover { transform: translateY(-2px); box-shadow: 0 8px 0 0 var(--color-primary); background: #fff; }
.btn-secondary:active { transform: translateY(3px); box-shadow: 0 2px 0 0 var(--color-primary); }
.card { /* Sticker-Karte — leicht gekippt, richtet sich beim Hover auf */
@apply rounded-2xl bg-white border p-6 transition-shadow duration-200; .card,
border-color: var(--color-border); .sticker {
@apply rounded-3xl bg-white p-6;
border: 1px solid var(--color-border);
box-shadow: 0 1px 0 rgba(0,0,0,0.02), 0 18px 40px -24px rgba(42,36,51,0.35);
transition: transform .25s cubic-bezier(.2,.8,.2,1), box-shadow .25s ease;
} }
.card:hover { box-shadow: 0 8px 30px rgba(107,63,160,0.12); } .card:hover,
.sticker:hover {
transform: translateY(-6px) rotate(0deg);
box-shadow: 0 28px 50px -24px rgba(42,36,51,0.45);
}
.tilt-l { transform: rotate(-1.4deg); }
.tilt-r { transform: rotate(1.4deg); }
.section { @apply py-16 px-4 max-w-6xl mx-auto; } /* Chip / Badge */
.section-sm { @apply py-10 px-4 max-w-6xl mx-auto; } .chip {
@apply inline-flex items-center gap-1.5 rounded-full px-3 py-1 text-xs font-semibold;
background: var(--color-accent-light);
color: var(--color-accent-dark);
}
/* Regenbogen-Balken */
.rainbow-bar {
height: 6px;
background: linear-gradient(90deg,
var(--color-rb-red), var(--color-rb-orange), var(--color-rb-yellow),
var(--color-rb-green), var(--color-rb-cyan), var(--color-rb-blue), var(--color-rb-violet));
}
/* Regenbogen-Text (Verlauf) */
.rainbow-text {
background: linear-gradient(100deg,
var(--color-rb-red), var(--color-rb-orange), var(--color-rb-green),
var(--color-rb-cyan), var(--color-rb-violet));
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
color: transparent;
}
/* Hand-gezeichnete Unterstreichung (für Schlüsselwörter) */
.squiggle {
position: relative;
display: inline-block;
}
.squiggle::after {
content: "";
position: absolute;
left: -2%;
right: -2%;
bottom: -0.12em;
height: 0.34em;
background: no-repeat center/100% 100% url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 18' preserveAspectRatio='none'%3E%3Cpath d='M2 12 C 40 4, 70 16, 100 9 S 165 3, 198 11' fill='none' stroke='%23F5820D' stroke-width='5' stroke-linecap='round'/%3E%3C/svg%3E");
}
.squiggle-violet::after {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 18' preserveAspectRatio='none'%3E%3Cpath d='M2 12 C 40 4, 70 16, 100 9 S 165 3, 198 11' fill='none' stroke='%236B3FA0' stroke-width='5' stroke-linecap='round'/%3E%3C/svg%3E");
}
/* Organischer Blob-Container (Bilder/Badges) */
.blob { border-radius: var(--radius-blob); }
/* Foto-„Klebeband" Look */
.photo-frame {
background: #fff;
padding: 0.6rem;
border-radius: 1rem;
box-shadow: 0 18px 40px -22px rgba(42,36,51,0.5);
}
.photo-frame img { border-radius: 0.6rem; display: block; width: 100%; height: 100%; object-fit: cover; }
/* Sektions-Helfer */
.section { @apply py-20 px-4 max-w-6xl mx-auto; }
.section-sm { @apply py-12 px-4 max-w-6xl mx-auto; }
/* Fließtext (CMS-Body, lange Texte) — eigener Stil, kein Typography-Plugin nötig */
.prose { color: var(--color-text-muted); line-height: 1.75; }
.prose > * + * { margin-top: 1.05em; }
.prose h2 { font-family: var(--font-display); color: var(--color-text); font-size: 1.6rem; font-weight: 700; margin-top: 1.8em; line-height: 1.2; }
.prose h3 { font-family: var(--font-display); color: var(--color-text); font-size: 1.25rem; font-weight: 700; margin-top: 1.5em; }
.prose a { color: var(--color-primary); text-decoration: underline; text-underline-offset: 3px; }
.prose a:hover { color: var(--color-primary-dark); }
.prose strong { color: var(--color-text); font-weight: 700; }
.prose ul { list-style: disc; padding-left: 1.4em; }
.prose ol { list-style: decimal; padding-left: 1.4em; }
.prose li + li { margin-top: 0.4em; }
.prose blockquote { border-left: 4px solid var(--color-accent); padding-left: 1em; font-style: italic; color: var(--color-text); }
.prose img { border-radius: 1rem; }
} /* @layer components */
/* ============================================================
Motion
============================================================ */
@keyframes float { 0%,100%{ transform: translateY(0) } 50%{ transform: translateY(-14px) } }
@keyframes float-slow { 0%,100%{ transform: translateY(0) rotate(0) } 50%{ transform: translateY(-22px) rotate(3deg) } }
@keyframes spin-slow { to { transform: rotate(360deg) } }
@keyframes wiggle { 0%,100%{ transform: rotate(-3deg) } 50%{ transform: rotate(3deg) } }
@keyframes fade-up { from { opacity:0; transform: translateY(24px) } to { opacity:1; transform: translateY(0) } }
@keyframes pop-in { 0%{ opacity:0; transform: scale(.8) } 100%{ opacity:1; transform: scale(1) } }
.anim-float { animation: float 6s ease-in-out infinite; }
.anim-float-slow { animation: float-slow 9s ease-in-out infinite; }
.anim-spin-slow { animation: spin-slow 26s linear infinite; }
.anim-wiggle { animation: wiggle 4s ease-in-out infinite; }
/* Auftritt beim Laden, gestaffelt */
.reveal { opacity: 0; animation: fade-up .7s cubic-bezier(.2,.8,.2,1) forwards; }
.reveal.d1 { animation-delay: .08s; }
.reveal.d2 { animation-delay: .18s; }
.reveal.d3 { animation-delay: .30s; }
.reveal.d4 { animation-delay: .44s; }
.reveal.d5 { animation-delay: .58s; }
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: .001ms !important;
animation-iteration-count: 1 !important;
scroll-behavior: auto !important;
transition-duration: .001ms !important;
}
.reveal { opacity: 1; }
}