Files
djnizz-website/src/components/About.astro
T
Nizz05andClaude Opus 5 de7e8e3c37 CSP: Inline-Styles entfernt, Policy vom Build erzeugen lassen
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>
2026-08-18 23:03:57 +02:00

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>