diff --git a/src/components/cart-landing-effect.tsx b/src/components/cart-landing-effect.tsx
index 66e5125..f8f04f1 100644
--- a/src/components/cart-landing-effect.tsx
+++ b/src/components/cart-landing-effect.tsx
@@ -85,32 +85,34 @@ export function CartLandingEffect() {
- {reduceMotion ? null : (
-
- {/* Gleiche Honigtoene wie der fliegende Tropfen in cart-flight.tsx. */}
-
-
- )}
+ {/* Immer gerendert, nur bei reduzierter Bewegung nie animiert (bleibt
+ bei opacity 0). Ein bedingtes Rendern wich zwischen Server
+ (useReducedMotion = null) und Browser ab und loeste einen
+ Hydration-Fehler aus. */}
+
+ {/* Gleiche Honigtoene wie der fliegende Tropfen in cart-flight.tsx. */}
+
+
);
}
diff --git a/src/components/cookie-consent.tsx b/src/components/cookie-consent.tsx
index e65c272..e4337cb 100644
--- a/src/components/cookie-consent.tsx
+++ b/src/components/cookie-consent.tsx
@@ -54,7 +54,11 @@ export function CookieConsentBanner() {
verlangen, dass Ablehnen nicht schwerer faellt als Zustimmen).
Vorher war "Alle akzeptieren" Waldgruen auf Waldgruen und damit
kaum als Knopf erkennbar. */}
-
+ {/* Auf schmalen Telefonen untereinander: nebeneinander und ohne
+ Umbruch liefen "Nur notwendige" und "Alle akzeptieren" bei 390 px
+ ineinander. Gestapelt bleiben beide gleich breit und gleich
+ gewichtet. */}
+
diff --git a/src/lib/certificate/layout.test.ts b/src/lib/certificate/layout.test.ts
index b19840b..4724ee5 100644
--- a/src/lib/certificate/layout.test.ts
+++ b/src/lib/certificate/layout.test.ts
@@ -142,7 +142,10 @@ function assertSound(layout: CertificateLayout, personalization: Personalization
describe.each(listTemplateVersions())("Vorlage %s", (version) => {
describe.each(Object.entries(DATASETS))("Datensatz %s", (_name, data) => {
- test.each(["de", "en"] as const)("Geschenk und eigene Patenschaft (%s)", (locale) => {
+ // Grosszuegige Zeitgrenze: jeder Fall setzt mehrere Seiten mit echten
+ // Schriftmetriken. Auf den CI-Runnern (geteilte CPU) reichten die
+ // voreingestellten 5 Sekunden nicht immer, lokal braucht es Bruchteile.
+ test.each(["de", "en"] as const)("Geschenk und eigene Patenschaft (%s)", { timeout: 60_000 }, (locale) => {
for (const occasion of ["GEBURTSTAG", "SELBST"] as const) {
const { layout, personalization } = build(version, data, occasion, locale, TERMS.einmalig);
assertSound(layout, personalization);
diff --git a/vitest.config.ts b/vitest.config.ts
index ea29414..35ae287 100644
--- a/vitest.config.ts
+++ b/vitest.config.ts
@@ -17,5 +17,10 @@ export default defineConfig({
include: ["src/**/*.test.ts", "src/**/*.test.tsx"],
exclude: ["e2e/**"],
setupFiles: ["./vitest.setup.ts"],
+ // Urkunden-, Medaillen- und PDF-Tests setzen echte Schriften und rendern
+ // Bilder. Auf den CI-Runnern (geteilte CPU) dauert das ein Vielfaches
+ // der lokalen Zeit; die voreingestellten 5 Sekunden liessen dort einzelne
+ // Faelle zufaellig scheitern.
+ testTimeout: 30_000,
},
});