feat: kamp page
This commit is contained in:
@@ -8,7 +8,10 @@ import { Header } from "./Header";
|
|||||||
export function SiteHeader() {
|
export function SiteHeader() {
|
||||||
const { data: session } = authClient.useSession();
|
const { data: session } = authClient.useSession();
|
||||||
const routerState = useRouterState();
|
const routerState = useRouterState();
|
||||||
const isHomepage = routerState.location.pathname === "/";
|
const pathname = routerState.location.pathname;
|
||||||
|
const isHomepage = pathname === "/";
|
||||||
|
|
||||||
|
if (pathname === "/kamp") return null;
|
||||||
|
|
||||||
const [isVisible, setIsVisible] = useState(false);
|
const [isVisible, setIsVisible] = useState(false);
|
||||||
|
|
||||||
|
|||||||
@@ -12,8 +12,8 @@ import { Route as rootRouteImport } from './routes/__root'
|
|||||||
import { Route as TermsRouteImport } from './routes/terms'
|
import { Route as TermsRouteImport } from './routes/terms'
|
||||||
import { Route as ResetPasswordRouteImport } from './routes/reset-password'
|
import { Route as ResetPasswordRouteImport } from './routes/reset-password'
|
||||||
import { Route as PrivacyRouteImport } from './routes/privacy'
|
import { Route as PrivacyRouteImport } from './routes/privacy'
|
||||||
import { Route as OpenMicRouteImport } from './routes/open-mic'
|
|
||||||
import { Route as LoginRouteImport } from './routes/login'
|
import { Route as LoginRouteImport } from './routes/login'
|
||||||
|
import { Route as KampRouteImport } from './routes/kamp'
|
||||||
import { Route as ForgotPasswordRouteImport } from './routes/forgot-password'
|
import { Route as ForgotPasswordRouteImport } from './routes/forgot-password'
|
||||||
import { Route as DrinkkaartRouteImport } from './routes/drinkkaart'
|
import { Route as DrinkkaartRouteImport } from './routes/drinkkaart'
|
||||||
import { Route as ContactRouteImport } from './routes/contact'
|
import { Route as ContactRouteImport } from './routes/contact'
|
||||||
@@ -42,16 +42,16 @@ const PrivacyRoute = PrivacyRouteImport.update({
|
|||||||
path: '/privacy',
|
path: '/privacy',
|
||||||
getParentRoute: () => rootRouteImport,
|
getParentRoute: () => rootRouteImport,
|
||||||
} as any)
|
} as any)
|
||||||
const OpenMicRoute = OpenMicRouteImport.update({
|
|
||||||
id: '/open-mic',
|
|
||||||
path: '/open-mic',
|
|
||||||
getParentRoute: () => rootRouteImport,
|
|
||||||
} as any)
|
|
||||||
const LoginRoute = LoginRouteImport.update({
|
const LoginRoute = LoginRouteImport.update({
|
||||||
id: '/login',
|
id: '/login',
|
||||||
path: '/login',
|
path: '/login',
|
||||||
getParentRoute: () => rootRouteImport,
|
getParentRoute: () => rootRouteImport,
|
||||||
} as any)
|
} as any)
|
||||||
|
const KampRoute = KampRouteImport.update({
|
||||||
|
id: '/kamp',
|
||||||
|
path: '/kamp',
|
||||||
|
getParentRoute: () => rootRouteImport,
|
||||||
|
} as any)
|
||||||
const ForgotPasswordRoute = ForgotPasswordRouteImport.update({
|
const ForgotPasswordRoute = ForgotPasswordRouteImport.update({
|
||||||
id: '/forgot-password',
|
id: '/forgot-password',
|
||||||
path: '/forgot-password',
|
path: '/forgot-password',
|
||||||
@@ -119,8 +119,8 @@ export interface FileRoutesByFullPath {
|
|||||||
'/contact': typeof ContactRoute
|
'/contact': typeof ContactRoute
|
||||||
'/drinkkaart': typeof DrinkkaartRoute
|
'/drinkkaart': typeof DrinkkaartRoute
|
||||||
'/forgot-password': typeof ForgotPasswordRoute
|
'/forgot-password': typeof ForgotPasswordRoute
|
||||||
|
'/kamp': typeof KampRoute
|
||||||
'/login': typeof LoginRoute
|
'/login': typeof LoginRoute
|
||||||
'/open-mic': typeof OpenMicRoute
|
|
||||||
'/privacy': typeof PrivacyRoute
|
'/privacy': typeof PrivacyRoute
|
||||||
'/reset-password': typeof ResetPasswordRoute
|
'/reset-password': typeof ResetPasswordRoute
|
||||||
'/terms': typeof TermsRoute
|
'/terms': typeof TermsRoute
|
||||||
@@ -138,8 +138,8 @@ export interface FileRoutesByTo {
|
|||||||
'/contact': typeof ContactRoute
|
'/contact': typeof ContactRoute
|
||||||
'/drinkkaart': typeof DrinkkaartRoute
|
'/drinkkaart': typeof DrinkkaartRoute
|
||||||
'/forgot-password': typeof ForgotPasswordRoute
|
'/forgot-password': typeof ForgotPasswordRoute
|
||||||
|
'/kamp': typeof KampRoute
|
||||||
'/login': typeof LoginRoute
|
'/login': typeof LoginRoute
|
||||||
'/open-mic': typeof OpenMicRoute
|
|
||||||
'/privacy': typeof PrivacyRoute
|
'/privacy': typeof PrivacyRoute
|
||||||
'/reset-password': typeof ResetPasswordRoute
|
'/reset-password': typeof ResetPasswordRoute
|
||||||
'/terms': typeof TermsRoute
|
'/terms': typeof TermsRoute
|
||||||
@@ -158,8 +158,8 @@ export interface FileRoutesById {
|
|||||||
'/contact': typeof ContactRoute
|
'/contact': typeof ContactRoute
|
||||||
'/drinkkaart': typeof DrinkkaartRoute
|
'/drinkkaart': typeof DrinkkaartRoute
|
||||||
'/forgot-password': typeof ForgotPasswordRoute
|
'/forgot-password': typeof ForgotPasswordRoute
|
||||||
|
'/kamp': typeof KampRoute
|
||||||
'/login': typeof LoginRoute
|
'/login': typeof LoginRoute
|
||||||
'/open-mic': typeof OpenMicRoute
|
|
||||||
'/privacy': typeof PrivacyRoute
|
'/privacy': typeof PrivacyRoute
|
||||||
'/reset-password': typeof ResetPasswordRoute
|
'/reset-password': typeof ResetPasswordRoute
|
||||||
'/terms': typeof TermsRoute
|
'/terms': typeof TermsRoute
|
||||||
@@ -179,8 +179,8 @@ export interface FileRouteTypes {
|
|||||||
| '/contact'
|
| '/contact'
|
||||||
| '/drinkkaart'
|
| '/drinkkaart'
|
||||||
| '/forgot-password'
|
| '/forgot-password'
|
||||||
|
| '/kamp'
|
||||||
| '/login'
|
| '/login'
|
||||||
| '/open-mic'
|
|
||||||
| '/privacy'
|
| '/privacy'
|
||||||
| '/reset-password'
|
| '/reset-password'
|
||||||
| '/terms'
|
| '/terms'
|
||||||
@@ -198,8 +198,8 @@ export interface FileRouteTypes {
|
|||||||
| '/contact'
|
| '/contact'
|
||||||
| '/drinkkaart'
|
| '/drinkkaart'
|
||||||
| '/forgot-password'
|
| '/forgot-password'
|
||||||
|
| '/kamp'
|
||||||
| '/login'
|
| '/login'
|
||||||
| '/open-mic'
|
|
||||||
| '/privacy'
|
| '/privacy'
|
||||||
| '/reset-password'
|
| '/reset-password'
|
||||||
| '/terms'
|
| '/terms'
|
||||||
@@ -217,8 +217,8 @@ export interface FileRouteTypes {
|
|||||||
| '/contact'
|
| '/contact'
|
||||||
| '/drinkkaart'
|
| '/drinkkaart'
|
||||||
| '/forgot-password'
|
| '/forgot-password'
|
||||||
|
| '/kamp'
|
||||||
| '/login'
|
| '/login'
|
||||||
| '/open-mic'
|
|
||||||
| '/privacy'
|
| '/privacy'
|
||||||
| '/reset-password'
|
| '/reset-password'
|
||||||
| '/terms'
|
| '/terms'
|
||||||
@@ -237,8 +237,8 @@ export interface RootRouteChildren {
|
|||||||
ContactRoute: typeof ContactRoute
|
ContactRoute: typeof ContactRoute
|
||||||
DrinkkaartRoute: typeof DrinkkaartRoute
|
DrinkkaartRoute: typeof DrinkkaartRoute
|
||||||
ForgotPasswordRoute: typeof ForgotPasswordRoute
|
ForgotPasswordRoute: typeof ForgotPasswordRoute
|
||||||
|
KampRoute: typeof KampRoute
|
||||||
LoginRoute: typeof LoginRoute
|
LoginRoute: typeof LoginRoute
|
||||||
OpenMicRoute: typeof OpenMicRoute
|
|
||||||
PrivacyRoute: typeof PrivacyRoute
|
PrivacyRoute: typeof PrivacyRoute
|
||||||
ResetPasswordRoute: typeof ResetPasswordRoute
|
ResetPasswordRoute: typeof ResetPasswordRoute
|
||||||
TermsRoute: typeof TermsRoute
|
TermsRoute: typeof TermsRoute
|
||||||
@@ -274,13 +274,6 @@ declare module '@tanstack/react-router' {
|
|||||||
preLoaderRoute: typeof PrivacyRouteImport
|
preLoaderRoute: typeof PrivacyRouteImport
|
||||||
parentRoute: typeof rootRouteImport
|
parentRoute: typeof rootRouteImport
|
||||||
}
|
}
|
||||||
'/open-mic': {
|
|
||||||
id: '/open-mic'
|
|
||||||
path: '/open-mic'
|
|
||||||
fullPath: '/open-mic'
|
|
||||||
preLoaderRoute: typeof OpenMicRouteImport
|
|
||||||
parentRoute: typeof rootRouteImport
|
|
||||||
}
|
|
||||||
'/login': {
|
'/login': {
|
||||||
id: '/login'
|
id: '/login'
|
||||||
path: '/login'
|
path: '/login'
|
||||||
@@ -288,6 +281,13 @@ declare module '@tanstack/react-router' {
|
|||||||
preLoaderRoute: typeof LoginRouteImport
|
preLoaderRoute: typeof LoginRouteImport
|
||||||
parentRoute: typeof rootRouteImport
|
parentRoute: typeof rootRouteImport
|
||||||
}
|
}
|
||||||
|
'/kamp': {
|
||||||
|
id: '/kamp'
|
||||||
|
path: '/kamp'
|
||||||
|
fullPath: '/kamp'
|
||||||
|
preLoaderRoute: typeof KampRouteImport
|
||||||
|
parentRoute: typeof rootRouteImport
|
||||||
|
}
|
||||||
'/forgot-password': {
|
'/forgot-password': {
|
||||||
id: '/forgot-password'
|
id: '/forgot-password'
|
||||||
path: '/forgot-password'
|
path: '/forgot-password'
|
||||||
@@ -381,8 +381,8 @@ const rootRouteChildren: RootRouteChildren = {
|
|||||||
ContactRoute: ContactRoute,
|
ContactRoute: ContactRoute,
|
||||||
DrinkkaartRoute: DrinkkaartRoute,
|
DrinkkaartRoute: DrinkkaartRoute,
|
||||||
ForgotPasswordRoute: ForgotPasswordRoute,
|
ForgotPasswordRoute: ForgotPasswordRoute,
|
||||||
|
KampRoute: KampRoute,
|
||||||
LoginRoute: LoginRoute,
|
LoginRoute: LoginRoute,
|
||||||
OpenMicRoute: OpenMicRoute,
|
|
||||||
PrivacyRoute: PrivacyRoute,
|
PrivacyRoute: PrivacyRoute,
|
||||||
ResetPasswordRoute: ResetPasswordRoute,
|
ResetPasswordRoute: ResetPasswordRoute,
|
||||||
TermsRoute: TermsRoute,
|
TermsRoute: TermsRoute,
|
||||||
|
|||||||
@@ -1,318 +1,168 @@
|
|||||||
import { createFileRoute, Link } from "@tanstack/react-router";
|
import { createFileRoute, Link } from "@tanstack/react-router";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
|
import EventRegistrationForm from "@/components/homepage/EventRegistrationForm";
|
||||||
|
import Footer from "@/components/homepage/Footer";
|
||||||
|
import Hero from "@/components/homepage/Hero";
|
||||||
|
import HoeInschrijven from "@/components/homepage/HoeInschrijven";
|
||||||
|
import Info from "@/components/homepage/Info";
|
||||||
|
|
||||||
|
const KAMP_BANNER_KEY = "kk_kamp_banner_dismissed";
|
||||||
|
|
||||||
export const Route = createFileRoute("/")({
|
export const Route = createFileRoute("/")({
|
||||||
component: SelectorPage,
|
component: HomePage,
|
||||||
});
|
});
|
||||||
|
|
||||||
function SelectorPage() {
|
function KampBanner({ onDismiss }: { onDismiss: () => void }) {
|
||||||
const [hovered, setHovered] = useState<"kamp" | "openmic" | null>(null);
|
const [visible, setVisible] = useState(false);
|
||||||
const [mounted, setMounted] = useState(false);
|
|
||||||
const [isMobile, setIsMobile] = useState(false);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const check = () => setIsMobile(window.innerWidth < 640);
|
if (!document.getElementById("kamp-banner-font")) {
|
||||||
check();
|
const el = document.createElement("link");
|
||||||
window.addEventListener("resize", check, { passive: true });
|
el.id = "kamp-banner-font";
|
||||||
return () => window.removeEventListener("resize", check);
|
el.rel = "stylesheet";
|
||||||
}, []);
|
el.href =
|
||||||
|
"https://fonts.googleapis.com/css2?family=Special+Elite&display=swap";
|
||||||
useEffect(() => {
|
document.head.appendChild(el);
|
||||||
const t = setTimeout(() => setMounted(true), 60);
|
}
|
||||||
|
const t = setTimeout(() => setVisible(true), 600);
|
||||||
return () => clearTimeout(t);
|
return () => clearTimeout(t);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const handleDismiss = () => {
|
||||||
|
setVisible(false);
|
||||||
|
setTimeout(onDismiss, 300);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className="flex h-[100dvh] w-full flex-col sm:flex-row"
|
role="banner"
|
||||||
style={{ gap: "6px", background: "#0a0a0a" }}
|
aria-label="Kunstenkamp inschrijvingen"
|
||||||
|
style={{
|
||||||
|
position: "fixed",
|
||||||
|
bottom: "1.25rem",
|
||||||
|
left: "50%",
|
||||||
|
transform: visible
|
||||||
|
? "translateX(-50%) translateY(0)"
|
||||||
|
: "translateX(-50%) translateY(120%)",
|
||||||
|
transition: "transform 0.35s cubic-bezier(0.34, 1.56, 0.64, 1)",
|
||||||
|
zIndex: 50,
|
||||||
|
width: "min(calc(100vw - 2rem), 480px)",
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{/* ── Kamp Inschrijvingen ───────────────────────────────────────── */}
|
<div
|
||||||
<a
|
|
||||||
href="https://ejv.be/jong/kampen/kunstenkamp/"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
className="group relative flex min-h-0 flex-col overflow-hidden"
|
|
||||||
style={{
|
style={{
|
||||||
flex: isMobile
|
background: "#ede4c8",
|
||||||
? "1 1 50%"
|
backgroundImage: `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.8' numOctaves='4' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='200' height='200' filter='url(%23n)' opacity='0.06'/%3E%3C/svg%3E")`,
|
||||||
: hovered === "openmic"
|
border: "1px solid #12100e",
|
||||||
? "0 0 30%"
|
outline: "3px solid rgba(18,16,14,0.1)",
|
||||||
: hovered === "kamp"
|
outlineOffset: "3px",
|
||||||
? "0 0 70%"
|
borderRadius: 0,
|
||||||
: "1 1 50%",
|
padding: "12px 14px 14px",
|
||||||
transition: "flex 0.65s cubic-bezier(0.76, 0, 0.24, 1)",
|
boxShadow: "3px 5px 20px rgba(0,0,0,0.25)",
|
||||||
background: "#214e51",
|
|
||||||
textDecoration: "none",
|
|
||||||
}}
|
}}
|
||||||
onMouseEnter={() => setHovered("kamp")}
|
|
||||||
onMouseLeave={() => setHovered(null)}
|
|
||||||
aria-label="Ga naar de kamp inschrijvingen op ejv.be"
|
|
||||||
>
|
>
|
||||||
{/* Diagonal stripe texture */}
|
{/* Top double rule */}
|
||||||
<div
|
<div style={{ marginBottom: "10px" }}>
|
||||||
aria-hidden="true"
|
<div style={{ height: "2px", background: "#12100e", marginBottom: "3px" }} />
|
||||||
className="pointer-events-none absolute inset-0"
|
<div style={{ height: "1px", background: "rgba(18,16,14,0.35)" }} />
|
||||||
style={{
|
</div>
|
||||||
backgroundImage:
|
|
||||||
"repeating-linear-gradient(135deg, rgba(255,255,255,0.03) 0px, rgba(255,255,255,0.03) 1px, transparent 1px, transparent 28px)",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{/* Mustard accent bar */}
|
<div style={{ display: "flex", alignItems: "flex-start", gap: "10px" }}>
|
||||||
<div
|
<div style={{ flex: 1, minWidth: 0 }}>
|
||||||
aria-hidden="true"
|
|
||||||
className="absolute top-0 left-0 w-[3px]"
|
|
||||||
style={{
|
|
||||||
background: "#d09035",
|
|
||||||
height: hovered === "kamp" ? "100%" : "0%",
|
|
||||||
transition: "height 0.65s cubic-bezier(0.76, 0, 0.24, 1)",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{/* Content — constrained width, centered */}
|
|
||||||
<div className="relative z-10 my-auto w-full px-6 py-8 sm:px-10 sm:py-12">
|
|
||||||
<div className="w-full max-w-sm">
|
|
||||||
{/* Top eyebrow */}
|
|
||||||
<p
|
<p
|
||||||
className="mb-3 font-['DM_Sans',sans-serif] text-[10px] uppercase tracking-[0.25em] sm:mb-4"
|
|
||||||
style={{
|
style={{
|
||||||
color: "#d09035",
|
fontFamily: "'Special Elite', cursive",
|
||||||
opacity: mounted ? 1 : 0,
|
fontSize: "8px",
|
||||||
transform: mounted ? "translateY(0)" : "translateY(-8px)",
|
letterSpacing: "0.3em",
|
||||||
transition: "opacity 0.7s ease 0.1s, transform 0.7s ease 0.1s",
|
textTransform: "uppercase",
|
||||||
|
color: "rgba(18,16,14,0.45)",
|
||||||
|
marginBottom: "6px",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Kunstenkamp
|
✦ Aankondiging · Zomerkamp 2026 ✦
|
||||||
</p>
|
</p>
|
||||||
|
<p
|
||||||
<h2
|
|
||||||
className="font-['Intro',sans-serif] text-white uppercase leading-[0.88]"
|
|
||||||
style={{
|
style={{
|
||||||
fontSize: "clamp(1.6rem, 3.5vw, 2.8rem)",
|
fontFamily: "'Playfair Display', serif",
|
||||||
opacity: mounted ? 1 : 0,
|
fontWeight: 700,
|
||||||
transform: mounted ? "translateY(0)" : "translateY(16px)",
|
fontSize: "14px",
|
||||||
transition: "opacity 0.8s ease 0.2s, transform 0.8s ease 0.2s",
|
color: "#12100e",
|
||||||
|
lineHeight: 1.35,
|
||||||
|
marginBottom: "12px",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<span className="block whitespace-nowrap">Kamp</span>
|
Inschrijvingen voor de zomerkampen zijn open!
|
||||||
<span className="block whitespace-nowrap">Inschrijvingen</span>
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
{/* Details */}
|
|
||||||
<div
|
|
||||||
className="mt-4 grid grid-cols-2 gap-x-6 gap-y-3 sm:mt-5 sm:gap-y-3"
|
|
||||||
style={{
|
|
||||||
opacity: mounted ? 1 : 0,
|
|
||||||
transform: mounted ? "translateY(0)" : "translateY(8px)",
|
|
||||||
transition: "opacity 0.5s ease 0.3s, transform 0.5s ease 0.3s",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div>
|
|
||||||
<p className="font-['DM_Sans',sans-serif] text-[9px] text-white/40 uppercase tracking-[0.2em]">
|
|
||||||
Leeftijd
|
|
||||||
</p>
|
</p>
|
||||||
<p className="mt-0.5 font-['DM_Sans',sans-serif] text-white/80 text-xs leading-snug sm:text-sm">
|
|
||||||
9<sup>*</sup>–18 jaar
|
|
||||||
</p>
|
|
||||||
<p className="mt-0.5 font-['DM_Sans',sans-serif] text-[9px] text-white/35 italic">
|
|
||||||
* geboortejaar dat je 10 wordt
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<p className="font-['DM_Sans',sans-serif] text-[9px] text-white/40 uppercase tracking-[0.2em]">
|
|
||||||
Data
|
|
||||||
</p>
|
|
||||||
<p className="mt-0.5 font-['DM_Sans',sans-serif] text-white/80 text-xs leading-snug sm:text-sm">
|
|
||||||
20/07–25/07/2026
|
|
||||||
<br />
|
|
||||||
27/07–01/08/2026
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div className="col-span-2">
|
|
||||||
<p className="font-['DM_Sans',sans-serif] text-[9px] text-white/40 uppercase tracking-[0.2em]">
|
|
||||||
Locatie
|
|
||||||
</p>
|
|
||||||
<p className="mt-0.5 font-['DM_Sans',sans-serif] text-white/80 text-xs leading-snug sm:text-sm">
|
|
||||||
Camp de Limauges · Chemin de Bigaumont 2 · 1341 Ceroux-Mousty
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* CTA */}
|
|
||||||
<div
|
|
||||||
className="mt-5 flex items-center gap-3 sm:mt-6"
|
|
||||||
style={{
|
|
||||||
opacity: mounted ? 1 : 0,
|
|
||||||
transition: "opacity 0.8s ease 0.3s",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
height: "1px",
|
|
||||||
background: "#d09035",
|
|
||||||
width: hovered === "kamp" ? "72px" : "32px",
|
|
||||||
transition: "width 0.5s cubic-bezier(0.76, 0, 0.24, 1)",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<span
|
|
||||||
className="font-['DM_Sans',sans-serif] text-[10px] uppercase tracking-[0.2em]"
|
|
||||||
style={{ color: "#d09035" }}
|
|
||||||
>
|
|
||||||
Ga verder →
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Corner decoration */}
|
|
||||||
<div
|
|
||||||
aria-hidden="true"
|
|
||||||
className="pointer-events-none absolute right-0 bottom-0"
|
|
||||||
style={{
|
|
||||||
width: "clamp(60px, 15%, 140px)",
|
|
||||||
height: "clamp(60px, 15%, 140px)",
|
|
||||||
borderTop: "1px solid rgba(208,144,53,0.12)",
|
|
||||||
borderLeft: "1px solid rgba(208,144,53,0.12)",
|
|
||||||
transform: "translate(50%, 50%)",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
{/* ── Open Mic Night ────────────────────────────────────────────── */}
|
|
||||||
<Link
|
<Link
|
||||||
to="/open-mic"
|
to="/kamp"
|
||||||
className="group relative flex min-h-0 flex-col overflow-hidden"
|
|
||||||
style={{
|
style={{
|
||||||
flex: isMobile
|
display: "inline-block",
|
||||||
? "1 1 50%"
|
fontFamily: "'Special Elite', cursive",
|
||||||
: hovered === "kamp"
|
fontSize: "9px",
|
||||||
? "0 0 30%"
|
letterSpacing: "0.22em",
|
||||||
: hovered === "openmic"
|
textTransform: "uppercase",
|
||||||
? "0 0 70%"
|
|
||||||
: "1 1 50%",
|
|
||||||
transition: "flex 0.65s cubic-bezier(0.76, 0, 0.24, 1)",
|
|
||||||
background: "#d82560",
|
|
||||||
textDecoration: "none",
|
textDecoration: "none",
|
||||||
}}
|
color: "#ede4c8",
|
||||||
onMouseEnter={() => setHovered("openmic")}
|
background: "#12100e",
|
||||||
onMouseLeave={() => setHovered(null)}
|
border: "1px solid rgba(18,16,14,0.4)",
|
||||||
aria-label="Ga naar de Open Mic Night inschrijvingen"
|
outline: "2px solid rgba(18,16,14,0.08)",
|
||||||
>
|
outlineOffset: "3px",
|
||||||
{/* Diagonal stripe texture */}
|
padding: "7px 12px 6px",
|
||||||
<div
|
|
||||||
aria-hidden="true"
|
|
||||||
className="pointer-events-none absolute inset-0"
|
|
||||||
style={{
|
|
||||||
backgroundImage:
|
|
||||||
"repeating-linear-gradient(135deg, rgba(255,255,255,0.05) 0px, rgba(255,255,255,0.05) 1px, transparent 1px, transparent 28px)",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{/* White accent bar */}
|
|
||||||
<div
|
|
||||||
aria-hidden="true"
|
|
||||||
className="absolute top-0 right-0 w-[3px]"
|
|
||||||
style={{
|
|
||||||
background: "rgba(255,255,255,0.7)",
|
|
||||||
height: hovered === "openmic" ? "100%" : "0%",
|
|
||||||
transition: "height 0.65s cubic-bezier(0.76, 0, 0.24, 1)",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{/* Content — constrained width, centered */}
|
|
||||||
<div className="relative z-10 my-auto w-full px-6 py-8 sm:px-10 sm:py-12">
|
|
||||||
<div className="w-full max-w-sm">
|
|
||||||
{/* Top eyebrow */}
|
|
||||||
<p
|
|
||||||
className="mb-3 font-['DM_Sans',sans-serif] text-[10px] text-white/50 uppercase tracking-[0.25em] sm:mb-4"
|
|
||||||
style={{
|
|
||||||
opacity: mounted ? 1 : 0,
|
|
||||||
transform: mounted ? "translateY(0)" : "translateY(-8px)",
|
|
||||||
transition:
|
|
||||||
"opacity 0.7s ease 0.15s, transform 0.7s ease 0.15s",
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Ongedesemd Woord
|
Schrijf je in →
|
||||||
</p>
|
|
||||||
|
|
||||||
<h2
|
|
||||||
className="font-['Intro',sans-serif] text-white uppercase leading-[0.88]"
|
|
||||||
style={{
|
|
||||||
fontSize: "clamp(1.6rem, 3.5vw, 2.8rem)",
|
|
||||||
opacity: mounted ? 1 : 0,
|
|
||||||
transform: mounted ? "translateY(0)" : "translateY(16px)",
|
|
||||||
transition:
|
|
||||||
"opacity 0.8s ease 0.25s, transform 0.8s ease 0.25s",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<span className="block whitespace-nowrap">Open</span>
|
|
||||||
<span className="block whitespace-nowrap">Mic Night</span>
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
{/* Details */}
|
|
||||||
<div
|
|
||||||
className="mt-4 grid grid-cols-2 gap-x-6 gap-y-3 sm:mt-5"
|
|
||||||
style={{
|
|
||||||
opacity: mounted ? 1 : 0,
|
|
||||||
transform: mounted ? "translateY(0)" : "translateY(8px)",
|
|
||||||
transition:
|
|
||||||
"opacity 0.5s ease 0.35s, transform 0.5s ease 0.35s",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div>
|
|
||||||
<p className="font-['DM_Sans',sans-serif] text-[9px] text-white/50 uppercase tracking-[0.2em]">
|
|
||||||
Datum
|
|
||||||
</p>
|
|
||||||
<p className="mt-0.5 font-['DM_Sans',sans-serif] text-white/90 text-xs leading-snug sm:text-sm">
|
|
||||||
Vrijdag 24 april 2026
|
|
||||||
<br />
|
|
||||||
19u30
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<p className="font-['DM_Sans',sans-serif] text-[9px] text-white/50 uppercase tracking-[0.2em]">
|
|
||||||
Optreden
|
|
||||||
</p>
|
|
||||||
<p className="mt-0.5 font-['DM_Sans',sans-serif] text-white/90 text-xs leading-snug sm:text-sm">
|
|
||||||
5 min podiumtijd
|
|
||||||
<br />
|
|
||||||
Alle kunstvormen
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div className="col-span-2">
|
|
||||||
<p className="font-['DM_Sans',sans-serif] text-[9px] text-white/50 uppercase tracking-[0.2em]">
|
|
||||||
Locatie
|
|
||||||
</p>
|
|
||||||
<p className="mt-0.5 font-['DM_Sans',sans-serif] text-white/90 text-xs leading-snug sm:text-sm">
|
|
||||||
Lange Winkelstraat 5 · 2000 Antwerpen
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* CTA */}
|
|
||||||
<div
|
|
||||||
className="mt-5 flex items-center gap-3 sm:mt-6"
|
|
||||||
style={{
|
|
||||||
opacity: mounted ? 1 : 0,
|
|
||||||
transition: "opacity 0.8s ease 0.35s",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
height: "1px",
|
|
||||||
background: "rgba(255,255,255,0.7)",
|
|
||||||
width: hovered === "openmic" ? "72px" : "32px",
|
|
||||||
transition: "width 0.5s cubic-bezier(0.76, 0, 0.24, 1)",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<span className="font-['DM_Sans',sans-serif] text-[10px] text-white/80 uppercase tracking-[0.2em]">
|
|
||||||
Ga verder →
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={handleDismiss}
|
||||||
|
aria-label="Sluit deze melding"
|
||||||
|
style={{
|
||||||
|
background: "none",
|
||||||
|
border: "none",
|
||||||
|
color: "rgba(18,16,14,0.3)",
|
||||||
|
cursor: "pointer",
|
||||||
|
padding: "2px",
|
||||||
|
flexShrink: 0,
|
||||||
|
fontSize: "18px",
|
||||||
|
lineHeight: 1,
|
||||||
|
fontFamily: "'Special Elite', cursive",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
×
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function HomePage() {
|
||||||
|
const [showBanner, setShowBanner] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!localStorage.getItem(KAMP_BANNER_KEY)) {
|
||||||
|
setShowBanner(true);
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const dismissBanner = () => {
|
||||||
|
localStorage.setItem(KAMP_BANNER_KEY, "1");
|
||||||
|
setShowBanner(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className="relative">
|
||||||
|
<main className="relative">
|
||||||
|
<Hero />
|
||||||
|
<Info />
|
||||||
|
<HoeInschrijven />
|
||||||
|
<EventRegistrationForm />
|
||||||
|
<Footer />
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
{showBanner && <KampBanner onDismiss={dismissBanner} />}
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
474
apps/web/src/routes/kamp.tsx
Normal file
474
apps/web/src/routes/kamp.tsx
Normal file
@@ -0,0 +1,474 @@
|
|||||||
|
import { createFileRoute, Link } from "@tanstack/react-router";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
|
||||||
|
const KAMP_URL = "https://ejv.be/jong/kampen/kunstenkamp/";
|
||||||
|
|
||||||
|
export const Route = createFileRoute("/kamp")({
|
||||||
|
component: KampPage,
|
||||||
|
});
|
||||||
|
|
||||||
|
const STYLES = `
|
||||||
|
@import url('https://fonts.googleapis.com/css2?family=UnifrakturMaguntia&family=Playfair+Display:ital,wght@0,400;0,700;0,900;1,400;1,700&family=EB+Garamond:ital,wght@0,400;0,500;1,400;1,500&family=Special+Elite&display=swap');
|
||||||
|
|
||||||
|
@keyframes kampPressIn {
|
||||||
|
from { opacity: 0; }
|
||||||
|
to { opacity: 1; }
|
||||||
|
}
|
||||||
|
|
||||||
|
body.kamp-page {
|
||||||
|
background-color: #d6cdb0 !important;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.kamp-page ::selection {
|
||||||
|
background: #12100e;
|
||||||
|
color: #ede4c8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kamp-scroll::-webkit-scrollbar {
|
||||||
|
width: 6px;
|
||||||
|
}
|
||||||
|
.kamp-scroll::-webkit-scrollbar-track {
|
||||||
|
background: #c9c0a4;
|
||||||
|
}
|
||||||
|
.kamp-scroll::-webkit-scrollbar-thumb {
|
||||||
|
background: #12100e;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const PAPER = "#ede4c8";
|
||||||
|
const INK = "#12100e";
|
||||||
|
const INK_MID = "rgba(18,16,14,0.5)";
|
||||||
|
const INK_GHOST = "rgba(18,16,14,0.2)";
|
||||||
|
const RULE_W = "rgba(18,16,14,0.75)";
|
||||||
|
|
||||||
|
function TripleRule() {
|
||||||
|
return (
|
||||||
|
<div style={{ display: "flex", flexDirection: "column", gap: "3px" }}>
|
||||||
|
<div style={{ height: "3px", background: INK }} />
|
||||||
|
<div style={{ height: "1px", background: RULE_W }} />
|
||||||
|
<div style={{ height: "2px", background: INK }} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function DoubleRule() {
|
||||||
|
return (
|
||||||
|
<div style={{ display: "flex", flexDirection: "column", gap: "3px" }}>
|
||||||
|
<div style={{ height: "2px", background: RULE_W }} />
|
||||||
|
<div style={{ height: "1px", background: RULE_W }} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function KampPage() {
|
||||||
|
const [mounted, setMounted] = useState(false);
|
||||||
|
const [ctaHovered, setCtaHovered] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!document.getElementById("kamp-newspaper-styles")) {
|
||||||
|
const el = document.createElement("style");
|
||||||
|
el.id = "kamp-newspaper-styles";
|
||||||
|
el.textContent = STYLES;
|
||||||
|
document.head.appendChild(el);
|
||||||
|
}
|
||||||
|
document.body.classList.add("kamp-page");
|
||||||
|
const t = setTimeout(() => setMounted(true), 60);
|
||||||
|
return () => {
|
||||||
|
document.body.classList.remove("kamp-page");
|
||||||
|
clearTimeout(t);
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
height: "100dvh",
|
||||||
|
background: "#d6cdb0",
|
||||||
|
backgroundImage: `url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='400' height='400'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.65' numOctaves='4' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='400' height='400' filter='url(%23n)' opacity='0.12'/%3E%3C/svg%3E")`,
|
||||||
|
backgroundRepeat: "repeat",
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "center",
|
||||||
|
padding: "1.5rem 1rem",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{/* Newspaper page */}
|
||||||
|
<article
|
||||||
|
className="kamp-scroll"
|
||||||
|
style={{
|
||||||
|
width: "100%",
|
||||||
|
maxWidth: "700px",
|
||||||
|
height: "100%",
|
||||||
|
background: PAPER,
|
||||||
|
backgroundImage: `url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='300' height='300'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='4' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='300' height='300' filter='url(%23n)' opacity='0.06'/%3E%3C/svg%3E")`,
|
||||||
|
border: `1px solid ${INK}`,
|
||||||
|
boxShadow:
|
||||||
|
"3px 5px 24px rgba(0,0,0,0.18), 0 1px 3px rgba(0,0,0,0.12)",
|
||||||
|
opacity: mounted ? 1 : 0,
|
||||||
|
animation: mounted ? "kampPressIn 0.9s ease both" : undefined,
|
||||||
|
overflowY: "auto",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{/* Outer decorative border inset */}
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
margin: "6px",
|
||||||
|
border: `1px solid ${INK}`,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{/* Top flag strip */}
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
borderBottom: `1px solid ${INK}`,
|
||||||
|
padding: "7px 20px 6px",
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
alignItems: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Link
|
||||||
|
to="/"
|
||||||
|
style={{
|
||||||
|
fontFamily: "'Special Elite', cursive",
|
||||||
|
fontSize: "10px",
|
||||||
|
letterSpacing: "0.18em",
|
||||||
|
color: INK,
|
||||||
|
textDecoration: "none",
|
||||||
|
borderBottom: `1px solid ${INK}`,
|
||||||
|
paddingBottom: "1px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
← Open Mic Night
|
||||||
|
</Link>
|
||||||
|
<span
|
||||||
|
style={{
|
||||||
|
fontFamily: "'Special Elite', cursive",
|
||||||
|
fontSize: "9px",
|
||||||
|
letterSpacing: "0.18em",
|
||||||
|
color: INK_MID,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
✦ · ✦ · ✦
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
style={{
|
||||||
|
fontFamily: "'Special Elite', cursive",
|
||||||
|
fontSize: "9px",
|
||||||
|
letterSpacing: "0.22em",
|
||||||
|
textTransform: "uppercase",
|
||||||
|
color: INK_MID,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Anno 2026
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Masthead */}
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
padding: "20px 24px 16px",
|
||||||
|
textAlign: "center",
|
||||||
|
borderBottom: `1px solid ${INK}`,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<h1
|
||||||
|
style={{
|
||||||
|
fontFamily: "'UnifrakturMaguntia', cursive",
|
||||||
|
fontSize: "clamp(2.4rem, 9vw, 4.5rem)",
|
||||||
|
color: INK,
|
||||||
|
margin: 0,
|
||||||
|
lineHeight: 1,
|
||||||
|
letterSpacing: "0.02em",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
De Kunstenkamp Gazet
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Publication bar */}
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
padding: "6px 20px 5px",
|
||||||
|
borderBottom: `1px solid ${INK}`,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{[
|
||||||
|
"Vol. CCXXVI",
|
||||||
|
"Zomerkamp · Juli 2026",
|
||||||
|
"Prijs: uw aanwezigheid",
|
||||||
|
].map((t) => (
|
||||||
|
<span
|
||||||
|
key={t}
|
||||||
|
style={{
|
||||||
|
fontFamily: "'Special Elite', cursive",
|
||||||
|
fontSize: "10px",
|
||||||
|
color: INK_MID,
|
||||||
|
letterSpacing: "0.1em",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{t}
|
||||||
|
</span>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Main content area */}
|
||||||
|
<div style={{ padding: "28px 28px 24px" }}>
|
||||||
|
{/* Triple rule */}
|
||||||
|
<div style={{ marginBottom: "24px" }}>
|
||||||
|
<TripleRule />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Main headline */}
|
||||||
|
<div style={{ textAlign: "center", marginBottom: "16px" }}>
|
||||||
|
<h2
|
||||||
|
style={{
|
||||||
|
fontFamily: "'Playfair Display', serif",
|
||||||
|
fontWeight: 900,
|
||||||
|
fontSize: "clamp(2.6rem, 9vw, 4.5rem)",
|
||||||
|
color: INK,
|
||||||
|
textTransform: "uppercase",
|
||||||
|
letterSpacing: "0.06em",
|
||||||
|
lineHeight: 0.95,
|
||||||
|
margin: "0 0 14px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Wat Is Waar?
|
||||||
|
</h2>
|
||||||
|
<p
|
||||||
|
style={{
|
||||||
|
fontFamily: "'Playfair Display', serif",
|
||||||
|
fontStyle: "italic",
|
||||||
|
fontSize: "clamp(1rem, 2.5vw, 1.2rem)",
|
||||||
|
color: INK_MID,
|
||||||
|
margin: 0,
|
||||||
|
lineHeight: 1.45,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Een krant. Een tijdmachine. De waarheid doorheen de eeuwen.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Triple rule */}
|
||||||
|
<div style={{ marginBottom: "22px" }}>
|
||||||
|
<TripleRule />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Editorial body copy */}
|
||||||
|
<p
|
||||||
|
style={{
|
||||||
|
fontFamily: "'EB Garamond', serif",
|
||||||
|
fontSize: "clamp(1.05rem, 2.2vw, 1.2rem)",
|
||||||
|
color: INK,
|
||||||
|
lineHeight: 1.75,
|
||||||
|
margin: "0 0 10px",
|
||||||
|
textAlign: "justify",
|
||||||
|
hyphens: "auto",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
In de zomer van 1826 — en opnieuw in 2026 — reizen onze verslaggevers
|
||||||
|
terug naar de roerige redactiezalen van de negentiende eeuw. Waar de
|
||||||
|
drukpers ronkt, de rookmachines tieren en elke kop een mening
|
||||||
|
verbergt, stellen wij de vraag die door alle eeuwen galmt:{" "}
|
||||||
|
<em>wat mogen wij geloven?</em>
|
||||||
|
</p>
|
||||||
|
<p
|
||||||
|
style={{
|
||||||
|
fontFamily: "'EB Garamond', serif",
|
||||||
|
fontStyle: "italic",
|
||||||
|
fontSize: "clamp(0.95rem, 2vw, 1.08rem)",
|
||||||
|
color: INK_MID,
|
||||||
|
lineHeight: 1.7,
|
||||||
|
margin: "0 0 24px",
|
||||||
|
textAlign: "justify",
|
||||||
|
hyphens: "auto",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Twee waarheden en een leugen. Vier bolhoeden en één typmachine.
|
||||||
|
Bereid u voor op een week journalistiek, theater, dans en woordkunst
|
||||||
|
— alles gehuld in inkt en papier-maché.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
{/* Ornamental divider */}
|
||||||
|
<p
|
||||||
|
style={{
|
||||||
|
textAlign: "center",
|
||||||
|
fontFamily: "'EB Garamond', serif",
|
||||||
|
fontSize: "13px",
|
||||||
|
color: INK_GHOST,
|
||||||
|
margin: "0 0 24px",
|
||||||
|
letterSpacing: "0.4em",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
— ✦ · ✦ · ✦ —
|
||||||
|
</p>
|
||||||
|
|
||||||
|
{/* Details grid */}
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: "grid",
|
||||||
|
gridTemplateColumns: "1fr 1fr",
|
||||||
|
border: `1px solid ${INK}`,
|
||||||
|
marginBottom: "28px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{[
|
||||||
|
{ label: "Primo", value: "20 – 25 Juli 2026" },
|
||||||
|
{ label: "Secundo", value: "27 Juli – 1 Aug 2026" },
|
||||||
|
{
|
||||||
|
label: "Leeftijd",
|
||||||
|
value: "9 – 18 jaar",
|
||||||
|
sub: "* geboortejaar dat je 10 wordt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Locatie",
|
||||||
|
value: "Camp de Limauges",
|
||||||
|
sub: "Ceroux-Mousty · België",
|
||||||
|
},
|
||||||
|
].map(({ label, value, sub }, i) => (
|
||||||
|
<div
|
||||||
|
key={label}
|
||||||
|
style={{
|
||||||
|
padding: "16px 18px",
|
||||||
|
borderRight:
|
||||||
|
i % 2 === 0 ? `1px solid ${INK}` : undefined,
|
||||||
|
borderTop: i >= 2 ? `1px solid ${INK}` : undefined,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<p
|
||||||
|
style={{
|
||||||
|
fontFamily: "'Special Elite', cursive",
|
||||||
|
fontSize: "9px",
|
||||||
|
letterSpacing: "0.3em",
|
||||||
|
textTransform: "uppercase",
|
||||||
|
color: INK_MID,
|
||||||
|
margin: "0 0 6px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{label}
|
||||||
|
</p>
|
||||||
|
<p
|
||||||
|
style={{
|
||||||
|
fontFamily: "'Playfair Display', serif",
|
||||||
|
fontWeight: 700,
|
||||||
|
fontSize: "clamp(1rem, 2.5vw, 1.15rem)",
|
||||||
|
color: INK,
|
||||||
|
margin: 0,
|
||||||
|
lineHeight: 1.3,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{value}
|
||||||
|
</p>
|
||||||
|
{sub && (
|
||||||
|
<p
|
||||||
|
style={{
|
||||||
|
fontFamily: "'EB Garamond', serif",
|
||||||
|
fontStyle: "italic",
|
||||||
|
fontSize: "13px",
|
||||||
|
color: INK_MID,
|
||||||
|
margin: "4px 0 0",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{sub}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Double rule */}
|
||||||
|
<div style={{ marginBottom: "24px" }}>
|
||||||
|
<DoubleRule />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* CTA — inverted ink block */}
|
||||||
|
<div style={{ marginBottom: "4px" }}>
|
||||||
|
<p
|
||||||
|
style={{
|
||||||
|
fontFamily: "'Special Elite', cursive",
|
||||||
|
fontSize: "9px",
|
||||||
|
letterSpacing: "0.35em",
|
||||||
|
textTransform: "uppercase",
|
||||||
|
color: INK_MID,
|
||||||
|
textAlign: "center",
|
||||||
|
margin: "0 0 10px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
✦ Aankondiging ✦
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<a
|
||||||
|
href={KAMP_URL}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
onMouseEnter={() => setCtaHovered(true)}
|
||||||
|
onMouseLeave={() => setCtaHovered(false)}
|
||||||
|
style={{
|
||||||
|
display: "block",
|
||||||
|
background: ctaHovered ? "#2a2418" : INK,
|
||||||
|
color: PAPER,
|
||||||
|
textDecoration: "none",
|
||||||
|
textAlign: "center",
|
||||||
|
padding: "28px 32px 26px",
|
||||||
|
outline: `2px solid ${INK}`,
|
||||||
|
outlineOffset: "4px",
|
||||||
|
transition: "background 0.2s ease",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
style={{
|
||||||
|
display: "block",
|
||||||
|
fontFamily: "'Playfair Display', serif",
|
||||||
|
fontWeight: 900,
|
||||||
|
fontSize: "clamp(1.5rem, 5vw, 2.4rem)",
|
||||||
|
textTransform: "uppercase",
|
||||||
|
letterSpacing: "0.1em",
|
||||||
|
lineHeight: 1,
|
||||||
|
marginBottom: "10px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Schrijf U In
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
style={{
|
||||||
|
display: "block",
|
||||||
|
fontFamily: "'Special Elite', cursive",
|
||||||
|
fontSize: "clamp(0.7rem, 2vw, 0.85rem)",
|
||||||
|
letterSpacing: "0.25em",
|
||||||
|
opacity: 0.65,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
via ejv.be →
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Footer */}
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
borderTop: `1px solid ${INK}`,
|
||||||
|
padding: "7px 20px 8px",
|
||||||
|
textAlign: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<p
|
||||||
|
style={{
|
||||||
|
fontFamily: "'EB Garamond', serif",
|
||||||
|
fontStyle: "italic",
|
||||||
|
fontSize: "12px",
|
||||||
|
color: INK_GHOST,
|
||||||
|
margin: 0,
|
||||||
|
letterSpacing: "0.06em",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Kunst · Expressie · Avontuur · Waar is de waarheid?
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
import { createFileRoute } from "@tanstack/react-router";
|
|
||||||
import EventRegistrationForm from "@/components/homepage/EventRegistrationForm";
|
|
||||||
import Footer from "@/components/homepage/Footer";
|
|
||||||
import Hero from "@/components/homepage/Hero";
|
|
||||||
import HoeInschrijven from "@/components/homepage/HoeInschrijven";
|
|
||||||
import Info from "@/components/homepage/Info";
|
|
||||||
|
|
||||||
export const Route = createFileRoute("/open-mic")({
|
|
||||||
component: OpenMicPage,
|
|
||||||
});
|
|
||||||
|
|
||||||
function OpenMicPage() {
|
|
||||||
return (
|
|
||||||
<div className="relative">
|
|
||||||
<main className="relative">
|
|
||||||
<Hero />
|
|
||||||
<Info />
|
|
||||||
<HoeInschrijven />
|
|
||||||
<EventRegistrationForm />
|
|
||||||
<Footer />
|
|
||||||
</main>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user