diff --git a/.pa11yci/report.json b/.pa11yci/report.json new file mode 100644 index 000000000..83d2fca51 --- /dev/null +++ b/.pa11yci/report.json @@ -0,0 +1 @@ +{"total":20,"passes":0,"errors":16,"results":{"http://localhost:3000/de":[{"code":"document-title","type":"error","typeCode":1,"message":"Documents must have element to aid in navigation (https://dequeuniversity.com/rules/axe/4.11/document-title?application=axeAPI)","context":"<html><head><link rel=\"stylesheet\" hr...</html>","selector":"html","runner":"axe","runnerExtras":{"description":"Ensure each HTML document contains a non-empty <title> element","impact":"serious","needsFurtherReview":false,"help":"Documents must have <title> element to aid in navigation","helpUrl":"https://dequeuniversity.com/rules/axe/4.11/document-title?application=axeAPI"}},{"code":"html-has-lang","type":"error","typeCode":1,"message":"<html> element must have a lang attribute (https://dequeuniversity.com/rules/axe/4.11/html-has-lang?application=axeAPI)","context":"<html><head><link rel=\"stylesheet\" hr...</html>","selector":"html","runner":"axe","runnerExtras":{"description":"Ensure every HTML document has a lang attribute","impact":"serious","needsFurtherReview":false,"help":"<html> element must have a lang attribute","helpUrl":"https://dequeuniversity.com/rules/axe/4.11/html-has-lang?application=axeAPI"}}],"http://localhost:3000/en":[{"code":"document-title","type":"error","typeCode":1,"message":"Documents must have <title> element to aid in navigation (https://dequeuniversity.com/rules/axe/4.11/document-title?application=axeAPI)","context":"<html><head><link rel=\"stylesheet\" hr...</html>","selector":"html","runner":"axe","runnerExtras":{"description":"Ensure each HTML document contains a non-empty <title> element","impact":"serious","needsFurtherReview":false,"help":"Documents must have <title> element to aid in navigation","helpUrl":"https://dequeuniversity.com/rules/axe/4.11/document-title?application=axeAPI"}},{"code":"html-has-lang","type":"error","typeCode":1,"message":"<html> element must have a lang attribute (https://dequeuniversity.com/rules/axe/4.11/html-has-lang?application=axeAPI)","context":"<html><head><link rel=\"stylesheet\" hr...</html>","selector":"html","runner":"axe","runnerExtras":{"description":"Ensure every HTML document has a lang attribute","impact":"serious","needsFurtherReview":false,"help":"<html> element must have a lang attribute","helpUrl":"https://dequeuniversity.com/rules/axe/4.11/html-has-lang?application=axeAPI"}}],"http://localhost:3000/de/agbs":[{"message":"Navigation timeout of 60000 ms exceeded"}],"http://localhost:3000/de/blog":[{"code":"document-title","type":"error","typeCode":1,"message":"Documents must have <title> element to aid in navigation (https://dequeuniversity.com/rules/axe/4.11/document-title?application=axeAPI)","context":"<html><head><link rel=\"stylesheet\" hr...</html>","selector":"html","runner":"axe","runnerExtras":{"description":"Ensure each HTML document contains a non-empty <title> element","impact":"serious","needsFurtherReview":false,"help":"Documents must have <title> element to aid in navigation","helpUrl":"https://dequeuniversity.com/rules/axe/4.11/document-title?application=axeAPI"}},{"code":"html-has-lang","type":"error","typeCode":1,"message":"<html> element must have a lang attribute (https://dequeuniversity.com/rules/axe/4.11/html-has-lang?application=axeAPI)","context":"<html><head><link rel=\"stylesheet\" hr...</html>","selector":"html","runner":"axe","runnerExtras":{"description":"Ensure every HTML document has a lang attribute","impact":"serious","needsFurtherReview":false,"help":"<html> element must have a lang attribute","helpUrl":"https://dequeuniversity.com/rules/axe/4.11/html-has-lang?application=axeAPI"}}],"http://localhost:3000/de/blog/100-erneuerbare-energie-nur-mit-der-richtigen-kabelinfrastruktur":[{"message":"Navigation timeout of 60000 ms exceeded"}],"http://localhost:3000/de/blog/das-muessen-sie-ueber-erneuerbare-energien-im-jahr-2025-wissen":[{"message":"Navigation timeout of 60000 ms exceeded"}],"http://localhost:3000/de/blog/die-besten-erdkabel-fuer-windkraft-und-solar-jetzt-bei-uns-bestellen":[{"message":"Navigation timeout of 60000 ms exceeded"}],"http://localhost:3000/de/blog/die-kunst-der-kabellogistik-der-transport-des-fundamentes-moderner-energienetze":[{"message":"Navigation timeout of 60000 ms exceeded"}],"http://localhost:3000/de/blog/die-perfekte-kabelanfrage-so-sparen-sie-sich-unnoetige-rueckfragen":[{"code":"document-title","type":"error","typeCode":1,"message":"Documents must have <title> element to aid in navigation (https://dequeuniversity.com/rules/axe/4.11/document-title?application=axeAPI)","context":"<html><head><link rel=\"stylesheet\" hr...</html>","selector":"html","runner":"axe","runnerExtras":{"description":"Ensure each HTML document contains a non-empty <title> element","impact":"serious","needsFurtherReview":false,"help":"Documents must have <title> element to aid in navigation","helpUrl":"https://dequeuniversity.com/rules/axe/4.11/document-title?application=axeAPI"}},{"code":"html-has-lang","type":"error","typeCode":1,"message":"<html> element must have a lang attribute (https://dequeuniversity.com/rules/axe/4.11/html-has-lang?application=axeAPI)","context":"<html><head><link rel=\"stylesheet\" hr...</html>","selector":"html","runner":"axe","runnerExtras":{"description":"Ensure every HTML document has a lang attribute","impact":"serious","needsFurtherReview":false,"help":"<html> element must have a lang attribute","helpUrl":"https://dequeuniversity.com/rules/axe/4.11/html-has-lang?application=axeAPI"}}],"http://localhost:3000/de/blog/erkenntnisse-ueber-die-gruene-energiewende-herausforderungen-und-chancen":[{"message":"Navigation timeout of 60000 ms exceeded"}],"http://localhost:3000/de/blog/gruene-energie-beginnt-unter-der-erde-und-zwar-mit-plan":[{"code":"document-title","type":"error","typeCode":1,"message":"Documents must have <title> element to aid in navigation (https://dequeuniversity.com/rules/axe/4.11/document-title?application=axeAPI)","context":"<html><head><link rel=\"stylesheet\" hr...</html>","selector":"html","runner":"axe","runnerExtras":{"description":"Ensure each HTML document contains a non-empty <title> element","impact":"serious","needsFurtherReview":false,"help":"Documents must have <title> element to aid in navigation","helpUrl":"https://dequeuniversity.com/rules/axe/4.11/document-title?application=axeAPI"}},{"code":"html-has-lang","type":"error","typeCode":1,"message":"<html> element must have a lang attribute (https://dequeuniversity.com/rules/axe/4.11/html-has-lang?application=axeAPI)","context":"<html><head><link rel=\"stylesheet\" hr...</html>","selector":"html","runner":"axe","runnerExtras":{"description":"Ensure every HTML document has a lang attribute","impact":"serious","needsFurtherReview":false,"help":"<html> element must have a lang attribute","helpUrl":"https://dequeuniversity.com/rules/axe/4.11/html-has-lang?application=axeAPI"}}],"http://localhost:3000/de/blog/johannes-gleich-startet-als-senior-key-account-manager-durch":[{"code":"document-title","type":"error","typeCode":1,"message":"Documents must have <title> element to aid in navigation (https://dequeuniversity.com/rules/axe/4.11/document-title?application=axeAPI)","context":"<html><head><link rel=\"stylesheet\" hr...</html>","selector":"html","runner":"axe","runnerExtras":{"description":"Ensure each HTML document contains a non-empty <title> element","impact":"serious","needsFurtherReview":false,"help":"Documents must have <title> element to aid in navigation","helpUrl":"https://dequeuniversity.com/rules/axe/4.11/document-title?application=axeAPI"}},{"code":"html-has-lang","type":"error","typeCode":1,"message":"<html> element must have a lang attribute (https://dequeuniversity.com/rules/axe/4.11/html-has-lang?application=axeAPI)","context":"<html><head><link rel=\"stylesheet\" hr...</html>","selector":"html","runner":"axe","runnerExtras":{"description":"Ensure every HTML document has a lang attribute","impact":"serious","needsFurtherReview":false,"help":"<html> element must have a lang attribute","helpUrl":"https://dequeuniversity.com/rules/axe/4.11/html-has-lang?application=axeAPI"}}],"http://localhost:3000/de/blog/kabelabkuerzungen-entschluesselt-der-schluessel-zur-richtigen-kabelwahl":[{"message":"Navigation timeout of 60000 ms exceeded"}],"http://localhost:3000/de/blog/kabeltrommelqualitaet-die-grundlage-der-kabelzuverlaessigkeit":[{"message":"Navigation timeout of 60000 ms exceeded"}],"http://localhost:3000/de/blog/klimaneutral-bis-2050-was-wir-tun-muessen-um-das-ziel-zu-erreichen":[{"code":"document-title","type":"error","typeCode":1,"message":"Documents must have <title> element to aid in navigation (https://dequeuniversity.com/rules/axe/4.11/document-title?application=axeAPI)","context":"<html><head><link rel=\"stylesheet\" hr...</html>","selector":"html","runner":"axe","runnerExtras":{"description":"Ensure each HTML document contains a non-empty <title> element","impact":"serious","needsFurtherReview":false,"help":"Documents must have <title> element to aid in navigation","helpUrl":"https://dequeuniversity.com/rules/axe/4.11/document-title?application=axeAPI"}},{"code":"html-has-lang","type":"error","typeCode":1,"message":"<html> element must have a lang attribute (https://dequeuniversity.com/rules/axe/4.11/html-has-lang?application=axeAPI)","context":"<html><head><link rel=\"stylesheet\" hr...</html>","selector":"html","runner":"axe","runnerExtras":{"description":"Ensure every HTML document has a lang attribute","impact":"serious","needsFurtherReview":false,"help":"<html> element must have a lang attribute","helpUrl":"https://dequeuniversity.com/rules/axe/4.11/html-has-lang?application=axeAPI"}}],"http://localhost:3000/de/blog/klz-im-adressbuch-der-windenergie-2025":[{"message":"Navigation timeout of 60000 ms exceeded"}],"http://localhost:3000/de/blog/klz-waechst-weiter-neue-staerke-im-bereich-financial-sales":[{"message":"Navigation timeout of 60000 ms exceeded"}],"http://localhost:3000/de/blog/kostenvergleich-kupfer-vs-aluminiumkabel-in-windparks-was-lohnt-sich-langfristig":[{"message":"Navigation timeout of 60000 ms exceeded"}],"http://localhost:3000/de/blog/milliarden-paket-fuer-infrastruktur-der-kabel-boom-steht-bevor":[{"message":"Navigation timeout of 60000 ms exceeded"}],"http://localhost:3000/de/blog/n2xsf2y-mittelspannungskabel-energieprojekt":[{"code":"document-title","type":"error","typeCode":1,"message":"Documents must have <title> element to aid in navigation (https://dequeuniversity.com/rules/axe/4.11/document-title?application=axeAPI)","context":"<html><head><link rel=\"stylesheet\" hr...</html>","selector":"html","runner":"axe","runnerExtras":{"description":"Ensure each HTML document contains a non-empty <title> element","impact":"serious","needsFurtherReview":false,"help":"Documents must have <title> element to aid in navigation","helpUrl":"https://dequeuniversity.com/rules/axe/4.11/document-title?application=axeAPI"}},{"code":"html-has-lang","type":"error","typeCode":1,"message":"<html> element must have a lang attribute (https://dequeuniversity.com/rules/axe/4.11/html-has-lang?application=axeAPI)","context":"<html><head><link rel=\"stylesheet\" hr...</html>","selector":"html","runner":"axe","runnerExtras":{"description":"Ensure every HTML document has a lang attribute","impact":"serious","needsFurtherReview":false,"help":"<html> element must have a lang attribute","helpUrl":"https://dequeuniversity.com/rules/axe/4.11/html-has-lang?application=axeAPI"}}]}} diff --git a/.pa11yci/single-test.json b/.pa11yci/single-test.json new file mode 100644 index 000000000..2901369c6 --- /dev/null +++ b/.pa11yci/single-test.json @@ -0,0 +1,18 @@ +{ + "defaults": { + "runners": ["axe"], + "timeout": 60000, + "chromeLaunchConfig": { + "args": [ + "--no-sandbox", + "--disable-setuid-sandbox", + "--disable-dev-shm-usage", + "--disable-gpu" + ] + }, + "ignore": [] + }, + "urls": [ + "http://etib.localhost/de/blog/moderne-verfahren-kabeltiefbau" + ] +} diff --git a/.pa11yci/test-html.json b/.pa11yci/test-html.json new file mode 100644 index 000000000..9e2ff0f17 --- /dev/null +++ b/.pa11yci/test-html.json @@ -0,0 +1,9 @@ +{ + "defaults": { + "runners": ["axe"], + "ignore": ["color-contrast"] + }, + "urls": [ + "file:////Volumes/Alpha SSD/Coding/e-tib.com/test.html" + ] +} diff --git a/app/[locale]/blog/[slug]/page.tsx b/app/[locale]/blog/[slug]/page.tsx index e105cf94f..fb76bd5a1 100644 --- a/app/[locale]/blog/[slug]/page.tsx +++ b/app/[locale]/blog/[slug]/page.tsx @@ -24,13 +24,13 @@ const mdxComponents = { h2: (props: any) => <Heading level={2} size="3" className="mt-16 mb-6 border-b border-neutral-100 pb-4" {...props} />, h3: (props: any) => <Heading level={3} size="4" className="mt-12 mb-4 text-primary" {...props} />, h4: (props: any) => <Heading level={4} size="5" className="mt-8 mb-4 uppercase tracking-widest text-neutral-500" {...props} />, - p: (props: any) => <p className="text-base md:text-lg text-text-secondary leading-[1.8] mb-6 font-medium max-w-3xl" {...props} />, - ul: (props: any) => <ul className="list-none mb-8 space-y-3 text-base md:text-lg text-text-secondary font-medium max-w-3xl" {...props} />, - ol: (props: any) => <ol className="list-decimal pl-6 mb-8 space-y-3 text-base md:text-lg text-text-secondary font-medium max-w-3xl" {...props} />, + p: (props: any) => <p className="text-base md:text-lg text-text-secondary leading-[1.8] mb-6 font-normal max-w-3xl" {...props} />, + ul: (props: any) => <ul className="list-none mb-8 space-y-3 text-base md:text-lg text-text-secondary font-normal max-w-3xl" {...props} />, + ol: (props: any) => <ol className="list-decimal pl-6 mb-8 space-y-3 text-base md:text-lg text-text-secondary font-normal max-w-3xl" {...props} />, li: (props: any) => ( <li className="relative pl-6 before:content-[''] before:absolute before:left-0 before:top-[0.6em] before:w-2 before:h-2 before:bg-primary/50 before:rounded-sm" {...props} /> ), - a: (props: any) => <a className="text-primary hover:text-primary-dark underline decoration-primary/30 underline-offset-4 hover:decoration-primary transition-all font-bold" {...props} />, + a: (props: any) => <a className="text-text-secondary underline decoration-primary decoration-2 underline-offset-4 hover:text-primary transition-all font-bold" {...props} />, strong: (props: any) => <strong className="font-bold text-neutral-900" {...props} />, blockquote: (props: any) => ( <blockquote className="border-l-4 border-primary pl-6 py-3 my-10 italic bg-neutral-50 rounded-r-2xl text-neutral-700 font-medium max-w-3xl shadow-sm" {...props} /> @@ -114,12 +114,12 @@ export default async function BlogPost({ params }: BlogPostProps) { }} /> </div> - <div className="absolute inset-0 bg-gradient-to-t from-neutral-dark/90 via-neutral-dark/40 to-transparent" /> + <div className="absolute inset-0 bg-gradient-to-t from-neutral-dark/90 via-neutral-dark/70 to-neutral-dark/30" /> {/* Title overlay on image */} <div className="absolute inset-0 flex flex-col justify-end pb-16 md:pb-24"> <div className="container mx-auto px-4"> - <div className="max-w-4xl"> + <div className="max-w-4xl bg-neutral-dark/40 backdrop-blur-md p-6 rounded-2xl border border-white/10"> {post.frontmatter.category && ( <div className="overflow-hidden mb-6"> <span className="inline-block px-4 py-1.5 bg-accent text-neutral-dark text-xs font-bold uppercase tracking-[0.2em] rounded-sm"> @@ -127,10 +127,10 @@ export default async function BlogPost({ params }: BlogPostProps) { </span> </div> )} - <Heading level={1} className="text-white mb-8 drop-shadow-2xl"> + <Heading level={1} className="text-white mb-8 drop-shadow-md"> {post.frontmatter.title} </Heading> - <div className="flex flex-wrap items-center gap-6 text-white/80 text-sm md:text-base font-medium"> + <div className="flex flex-wrap items-center gap-6 text-white text-sm md:text-base font-medium drop-shadow-sm"> <time dateTime={post.frontmatter.date} suppressHydrationWarning> {new Date(post.frontmatter.date).toLocaleDateString(locale || 'de', { year: 'numeric', @@ -138,7 +138,7 @@ export default async function BlogPost({ params }: BlogPostProps) { day: 'numeric', })} </time> - <span className="w-1 h-1 bg-white/30 rounded-full" /> + <span className="w-1 h-1 bg-white/50 rounded-full" /> <span>{readingTime} min read</span> {(new Date(post.frontmatter.date) > new Date() || post.frontmatter.public === false) && ( @@ -206,7 +206,7 @@ export default async function BlogPost({ params }: BlogPostProps) { )} {/* Main content */} - <div className="w-full"> + <div className="w-full [&_a]:text-primary [&_a:hover]:text-primary-dark [&_a]:underline [&_a]:decoration-primary [&_a]:underline-offset-4 [&_a]:transition-all [&_a]:font-bold [&_a_strong]:text-inherit"> <MDXRemote source={post.content} components={mdxComponents} /> </div> diff --git a/components/blog/PowerCTA.tsx b/components/blog/PowerCTA.tsx index e50e6a63e..2743bc61c 100644 --- a/components/blog/PowerCTA.tsx +++ b/components/blog/PowerCTA.tsx @@ -19,13 +19,13 @@ export default function PowerCTA({ locale }: PowerCTAProps) { <div className="absolute top-0 right-0 w-64 h-64 bg-primary/20 rounded-full blur-3xl -mr-32 -mt-32 transition-transform group-hover:scale-110 duration-1000" /> <div className="relative z-10"> - <div className="inline-block px-4 py-1 bg-accent/20 text-accent text-xs font-bold uppercase tracking-[0.2em] rounded-full mb-8"> + <div className="inline-block px-4 py-1 bg-primary-light/20 text-primary-light text-xs font-bold uppercase tracking-[0.2em] rounded-full mb-8"> {isDe ? 'Lösungen' : 'Solutions'} </div> <h3 className="text-2xl md:text-4xl font-bold text-white mb-8 leading-tight"> {isDe ? 'Bereit für die' : 'Ready for the'} - <span className="text-accent block">{isDe ? 'Energiewende?' : 'Energy Transition?'}</span> + <span className="text-primary-light block">{isDe ? 'Energiewende?' : 'Energy Transition?'}</span> </h3> <p className="text-xl text-white/90 mb-10 leading-relaxed max-w-2xl"> @@ -46,9 +46,9 @@ export default function PowerCTA({ locale }: PowerCTAProps) { : 'Certified quality according to EU standards', ].map((item, i) => ( <div key={i} className="flex items-center gap-4 text-white/90"> - <div className="w-6 h-6 rounded-full bg-accent/20 flex items-center justify-center flex-shrink-0"> + <div className="w-6 h-6 rounded-full bg-primary-light/20 flex items-center justify-center flex-shrink-0"> <svg - className="w-3 h-3 text-accent" + className="w-3 h-3 text-primary-light" fill="none" stroke="currentColor" viewBox="0 0 24 24" diff --git a/components/layout/Footer.tsx b/components/layout/Footer.tsx index 7e70fc2dc..757559deb 100644 --- a/components/layout/Footer.tsx +++ b/components/layout/Footer.tsx @@ -40,7 +40,7 @@ export function Footer({ companyInfo }: FooterProps) { className="object-contain object-left transition-transform duration-500 group-hover/logo:scale-105 origin-left" /> </TransitionLink> - <p className="text-white/60 text-base leading-relaxed max-w-sm"> + <p className="text-neutral-400 text-base leading-relaxed max-w-sm"> {locale === 'de' ? 'Die Experten für Kabeltiefbau, Horizontalspülbohrungen und umfassende Infrastrukturprojekte. Qualität und Zuverlässigkeit aus Guben.' : 'Experts in cable construction, horizontal directional drilling, and comprehensive infrastructure projects. Quality and reliability from Guben.'} @@ -54,18 +54,18 @@ export function Footer({ companyInfo }: FooterProps) { <svg xmlns="http://www.w3.org/2000/svg" className="w-5 h-5 text-primary" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z" /><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 11a3 3 0 11-6 0 3 3 0 016 0z" /></svg> </div> <div> - <p className="text-xs text-white/40 uppercase tracking-wider mb-1 font-heading">{locale === 'de' ? 'Hauptsitz' : 'Headquarters'}</p> - <p className="whitespace-pre-line font-medium text-white/90">{companyInfo.address}</p> + <p className="text-xs text-neutral-400 uppercase tracking-wider mb-1 font-heading">{locale === 'de' ? 'Hauptsitz' : 'Headquarters'}</p> + <p className="whitespace-pre-line font-medium text-neutral-200">{companyInfo.address}</p> </div> </div> <div className="grid grid-cols-2 gap-3 md:gap-4"> <a href={`mailto:${companyInfo.contactEmail}`} className="flex flex-col gap-2 p-4 rounded-2xl bg-white/[0.03] border border-white/[0.05] hover:bg-white/[0.08] hover:border-primary/30 transition-all group/contact cursor-pointer"> - <p className="text-xs text-white/40 uppercase tracking-wider font-heading">E-Mail</p> - <p className="font-medium text-white/90 group-hover/contact:text-primary transition-colors truncate">{companyInfo.contactEmail}</p> + <p className="text-xs text-neutral-400 uppercase tracking-wider font-heading">E-Mail</p> + <p className="font-medium text-neutral-200 group-hover/contact:text-primary transition-colors truncate">{companyInfo.contactEmail}</p> </a> <a href={`tel:${companyInfo.contactPhone.replace(/\s+/g, '')}`} className="flex flex-col gap-2 p-4 rounded-2xl bg-white/[0.03] border border-white/[0.05] hover:bg-white/[0.08] hover:border-primary/30 transition-all group/contact cursor-pointer"> - <p className="text-xs text-white/40 uppercase tracking-wider font-heading">{locale === 'de' ? 'Telefon' : 'Phone'}</p> - <p className="font-medium text-white/90 group-hover/contact:text-primary transition-colors truncate">{companyInfo.contactPhone}</p> + <p className="text-xs text-neutral-400 uppercase tracking-wider font-heading">{locale === 'de' ? 'Telefon' : 'Phone'}</p> + <p className="font-medium text-neutral-200 group-hover/contact:text-primary transition-colors truncate">{companyInfo.contactPhone}</p> </a> </div> </div> @@ -91,7 +91,7 @@ export function Footer({ companyInfo }: FooterProps) { { label: locale === 'de' ? 'Kontakt' : 'Contact', href: `/${locale}/${locale === 'de' ? 'kontakt' : 'contact'}` }, ].map((link) => ( <li key={link.href}> - <TransitionLink href={link.href} className="group/link flex items-center text-white/60 hover:text-white transition-colors py-1 cursor-pointer"> + <TransitionLink href={link.href} className="group/link flex items-center text-neutral-400 hover:text-white transition-colors py-1 cursor-pointer"> <span className="w-0 h-px bg-primary mr-0 group-hover/link:w-4 group-hover/link:mr-3 transition-all duration-300" /> <span className="font-medium">{link.label}</span> </TransitionLink> @@ -114,8 +114,8 @@ export function Footer({ companyInfo }: FooterProps) { { label: locale === 'de' ? 'AGB' : 'Terms', href: `/${locale}/${locale === 'de' ? 'agb' : 'terms'}` }, ].map((link) => ( <li key={link.href}> - <TransitionLink href={link.href} className="group/link flex items-center text-white/50 hover:text-white transition-colors py-1 cursor-pointer"> - <span className="w-0 h-px bg-white/30 mr-0 group-hover/link:w-3 group-hover/link:mr-3 transition-all duration-300" /> + <TransitionLink href={link.href} className="group/link flex items-center text-neutral-400 hover:text-white transition-colors py-1 cursor-pointer"> + <span className="w-0 h-px bg-neutral-500 mr-0 group-hover/link:w-3 group-hover/link:mr-3 transition-all duration-300" /> <span className="font-medium">{link.label}</span> </TransitionLink> </li> @@ -133,12 +133,12 @@ export function Footer({ companyInfo }: FooterProps) { <div className="container relative z-10"> <div className="flex flex-col md:flex-row justify-between items-center gap-4 md:gap-6 py-4 px-5 md:py-6 md:px-8 rounded-2xl bg-white/[0.02] border border-white/5 backdrop-blur-md text-center md:text-left"> <div className="flex flex-col md:flex-row items-center gap-4 md:gap-6 h-full"> - <p className="text-white/50 text-xs font-medium m-0">© {new Date().getFullYear()} E-TIB GmbH. {locale === 'de' ? 'Alle Rechte vorbehalten.' : 'All rights reserved.'}</p> + <p className="text-neutral-400 text-xs font-medium m-0">© {new Date().getFullYear()} E-TIB GmbH. {locale === 'de' ? 'Alle Rechte vorbehalten.' : 'All rights reserved.'}</p> - <div className="hidden md:block w-px h-3 bg-white/10" /> + <div className="hidden md:block w-px h-3 bg-neutral-800" /> - <div className="flex items-center gap-3 text-white/30 text-xs"> - <a href="https://mintel.me" target="_blank" rel="noopener noreferrer" className="hover:text-white/60 transition-colors flex items-center gap-2"> + <div className="flex items-center gap-3 text-neutral-400 text-xs"> + <a href="https://mintel.me" target="_blank" rel="noopener noreferrer" className="hover:text-neutral-200 transition-colors flex items-center gap-2"> <span>Designed & Engineered by Mintel</span> </a> {process.env.NEXT_PUBLIC_APP_VERSION && ( @@ -163,11 +163,11 @@ export function Footer({ companyInfo }: FooterProps) { </div> {/* Quality Badges */} - <div className="mt-4 md:mt-6 flex flex-wrap justify-center gap-x-4 gap-y-3 md:gap-x-8 md:gap-y-4 text-white/30 text-[10px] md:text-xs font-medium uppercase tracking-wider px-2"> - <div className="flex items-center gap-2"><ShieldCheck className="w-4 h-4 text-white/40" /><span>SSL Secured</span></div> - <div className="flex items-center gap-2"><Leaf className="w-4 h-4 text-primary/60" /><span>Green Hosting</span></div> - <div className="flex items-center gap-2"><Lock className="w-4 h-4 text-white/40" /><span>DSGVO Compliant</span></div> - <div className="flex items-center gap-2"><Zap className="w-4 h-4 text-white/40" /><span>High Performance</span></div> + <div className="mt-4 md:mt-6 flex flex-wrap justify-center gap-x-4 gap-y-3 md:gap-x-8 md:gap-y-4 text-neutral-400 text-[10px] md:text-xs font-medium uppercase tracking-wider px-2"> + <div className="flex items-center gap-2"><ShieldCheck className="w-4 h-4 text-neutral-400" /><span>SSL Secured</span></div> + <div className="flex items-center gap-2"><Leaf className="w-4 h-4 text-primary" /><span>Green Hosting</span></div> + <div className="flex items-center gap-2"><Lock className="w-4 h-4 text-neutral-400" /><span>DSGVO Compliant</span></div> + <div className="flex items-center gap-2"><Zap className="w-4 h-4 text-neutral-400" /><span>High Performance</span></div> </div> </div> </footer> diff --git a/components/layout/LanguageSwitcher.tsx b/components/layout/LanguageSwitcher.tsx index 04ce34cb7..3f702342a 100644 --- a/components/layout/LanguageSwitcher.tsx +++ b/components/layout/LanguageSwitcher.tsx @@ -73,7 +73,7 @@ export function LanguageSwitcher({ mobile = false, isSolidMode = false }: Langua } else { linkClass = isSolidMode ? 'text-text-secondary hover:text-primary' - : 'text-white/70 hover:text-white'; + : 'text-white/90 hover:text-white'; } const currentLocObj = locales.find(l => l.code === currentLocale) || locales[0]; diff --git a/styles/globals.css b/styles/globals.css index 56bd8f4dc..25188759a 100644 --- a/styles/globals.css +++ b/styles/globals.css @@ -200,6 +200,13 @@ line-height: 1.7; } + *:focus-visible { + outline: 3px solid var(--color-primary); + outline-offset: 3px; + border-radius: 2px; + } + + h1, h2, h3, @@ -241,7 +248,7 @@ /* Link styles */ a { - @apply no-underline transition-all duration-200; + @apply transition-all duration-200; } /* List styles */