Make the grain texture universally visible via a fixed overlay

Previously the grain lived on .page-texture's own background-image, so
any section with its own opaque background color (bg-neutral-50 bands)
painted right over it. Moved the grain to a fixed, full-viewport overlay
that sits on top of everything instead.

Also fixed a failed attempt at using mix-blend-mode: overlay for a
single theme-agnostic texture - that blend mode has almost no visible
effect on backgrounds this close to pure white/black, since its math
compresses toward the backdrop at the extremes. Back to plain alpha
transparency with separate light/dark speckle colors, moderate opacity.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Maaxxs 2026-07-07 00:23:44 +02:00
parent b67ed2619d
commit e89e2aed34
2 changed files with 23 additions and 6 deletions

View file

@ -62,6 +62,7 @@ export default function PublicLayout() {
<MaintenanceProvider value={{ ...status, bypass }}> <MaintenanceProvider value={{ ...status, bypass }}>
<SiteSettingsProvider value={siteSettings}> <SiteSettingsProvider value={siteSettings}>
<div className="page-texture flex min-h-screen flex-col text-neutral-900 dark:text-neutral-100"> <div className="page-texture flex min-h-screen flex-col text-neutral-900 dark:text-neutral-100">
<div className="grain-overlay" aria-hidden="true" />
{bypass && status.global.enabled && <MaintenanceBypassBanner />} {bypass && status.global.enabled && <MaintenanceBypassBanner />}
<ScrollProgress /> <ScrollProgress />
<Navbar /> <Navbar />

View file

@ -11,16 +11,32 @@ html {
mask-image: linear-gradient(to right, transparent, black 6%, black 94%, transparent); mask-image: linear-gradient(to right, transparent, black 6%, black 94%, transparent);
} }
/* Deutlich sichtbares Papierkorn als Hintergrundstruktur statt einer reinen Flaeche - /* Grundflaeche der Seite - die eigentliche Koernung kommt separat vom .grain-overlay,
erinnert an grobkoerniges Papier/Filmkorn. Bewusst kraeftiger eingestellt (hoher Alpha- damit sie ueber JEDEM Abschnitt sichtbar bleibt, auch ueber Bereichen mit eigener
Multiplikator in der feColorMatrix), damit die Struktur ohne genaues Hinsehen auffaellt. */ deckender Hintergrundfarbe (z.B. bg-neutral-50 Baendern). */
.page-texture { .page-texture {
background-color: #f6f5f0; background-color: #f6f5f0;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.7' numOctaves='3' stitchTiles='stitch' result='noise'/%3E%3CfeColorMatrix in='noise' type='matrix' values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.35 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
background-size: 180px 180px;
} }
.dark .page-texture { .dark .page-texture {
background-color: #0a0b07; background-color: #0a0b07;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.7' numOctaves='3' stitchTiles='stitch' result='noise'/%3E%3CfeColorMatrix in='noise' type='matrix' values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.4 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E"); }
/* Papierkorn als fixierter Ueberzug ueber der gesamten Seite statt als Hintergrundbild
eines einzelnen Elements, damit es ueber JEDER Sektion sichtbar bleibt (auch ueber
Baendern mit eigener deckender bg-neutral-50-Farbe). Normale Alpha-Transparenz statt
mix-blend-mode: "overlay"/"soft-light" haben auf Hintergruende nahe Weiss/Schwarz (wie
unsere Basisfarben) fast keinen sichtbaren Effekt, da die Blend-Mathematik dort kaum
noch Kontrast erzeugt - reine Deckkraft-Ueberlagerung funktioniert unabhaengig davon. */
.grain-overlay {
position: fixed;
inset: 0;
z-index: 40;
pointer-events: none;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.7' numOctaves='3' stitchTiles='stitch' result='noise'/%3E%3CfeColorMatrix in='noise' type='matrix' values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.18 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
background-size: 180px 180px;
}
.dark .grain-overlay {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.7' numOctaves='3' stitchTiles='stitch' result='noise'/%3E%3CfeColorMatrix in='noise' type='matrix' values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.2 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
} }