Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3393de2286 | ||
|
|
368985c0cf |
No files matched your search
@@ -9,6 +9,13 @@
|
||||
hellem Grund (Hintergrund/Cream), -light fuer Text auf bg-forest. */
|
||||
--color-honey-dark: #8a6531;
|
||||
--color-honey-light: #c9a468;
|
||||
/* Fuer Text ueber BILDERN statt ueber einer Volltonflaeche. -light besteht
|
||||
4.5:1 nur gegen deckendes bg-forest; im Hero liegt der Text aber auf einem
|
||||
Foto mit halbdurchlaessiger Abdunklung, und je nach Motiv (helles Holz,
|
||||
Himmel) sank der Kontrast dort auf 1,34:1 — die Zeile war praktisch
|
||||
unsichtbar. -pale haelt bei der im Hero gesetzten Abdunklung 4,8:1 bis
|
||||
7,0:1 und behaelt den Honigton. */
|
||||
--color-honey-pale: #e4cfa4;
|
||||
--color-background: #faf8f3;
|
||||
--color-ink: #242424;
|
||||
--color-sage: #788774;
|
||||
@@ -20,6 +27,7 @@
|
||||
--color-honey: var(--color-honey);
|
||||
--color-honey-dark: var(--color-honey-dark);
|
||||
--color-honey-light: var(--color-honey-light);
|
||||
--color-honey-pale: var(--color-honey-pale);
|
||||
--color-background: var(--color-background);
|
||||
--color-ink: var(--color-ink);
|
||||
--color-sage: var(--color-sage);
|
||||
|
||||
+1
-1
@@ -63,7 +63,7 @@ export default async function HomePage() {
|
||||
<Sustainability />
|
||||
<BusinessTeaser />
|
||||
<Reviews />
|
||||
<NewsletterSignup />
|
||||
<NewsletterSignup turnstileSiteKey={process.env.NEXT_PUBLIC_TURNSTILE_SITE_KEY} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -51,7 +51,7 @@ export default async function UnternehmenPage() {
|
||||
|
||||
<ScrollReveal className="mt-20 max-w-2xl">
|
||||
<h2 className="text-2xl text-forest mb-8">{t.unternehmenPage.inquiryHeading}</h2>
|
||||
<BusinessInquiryForm />
|
||||
<BusinessInquiryForm turnstileSiteKey={process.env.NEXT_PUBLIC_TURNSTILE_SITE_KEY} />
|
||||
</ScrollReveal>
|
||||
</Container>
|
||||
</div>
|
||||
|
||||
@@ -7,9 +7,24 @@ import { useI18n } from "@/i18n/i18n-provider";
|
||||
|
||||
type Status = "idle" | "loading" | "success" | "error";
|
||||
|
||||
const TURNSTILE_SITE_KEY = process.env.NEXT_PUBLIC_TURNSTILE_SITE_KEY;
|
||||
|
||||
export function BusinessInquiryForm() {
|
||||
/**
|
||||
* Der Turnstile-Sitekey kommt als Prop vom Server und NICHT aus
|
||||
* process.env in dieser Datei.
|
||||
*
|
||||
* Grund: NEXT_PUBLIC_-Variablen werden in Client Components zur BUILD-Zeit
|
||||
* ins Bundle eingebacken. Der Wert wird hier aber erst zur Laufzeit gesetzt
|
||||
* (k8s/01-configmap.yaml). Ein Zugriff auf process.env an dieser Stelle
|
||||
* ergibt deshalb dauerhaft undefined — das Widget erschiene nie, waehrend die
|
||||
* Serverseite bei gesetztem TURNSTILE_SECRET_KEY sehr wohl einen Token
|
||||
* verlangt. Das Formular waere damit unabsendbar, ohne dass irgendwo ein
|
||||
* Fehler auftaucht.
|
||||
*
|
||||
* Alle uebrigen Formulare (Login, Registrierung, Passwort-Reset, Zwei-Faktor,
|
||||
* Checkout, Verfuegbarkeits-Benachrichtigung) lesen den Wert bereits im
|
||||
* Server Component und reichen ihn als Prop weiter. Diese Datei folgt jetzt
|
||||
* demselben Muster.
|
||||
*/
|
||||
export function BusinessInquiryForm({ turnstileSiteKey }: { turnstileSiteKey?: string }) {
|
||||
const { t } = useI18n();
|
||||
const [status, setStatus] = useState<Status>("idle");
|
||||
const [errorMessage, setErrorMessage] = useState<string | null>(null);
|
||||
@@ -96,8 +111,8 @@ export function BusinessInquiryForm() {
|
||||
|
||||
{errorMessage ? <p className="text-sm text-red-700">{errorMessage}</p> : null}
|
||||
|
||||
{TURNSTILE_SITE_KEY ? (
|
||||
<TurnstileWidget siteKey={TURNSTILE_SITE_KEY} onVerify={setTurnstileToken} />
|
||||
{turnstileSiteKey ? (
|
||||
<TurnstileWidget siteKey={turnstileSiteKey} onVerify={setTurnstileToken} />
|
||||
) : null}
|
||||
|
||||
<Button type="submit" disabled={status === "loading"}>
|
||||
|
||||
+17
-3
@@ -110,7 +110,21 @@ export function Hero({
|
||||
unlesbar machen kann. Der gerichtete Verlauf darunter verstaerkt das
|
||||
gezielt dort, wo die Textspalte tatsaechlich sitzt (unten links). */}
|
||||
<div className="absolute inset-0 bg-forest/25" />
|
||||
<div className="absolute inset-0 flex items-center bg-gradient-to-tr from-forest/70 via-forest/25 to-transparent">
|
||||
{/* Senkrecht auf schmalen Schirmen, waagerecht ab md.
|
||||
|
||||
Der frueher hier stehende to-tr-Verlauf liess die Textspalte auf
|
||||
rund 44 % Abdunklung liegen. Ueber hellem Motiv (Holz, Himmel)
|
||||
ergab das 1,34:1 fuer die Ortszeile und 2,73:1 fuer die
|
||||
Ueberschrift — beides weit unter WCAG AA. Lighthouse meldet das
|
||||
nicht, weil es Text ueber Bildern nicht bewerten kann.
|
||||
|
||||
Waagerecht funktioniert nur ab md: dort endet die Textspalte bei
|
||||
etwa 45 % Breite und liegt damit ganz im dunklen Teil, waehrend
|
||||
die rechte Bildhaelfte unangetastet bleibt. Auf dem Handy laeuft
|
||||
der Text ueber die volle Breite und geriete rechts in den
|
||||
durchsichtigen Teil — deshalb dort senkrecht, was horizontal
|
||||
gleichmaessig abdunkelt und den oberen Bildrand frei laesst. */}
|
||||
<div className="absolute inset-0 flex items-center bg-gradient-to-t from-forest/85 via-forest/70 to-forest/10 md:bg-gradient-to-r md:from-forest/85 md:via-forest/70 md:to-transparent">
|
||||
<Container>
|
||||
<motion.div
|
||||
className="max-w-xl text-cream"
|
||||
@@ -120,7 +134,7 @@ export function Hero({
|
||||
>
|
||||
<motion.p
|
||||
data-reveal="" variants={itemVariants}
|
||||
className="tracking-wide-caps text-xs text-honey-light mb-4"
|
||||
className="tracking-wide-caps text-xs text-honey-pale mb-4"
|
||||
>
|
||||
{location}
|
||||
</motion.p>
|
||||
@@ -140,7 +154,7 @@ export function Hero({
|
||||
{t.home.hero.ctaSecondary}
|
||||
</LinkButton>
|
||||
</motion.div>
|
||||
<motion.p data-reveal="" variants={itemVariants} className="mt-8 text-xs text-cream/60 tracking-wide">
|
||||
<motion.p data-reveal="" variants={itemVariants} className="mt-8 text-xs text-cream/80 tracking-wide">
|
||||
{footnote}
|
||||
</motion.p>
|
||||
</motion.div>
|
||||
|
||||
@@ -8,9 +8,24 @@ import { useI18n } from "@/i18n/i18n-provider";
|
||||
|
||||
type Status = "idle" | "loading" | "success" | "error";
|
||||
|
||||
const TURNSTILE_SITE_KEY = process.env.NEXT_PUBLIC_TURNSTILE_SITE_KEY;
|
||||
|
||||
export function NewsletterSignup() {
|
||||
/**
|
||||
* Der Turnstile-Sitekey kommt als Prop vom Server und NICHT aus
|
||||
* process.env in dieser Datei.
|
||||
*
|
||||
* Grund: NEXT_PUBLIC_-Variablen werden in Client Components zur BUILD-Zeit
|
||||
* ins Bundle eingebacken. Der Wert wird hier aber erst zur Laufzeit gesetzt
|
||||
* (k8s/01-configmap.yaml). Ein Zugriff auf process.env an dieser Stelle
|
||||
* ergibt deshalb dauerhaft undefined — das Widget erschiene nie, waehrend die
|
||||
* Serverseite bei gesetztem TURNSTILE_SECRET_KEY sehr wohl einen Token
|
||||
* verlangt. Das Formular waere damit unabsendbar, ohne dass irgendwo ein
|
||||
* Fehler auftaucht.
|
||||
*
|
||||
* Alle uebrigen Formulare (Login, Registrierung, Passwort-Reset, Zwei-Faktor,
|
||||
* Checkout, Verfuegbarkeits-Benachrichtigung) lesen den Wert bereits im
|
||||
* Server Component und reichen ihn als Prop weiter. Diese Datei folgt jetzt
|
||||
* demselben Muster.
|
||||
*/
|
||||
export function NewsletterSignup({ turnstileSiteKey }: { turnstileSiteKey?: string }) {
|
||||
const { t } = useI18n();
|
||||
const [email, setEmail] = useState("");
|
||||
const [status, setStatus] = useState<Status>("idle");
|
||||
@@ -63,9 +78,9 @@ export function NewsletterSignup() {
|
||||
<Button type="submit" disabled={status === "loading"} className="flex-shrink-0 whitespace-nowrap">
|
||||
{status === "loading" ? t.home.newsletter.subscribing : t.home.newsletter.subscribe}
|
||||
</Button>
|
||||
{TURNSTILE_SITE_KEY ? (
|
||||
{turnstileSiteKey ? (
|
||||
<div className="w-full flex justify-center">
|
||||
<TurnstileWidget siteKey={TURNSTILE_SITE_KEY} onVerify={setTurnstileToken} />
|
||||
<TurnstileWidget siteKey={turnstileSiteKey} onVerify={setTurnstileToken} />
|
||||
</div>
|
||||
) : null}
|
||||
</form>
|
||||
|
||||
Reference in new issue
Block a user