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>
This commit is contained in:
2026-08-18 23:03:57 +02:00
co-authored by Claude Opus 5
parent 50150639ee
commit de7e8e3c37
3 changed files with 60 additions and 25 deletions
+18 -12
View File
@@ -3,13 +3,9 @@ import { Image } from 'astro:assets';
import banner from '../assets/hero-banner.jpg';
import { ABOUT, GENRES, CONTACT } from '../data/site';
const accentVar: Record<(typeof GENRES)[number]['accent'], string> = {
magenta: 'var(--color-laser-magenta)',
cyan: 'var(--color-laser-cyan)',
gold: 'var(--color-gold-400)',
violet: 'var(--color-laser-violet)',
lime: 'var(--color-laser-lime)',
};
// 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">
@@ -84,18 +80,16 @@ const accentVar: Record<(typeof GENRES)[number]['accent'], string> = {
{
GENRES.map((genre, i) => (
<article
class="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"
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="absolute inset-x-0 top-0 h-px opacity-60 transition-opacity duration-300 group-hover:opacity-100"
style={`background:linear-gradient(to right, transparent, ${accentVar[genre.accent]}, transparent);`}
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="absolute -top-16 -right-16 h-40 w-40 rounded-full opacity-0 blur-3xl transition-opacity duration-500 group-hover:opacity-30"
style={`background:${accentVar[genre.accent]};`}
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>
@@ -106,3 +100,15 @@ const accentVar: Record<(typeof GENRES)[number]['accent'], string> = {
</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>