Compare commits
2
Commits
5870c60c50
...
3393de2286
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3393de2286 | ||
|
|
368985c0cf |
No files matched your search
@@ -9,6 +9,13 @@
|
|||||||
hellem Grund (Hintergrund/Cream), -light fuer Text auf bg-forest. */
|
hellem Grund (Hintergrund/Cream), -light fuer Text auf bg-forest. */
|
||||||
--color-honey-dark: #8a6531;
|
--color-honey-dark: #8a6531;
|
||||||
--color-honey-light: #c9a468;
|
--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-background: #faf8f3;
|
||||||
--color-ink: #242424;
|
--color-ink: #242424;
|
||||||
--color-sage: #788774;
|
--color-sage: #788774;
|
||||||
@@ -20,6 +27,7 @@
|
|||||||
--color-honey: var(--color-honey);
|
--color-honey: var(--color-honey);
|
||||||
--color-honey-dark: var(--color-honey-dark);
|
--color-honey-dark: var(--color-honey-dark);
|
||||||
--color-honey-light: var(--color-honey-light);
|
--color-honey-light: var(--color-honey-light);
|
||||||
|
--color-honey-pale: var(--color-honey-pale);
|
||||||
--color-background: var(--color-background);
|
--color-background: var(--color-background);
|
||||||
--color-ink: var(--color-ink);
|
--color-ink: var(--color-ink);
|
||||||
--color-sage: var(--color-sage);
|
--color-sage: var(--color-sage);
|
||||||
|
|||||||
+1
-1
@@ -63,7 +63,7 @@ export default async function HomePage() {
|
|||||||
<Sustainability />
|
<Sustainability />
|
||||||
<BusinessTeaser />
|
<BusinessTeaser />
|
||||||
<Reviews />
|
<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">
|
<ScrollReveal className="mt-20 max-w-2xl">
|
||||||
<h2 className="text-2xl text-forest mb-8">{t.unternehmenPage.inquiryHeading}</h2>
|
<h2 className="text-2xl text-forest mb-8">{t.unternehmenPage.inquiryHeading}</h2>
|
||||||
<BusinessInquiryForm />
|
<BusinessInquiryForm turnstileSiteKey={process.env.NEXT_PUBLIC_TURNSTILE_SITE_KEY} />
|
||||||
</ScrollReveal>
|
</ScrollReveal>
|
||||||
</Container>
|
</Container>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -7,9 +7,24 @@ import { useI18n } from "@/i18n/i18n-provider";
|
|||||||
|
|
||||||
type Status = "idle" | "loading" | "success" | "error";
|
type Status = "idle" | "loading" | "success" | "error";
|
||||||
|
|
||||||
const TURNSTILE_SITE_KEY = process.env.NEXT_PUBLIC_TURNSTILE_SITE_KEY;
|
/**
|
||||||
|
* Der Turnstile-Sitekey kommt als Prop vom Server und NICHT aus
|
||||||
export function BusinessInquiryForm() {
|
* 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 { t } = useI18n();
|
||||||
const [status, setStatus] = useState<Status>("idle");
|
const [status, setStatus] = useState<Status>("idle");
|
||||||
const [errorMessage, setErrorMessage] = useState<string | null>(null);
|
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}
|
{errorMessage ? <p className="text-sm text-red-700">{errorMessage}</p> : null}
|
||||||
|
|
||||||
{TURNSTILE_SITE_KEY ? (
|
{turnstileSiteKey ? (
|
||||||
<TurnstileWidget siteKey={TURNSTILE_SITE_KEY} onVerify={setTurnstileToken} />
|
<TurnstileWidget siteKey={turnstileSiteKey} onVerify={setTurnstileToken} />
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
<Button type="submit" disabled={status === "loading"}>
|
<Button type="submit" disabled={status === "loading"}>
|
||||||
|
|||||||
+17
-3
@@ -110,7 +110,21 @@ export function Hero({
|
|||||||
unlesbar machen kann. Der gerichtete Verlauf darunter verstaerkt das
|
unlesbar machen kann. Der gerichtete Verlauf darunter verstaerkt das
|
||||||
gezielt dort, wo die Textspalte tatsaechlich sitzt (unten links). */}
|
gezielt dort, wo die Textspalte tatsaechlich sitzt (unten links). */}
|
||||||
<div className="absolute inset-0 bg-forest/25" />
|
<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>
|
<Container>
|
||||||
<motion.div
|
<motion.div
|
||||||
className="max-w-xl text-cream"
|
className="max-w-xl text-cream"
|
||||||
@@ -120,7 +134,7 @@ export function Hero({
|
|||||||
>
|
>
|
||||||
<motion.p
|
<motion.p
|
||||||
data-reveal="" variants={itemVariants}
|
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}
|
{location}
|
||||||
</motion.p>
|
</motion.p>
|
||||||
@@ -140,7 +154,7 @@ export function Hero({
|
|||||||
{t.home.hero.ctaSecondary}
|
{t.home.hero.ctaSecondary}
|
||||||
</LinkButton>
|
</LinkButton>
|
||||||
</motion.div>
|
</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}
|
{footnote}
|
||||||
</motion.p>
|
</motion.p>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
|
|||||||
@@ -8,9 +8,24 @@ import { useI18n } from "@/i18n/i18n-provider";
|
|||||||
|
|
||||||
type Status = "idle" | "loading" | "success" | "error";
|
type Status = "idle" | "loading" | "success" | "error";
|
||||||
|
|
||||||
const TURNSTILE_SITE_KEY = process.env.NEXT_PUBLIC_TURNSTILE_SITE_KEY;
|
/**
|
||||||
|
* Der Turnstile-Sitekey kommt als Prop vom Server und NICHT aus
|
||||||
export function NewsletterSignup() {
|
* 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 { t } = useI18n();
|
||||||
const [email, setEmail] = useState("");
|
const [email, setEmail] = useState("");
|
||||||
const [status, setStatus] = useState<Status>("idle");
|
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">
|
<Button type="submit" disabled={status === "loading"} className="flex-shrink-0 whitespace-nowrap">
|
||||||
{status === "loading" ? t.home.newsletter.subscribing : t.home.newsletter.subscribe}
|
{status === "loading" ? t.home.newsletter.subscribing : t.home.newsletter.subscribe}
|
||||||
</Button>
|
</Button>
|
||||||
{TURNSTILE_SITE_KEY ? (
|
{turnstileSiteKey ? (
|
||||||
<div className="w-full flex justify-center">
|
<div className="w-full flex justify-center">
|
||||||
<TurnstileWidget siteKey={TURNSTILE_SITE_KEY} onVerify={setTurnstileToken} />
|
<TurnstileWidget siteKey={turnstileSiteKey} onVerify={setTurnstileToken} />
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
Reference in new issue
Block a user