Ein CSP-Header im Reverse-Proxy hat die Seite still zerlegt: Astro liefert seine Skripte als inline type=module aus, "script-src 'self'" blockiert die. Im Browser blieb data-reveal leer und das Mobilmenue reagierte nicht, ohne dass eine Fehlermeldung sichtbar war. Astro kennt die Hashes seiner eigenen Bundles, deshalb setzt jetzt der Build die Policy per <meta> (security.csp in astro.config.mjs). Damit die Policy auch fuer Styles streng bleiben kann, sind die letzten drei style-Attribute raus: sobald eine CSP Hashes fuer Styles enthaelt, ignorieren Browser 'unsafe-inline', inline gesetzte Farben waeren also ohnehin verloren. - Laserstrahlen im Hero: .beam-1 bis .beam-5 im <style>-Block - Genre-Akzentfarben: .accent-<name> statt berechnetem style-Attribut Geprueft im Browser hinter Caddy: Skripte laufen, Laser-Winkel und Akzentfarben stimmen, keine Verstoesse in der Konsole. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
115 lines
4.8 KiB
Plaintext
115 lines
4.8 KiB
Plaintext
---
|
|
import { Image } from 'astro:assets';
|
|
import banner from '../assets/hero-banner.jpg';
|
|
import { ABOUT, GENRES, CONTACT } from '../data/site';
|
|
|
|
// Die Akzentfarbe kommt ueber die Klasse accent-<name> aus dem <style>-Block
|
|
// unten. Bewusst kein style-Attribut: sobald die CSP Hashes fuer Styles setzt,
|
|
// ignorieren Browser 'unsafe-inline', und inline gesetzte Farben waeren weg.
|
|
---
|
|
|
|
<section id="about" class="relative overflow-hidden py-24 sm:py-32">
|
|
{/* Weicher Farbschimmer im Hintergrund */}
|
|
<div
|
|
class="pointer-events-none absolute inset-0 -z-10 bg-[radial-gradient(60%_45%_at_85%_5%,--alpha(var(--color-gold-500)/10%),transparent_70%),radial-gradient(50%_40%_at_5%_60%,--alpha(var(--color-laser-violet)/10%),transparent_70%)]"
|
|
aria-hidden="true"
|
|
>
|
|
</div>
|
|
|
|
<div class="mx-auto max-w-7xl px-5 sm:px-8">
|
|
<div class="grid items-center gap-12 lg:grid-cols-2 lg:gap-16">
|
|
<div class="relative" data-reveal>
|
|
<div class="overflow-hidden rounded-3xl border border-white/10 shadow-[0_30px_80px_-20px_rgba(0,0,0,0.8)]">
|
|
<Image
|
|
src={banner}
|
|
alt="DJ NIZZ Key Visual: Bühne mit Lasern und Crowd"
|
|
widths={[640, 960, 1400]}
|
|
sizes="(min-width: 1024px) 40rem, 92vw"
|
|
loading="lazy"
|
|
class="h-full w-full object-cover"
|
|
/>
|
|
</div>
|
|
|
|
{/* Kleiner Akzent, der aus der Karte herausragt */}
|
|
<div
|
|
class="absolute -bottom-6 -left-2 hidden rounded-2xl border border-white/10 bg-ink-900/90 px-5 py-4 backdrop-blur-md sm:-left-6 sm:block"
|
|
>
|
|
<p class="font-display text-2xl text-gold-400">{GENRES.length}</p>
|
|
<p class="mt-0.5 text-xs tracking-[0.16em] text-white/55 uppercase">Genres, ein Flow</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div data-reveal data-reveal-delay="120">
|
|
<p class="text-xs font-semibold tracking-[0.28em] text-gold-400 uppercase">{ABOUT.kicker}</p>
|
|
<h2 class="mt-4 font-display text-[clamp(2rem,5vw,3.25rem)] leading-[1.05] tracking-[-0.02em] text-white">
|
|
{ABOUT.headline}
|
|
</h2>
|
|
|
|
<p class="mt-6 text-balance-pretty text-lg leading-relaxed text-white/80">{ABOUT.lead}</p>
|
|
|
|
{
|
|
ABOUT.paragraphs.map((text) => (
|
|
<p class="mt-4 text-balance-pretty leading-relaxed text-white/60">{text}</p>
|
|
))
|
|
}
|
|
|
|
<dl class="mt-10 grid grid-cols-2 gap-x-6 gap-y-6 border-t border-white/10 pt-8">
|
|
{
|
|
ABOUT.facts.map((fact) => (
|
|
<div>
|
|
<dt class="text-xs tracking-[0.16em] text-white/45 uppercase">{fact.label}</dt>
|
|
<dd class="mt-1.5 font-medium text-white">{fact.value}</dd>
|
|
</div>
|
|
))
|
|
}
|
|
</dl>
|
|
|
|
<a
|
|
href={`mailto:${CONTACT.email}?subject=Booking-Anfrage`}
|
|
class="group mt-10 inline-flex items-center gap-2 font-semibold text-gold-400 transition-colors hover:text-gold-300"
|
|
>
|
|
Termin anfragen
|
|
<svg viewBox="0 0 20 20" class="h-4 w-4 transition-transform duration-300 group-hover:translate-x-1" fill="currentColor" aria-hidden="true">
|
|
<path d="M10.5 3.5 17 10l-6.5 6.5-1.4-1.4 4.1-4.1H3v-2h10.2L9.1 4.9z" />
|
|
</svg>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="mt-24 grid gap-5 sm:grid-cols-2 lg:grid-cols-3">
|
|
{
|
|
GENRES.map((genre, i) => (
|
|
<article
|
|
class={`accent-${genre.accent} group relative overflow-hidden rounded-2xl border border-white/10 bg-ink-900/50 p-6 transition duration-300 hover:-translate-y-1 hover:border-white/20 hover:bg-ink-850/70`}
|
|
data-reveal
|
|
data-reveal-delay={i * 90}
|
|
>
|
|
<span
|
|
class="accent-line absolute inset-x-0 top-0 h-px opacity-60 transition-opacity duration-300 group-hover:opacity-100"
|
|
aria-hidden="true"
|
|
/>
|
|
<span
|
|
class="accent-glow absolute -top-16 -right-16 h-40 w-40 rounded-full opacity-0 blur-3xl transition-opacity duration-500 group-hover:opacity-30"
|
|
aria-hidden="true"
|
|
/>
|
|
<h3 class="font-display text-xl text-white">{genre.name}</h3>
|
|
<p class="mt-3 text-sm leading-relaxed text-white/55">{genre.description}</p>
|
|
</article>
|
|
))
|
|
}
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<style>
|
|
/* Akzentfarbe pro Genre. Der Name muss zu `accent` in src/data/site.ts passen. */
|
|
.accent-magenta { --accent: var(--color-laser-magenta); }
|
|
.accent-cyan { --accent: var(--color-laser-cyan); }
|
|
.accent-gold { --accent: var(--color-gold-400); }
|
|
.accent-violet { --accent: var(--color-laser-violet); }
|
|
.accent-lime { --accent: var(--color-laser-lime); }
|
|
|
|
.accent-line { background: linear-gradient(to right, transparent, var(--accent), transparent); }
|
|
.accent-glow { background: var(--accent); }
|
|
</style>
|