Move Projekt-KIQ-HP bahn/ -> dhive/ (dhive project); add steering files
This commit is contained in:
@@ -0,0 +1,66 @@
|
||||
.bg-pattern-wrapper {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
z-index: -10;
|
||||
overflow: hidden;
|
||||
background-color: var(--bg-color);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.bg-scroll-container {
|
||||
display: flex;
|
||||
width: 4000px; /* 2 seamless blocks of 2000px width */
|
||||
height: 2000px;
|
||||
animation: endlessDrift 60s linear infinite;
|
||||
opacity: 0.15; /* Subtle blend */
|
||||
}
|
||||
|
||||
/*
|
||||
One seamless block consists of 4 flipped versions of the original 1000px image,
|
||||
making it a 2000px x 2000px perfectly seamless tile.
|
||||
*/
|
||||
.seamless-block {
|
||||
width: 2000px;
|
||||
height: 2000px;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.bg-quadrant {
|
||||
width: 1000px;
|
||||
height: 1000px;
|
||||
background-image: url('/logos/d_-hive-lines_1-1.svg');
|
||||
background-size: 1000px 1000px;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
/* Mirroring to force seamless edge matching */
|
||||
.top-left {
|
||||
transform: scale(1, 1);
|
||||
}
|
||||
|
||||
.top-right {
|
||||
transform: scale(-1, 1);
|
||||
}
|
||||
|
||||
.bottom-left {
|
||||
transform: scale(1, -1);
|
||||
}
|
||||
|
||||
.bottom-right {
|
||||
transform: scale(-1, -1);
|
||||
}
|
||||
|
||||
/* Move the entire double-block leftwards by the exact width of ONE block (2000px) */
|
||||
@keyframes endlessDrift {
|
||||
0% {
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
100% {
|
||||
transform: translate(-2000px, -500px); /* Move left 2000px, and up a bit for diagonal drift */
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
import React from 'react';
|
||||
import './BackgroundPattern.css';
|
||||
|
||||
export default function BackgroundPattern() {
|
||||
return (
|
||||
<div className="bg-pattern-wrapper">
|
||||
{/*
|
||||
To create a perfectly seamless infinite tile from a non-seamless image,
|
||||
we create a single massive seamless "block" by mirroring the image
|
||||
in all 4 directions (Top-Left, Top-Right, Bottom-Left, Bottom-Right).
|
||||
Then we duplicate this massive block to loop it.
|
||||
*/}
|
||||
<div className="bg-scroll-container">
|
||||
|
||||
{/* Block 1 */}
|
||||
<div className="seamless-block">
|
||||
<div className="bg-quadrant top-left"></div>
|
||||
<div className="bg-quadrant top-right"></div>
|
||||
<div className="bg-quadrant bottom-left"></div>
|
||||
<div className="bg-quadrant bottom-right"></div>
|
||||
</div>
|
||||
|
||||
{/* Block 2 (Duplicate for infinite seamless scroll) */}
|
||||
<div className="seamless-block">
|
||||
<div className="bg-quadrant top-left"></div>
|
||||
<div className="bg-quadrant top-right"></div>
|
||||
<div className="bg-quadrant bottom-left"></div>
|
||||
<div className="bg-quadrant bottom-right"></div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
.dock-container {
|
||||
position: fixed;
|
||||
bottom: 30px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
z-index: 1000;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.dock {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
/* background/border is now handled by pseudo-elements for the light effect */
|
||||
padding: 8px 12px;
|
||||
border-radius: 24px; /* Pill shape */
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
align-items: center;
|
||||
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.5), 0 0 20px rgba(0, 255, 0, 0.05);
|
||||
transition: all 0.3s ease;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
/* The running light (rotating gradient) */
|
||||
.dock::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 250%; /* Make it large enough to cover the pill shape while rotating */
|
||||
height: 250%;
|
||||
background: conic-gradient(transparent, transparent, transparent, rgba(0, 255, 0, 1));
|
||||
transform: translate(-50%, -50%);
|
||||
animation: rotateLight 4s linear infinite;
|
||||
z-index: -2;
|
||||
}
|
||||
|
||||
/* The inner mask that creates the border thickness */
|
||||
.dock::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 1px;
|
||||
left: 1px;
|
||||
right: 1px;
|
||||
bottom: 1px;
|
||||
background: rgba(20, 20, 20, 0.9);
|
||||
backdrop-filter: blur(20px);
|
||||
-webkit-backdrop-filter: blur(20px);
|
||||
border-radius: 23px; /* Matches inner curve */
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
@keyframes rotateLight {
|
||||
0% { transform: translate(-50%, -50%) rotate(0deg); }
|
||||
100% { transform: translate(-50%, -50%) rotate(360deg); }
|
||||
}
|
||||
|
||||
.dock-item-wrapper {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
z-index: 2; /* Keep above the inner mask */
|
||||
}
|
||||
|
||||
.dock-item {
|
||||
position: relative;
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border-radius: 16px;
|
||||
color: var(--text-secondary);
|
||||
transition: all 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.dock-item:hover {
|
||||
color: var(--text-primary);
|
||||
background: rgba(255, 255, 255, 0.08);
|
||||
transform: translateY(-8px) scale(1.15);
|
||||
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.dock-item.active {
|
||||
color: var(--accent-color);
|
||||
background: rgba(0, 255, 0, 0.1);
|
||||
}
|
||||
|
||||
.dock-item.active::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: -4px;
|
||||
width: 4px;
|
||||
height: 4px;
|
||||
border-radius: 50%;
|
||||
background-color: var(--accent-color);
|
||||
box-shadow: 0 0 10px var(--accent-color);
|
||||
}
|
||||
|
||||
/* Tooltip */
|
||||
.dock-tooltip {
|
||||
position: absolute;
|
||||
top: -45px;
|
||||
background: rgba(10, 10, 10, 0.9);
|
||||
color: #fff;
|
||||
padding: 6px 12px;
|
||||
border-radius: 8px;
|
||||
font-size: 0.8rem;
|
||||
font-weight: 500;
|
||||
white-space: nowrap;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
transform: translateY(10px);
|
||||
transition: all 0.3s ease;
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
.dock-item:hover ~ .dock-tooltip,
|
||||
.dock-item-wrapper:hover .dock-tooltip {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
import React from 'react';
|
||||
import { Link, useLocation } from 'react-router-dom';
|
||||
import { Home, Lightbulb, FileText, Settings, Lock } from 'lucide-react';
|
||||
import { useAuth } from '../contexts/AuthContext';
|
||||
import './BottomDock.css';
|
||||
|
||||
export default function BottomDock() {
|
||||
const location = useLocation();
|
||||
const { session, role } = useAuth();
|
||||
|
||||
const publicItems = [
|
||||
{ label: 'Home', path: '/', icon: <Home size={22} /> },
|
||||
{ label: 'Use Cases', path: '/usecases', icon: <Lightbulb size={22} /> },
|
||||
{ label: 'Zugang anfragen', path: '/request-access', icon: <FileText size={22} /> },
|
||||
];
|
||||
|
||||
// Both investor and admin can see the locked area
|
||||
const investorItems = session
|
||||
? [{ label: 'Investor Area', path: '/restricted', icon: <Lock size={22} /> }]
|
||||
: [];
|
||||
|
||||
// Only admin sees the admin panel
|
||||
const adminItems = role === 'admin'
|
||||
? [{ label: 'Admin', path: '/admin', icon: <Settings size={22} /> }]
|
||||
: [];
|
||||
|
||||
const navItems = [...publicItems, ...investorItems, ...adminItems];
|
||||
|
||||
return (
|
||||
<div className="dock-container">
|
||||
<nav className="dock">
|
||||
{navItems.map((item, index) => {
|
||||
const isActive = location.pathname === item.path;
|
||||
return (
|
||||
<div className="dock-item-wrapper" key={index}>
|
||||
<span className="dock-tooltip">{item.label}</span>
|
||||
<Link
|
||||
to={item.path}
|
||||
className={`dock-item ${isActive ? 'active' : ''}`}
|
||||
>
|
||||
{item.icon}
|
||||
</Link>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</nav>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
import React from 'react';
|
||||
import './Marquee.css';
|
||||
|
||||
// Import logos via Vite asset pipeline for robustness
|
||||
import arvosLogo from '../assets/logos/arvos.svg';
|
||||
import estererLogo from '../assets/logos/esterer.svg';
|
||||
import mtoLogo from '../assets/logos/Logo-MTO.png';
|
||||
import beierLogo from '../assets/logos/Paul-Beier-GmbH-Logo-white.png';
|
||||
import sikaLogo from '../assets/logos/sika-logo.png';
|
||||
import hexagonLogo from '../assets/logos/hexagon-purus-logo-4aa648.svg';
|
||||
|
||||
export default function Customers() {
|
||||
const customerLogos = [
|
||||
{ src: arvosLogo, link: 'https://www.arvos-group.com/', styleType: 'white-bg' },
|
||||
{ src: estererLogo, link: 'https://www.esterer.de/', styleType: 'white-bg' },
|
||||
{ src: mtoLogo, link: 'https://www.mto-kassel.de/', styleType: 'original' },
|
||||
{ src: beierLogo, link: 'https://www.paul-beier.de/', styleType: 'original' },
|
||||
{ src: sikaLogo, link: 'https://www.sika.com/', styleType: 'original' },
|
||||
{ src: hexagonLogo, link: 'https://www.hexagonpurus.com/', styleType: 'original' },
|
||||
];
|
||||
|
||||
// Triple the array for smooth infinite scrolling
|
||||
const marqueeItems = [...customerLogos, ...customerLogos, ...customerLogos];
|
||||
|
||||
return (
|
||||
<section id="kunden" className="marquee-section">
|
||||
<div className="section-header">
|
||||
<h2 className="section-title" style={{fontSize: '2rem', marginBottom: '40px'}}>Unsere <span className="text-gradient">Kunden</span></h2>
|
||||
</div>
|
||||
|
||||
<div className="marquee-fade-left"></div>
|
||||
<div className="marquee-fade-right"></div>
|
||||
|
||||
<div className="marquee-container">
|
||||
<div className="marquee-content">
|
||||
{marqueeItems.map((item, index) => {
|
||||
const isWhiteBg = item.styleType === 'white-bg';
|
||||
const isMonochrome = item.styleType === 'monochrome';
|
||||
|
||||
return (
|
||||
<a
|
||||
href={item.link}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className={`marquee-item logo-item ${isWhiteBg ? 'logo-white-bg' : ''}`}
|
||||
key={index}
|
||||
>
|
||||
<img
|
||||
src={item.src}
|
||||
alt="Kundenlogo"
|
||||
style={{
|
||||
height: '40px',
|
||||
width: 'auto',
|
||||
display: 'block',
|
||||
filter: isMonochrome ? 'brightness(0) invert(1)' : 'none',
|
||||
transition: 'transform 0.3s ease'
|
||||
}}
|
||||
onMouseOver={(e) => e.currentTarget.style.transform = 'scale(1.1)'}
|
||||
onMouseOut={(e) => e.currentTarget.style.transform = 'scale(1)'}
|
||||
/>
|
||||
</a>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
.footer-section {
|
||||
padding: 80px 0 40px 0;
|
||||
background-color: var(--bg-color);
|
||||
}
|
||||
|
||||
.cta-container {
|
||||
margin-bottom: 80px;
|
||||
}
|
||||
|
||||
.cta-content {
|
||||
text-align: center;
|
||||
padding: 80px 40px;
|
||||
background: linear-gradient(145deg, rgba(25, 25, 25, 0.8), rgba(10, 10, 10, 0.9));
|
||||
border: 1px solid rgba(16, 185, 129, 0.2);
|
||||
box-shadow: 0 20px 50px rgba(0, 0, 0, 0.5), inset 0 0 0 1px rgba(255, 255, 255, 0.05);
|
||||
}
|
||||
|
||||
.cta-content h2 {
|
||||
font-size: 2.5rem;
|
||||
margin-bottom: 20px;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.cta-content p {
|
||||
color: var(--text-secondary);
|
||||
font-size: 1.2rem;
|
||||
max-width: 600px;
|
||||
margin: 0 auto 40px auto;
|
||||
}
|
||||
|
||||
.footer-bottom {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
border-top: 1px solid rgba(255, 255, 255, 0.05);
|
||||
padding-top: 40px;
|
||||
}
|
||||
|
||||
.footer-logo {
|
||||
font-size: 1.5rem;
|
||||
font-weight: 800;
|
||||
letter-spacing: -1px;
|
||||
}
|
||||
|
||||
.footer-links {
|
||||
display: flex;
|
||||
gap: 24px;
|
||||
}
|
||||
|
||||
.footer-links a {
|
||||
color: var(--text-secondary);
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.footer-links a:hover {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.footer-copyright {
|
||||
color: var(--text-secondary);
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.footer-bottom {
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
import React from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import './Footer.css';
|
||||
|
||||
export default function Footer() {
|
||||
return (
|
||||
<footer id="kontakt" className="footer-section">
|
||||
<div className="cta-container app-container">
|
||||
<div className="cta-content glass-panel">
|
||||
<h2>Ihr habt ein spannendes Projekt?</h2>
|
||||
<p>Lasst uns gemeinsam herausfinden, wie wir eure Prozesse intelligenter machen können.</p>
|
||||
<a href="mailto:KIQ@d-hive.de" className="primary-button">Jetzt Kontakt aufnehmen</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="footer-bottom app-container">
|
||||
<div className="footer-logo">
|
||||
<img src="/logos/d-Hive_logo_transparent_crop.png" alt="d-HIVE" style={{ height: '50px', objectFit: 'contain' }} />
|
||||
</div>
|
||||
<div className="footer-links">
|
||||
<Link to="/impressum">Impressum</Link>
|
||||
<Link to="/datenschutz">Datenschutz</Link>
|
||||
</div>
|
||||
<div className="footer-copyright">
|
||||
© {new Date().getFullYear()} dHIVE. Alle Rechte vorbehalten.
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
import React from 'react';
|
||||
|
||||
export default function Gefoerdert() {
|
||||
return (
|
||||
<section className="app-container" style={{ padding: '60px 20px', textAlign: 'center', borderTop: '1px solid rgba(255, 255, 255, 0.05)' }}>
|
||||
<h3 style={{ fontSize: '1.2rem', color: 'var(--text-secondary)', marginBottom: '30px', fontWeight: '600', letterSpacing: '1px', textTransform: 'uppercase' }}>Gefördert durch</h3>
|
||||
<div style={{ display: 'flex', justifyContent: 'center' }}>
|
||||
<a
|
||||
href="https://digitales.hessen.de/foerderprogramme/distral"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
style={{
|
||||
display: 'inline-block',
|
||||
background: '#ffffff',
|
||||
padding: '15px 30px',
|
||||
borderRadius: '16px',
|
||||
transition: 'transform 0.3s ease',
|
||||
textDecoration: 'none'
|
||||
}}
|
||||
onMouseOver={(e) => e.currentTarget.style.transform = 'scale(1.05)'}
|
||||
onMouseOut={(e) => e.currentTarget.style.transform = 'scale(1)'}
|
||||
>
|
||||
<img
|
||||
src="/logos/download-logo-distral-data.png"
|
||||
alt="Gefördert durch distral"
|
||||
style={{ maxHeight: '90px', maxWidth: '300px', objectFit: 'contain', display: 'block' }}
|
||||
/>
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
.hero {
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
text-align: center;
|
||||
padding-top: 80px;
|
||||
}
|
||||
|
||||
.hero-content {
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
max-width: 900px;
|
||||
animation: fadeUp 1s cubic-bezier(0.16, 1, 0.3, 1) forwards;
|
||||
}
|
||||
|
||||
.hero h1 {
|
||||
font-size: clamp(2.5rem, 6vw, 4.5rem);
|
||||
line-height: 1.1;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.text-gradient {
|
||||
background: var(--accent-gradient);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.hero-subtext {
|
||||
font-size: clamp(1.1rem, 2vw, 1.3rem);
|
||||
color: var(--text-secondary);
|
||||
max-width: 700px;
|
||||
margin: 0 auto 40px auto;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.background-mesh {
|
||||
position: absolute;
|
||||
top: -20%;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
width: 1000px;
|
||||
height: 600px;
|
||||
background: radial-gradient(circle, rgba(16, 185, 129, 0.15) 0%, rgba(10, 10, 10, 0) 70%);
|
||||
z-index: 1;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
@keyframes fadeUp {
|
||||
0% { opacity: 0; transform: translateY(30px); }
|
||||
100% { opacity: 1; transform: translateY(0); }
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
import React from 'react';
|
||||
import './Hero.css';
|
||||
|
||||
export default function Hero() {
|
||||
return (
|
||||
<section className="hero">
|
||||
<div className="hero-glow background-mesh"></div>
|
||||
<div className="app-container hero-content">
|
||||
<h1>
|
||||
Das souveräne KI-Betriebssystem <br />
|
||||
<span className="text-gradient">für den deutschen Mittelstand</span>
|
||||
</h1>
|
||||
<p className="hero-subtext">
|
||||
Modernste KI-Anwendungen, souverän komplett aus Deutschland.
|
||||
Völlig unabhängig von amerikanischen Hyperscalern oder chinesischem Big-Tech.
|
||||
Höchste Performance trifft auf digitale Souveränität.
|
||||
</p>
|
||||
<div className="hero-actions">
|
||||
<a href="/request-access" className="primary-button">Access Request</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
.marquee-section {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
padding: 80px 0;
|
||||
background-color: var(--bg-color); /* pure black */
|
||||
overflow: hidden;
|
||||
border-top: 1px solid rgba(255, 255, 255, 0.03);
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.03);
|
||||
}
|
||||
|
||||
.marquee-fade-left, .marquee-fade-right {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
width: 15%;
|
||||
height: 100%;
|
||||
z-index: 2;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.marquee-fade-left {
|
||||
left: 0;
|
||||
background: linear-gradient(to right, var(--bg-color), transparent);
|
||||
}
|
||||
|
||||
.marquee-fade-right {
|
||||
right: 0;
|
||||
background: linear-gradient(to left, var(--bg-color), transparent);
|
||||
}
|
||||
|
||||
.marquee-container {
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.marquee-content {
|
||||
display: flex;
|
||||
width: fit-content;
|
||||
animation: scroll 30s linear infinite;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.marquee-item {
|
||||
margin: 0 40px;
|
||||
white-space: nowrap;
|
||||
transition: transform 0.4s ease;
|
||||
}
|
||||
|
||||
.logo-item img {
|
||||
max-height: 60px;
|
||||
max-width: 200px;
|
||||
object-fit: contain;
|
||||
transition: all 0.4s ease;
|
||||
opacity: 0.8; /* Base opacity for all */
|
||||
}
|
||||
|
||||
.logo-white-bg {
|
||||
background: #ffffff;
|
||||
padding: 10px 18px;
|
||||
border-radius: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-shadow: 0 4px 12px rgba(0,0,0,0.2);
|
||||
}
|
||||
|
||||
.logo-white-bg img {
|
||||
opacity: 1 !important;
|
||||
filter: none !important;
|
||||
}
|
||||
|
||||
.marquee-item:hover img {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
@keyframes scroll {
|
||||
0% { transform: translateX(0); }
|
||||
100% { transform: translateX(-33.33%); }
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
import React from 'react';
|
||||
|
||||
export default function Memberships() {
|
||||
const membershipLogos = [
|
||||
{ src: 'DE_KI-Verband-Logo_weiss-scaled.png', link: 'https://ki-verband.de/' },
|
||||
{ src: 'GKS_Logo.jpg', link: 'https://gemeinsamklimaschuetzen.de/' },
|
||||
{ src: 'science-park-kassel-logo.png', link: 'https://www.sciencepark-kassel.de/' }
|
||||
];
|
||||
|
||||
return (
|
||||
<section id="netzwerk" className="app-container" style={{ padding: '60px 20px', textAlign: 'center' }}>
|
||||
<h2 style={{ fontSize: '2rem', marginBottom: '40px' }}>Mitgliedschaften & <span className="text-gradient">Partnerschaften</span></h2>
|
||||
<div style={{ display: 'flex', justifyContent: 'center', gap: '60px', flexWrap: 'wrap', alignItems: 'center' }}>
|
||||
{membershipLogos.map((item, index) => (
|
||||
<a key={index} href={item.link} target="_blank" rel="noopener noreferrer" style={{ display: 'block' }}>
|
||||
<img
|
||||
src={`/logos/${item.src}`}
|
||||
alt="Mitgliedschaft / Partner"
|
||||
style={{ maxHeight: '80px', maxWidth: '200px', objectFit: 'contain', transition: 'transform 0.3s ease' }}
|
||||
onMouseOver={(e) => e.currentTarget.style.transform = 'scale(1.1)'}
|
||||
onMouseOut={(e) => e.currentTarget.style.transform = 'scale(1)'}
|
||||
/>
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
.navigation {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
z-index: 1000;
|
||||
transition: all 0.3s ease;
|
||||
padding: 20px 0;
|
||||
}
|
||||
|
||||
.navigation.scrolled {
|
||||
padding: 15px 0;
|
||||
border-bottom: 1px solid var(--glass-border);
|
||||
border-radius: 0;
|
||||
backdrop-filter: blur(12px);
|
||||
background: rgba(10, 10, 10, 0.8);
|
||||
}
|
||||
|
||||
.nav-container {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.logo-image {
|
||||
height: 70px;
|
||||
width: auto;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
/* Hamburger Menu */
|
||||
.hamburger {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
background: transparent;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
z-index: 1001; /* Above overlay */
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.hamburger span {
|
||||
display: block;
|
||||
width: 30px;
|
||||
height: 2px;
|
||||
background-color: var(--text-primary);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.hamburger.active span:nth-child(1) {
|
||||
transform: translateY(8px) rotate(45deg);
|
||||
}
|
||||
|
||||
.hamburger.active span:nth-child(2) {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.hamburger.active span:nth-child(3) {
|
||||
transform: translateY(-8px) rotate(-45deg);
|
||||
}
|
||||
|
||||
/* Overlay Navigation */
|
||||
.nav-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
background: rgba(10, 10, 10, 0.95);
|
||||
backdrop-filter: blur(15px);
|
||||
-webkit-backdrop-filter: blur(15px);
|
||||
z-index: 999; /* Below header */
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
transition: all 0.4s cubic-bezier(0.16, 1, 0.3, 1);
|
||||
}
|
||||
|
||||
.nav-overlay.open {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.overlay-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 40px;
|
||||
}
|
||||
|
||||
.overlay-link {
|
||||
font-size: 3rem;
|
||||
font-weight: 800;
|
||||
color: var(--text-primary);
|
||||
text-decoration: none;
|
||||
opacity: 0;
|
||||
transform: translateY(20px);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.nav-overlay.open .overlay-link {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
.nav-overlay.open .overlay-link:nth-child(1) { transition-delay: 0.1s; }
|
||||
.nav-overlay.open .overlay-link:nth-child(2) { transition-delay: 0.2s; }
|
||||
.nav-overlay.open .overlay-link:nth-child(3) { transition-delay: 0.3s; }
|
||||
.nav-overlay.open .overlay-link:nth-child(4) { transition-delay: 0.4s; }
|
||||
|
||||
.overlay-link:hover {
|
||||
color: var(--accent-color);
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { Link, useLocation } from 'react-router-dom';
|
||||
import './Navigation.css';
|
||||
|
||||
export default function Navigation() {
|
||||
const [scrolled, setScrolled] = useState(false);
|
||||
const [isOverlayOpen, setIsOverlayOpen] = useState(false);
|
||||
const location = useLocation();
|
||||
|
||||
useEffect(() => {
|
||||
const handleScroll = () => {
|
||||
setScrolled(window.scrollY > 50);
|
||||
};
|
||||
window.addEventListener('scroll', handleScroll);
|
||||
return () => window.removeEventListener('scroll', handleScroll);
|
||||
}, []);
|
||||
|
||||
// Close overlay on route change — use a layout effect to avoid setState-in-body lint
|
||||
const prevPathRef = React.useRef(location.pathname);
|
||||
React.useLayoutEffect(() => {
|
||||
if (prevPathRef.current !== location.pathname) {
|
||||
prevPathRef.current = location.pathname;
|
||||
setIsOverlayOpen(false);
|
||||
}
|
||||
}, [location.pathname]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<nav className={`navigation ${scrolled ? 'scrolled glass-panel' : ''}`}>
|
||||
<div className="nav-container app-container">
|
||||
<Link to="/" className="logo">
|
||||
<img src="/logos/logo-dHIVE-2x.webp" alt="d-HIVE Logo" className="logo-image" />
|
||||
</Link>
|
||||
|
||||
<button
|
||||
className={`hamburger ${isOverlayOpen ? 'active' : ''}`}
|
||||
onClick={() => setIsOverlayOpen(!isOverlayOpen)}
|
||||
aria-label="Toggle menu"
|
||||
>
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
</button>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
{/* Overlay Menu */}
|
||||
<div className={`nav-overlay ${isOverlayOpen ? 'open' : ''}`}>
|
||||
<div className="overlay-content">
|
||||
<Link to="/" className="overlay-link" onClick={() => setIsOverlayOpen(false)}>Home</Link>
|
||||
<Link to="/usecases" className="overlay-link" onClick={() => setIsOverlayOpen(false)}>Use Cases</Link>
|
||||
<Link to="/request-access" className="overlay-link" onClick={() => setIsOverlayOpen(false)}>Request Access</Link>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
.platform-usp {
|
||||
padding: 100px 0;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.usp-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
||||
gap: 30px;
|
||||
margin-top: 60px;
|
||||
}
|
||||
|
||||
.usp-card {
|
||||
padding: 40px;
|
||||
border-radius: 24px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
transition: transform 0.3s ease, box-shadow 0.3s ease, border-color 0.3s ease;
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
min-height: 380px;
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
justify-content: flex-end; /* Align content to bottom for a modern look */
|
||||
}
|
||||
|
||||
.usp-card:hover {
|
||||
transform: translateY(-8px);
|
||||
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.5);
|
||||
border-color: var(--accent-color);
|
||||
}
|
||||
|
||||
.usp-card h3 {
|
||||
font-size: 1.6rem;
|
||||
margin-bottom: 20px;
|
||||
color: #fff;
|
||||
text-shadow: 0 2px 4px rgba(0,0,0,0.5);
|
||||
}
|
||||
|
||||
.usp-card ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.usp-card li {
|
||||
color: #efefef; /* Slightly brighter for readability against dark overlay */
|
||||
line-height: 1.6;
|
||||
margin-bottom: 12px;
|
||||
padding-left: 24px;
|
||||
position: relative;
|
||||
font-size: 0.95rem;
|
||||
text-shadow: 0 1px 2px rgba(0,0,0,0.5);
|
||||
}
|
||||
|
||||
.usp-card li::before {
|
||||
content: '→';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
color: var(--accent-color);
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
import React from 'react';
|
||||
import './PlatformUSP.css';
|
||||
|
||||
// Import background images
|
||||
import devBg from '../assets/usp/developer.png';
|
||||
import bizBg from '../assets/usp/business.png';
|
||||
import sovBg from '../assets/usp/sovereignty.png';
|
||||
|
||||
const features = [
|
||||
{
|
||||
title: 'Für Entwickler: Speed & Participation',
|
||||
points: [
|
||||
'Maximale Liefergeschwindigkeit durch fertige Infrastruktur.',
|
||||
'Direkte Beteiligung am Erfolg jedes Use-Cases (Shared Benefit).',
|
||||
'Die besten Entwickler Deutschlands bündeln ihre Kraft.'
|
||||
],
|
||||
bgImage: devBg
|
||||
},
|
||||
{
|
||||
title: 'Für Unternehmen: Time-to-Value',
|
||||
points: [
|
||||
'Use-Cases sofort sehen und für sich nutzbar machen.',
|
||||
'Kein IT-Overhead, kein Setup-Stress.',
|
||||
'Direkter Zugang zu High-End KI-Expertise.'
|
||||
],
|
||||
bgImage: bizBg
|
||||
},
|
||||
{
|
||||
title: '100% Souveränität',
|
||||
points: [
|
||||
'Komplett Made in Germany.',
|
||||
'Keine Abhängigkeit von US-Hyperscalern.',
|
||||
'Kein chinesisches Big-Tech.',
|
||||
'Sicherer Hafen für sensibelste Unternehmensdaten.'
|
||||
],
|
||||
bgImage: sovBg
|
||||
}
|
||||
];
|
||||
|
||||
export default function PlatformUSP() {
|
||||
return (
|
||||
<section className="platform-usp">
|
||||
<div className="app-container">
|
||||
<div className="section-header">
|
||||
<h2 className="section-title">Die <span className="text-gradient">Plattform-Vision</span></h2>
|
||||
<p className="section-subtitle">
|
||||
Wo die besten Entwickler für die besten Unternehmen bauen — und alle direkt profitieren.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="usp-grid">
|
||||
{features.map((f, i) => (
|
||||
<div
|
||||
key={i}
|
||||
className="usp-card glass-panel"
|
||||
style={{
|
||||
backgroundImage: `linear-gradient(rgba(0, 0, 0, 0.75), rgba(0, 0, 0, 0.85)), url(${f.bgImage})`
|
||||
}}
|
||||
>
|
||||
<h3>{f.title}</h3>
|
||||
<ul>
|
||||
{f.points.map((p, j) => (
|
||||
<li key={j}>{p}</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
import React from 'react';
|
||||
import { Navigate, useLocation } from 'react-router-dom';
|
||||
import { useAuth } from '../contexts/AuthContext';
|
||||
|
||||
/**
|
||||
* ProtectedRoute: checks session via AuthContext.
|
||||
* allowedRoles: array of roles that can access this route.
|
||||
* If no session, redirects to /login.
|
||||
* If role set but not allowed, redirects to /.
|
||||
*/
|
||||
export default function ProtectedRoute({ children, allowedRoles }) {
|
||||
const { session, role, loading } = useAuth();
|
||||
const location = useLocation();
|
||||
|
||||
if (loading) {
|
||||
return <div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100vh', color: '#00FF00', fontFamily: 'monospace' }}>Authentifizierung läuft...</div>;
|
||||
}
|
||||
|
||||
if (!session) {
|
||||
return <Navigate to="/login" state={{ from: location }} replace />;
|
||||
}
|
||||
|
||||
if (allowedRoles && !allowedRoles.includes(role)) {
|
||||
return <Navigate to="/" replace />;
|
||||
}
|
||||
|
||||
return children;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import { useEffect } from 'react';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
|
||||
/**
|
||||
* ScrollToTop component ensures that the page scroll position
|
||||
* is reset to (0, 0) whenever the route changes.
|
||||
*/
|
||||
export default function ScrollToTop() {
|
||||
const { pathname } = useLocation();
|
||||
|
||||
useEffect(() => {
|
||||
window.scrollTo(0, 0);
|
||||
}, [pathname]);
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
.services-section {
|
||||
padding: 120px 20px;
|
||||
}
|
||||
|
||||
.section-header {
|
||||
text-align: center;
|
||||
max-width: 700px;
|
||||
margin: 0 auto 60px auto;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 3rem;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.section-subtitle {
|
||||
color: var(--text-secondary);
|
||||
font-size: 1.1rem;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.bento-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 24px;
|
||||
max-width: 1000px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.bento-item {
|
||||
position: relative;
|
||||
border-radius: 24px;
|
||||
padding: 40px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-end;
|
||||
min-height: 300px;
|
||||
overflow: hidden;
|
||||
transition: transform 0.4s cubic-bezier(0.16, 1, 0.3, 1);
|
||||
border: 1px solid rgba(255, 255, 255, 0.05);
|
||||
}
|
||||
|
||||
.bento-item.span-2 {
|
||||
grid-column: span 2;
|
||||
}
|
||||
|
||||
.bento-content {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.bento-title {
|
||||
font-size: 1.5rem;
|
||||
margin-bottom: 12px;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.bento-text {
|
||||
color: var(--text-secondary);
|
||||
line-height: 1.6;
|
||||
font-size: 1rem;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.bento-glow {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: radial-gradient(circle at 100% 100%, rgba(16, 185, 129, 0.1), transparent 50%);
|
||||
opacity: 0;
|
||||
transition: opacity 0.4s ease;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.bento-item:hover {
|
||||
transform: translateY(-8px);
|
||||
border-color: rgba(16, 185, 129, 0.3);
|
||||
}
|
||||
|
||||
.bento-item:hover .bento-glow {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.bento-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
.bento-item.span-2 {
|
||||
grid-column: span 1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
import React from 'react';
|
||||
import './Services.css';
|
||||
|
||||
export default function Services() {
|
||||
const services = [
|
||||
{
|
||||
title: 'Datenschutz & Souveränität',
|
||||
desc: 'Wir garantieren 100% DSGVO- und AI-Act konforme KI-Lösungen ohne Lock-in durch US-Hyperscaler wie OpenAI oder Google.',
|
||||
bg: '/images/automation_bg.png', // Temporary placeholder visuals
|
||||
span: 'span-2'
|
||||
},
|
||||
{
|
||||
title: 'Plug and Play KI',
|
||||
desc: 'Kein Ressourcenmangel mehr. Out-of-the-box Infrastruktur für smarte Anwendungsfälle.',
|
||||
bg: '/images/ai_bg.png',
|
||||
span: ''
|
||||
},
|
||||
{
|
||||
title: 'Netzwerk & Forschung',
|
||||
desc: 'Partnerschaft zwischen Unternehmen und Universität Kassel für modernste Begleitung.',
|
||||
bg: '/images/workshops_bg.png',
|
||||
span: ''
|
||||
},
|
||||
{
|
||||
title: 'Vorausschauende Wartung & Automatisierung',
|
||||
desc: 'Nutzen Sie Custom GPTs für B2B: Von Predictive Maintenance bis komplexe Dokumentenverarbeitung out-of-the-box.',
|
||||
bg: '/images/transformation_bg.png',
|
||||
span: 'span-2'
|
||||
}
|
||||
];
|
||||
|
||||
return (
|
||||
<section id="leistungen" className="services-section app-container">
|
||||
<div className="section-header">
|
||||
<h2 className="section-title">Unsere <span className="text-gradient">Lösung</span></h2>
|
||||
<p className="section-subtitle">Project KIQ liefert die gesamte KI-Infrastruktur out-of-the-box. Radikaler Fokus auf den Use Case.</p>
|
||||
</div>
|
||||
|
||||
<div className="bento-grid">
|
||||
{services.map((service, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className={`bento-item glass-panel ${service.span}`}
|
||||
style={{
|
||||
backgroundImage: `linear-gradient(to bottom, rgba(10, 10, 10, 0.4), rgba(10, 10, 10, 0.95)), url(${service.bg})`,
|
||||
backgroundSize: 'cover',
|
||||
backgroundPosition: 'center',
|
||||
backgroundRepeat: 'no-repeat'
|
||||
}}
|
||||
>
|
||||
<div className="bento-content">
|
||||
<h3 className="bento-title">{service.title}</h3>
|
||||
<p className="bento-text">{service.desc}</p>
|
||||
</div>
|
||||
<div className="bento-glow"></div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
.cube-section {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 100px 20px 150px 20px;
|
||||
perspective: 1200px;
|
||||
}
|
||||
|
||||
.cube-container {
|
||||
width: 300px;
|
||||
height: 300px;
|
||||
position: relative;
|
||||
transform-style: preserve-3d;
|
||||
animation: spinCube 16s infinite cubic-bezier(0.25, 0.1, 0.25, 1);
|
||||
}
|
||||
|
||||
.cube-face {
|
||||
position: absolute;
|
||||
width: 300px;
|
||||
height: 300px;
|
||||
background: rgba(15, 15, 15, 0.95); /* solid background prevents seeing through nicely */
|
||||
border: 1px solid rgba(0, 255, 0, 0.2);
|
||||
backdrop-filter: blur(10px);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
box-shadow: 0 0 40px rgba(0, 255, 0, 0.1) inset, 0 10px 40px rgba(0, 0, 0, 0.5);
|
||||
backface-visibility: hidden; /* Hide faces turned away to prevent jumbled mess if translucent */
|
||||
}
|
||||
|
||||
/* 3D Geometry */
|
||||
.face-1 { transform: rotateY(0deg) translateZ(150px); }
|
||||
.face-2 { transform: rotateY(90deg) translateZ(150px); }
|
||||
.face-3 { transform: rotateY(180deg) translateZ(150px); }
|
||||
.face-4 { transform: rotateY(-90deg) translateZ(150px); }
|
||||
|
||||
@keyframes spinCube {
|
||||
0%, 15% { transform: rotateY(0deg); }
|
||||
25%, 40% { transform: rotateY(-90deg); }
|
||||
50%, 65% { transform: rotateY(-180deg); }
|
||||
75%, 90% { transform: rotateY(-270deg); }
|
||||
100% { transform: rotateY(-360deg); }
|
||||
}
|
||||
|
||||
.stat-value {
|
||||
font-size: 4rem;
|
||||
font-weight: 800;
|
||||
margin-bottom: 10px;
|
||||
color: #fff;
|
||||
filter: drop-shadow(0 0 15px rgba(0, 255, 0, 0.5));
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
font-size: 1.5rem;
|
||||
color: var(--text-secondary);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 2px;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
import React from 'react';
|
||||
import './Stats.css';
|
||||
|
||||
export default function Stats() {
|
||||
const stats = [
|
||||
{ value: '6', label: 'Pilotkunden', faceClass: 'face-1' },
|
||||
{ value: '100%', label: 'DSGVO & AI-Act', faceClass: 'face-2' },
|
||||
{ value: '6', label: 'Use Cases live', faceClass: 'face-3' },
|
||||
{ value: 'EU', label: 'Hosting', faceClass: 'face-4' },
|
||||
];
|
||||
|
||||
return (
|
||||
<section className="cube-section app-container">
|
||||
<div className="cube-container">
|
||||
{stats.map((stat, i) => (
|
||||
<div className={`cube-face ${stat.faceClass}`} key={i}>
|
||||
<div className="stat-value text-gradient">{stat.value}</div>
|
||||
<div className="stat-label">{stat.label}</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
import React from 'react';
|
||||
|
||||
export default function Team() {
|
||||
return (
|
||||
<section className="app-container" style={{ padding: '40px 20px 100px 20px' }}>
|
||||
<div className="glass-panel" style={{ padding: '60px', borderRadius: '24px', border: '1px solid rgba(0, 255, 0, 0.1)' }}>
|
||||
<h2 style={{ fontSize: '2rem', marginBottom: '20px', color: '#fff' }}>Das sind wir</h2>
|
||||
<p style={{ color: 'var(--text-secondary)', lineHeight: '1.8', marginBottom: '30px', fontSize: '1.05rem', maxWidth: '800px' }}>
|
||||
Unser Team setzt sich zusammen aus Problemlösern mit wissenschaftlichen Hintergründen in den Bereichen der Regelungs- und Elektrotechnik, Mechatronik, Maschinenbau, Informatik und Physik. Und wir alle haben uns in irgendeiner Form dem Generieren von Wissen durch das Erheben und Verarbeiten von Daten verschrieben.
|
||||
<br/><br/>
|
||||
Stellvertretend für unser Team stellen wir hier unsere Gründer vor: André – unser KI, Leadership und Sensorik-Experte – und Alex – unser Mess-, Regelungs und Automatisierungs-Experte. Die beiden begleiten unsere Kunden und unsere internen und externen Mitarbeitenden durch die Projekte.
|
||||
</p>
|
||||
|
||||
{/* Founders Grid */}
|
||||
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(340px, 1fr))', gap: '40px', marginTop: '60px' }}>
|
||||
|
||||
{/* André */}
|
||||
<div style={{ background: 'rgba(255,255,255,0.02)', padding: '40px', borderRadius: '20px', border: '1px solid rgba(255,255,255,0.05)' }}>
|
||||
<h3 style={{ fontSize: '1.8rem', color: '#fff', marginBottom: '5px' }}>Dr. André Knie</h3>
|
||||
<p style={{ color: 'var(--accent-color)', fontWeight: '600', marginBottom: '25px', fontSize: '1.1rem' }}>Mensch-Maschine-Moderator</p>
|
||||
|
||||
<div style={{ fontStyle: 'italic', color: '#ccc', borderLeft: '3px solid var(--accent-color)', paddingLeft: '15px', marginBottom: '20px', lineHeight: '1.7' }}>
|
||||
„Die Angst vor Technologie und Veränderung lähmt viele Organisationen und Menschen. Ich helfe dabei, diese Ängste zu überwinden, und gestalte Technologie sowie Change-Prozesse so, dass sie echten Mehrwert schaffen und Begeisterung auslösen."
|
||||
</div>
|
||||
|
||||
<p style={{ color: 'var(--text-secondary)', lineHeight: '1.7', marginBottom: '15px' }}>
|
||||
Als promovierter Physiker betrachte ich Systeme und Zusammenhänge aus einer einzigartigen Perspektive.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Alex */}
|
||||
<div style={{ background: 'rgba(255,255,255,0.02)', padding: '40px', borderRadius: '20px', border: '1px solid rgba(255,255,255,0.05)' }}>
|
||||
<h3 style={{ fontSize: '1.8rem', color: '#fff', marginBottom: '5px' }}>Dr.-Ing. Alexander Schrodt</h3>
|
||||
<p style={{ color: 'var(--accent-color)', fontWeight: '600', marginBottom: '25px', fontSize: '1.1rem' }}>Automatisierungs-Analyse-Architekt</p>
|
||||
|
||||
<div style={{ fontStyle: 'italic', color: '#ccc', borderLeft: '3px solid var(--accent-color)', paddingLeft: '15px', marginBottom: '20px', lineHeight: '1.7' }}>
|
||||
„Ich führe die KI-Diskussion über Buzzwords hinaus: Für mich ist KI keine universelle Antwort, sondern ein hochspezialisiertes Werkzeug, um in technischen Systemen echten, messbaren Mehrwert zu schaffen."
|
||||
</div>
|
||||
|
||||
<p style={{ color: 'var(--text-secondary)', lineHeight: '1.7', marginBottom: '15px' }}>
|
||||
Mein Fundament als promovierter Regelungstechniker ist die Systemtheorie. Ich verstehe, wie technische Prozesse im Kern funktionieren, wie sie stabil designt und sicher betrieben werden.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
.uct-section {
|
||||
padding: 100px 20px;
|
||||
}
|
||||
|
||||
.uct-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
|
||||
gap: 20px;
|
||||
margin-top: 48px;
|
||||
}
|
||||
|
||||
.uct-card {
|
||||
padding: 28px;
|
||||
border-radius: 18px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
transition: border-color 0.25s, transform 0.25s;
|
||||
}
|
||||
|
||||
.uct-card:hover {
|
||||
border-color: rgba(0, 255, 0, 0.25);
|
||||
transform: translateY(-3px);
|
||||
}
|
||||
|
||||
.uct-icon {
|
||||
font-size: 1.8rem;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.uct-title {
|
||||
font-size: 1.15rem;
|
||||
color: #fff;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.uct-summary {
|
||||
color: var(--text-secondary);
|
||||
font-size: 0.88rem;
|
||||
line-height: 1.6;
|
||||
margin: 0;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.uct-status {
|
||||
display: inline-block;
|
||||
align-self: flex-start;
|
||||
background: rgba(0,255,0,0.08);
|
||||
border: 1px solid rgba(0,255,0,0.2);
|
||||
color: var(--accent-color);
|
||||
font-size: 0.73rem;
|
||||
font-weight: 700;
|
||||
padding: 3px 10px;
|
||||
border-radius: 50px;
|
||||
letter-spacing: 0.06em;
|
||||
}
|
||||
|
||||
.uct-cta {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-top: 48px;
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
import React from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { USE_CASES } from '../data/useCases';
|
||||
import './UseCasesTeaser.css';
|
||||
|
||||
export default function UseCasesTeaser() {
|
||||
return (
|
||||
<section className="uct-section app-container">
|
||||
<div className="section-header">
|
||||
<h2 className="section-title">Bewiesene <span className="text-gradient">Use Cases</span></h2>
|
||||
<p className="section-subtitle">
|
||||
Fünf KI-Agenten, bereits im Einsatz bei Praxispartnern aus der Region Kassel.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="uct-grid">
|
||||
{USE_CASES.map((uc) => (
|
||||
<div key={uc.id} className="uct-card glass-panel">
|
||||
<div className="uct-icon">{uc.icon}</div>
|
||||
<h3 className="uct-title">{uc.title}</h3>
|
||||
<p className="uct-summary">{uc.summary}</p>
|
||||
<span className="uct-status">✓ Live</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="uct-cta">
|
||||
<Link to="/usecases" className="primary-button">
|
||||
Alle Use Cases ansehen →
|
||||
</Link>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user