Homepage V1
This commit is contained in:
BIN
src/assets/icon.png
Normal file
BIN
src/assets/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 40 KiB |
BIN
src/assets/logo.png
Normal file
BIN
src/assets/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 96 KiB |
BIN
src/assets/test_logo.png
Normal file
BIN
src/assets/test_logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 99 KiB |
59
src/components/About.tsx
Normal file
59
src/components/About.tsx
Normal file
@@ -0,0 +1,59 @@
|
||||
import { getLanguage, translations } from '../i18n';
|
||||
|
||||
function About() {
|
||||
const lang = getLanguage();
|
||||
const t = translations[lang].about;
|
||||
|
||||
return (
|
||||
<section id="about" className="section">
|
||||
<div className="container" style={{ textAlign: 'center' }}>
|
||||
<h2>{t.title}</h2>
|
||||
<p style={{ fontSize: '1.2rem', maxWidth: '900px', margin: '2rem auto', color: 'var(--text-secondary)' }}>
|
||||
{t.description}
|
||||
</p>
|
||||
<div className="about-grid">
|
||||
<div>
|
||||
<h3 style={{ marginBottom: '1rem' }}>{t.expertise.title}</h3>
|
||||
<p>{t.expertise.text}</p>
|
||||
</div>
|
||||
<div>
|
||||
<h3 style={{ marginBottom: '1rem' }}>{t.security.title}</h3>
|
||||
<p>{t.security.text}</p>
|
||||
</div>
|
||||
<div>
|
||||
<h3 style={{ marginBottom: '1rem' }}>{t.sovereignty.title}</h3>
|
||||
<p>{t.sovereignty.text}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style={{ marginTop: '8rem' }}>
|
||||
<h2 style={{ marginBottom: '4rem' }}>{t.team.title}</h2>
|
||||
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(280px, 1fr))', gap: '4rem' }}>
|
||||
{[t.team.member1, t.team.member2, t.team.member3].map((member, i) => (
|
||||
<div key={i} style={{ display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
|
||||
<div style={{
|
||||
width: '180px',
|
||||
height: '180px',
|
||||
borderRadius: '50%',
|
||||
backgroundColor: 'var(--bg-light)',
|
||||
marginBottom: '1.5rem',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
border: '1px solid var(--border-color)'
|
||||
}}>
|
||||
<span className="material-icons" style={{ fontSize: '4rem', opacity: 0.2 }}>person</span>
|
||||
</div>
|
||||
<h3 style={{ marginBottom: '0.5rem', fontSize: '1.3rem' }}>{member.name}</h3>
|
||||
<p style={{ color: 'var(--primary-color)', fontWeight: 'bold', marginBottom: '1rem', fontSize: '0.9rem', textTransform: 'uppercase' }}>{member.role}</p>
|
||||
<p style={{ fontSize: '0.95rem', maxWidth: '300px' }}>{member.bio}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
export default About;
|
||||
35
src/components/Contact.tsx
Normal file
35
src/components/Contact.tsx
Normal file
@@ -0,0 +1,35 @@
|
||||
import { getLanguage, translations } from '../i18n';
|
||||
|
||||
function Contact() {
|
||||
const lang = getLanguage();
|
||||
const t = translations[lang].contact;
|
||||
|
||||
return (
|
||||
<section id="contact" className="section">
|
||||
<div className="container">
|
||||
<h2 style={{ textAlign: 'center' }}>{t.title}</h2>
|
||||
<p style={{ textAlign: 'center', marginBottom: '3rem', maxWidth: '600px', margin: '1rem auto 3rem' }}>
|
||||
{t.subtitle}
|
||||
</p>
|
||||
|
||||
<form className="contact-form">
|
||||
<div className="form-group">
|
||||
<input type="text" placeholder={t.name} className="form-input" required />
|
||||
</div>
|
||||
<div className="form-group">
|
||||
<input type="email" placeholder={t.email} className="form-input" required />
|
||||
</div>
|
||||
<div className="form-group">
|
||||
<input type="text" placeholder={t.company} className="form-input" />
|
||||
</div>
|
||||
<div className="form-group">
|
||||
<textarea placeholder={t.message} rows={5} className="form-input" required></textarea>
|
||||
</div>
|
||||
<button type="submit" className="submit-btn">{t.submit}</button>
|
||||
</form>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
export default Contact;
|
||||
25
src/components/Footer.tsx
Normal file
25
src/components/Footer.tsx
Normal file
@@ -0,0 +1,25 @@
|
||||
import { getLanguage, translations } from '../i18n';
|
||||
|
||||
function Footer() {
|
||||
const lang = getLanguage();
|
||||
const t = translations[lang].footer;
|
||||
|
||||
return (
|
||||
<footer className="footer">
|
||||
<div className="container">
|
||||
<p>© {new Date().getFullYear()} Euastra GmbH. {t.rights}</p>
|
||||
<p style={{ marginTop: '0.5rem', opacity: 0.8, fontSize: '0.9rem' }}>
|
||||
{t.tagline}
|
||||
</p>
|
||||
<div className="footer-links">
|
||||
<a href="/impressum.html" className="footer-link">{t.imprint}</a>
|
||||
<a href="/datenschutz.html" className="footer-link">{t.privacy}</a>
|
||||
<a href="/about.html" className="footer-link">{translations[lang].nav.about}</a>
|
||||
<a href="/contact.html" className="footer-link">{translations[lang].nav.contact}</a>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
);
|
||||
}
|
||||
|
||||
export default Footer;
|
||||
52
src/components/Header.tsx
Normal file
52
src/components/Header.tsx
Normal file
@@ -0,0 +1,52 @@
|
||||
import logo from '../assets/logo.png';
|
||||
import { getLanguage, setLanguage, translations } from '../i18n';
|
||||
|
||||
function Header() {
|
||||
const lang = getLanguage();
|
||||
const t = translations[lang];
|
||||
|
||||
return (
|
||||
<header className="header">
|
||||
<a href="/" className="logo-link">
|
||||
<img src={logo} alt="Euastra Logo" className="logo-img" />
|
||||
</a>
|
||||
<nav>
|
||||
<ul className="nav-list">
|
||||
<li><a href="/about.html" className="nav-link">{t.nav.about}</a></li>
|
||||
<li className="nav-item-dropdown">
|
||||
<a href="/products.html" className="nav-link nav-link-with-icon">
|
||||
{t.nav.products} <span className="material-icons" style={{ fontSize: '1.2rem' }}>expand_more</span>
|
||||
</a>
|
||||
<div className="dropdown-menu">
|
||||
<a href="/boss4j.html" className="dropdown-link">
|
||||
<span className="material-icons">layers</span>
|
||||
{t.products.boss4j.title}
|
||||
</a>
|
||||
<a href="/zertifikatsverwaltung.html" className="dropdown-link">
|
||||
<span className="material-icons">verified_user</span>
|
||||
{t.products.cert.title}
|
||||
</a>
|
||||
<a href="/beratung.html" className="dropdown-link">
|
||||
<span className="material-icons">engineering</span>
|
||||
{t.products.consulting.title}
|
||||
</a>
|
||||
</div>
|
||||
</li>
|
||||
<li><a href="/contact.html" className="nav-link">{t.nav.contact}</a></li>
|
||||
<li className="lang-switch">
|
||||
<button
|
||||
className={`lang-btn ${lang === 'de' ? 'active' : ''}`}
|
||||
onClick={() => setLanguage('de')}
|
||||
>DE</button>
|
||||
<button
|
||||
className={`lang-btn ${lang === 'en' ? 'active' : ''}`}
|
||||
onClick={() => setLanguage('en')}
|
||||
>EN</button>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</header>
|
||||
);
|
||||
}
|
||||
|
||||
export default Header;
|
||||
21
src/components/Hero.tsx
Normal file
21
src/components/Hero.tsx
Normal file
@@ -0,0 +1,21 @@
|
||||
import { getLanguage, translations } from '../i18n';
|
||||
|
||||
function Hero() {
|
||||
const lang = getLanguage();
|
||||
const t = translations[lang];
|
||||
|
||||
return (
|
||||
<section className="hero">
|
||||
<div className="container">
|
||||
<h1>{t.hero.title}</h1>
|
||||
<p>{t.hero.subtitle}</p>
|
||||
<a href="/products.html" className="hero-btn">{t.hero.cta}</a>
|
||||
<div className="vienna-signet">
|
||||
{t.hero.viennaGimmick}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
export default Hero;
|
||||
79
src/components/ProductPage.tsx
Normal file
79
src/components/ProductPage.tsx
Normal file
@@ -0,0 +1,79 @@
|
||||
import Header from './Header';
|
||||
import Footer from './Footer';
|
||||
import { getLanguage, translations } from '../i18n';
|
||||
|
||||
interface ProductPageProps {
|
||||
title: string;
|
||||
description: string;
|
||||
icon: string;
|
||||
trademark?: string;
|
||||
children?: React.ReactNode;
|
||||
}
|
||||
|
||||
function ProductPage({ title, description, icon, trademark, children }: ProductPageProps) {
|
||||
const lang = getLanguage();
|
||||
const t = translations[lang].common;
|
||||
|
||||
return (
|
||||
<>
|
||||
<Header />
|
||||
<main>
|
||||
<div className="hero" style={{ padding: '6rem 0' }}>
|
||||
<div className="container">
|
||||
<span className="material-icons" style={{ fontSize: '4rem', marginBottom: '1.5rem', color: 'var(--accent-color)' }}>{icon}</span>
|
||||
<h1>{title}</h1>
|
||||
<p style={{ maxWidth: '800px', margin: '0 auto' }}>{description}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<section className="section">
|
||||
<div className="container">
|
||||
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(300px, 1fr))', gap: '4rem', alignItems: 'center' }}>
|
||||
<div>
|
||||
<h2>{t.detailsTitle}</h2>
|
||||
<p>{t.detailsText}</p>
|
||||
<ul style={{ listStyle: 'none', marginTop: '2rem' }}>
|
||||
<li style={{ display: 'flex', alignItems: 'center', gap: '1rem', marginBottom: '1rem' }}>
|
||||
<span className="material-icons" style={{ color: 'var(--accent-color)' }}>check_circle</span>
|
||||
{t.featureSecurity}
|
||||
</li>
|
||||
<li style={{ display: 'flex', alignItems: 'center', gap: '1rem', marginBottom: '1rem' }}>
|
||||
<span className="material-icons" style={{ color: 'var(--accent-color)' }}>check_circle</span>
|
||||
{t.featureIntegration}
|
||||
</li>
|
||||
<li style={{ display: 'flex', alignItems: 'center', gap: '1rem', marginBottom: '1rem' }}>
|
||||
<span className="material-icons" style={{ color: 'var(--accent-color)' }}>check_circle</span>
|
||||
{t.featureSupport}
|
||||
</li>
|
||||
</ul>
|
||||
{trademark && (
|
||||
<p style={{ fontSize: '0.8rem', fontStyle: 'italic', marginTop: '2rem', opacity: 0.7 }}>
|
||||
{trademark}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
<div style={{
|
||||
backgroundColor: 'var(--bg-light)',
|
||||
height: '400px',
|
||||
borderRadius: '8px',
|
||||
border: '1px solid var(--border-color)',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
flexDirection: 'column',
|
||||
color: 'var(--text-secondary)'
|
||||
}}>
|
||||
<span className="material-icons" style={{ fontSize: '5rem', marginBottom: '1rem', opacity: 0.3 }}>image</span>
|
||||
<p>{t.screenshotPlaceholder}</p>
|
||||
</div>
|
||||
</div>
|
||||
{children}
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
<Footer />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default ProductPage;
|
||||
57
src/components/Products.tsx
Normal file
57
src/components/Products.tsx
Normal file
@@ -0,0 +1,57 @@
|
||||
import { getLanguage, translations } from '../i18n';
|
||||
|
||||
function Products() {
|
||||
const lang = getLanguage();
|
||||
const t = translations[lang].products;
|
||||
|
||||
return (
|
||||
<section id="products" className="section section-alt">
|
||||
<div className="container">
|
||||
<h2 style={{ textAlign: 'center' }}>{t.title}</h2>
|
||||
<p style={{ textAlign: 'center', maxWidth: '800px', margin: '1rem auto 4rem', fontSize: '1.1rem' }}>
|
||||
{t.subtitle}
|
||||
</p>
|
||||
|
||||
<div className="products-grid">
|
||||
<div className="product-card">
|
||||
<div className="product-icon">
|
||||
<span className="material-icons" style={{ fontSize: '2rem' }}>layers</span>
|
||||
</div>
|
||||
<h3>{t.boss4j.title}</h3>
|
||||
<p>{t.boss4j.text}</p>
|
||||
<p style={{ fontSize: '0.8rem', fontStyle: 'italic', marginTop: '1rem', opacity: 0.8 }}>
|
||||
{t.boss4j.trademark}
|
||||
</p>
|
||||
<a href="/boss4j.html" style={{ marginTop: 'auto', fontWeight: 'bold', display: 'flex', alignItems: 'center', gap: '0.5rem' }}>
|
||||
{translations[lang].common.moreInfo} <span className="material-icons">arrow_forward</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div className="product-card">
|
||||
<div className="product-icon">
|
||||
<span className="material-icons" style={{ fontSize: '2rem' }}>verified_user</span>
|
||||
</div>
|
||||
<h3>{t.cert.title}</h3>
|
||||
<p>{t.cert.text}</p>
|
||||
<a href="/zertifikatsverwaltung.html" style={{ marginTop: 'auto', fontWeight: 'bold', display: 'flex', alignItems: 'center', gap: '0.5rem' }}>
|
||||
{translations[lang].common.moreInfo} <span className="material-icons">arrow_forward</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div className="product-card">
|
||||
<div className="product-icon">
|
||||
<span className="material-icons" style={{ fontSize: '2rem' }}>engineering</span>
|
||||
</div>
|
||||
<h3>{t.consulting.title}</h3>
|
||||
<p>{t.consulting.text}</p>
|
||||
<a href="/beratung.html" style={{ marginTop: 'auto', fontWeight: 'bold', display: 'flex', alignItems: 'center', gap: '0.5rem' }}>
|
||||
{translations[lang].common.moreInfo} <span className="material-icons">arrow_forward</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
export default Products;
|
||||
288
src/i18n.ts
Normal file
288
src/i18n.ts
Normal file
@@ -0,0 +1,288 @@
|
||||
|
||||
type Language = 'de' | 'en';
|
||||
|
||||
export const translations = {
|
||||
de: {
|
||||
nav: {
|
||||
about: 'Über uns',
|
||||
products: 'Produkte',
|
||||
contact: 'Kontakt',
|
||||
},
|
||||
hero: {
|
||||
title: 'Enterprise Software. Digitale Souveränität.',
|
||||
subtitle: 'Wir liefern die Werkzeuge für die IT-Infrastruktur von morgen. Sicher, leistungsstark und zu 100% unter Ihrer Kontrolle.',
|
||||
cta: 'Lösungen entdecken',
|
||||
viennaGimmick: 'Enterprise Technologie & Lösungen\naus Wien',
|
||||
},
|
||||
about: {
|
||||
title: 'Über Euastra',
|
||||
description: 'Bei der Euastra GmbH widmen wir uns der Bereitstellung leistungsstarker, sicherer und datensouveräner Softwarelösungen für das moderne europäische Unternehmen. In einer Zeit der digitalen Transformation ist Vertrauen in die eigene IT-Infrastruktur unser höchstes Gut.',
|
||||
expertise: {
|
||||
title: 'Expertise',
|
||||
text: 'Tiefes technisches Verständnis für Middleware und komplexe Enterprise-Umgebungen.',
|
||||
},
|
||||
security: {
|
||||
title: 'Sicherheit',
|
||||
text: 'Sicherung digitaler Identitäten und Zertifikate nach höchsten Standards.',
|
||||
},
|
||||
sovereignty: {
|
||||
title: 'Souveränität',
|
||||
text: 'Softwarelösungen, die Ihnen die volle Kontrolle über Ihre Daten und Infrastruktur lassen.',
|
||||
},
|
||||
team: {
|
||||
title: 'Ihre Ansprechpartner bei Euastra',
|
||||
member1: {
|
||||
name: 'Ing. Dionis Ramadani, MSc',
|
||||
role: 'Geschäftsführung & Strategie',
|
||||
bio: 'Experte für Enterprise-Softwareentwicklung und komplexe IT-Architekturen.',
|
||||
},
|
||||
member2: {
|
||||
name: 'Mohammed Laktaoui, BSc',
|
||||
role: 'Geschäftsführung & Software-Engineering',
|
||||
bio: 'Spezialist für Java-Middleware und die Entwicklung hochverfügbarer Cloud-Infrastrukturen.',
|
||||
},
|
||||
member3: {
|
||||
name: 'Felix Oskar Lanz, MSc',
|
||||
role: 'IT-Consulting & Automatisierung',
|
||||
bio: 'Experte für DevOps-Prozesse und die Optimierung von Enterprise-Workflows.',
|
||||
},
|
||||
},
|
||||
},
|
||||
products: {
|
||||
title: 'Unsere Produkte',
|
||||
subtitle: 'Wir entwickeln spezialisierte Software für höchste Ansprüche an Sicherheit, Zuverlässigkeit und Effizienz in Enterprise-Umgebungen.',
|
||||
boss4j: {
|
||||
title: 'Boss4J',
|
||||
text: 'Die erstklassige Orchestrierungs-Suite für JBoss® und WildFly® Anwendungsserver. Vereinfachen Sie die Verwaltung komplexer Cluster und automatisieren Sie Deployments.',
|
||||
trademark: 'JBoss® und WildFly® sind eingetragene Marken von Red Hat, Inc.',
|
||||
},
|
||||
cert: {
|
||||
title: 'Zertifikatsverwaltung',
|
||||
text: 'Automatisierte Suite für das Lebenszyklusmanagement digitaler Zertifikate. Behalten Sie die Kontrolle über Ihre Java-Keystores und SSL/TLS-Zertifikate.',
|
||||
},
|
||||
consulting: {
|
||||
title: 'IT-Beratung',
|
||||
text: 'Ganzheitliche Beratung zur Optimierung Ihrer IT-Prozesse. Unser Fokus liegt auf Individualsoftware-Entwicklung, Infrastruktur-Automatisierung sowie dem Customizing bestehender Systeme für maximale Effizienz.',
|
||||
},
|
||||
},
|
||||
common: {
|
||||
detailsTitle: 'Details & Features',
|
||||
detailsText: 'Hier finden Sie detaillierte Informationen zu den Funktionen und Vorteilen unserer Lösung. Wir unterstützen Sie bei der Implementierung und dem Betrieb in Ihrer spezifischen Enterprise-Umgebung.',
|
||||
featureSecurity: 'Höchste Sicherheitsstandards',
|
||||
featureIntegration: 'Nahtlose Integration',
|
||||
featureSupport: 'Enterprise Support',
|
||||
screenshotPlaceholder: 'Screenshot Platzhalter',
|
||||
moreInfo: 'Mehr erfahren',
|
||||
},
|
||||
contact: {
|
||||
title: 'Kontaktieren Sie uns',
|
||||
subtitle: 'Interessieren Sie sich für unsere Lösungen? Wir freuen uns auf Ihre Nachricht.',
|
||||
name: 'Vollständiger Name',
|
||||
email: 'Geschäftliche E-Mail',
|
||||
company: 'Unternehmen',
|
||||
message: 'Wie können wir Ihnen helfen?',
|
||||
submit: 'Anfrage senden',
|
||||
},
|
||||
impressum: {
|
||||
title: 'Impressum',
|
||||
disclosure: 'Offenlegungspflicht gemäß § 25 Mediengesetz und Informationspflichten gemäß § 5 E-Commerce-Gesetz (ECG) und § 14 Unternehmensgesetzbuch (UGB):',
|
||||
address: {
|
||||
street: 'Seitenstettengasse 5/37',
|
||||
city: '1010 Wien, Österreich',
|
||||
},
|
||||
purpose: {
|
||||
label: 'Unternehmensgegenstand:',
|
||||
value: 'Die Entwicklung, die Lizenzierung und der Vertrieb von Software sowie die Einbringung von IT-Beratungsdienstleistungen.',
|
||||
},
|
||||
registry: {
|
||||
label: 'Firmenbuchnummer:',
|
||||
value: 'FN [noch offen]',
|
||||
},
|
||||
court: {
|
||||
label: 'Firmenbuchgericht:',
|
||||
value: 'Handelsgericht Wien',
|
||||
},
|
||||
uid: {
|
||||
label: 'UID-Nummer:',
|
||||
value: '[beantragt]',
|
||||
},
|
||||
contact: {
|
||||
label: 'Kontakt:',
|
||||
email: 'info@euastra.at',
|
||||
phone: '+43 1 2345678',
|
||||
},
|
||||
managingDirector: {
|
||||
label: 'Geschäftsführer:',
|
||||
name: 'Ing. Dionis Ramadani, MSc; Mohammed Laktaoui, BSc',
|
||||
}
|
||||
},
|
||||
privacy: {
|
||||
title: 'Datenschutzerklärung',
|
||||
intro: 'Der Schutz Ihrer persönlichen Daten ist uns ein besonderes Anliegen. Wir verarbeiten Ihre Daten daher ausschließlich auf Grundlage der gesetzlichen Bestimmungen (DSGVO, TKG 2003).',
|
||||
contact: {
|
||||
title: 'Kontakt mit uns',
|
||||
text: 'Wenn Sie per Formular auf der Website oder per E-Mail Kontakt mit uns aufnehmen, werden Ihre angegebenen Daten zwecks Bearbeitung der Anfrage und für den Fall von Anschlussfragen sechs Monate bei uns gespeichert. Diese Daten geben wir nicht ohne Ihre Einwilligung weiter.',
|
||||
},
|
||||
rights: {
|
||||
title: 'Ihre Rechte',
|
||||
text: 'Ihnen stehen grundsätzlich die Rechte auf Auskunft, Berichtigung, Löschung, Einschränkung, Datenübertragbarkeit, Widerruf und Widerspruch zu. Wenn Sie glauben, dass die Verarbeitung Ihrer Daten gegen das Datenschutzrecht verstößt oder Ihre datenschutzrechtlichen Ansprüche sonst in einer Weise verletzt worden sind, können Sie sich bei der Aufsichtsbehörde beschweren. In Österreich ist dies die Datenschutzbehörde.',
|
||||
},
|
||||
controller: {
|
||||
title: 'Verantwortliche Stelle',
|
||||
}
|
||||
},
|
||||
footer: {
|
||||
rights: 'Alle Rechte vorbehalten.',
|
||||
tagline: 'Professionelle Softwarelösungen für komplexe IT-Infrastrukturen.',
|
||||
imprint: 'Impressum',
|
||||
privacy: 'Datenschutz',
|
||||
}
|
||||
},
|
||||
en: {
|
||||
nav: {
|
||||
about: 'About Us',
|
||||
products: 'Products',
|
||||
contact: 'Contact',
|
||||
},
|
||||
hero: {
|
||||
title: "Enterprise Software. Digital Sovereignty.",
|
||||
subtitle: "Delivering the tools for tomorrow's IT infrastructure. Secure, powerful, and 100% under your control.",
|
||||
cta: "Explore Solutions",
|
||||
viennaGimmick: 'Enterprise Technology & Solutions\nfrom Vienna',
|
||||
},
|
||||
about: {
|
||||
title: 'About Euastra',
|
||||
description: 'At Euastra GmbH, we are dedicated to providing high-performance, secure, and data-sovereign software solutions for the modern European enterprise. In an age of digital transformation, trust in your own IT infrastructure is our greatest asset.',
|
||||
expertise: {
|
||||
title: 'Expertise',
|
||||
text: 'Deep technical understanding of middleware and complex enterprise environments.',
|
||||
},
|
||||
security: {
|
||||
title: 'Security',
|
||||
text: 'Securing digital identities and certificates to the highest standards.',
|
||||
},
|
||||
sovereignty: {
|
||||
title: 'Sovereignty',
|
||||
text: 'Software solutions that give you full control over your data and infrastructure.',
|
||||
},
|
||||
team: {
|
||||
title: 'Your Contacts at Euastra',
|
||||
member1: {
|
||||
name: 'Ing. Dionis Ramadani, MSc',
|
||||
role: 'CEO & Strategy',
|
||||
bio: 'Expert for enterprise software development and complex IT architectures.',
|
||||
},
|
||||
member2: {
|
||||
name: 'Mohammed Laktaoui, BSc',
|
||||
role: 'CEO & Software Engineering',
|
||||
bio: 'Specialist for Java middleware and the development of high-availability cloud infrastructures.',
|
||||
},
|
||||
member3: {
|
||||
name: 'Felix Oskar Lanz, MSc',
|
||||
role: 'IT Consulting & Automation',
|
||||
bio: 'Expert for DevOps processes and optimization of enterprise workflows.',
|
||||
},
|
||||
},
|
||||
},
|
||||
products: {
|
||||
title: 'Our Products',
|
||||
subtitle: 'We develop specialized software for the highest demands on security, reliability, and efficiency in enterprise environments.',
|
||||
boss4j: {
|
||||
title: 'Boss4J',
|
||||
text: 'The premier orchestration suite for JBoss® and WildFly® application servers. Simplify management of complex clusters and automate deployments.',
|
||||
trademark: 'JBoss® and WildFly® are registered trademarks of Red Hat, Inc.',
|
||||
},
|
||||
cert: {
|
||||
title: 'Certificate Management',
|
||||
text: 'Automated suite for digital certificate lifecycle management. Stay in control of your Java keystores and SSL/TLS certificates.',
|
||||
},
|
||||
consulting: {
|
||||
title: 'IT Consulting',
|
||||
text: 'Holistic consulting to optimize your IT processes. Our focus is on individual software development, infrastructure automation, and customizing existing systems for maximum efficiency.',
|
||||
},
|
||||
},
|
||||
common: {
|
||||
detailsTitle: 'Details & Features',
|
||||
detailsText: 'Here you will find detailed information about the functions and benefits of our solution. We support you in the implementation and operation in your specific enterprise environment.',
|
||||
featureSecurity: 'Highest Security Standards',
|
||||
featureIntegration: 'Seamless Integration',
|
||||
featureSupport: 'Enterprise Support',
|
||||
screenshotPlaceholder: 'Screenshot Placeholder',
|
||||
moreInfo: 'Learn more',
|
||||
},
|
||||
contact: {
|
||||
title: 'Contact Us',
|
||||
subtitle: 'Interested in our solutions? We look forward to hearing from you.',
|
||||
name: 'Full Name',
|
||||
email: 'Business Email',
|
||||
company: 'Company',
|
||||
message: 'How can we help you?',
|
||||
submit: 'Send Inquiry',
|
||||
},
|
||||
impressum: {
|
||||
title: 'Legal Notice / Imprint',
|
||||
disclosure: 'Disclosure obligation according to § 25 Media Act and information obligations according to § 5 E-Commerce Act (ECG) and § 14 Commercial Code (UGB):',
|
||||
address: {
|
||||
street: 'Seitenstettengasse 5/37',
|
||||
city: '1010 Vienna, Austria',
|
||||
},
|
||||
purpose: {
|
||||
label: 'Business Purpose:',
|
||||
value: 'The development, licensing and distribution of software as well as the provision of IT consulting services.',
|
||||
},
|
||||
registry: {
|
||||
label: 'Commercial Register Number:',
|
||||
value: 'FN [pending]',
|
||||
},
|
||||
court: {
|
||||
label: 'Register Court:',
|
||||
value: 'Commercial Court Vienna',
|
||||
},
|
||||
uid: {
|
||||
label: 'VAT Number:',
|
||||
value: '[applied for]',
|
||||
},
|
||||
contact: {
|
||||
label: 'Contact:',
|
||||
email: 'info@euastra.at',
|
||||
phone: '+43 1 2345678',
|
||||
},
|
||||
managingDirector: {
|
||||
label: 'Managing Director:',
|
||||
name: 'Ing. Dionis Ramadani, MSc; Mohammed Laktaoui, BSc',
|
||||
}
|
||||
},
|
||||
privacy: {
|
||||
title: 'Privacy Policy',
|
||||
intro: 'The protection of your personal data is of particular concern to us. We therefore process your data exclusively on the basis of the legal provisions (GDPR, TKG 2003).',
|
||||
contact: {
|
||||
title: 'Contacting Us',
|
||||
text: 'If you contact us via the form on the website or by email, the data you provide will be stored by us for six months for the purpose of processing the inquiry and in case of follow-up questions. We do not pass on this data without your consent.',
|
||||
},
|
||||
rights: {
|
||||
title: 'Your Rights',
|
||||
text: 'In principle, you have the right to information, correction, deletion, restriction, data portability, revocation, and objection. If you believe that the processing of your data violates data protection law or your data protection claims have otherwise been violated in any way, you can complain to the supervisory authority. In Austria, this is the Data Protection Authority (Datenschutzbehörde).',
|
||||
},
|
||||
controller: {
|
||||
title: 'Data Controller',
|
||||
}
|
||||
},
|
||||
footer: {
|
||||
rights: 'All rights reserved.',
|
||||
tagline: 'Professional software solutions for complex IT infrastructures.',
|
||||
imprint: 'Imprint',
|
||||
privacy: 'Privacy Policy',
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const getLanguage = (): Language => {
|
||||
const saved = localStorage.getItem('lang');
|
||||
if (saved === 'de' || saved === 'en') return saved;
|
||||
return navigator.language.startsWith('de') ? 'de' : 'en';
|
||||
};
|
||||
|
||||
export const setLanguage = (lang: Language) => {
|
||||
localStorage.setItem('lang', lang);
|
||||
window.location.reload();
|
||||
};
|
||||
16
src/pages/about/main.tsx
Normal file
16
src/pages/about/main.tsx
Normal file
@@ -0,0 +1,16 @@
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom/client'
|
||||
import Header from '../../components/Header'
|
||||
import About from '../../components/About'
|
||||
import Footer from '../../components/Footer'
|
||||
import '../../style.css'
|
||||
|
||||
ReactDOM.createRoot(document.getElementById('root')!).render(
|
||||
<React.StrictMode>
|
||||
<Header />
|
||||
<main>
|
||||
<About />
|
||||
</main>
|
||||
<Footer />
|
||||
</React.StrictMode>,
|
||||
)
|
||||
24
src/pages/beratung/main.tsx
Normal file
24
src/pages/beratung/main.tsx
Normal file
@@ -0,0 +1,24 @@
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom/client'
|
||||
import ProductPage from '../../components/ProductPage'
|
||||
import '../../style.css'
|
||||
import { getLanguage, translations } from '../../i18n'
|
||||
|
||||
const Page = () => {
|
||||
const lang = getLanguage();
|
||||
const t = translations[lang].products.consulting;
|
||||
|
||||
return (
|
||||
<ProductPage
|
||||
title={t.title}
|
||||
description={t.text}
|
||||
icon="engineering"
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
ReactDOM.createRoot(document.getElementById('root')!).render(
|
||||
<React.StrictMode>
|
||||
<Page />
|
||||
</React.StrictMode>,
|
||||
)
|
||||
25
src/pages/boss4j/main.tsx
Normal file
25
src/pages/boss4j/main.tsx
Normal file
@@ -0,0 +1,25 @@
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom/client'
|
||||
import ProductPage from '../../components/ProductPage'
|
||||
import '../../style.css'
|
||||
import { getLanguage, translations } from '../../i18n'
|
||||
|
||||
const Page = () => {
|
||||
const lang = getLanguage();
|
||||
const t = translations[lang].products.boss4j;
|
||||
|
||||
return (
|
||||
<ProductPage
|
||||
title={t.title}
|
||||
description={t.text}
|
||||
icon="layers"
|
||||
trademark={t.trademark}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
ReactDOM.createRoot(document.getElementById('root')!).render(
|
||||
<React.StrictMode>
|
||||
<Page />
|
||||
</React.StrictMode>,
|
||||
)
|
||||
16
src/pages/contact/main.tsx
Normal file
16
src/pages/contact/main.tsx
Normal file
@@ -0,0 +1,16 @@
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom/client'
|
||||
import Header from '../../components/Header'
|
||||
import Contact from '../../components/Contact'
|
||||
import Footer from '../../components/Footer'
|
||||
import '../../style.css'
|
||||
|
||||
ReactDOM.createRoot(document.getElementById('root')!).render(
|
||||
<React.StrictMode>
|
||||
<Header />
|
||||
<main>
|
||||
<Contact />
|
||||
</main>
|
||||
<Footer />
|
||||
</React.StrictMode>,
|
||||
)
|
||||
40
src/pages/datenschutz/main.tsx
Normal file
40
src/pages/datenschutz/main.tsx
Normal file
@@ -0,0 +1,40 @@
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom/client'
|
||||
import Header from '../../components/Header'
|
||||
import Footer from '../../components/Footer'
|
||||
import '../../style.css'
|
||||
import { getLanguage, translations } from '../../i18n'
|
||||
|
||||
const Datenschutz = () => {
|
||||
const lang = getLanguage();
|
||||
const t = translations[lang].privacy;
|
||||
const imp = translations[lang].impressum;
|
||||
|
||||
return (
|
||||
<main className="section container legal-page">
|
||||
<h2>{t.title}</h2>
|
||||
<p>{t.intro}</p>
|
||||
|
||||
<h3>{t.contact.title}</h3>
|
||||
<p>{t.contact.text}</p>
|
||||
|
||||
<h3>{t.rights.title}</h3>
|
||||
<p>{t.rights.text}</p>
|
||||
|
||||
<h3>{t.controller.title}</h3>
|
||||
<p>
|
||||
Euastra GmbH<br />
|
||||
{imp.address.street}<br />
|
||||
{imp.address.city}
|
||||
</p>
|
||||
</main>
|
||||
);
|
||||
};
|
||||
|
||||
ReactDOM.createRoot(document.getElementById('root')!).render(
|
||||
<React.StrictMode>
|
||||
<Header />
|
||||
<Datenschutz />
|
||||
<Footer />
|
||||
</React.StrictMode>,
|
||||
)
|
||||
16
src/pages/home/main.tsx
Normal file
16
src/pages/home/main.tsx
Normal file
@@ -0,0 +1,16 @@
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom/client'
|
||||
import Header from '../../components/Header'
|
||||
import Hero from '../../components/Hero'
|
||||
import Footer from '../../components/Footer'
|
||||
import '../../style.css'
|
||||
|
||||
ReactDOM.createRoot(document.getElementById('root')!).render(
|
||||
<React.StrictMode>
|
||||
<Header />
|
||||
<main>
|
||||
<Hero />
|
||||
</main>
|
||||
<Footer />
|
||||
</React.StrictMode>,
|
||||
)
|
||||
45
src/pages/impressum/main.tsx
Normal file
45
src/pages/impressum/main.tsx
Normal file
@@ -0,0 +1,45 @@
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom/client'
|
||||
import Header from '../../components/Header'
|
||||
import Footer from '../../components/Footer'
|
||||
import '../../style.css'
|
||||
import { getLanguage, translations } from '../../i18n'
|
||||
|
||||
const Impressum = () => {
|
||||
const lang = getLanguage();
|
||||
const t = translations[lang].impressum;
|
||||
|
||||
return (
|
||||
<main className="section container legal-page">
|
||||
<h2>{t.title}</h2>
|
||||
<p>{t.disclosure}</p>
|
||||
<p>
|
||||
<strong>Euastra GmbH</strong><br />
|
||||
{t.address.street}<br />
|
||||
{t.address.city}
|
||||
</p>
|
||||
<p>
|
||||
<strong>{t.purpose.label}</strong> <br></br>{t.purpose.value}<br />
|
||||
<strong>{t.registry.label}</strong> {t.registry.value}<br />
|
||||
<strong>{t.court.label}</strong> {t.court.value}<br />
|
||||
<strong>{t.uid.label}</strong> {t.uid.value}
|
||||
</p>
|
||||
<p>
|
||||
<strong>{t.contact.label}</strong><br />
|
||||
E-Mail: {t.contact.email}<br />
|
||||
Telefon: {t.contact.phone}
|
||||
</p>
|
||||
<p>
|
||||
<strong>{t.managingDirector.label}</strong> {t.managingDirector.name}
|
||||
</p>
|
||||
</main>
|
||||
);
|
||||
};
|
||||
|
||||
ReactDOM.createRoot(document.getElementById('root')!).render(
|
||||
<React.StrictMode>
|
||||
<Header />
|
||||
<Impressum />
|
||||
<Footer />
|
||||
</React.StrictMode>,
|
||||
)
|
||||
16
src/pages/products/main.tsx
Normal file
16
src/pages/products/main.tsx
Normal file
@@ -0,0 +1,16 @@
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom/client'
|
||||
import Header from '../../components/Header'
|
||||
import Products from '../../components/Products'
|
||||
import Footer from '../../components/Footer'
|
||||
import '../../style.css'
|
||||
|
||||
ReactDOM.createRoot(document.getElementById('root')!).render(
|
||||
<React.StrictMode>
|
||||
<Header />
|
||||
<main>
|
||||
<Products />
|
||||
</main>
|
||||
<Footer />
|
||||
</React.StrictMode>,
|
||||
)
|
||||
24
src/pages/zertifikatsverwaltung/main.tsx
Normal file
24
src/pages/zertifikatsverwaltung/main.tsx
Normal file
@@ -0,0 +1,24 @@
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom/client'
|
||||
import ProductPage from '../../components/ProductPage'
|
||||
import '../../style.css'
|
||||
import { getLanguage, translations } from '../../i18n'
|
||||
|
||||
const Page = () => {
|
||||
const lang = getLanguage();
|
||||
const t = translations[lang].products.cert;
|
||||
|
||||
return (
|
||||
<ProductPage
|
||||
title={t.title}
|
||||
description={t.text}
|
||||
icon="verified_user"
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
ReactDOM.createRoot(document.getElementById('root')!).render(
|
||||
<React.StrictMode>
|
||||
<Page />
|
||||
</React.StrictMode>,
|
||||
)
|
||||
537
src/style.css
Normal file
537
src/style.css
Normal file
@@ -0,0 +1,537 @@
|
||||
:root {
|
||||
--primary-color: #20446C; /* Blue from 'ASTRA' */
|
||||
--primary-dark: #0D2B4D; /* Dark Navy from 'EU' */
|
||||
--accent-color: #deaa0c; /* Gold from the Star */
|
||||
--text-primary: #1a1a1a;
|
||||
--text-secondary: #4a4a4a;
|
||||
--bg-white: #ffffff;
|
||||
--bg-light: #f4f7f9;
|
||||
--border-color: #e0e0e0;
|
||||
--max-width: 1200px;
|
||||
--transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
|
||||
line-height: 1.6;
|
||||
color: var(--text-primary);
|
||||
background-color: var(--bg-white);
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4 {
|
||||
font-family: 'Inter', sans-serif;
|
||||
font-weight: 700;
|
||||
color: var(--primary-color);
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 2.5rem;
|
||||
margin-bottom: 2rem;
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
h2::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: -10px;
|
||||
left: 0;
|
||||
width: 60px;
|
||||
height: 4px;
|
||||
background-color: var(--accent-color);
|
||||
}
|
||||
|
||||
p {
|
||||
margin-bottom: 1rem;
|
||||
color: var(--text-secondary);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: var(--primary-color);
|
||||
transition: var(--transition);
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: var(--accent-color);
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: var(--max-width);
|
||||
margin: 0 auto;
|
||||
padding: 0 2rem;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.section {
|
||||
padding: 6rem 0;
|
||||
}
|
||||
|
||||
.section-alt {
|
||||
background-color: var(--bg-light);
|
||||
}
|
||||
|
||||
/* Header Styles */
|
||||
.header {
|
||||
height: 100px;
|
||||
display: flex;
|
||||
justify-content: space-between; /* Logo left, Nav right */
|
||||
align-items: center;
|
||||
padding: 0 4rem;
|
||||
background-color: #ffffff;
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.logo-link {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 100px;
|
||||
}
|
||||
|
||||
.logo-img {
|
||||
height: 90px; /* Prominent size on the left */
|
||||
width: auto;
|
||||
display: block;
|
||||
mix-blend-mode: multiply;
|
||||
}
|
||||
|
||||
.nav-list {
|
||||
display: flex;
|
||||
gap: 3rem;
|
||||
list-style: none;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.nav-link {
|
||||
font-weight: 600;
|
||||
font-size: 1.1rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
padding: 1rem 0;
|
||||
}
|
||||
|
||||
/* Dropdown Menu */
|
||||
.nav-item-dropdown {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.dropdown-menu {
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
background-color: var(--bg-white);
|
||||
border: 1px solid var(--border-color);
|
||||
box-shadow: 0 10px 30px rgba(0,0,0,0.1);
|
||||
border-radius: 4px;
|
||||
min-width: 280px;
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
transition: all 0.2s ease;
|
||||
z-index: 1100;
|
||||
padding: 1rem 0;
|
||||
}
|
||||
|
||||
.nav-item-dropdown:hover .dropdown-menu {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
top: calc(100% - 10px);
|
||||
}
|
||||
|
||||
.dropdown-link {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
padding: 0.8rem 1.5rem;
|
||||
color: var(--text-primary);
|
||||
font-weight: 500;
|
||||
transition: var(--transition);
|
||||
}
|
||||
|
||||
.dropdown-link:hover {
|
||||
background-color: var(--bg-light);
|
||||
color: var(--primary-color);
|
||||
}
|
||||
|
||||
.dropdown-link .material-icons {
|
||||
font-size: 1.2rem;
|
||||
color: var(--accent-color);
|
||||
}
|
||||
|
||||
.material-icons {
|
||||
color: var(--accent-color);
|
||||
}
|
||||
|
||||
.nav-link-with-icon {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.3rem;
|
||||
}
|
||||
|
||||
.lang-switch {
|
||||
display: flex;
|
||||
gap: 0.5rem;
|
||||
margin-left: 1rem;
|
||||
border-left: 1px solid var(--border-color);
|
||||
padding-left: 1rem;
|
||||
}
|
||||
|
||||
.lang-btn {
|
||||
background: none;
|
||||
border: none;
|
||||
font-weight: 600;
|
||||
color: var(--text-secondary);
|
||||
cursor: pointer;
|
||||
padding: 0.2rem 0.5rem;
|
||||
border-radius: 4px;
|
||||
transition: var(--transition);
|
||||
}
|
||||
|
||||
.lang-btn.active {
|
||||
color: var(--primary-color);
|
||||
background-color: var(--bg-light);
|
||||
}
|
||||
|
||||
/* Hero Section */
|
||||
.hero {
|
||||
padding: 10rem 0 8rem;
|
||||
background: linear-gradient(135deg, var(--primary-color) 0%, var(--primary-dark) 100%);
|
||||
color: white;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.hero h1 {
|
||||
font-size: 3.5rem;
|
||||
color: white;
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
.hero p {
|
||||
font-size: 1.25rem;
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
max-width: 800px;
|
||||
margin: 0 auto 2.5rem;
|
||||
}
|
||||
|
||||
.hero-btn {
|
||||
display: inline-block;
|
||||
padding: 1rem 2.5rem;
|
||||
background-color: #ffc107f1;
|
||||
color: var(--primary-color);
|
||||
font-weight: 700;
|
||||
border-radius: 4px;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
|
||||
.hero-btn:hover {
|
||||
background-color: #ffc107;
|
||||
color: var(--primary-color);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
/* About Grid */
|
||||
.about-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
||||
gap: 3rem;
|
||||
margin-top: 4rem;
|
||||
}
|
||||
|
||||
/* Products Section */
|
||||
.products-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
|
||||
gap: 2.5rem;
|
||||
margin-top: 3rem;
|
||||
}
|
||||
|
||||
.product-card {
|
||||
background: white;
|
||||
padding: 2.5rem;
|
||||
border-radius: 8px;
|
||||
border: 1px solid var(--border-color);
|
||||
box-shadow: 0 4px 6px rgba(0,0,0,0.02);
|
||||
transition: var(--transition);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.product-card:hover {
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0 12px 20px rgba(0,0,0,0.08);
|
||||
border-color: var(--accent-color);
|
||||
}
|
||||
|
||||
.product-card h3 {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.product-icon {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
background-color: var(--bg-light);
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-bottom: 1.5rem;
|
||||
color: var(--accent-color);
|
||||
font-size: 1.2rem;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.legal-page {
|
||||
text-align: left !important;
|
||||
padding-left: 5% !important;
|
||||
padding-right: 5% !important;
|
||||
}
|
||||
|
||||
.legal-page p, .legal-page h2, .legal-page h3 {
|
||||
text-align: left !important;
|
||||
}
|
||||
|
||||
/* Contact Form */
|
||||
.contact-form {
|
||||
max-width: 700px;
|
||||
margin: 0 auto;
|
||||
background: white;
|
||||
padding: 3rem;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 10px 30px rgba(0,0,0,0.05);
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
.form-input {
|
||||
width: 100%;
|
||||
padding: 1rem;
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 4px;
|
||||
font-size: 1rem;
|
||||
transition: var(--transition);
|
||||
}
|
||||
|
||||
.form-input:focus {
|
||||
outline: none;
|
||||
border-color: var(--primary-color);
|
||||
box-shadow: 0 0 0 3px rgba(0, 51, 102, 0.1);
|
||||
}
|
||||
|
||||
.submit-btn {
|
||||
width: 100%;
|
||||
padding: 1rem;
|
||||
background-color: var(--primary-color);
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
font-weight: 700;
|
||||
font-size: 1.1rem;
|
||||
cursor: pointer;
|
||||
transition: var(--transition);
|
||||
}
|
||||
|
||||
.submit-btn:hover {
|
||||
background-color: #004080;
|
||||
}
|
||||
|
||||
.vienna-signet {
|
||||
margin-top: 5rem;
|
||||
font-size: 0.75rem;
|
||||
opacity: 0.5;
|
||||
letter-spacing: 2px;
|
||||
text-transform: uppercase;
|
||||
font-weight: 400;
|
||||
color: white;
|
||||
white-space: pre-line; /* Enables the linebreak from i18n */
|
||||
line-height: 1.8;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* Footer */
|
||||
.footer {
|
||||
background-color: var(--primary-color);
|
||||
color: white;
|
||||
padding: 4rem 0 2rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.footer p {
|
||||
color: rgba(255, 255, 255, 0.7);
|
||||
}
|
||||
|
||||
.footer-links {
|
||||
margin-top: 2rem;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 2rem;
|
||||
}
|
||||
|
||||
.footer-link {
|
||||
color: rgba(255, 255, 255, 0.8);
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.footer-link:hover {
|
||||
color: var(--accent-color);
|
||||
}
|
||||
|
||||
html {
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
|
||||
@media (max-width: 1024px) {
|
||||
.header {
|
||||
padding: 0 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.container {
|
||||
padding: 0 1.5rem;
|
||||
}
|
||||
|
||||
.section {
|
||||
padding: 4rem 0;
|
||||
}
|
||||
|
||||
.header {
|
||||
padding: 1rem;
|
||||
height: auto;
|
||||
flex-direction: column;
|
||||
gap: 1.5rem;
|
||||
position: relative; /* Stickiness can be annoying on very small headers if they are too tall */
|
||||
}
|
||||
|
||||
.logo-img {
|
||||
height: 70px;
|
||||
}
|
||||
|
||||
.nav-list {
|
||||
gap: 1.5rem;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.lang-switch {
|
||||
margin-left: 0;
|
||||
border-left: none;
|
||||
padding-left: 0;
|
||||
width: 100%;
|
||||
justify-content: center;
|
||||
margin-top: 0.5rem;
|
||||
border-top: 1px solid var(--border-color);
|
||||
padding-top: 1rem;
|
||||
}
|
||||
|
||||
.hero {
|
||||
padding: 6rem 0 4rem;
|
||||
}
|
||||
|
||||
.hero h1 {
|
||||
font-size: 2.2rem;
|
||||
padding: 0 1rem;
|
||||
}
|
||||
|
||||
.hero p {
|
||||
font-size: 1.1rem;
|
||||
padding: 0 1.5rem;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.about-grid, .products-grid {
|
||||
gap: 2rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* Target the third child specifically to center it when stacking */
|
||||
.about-grid > div:nth-child(3), .products-grid > div:nth-child(3) {
|
||||
grid-column: 1 / -1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.about-grid > div, .product-card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.product-icon {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.contact-form {
|
||||
padding: 2rem 1.5rem;
|
||||
}
|
||||
|
||||
.footer-links {
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.hero h1 {
|
||||
font-size: 1.8rem;
|
||||
}
|
||||
|
||||
.header {
|
||||
padding: 1rem 0.5rem;
|
||||
}
|
||||
|
||||
.nav-list {
|
||||
gap: 0.8rem;
|
||||
}
|
||||
|
||||
.nav-item-dropdown:hover .dropdown-menu {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.dropdown-menu {
|
||||
position: static;
|
||||
transform: none;
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
box-shadow: none;
|
||||
border: none;
|
||||
background-color: var(--bg-light);
|
||||
width: 100%;
|
||||
margin-top: 0.5rem;
|
||||
padding: 0.5rem 0;
|
||||
}
|
||||
|
||||
.dropdown-link {
|
||||
justify-content: center;
|
||||
padding: 0.5rem 1rem;
|
||||
}
|
||||
|
||||
.nav-link {
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user