From fb995cefdb9eda1f4ee3fc9954627f036d46a97dc04b6bb5689bfe687f40fdea Mon Sep 17 00:00:00 2001 From: Michael Schmeinck Date: Sun, 27 Sep 2026 18:30:34 +0200 Subject: [PATCH] mail ready --- .idea/.gitignore | 10 - .idea/dilibworld-site.iml | 8 - .idea/modules.xml | 8 - .idea/vcs.xml | 6 - .idea/workspace.xml | 72 ++ 404.html | 18 +- README.md | 9 +- assets/css/app.css | 1062 +++++++++++++++++++++++++- assets/img/hero-architecture.svg | 64 +- assets/img/og-cover.svg | 33 +- assets/img/platform-architecture.svg | 61 +- assets/img/product-ai.svg | 16 +- assets/img/product-idx.svg | 13 +- assets/img/product-masterdata.svg | 13 +- assets/img/product-process.svg | 13 +- assets/img/product-transfer.svg | 13 +- assets/js/app.js | 117 +-- backend/README.md | 11 + backend/app.py | 132 ++++ backend/contact.env | 7 + backend/contact.env.example | 7 + backend/nginx-contact.conf.example | 14 + backend/requirements.txt | 1 + de/datenschutz.html | 146 +++- de/kontakt.html | 154 +++- de/loesungen.html | 221 +++++- de/unternehmen.html | 161 +++- en/company.html | 157 +++- en/contact.html | 152 +++- en/privacy.html | 4 +- en/solutions.html | 216 +++++- index.html | 13 +- sitemap.xml | 48 +- 33 files changed, 2787 insertions(+), 193 deletions(-) delete mode 100644 .idea/.gitignore delete mode 100644 .idea/dilibworld-site.iml delete mode 100644 .idea/modules.xml delete mode 100644 .idea/vcs.xml create mode 100644 .idea/workspace.xml create mode 100644 backend/README.md create mode 100644 backend/app.py create mode 100644 backend/contact.env create mode 100644 backend/contact.env.example create mode 100644 backend/nginx-contact.conf.example create mode 100644 backend/requirements.txt diff --git a/.idea/.gitignore b/.idea/.gitignore deleted file mode 100644 index de60c0b..0000000 --- a/.idea/.gitignore +++ /dev/null @@ -1,10 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml -# Ignored default folder with query files -/queries/ -# Datasource local storage ignored files -/dataSources/ -/dataSources.local.xml -# Editor-based HTTP Client requests -/httpRequests/ diff --git a/.idea/dilibworld-site.iml b/.idea/dilibworld-site.iml deleted file mode 100644 index 16bfc95..0000000 --- a/.idea/dilibworld-site.iml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index e2b9b87..0000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 321f217..0000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml new file mode 100644 index 0000000..26bf304 --- /dev/null +++ b/.idea/workspace.xml @@ -0,0 +1,72 @@ + + + + + + + + { + "associatedIndex": 0 +} + + + + { + "keyToString": { + "ModuleVcsDetector.initialDetectionPerformed": "true", + "RunOnceActivity.ShowReadmeOnStart": "true", + "RunOnceActivity.TerminalTabsStorage.copyFrom.TerminalArrangementManager.252": "true", + "RunOnceActivity.typescript.service.memoryLimit.init": "true", + "git-widget-placeholder": "main", + "javascript.preferred.runtime.type.id": "node", + "last_opened_file_path": "/Users/m.schmeinck/gitprojects/dilibworld/homepage", + "nodejs_package_manager_path": "npm", + "vue.rearranger.settings.migration": "true" + } +} + + + + + + + + + + 1783957246577 + + + + + + + + + + \ No newline at end of file diff --git a/404.html b/404.html index fa2ec1d..ffc7b22 100644 --- a/404.html +++ b/404.html @@ -1 +1,17 @@ -404 | dilibworld
404

Seite nicht gefunden.

Page not found.

Zur Startseite / Home

\ No newline at end of file + + + + + + + + 404 | dilibworld + +
+
404 +

Seite nicht gefunden.

+

Page not found.

+

Zur Startseite / Home

+
+ + diff --git a/README.md b/README.md index 91d9418..39e4a87 100644 --- a/README.md +++ b/README.md @@ -21,10 +21,13 @@ Danach `http://localhost:8080` öffnen. ## Vor Veröffentlichung zwingend anpassen -1. **Impressum und Datenschutz:** Geschäftsführer, Registergericht, HRB, USt-ID, vollständige Firmenanschrift, Hosting-Anbieter und Löschfristen eintragen. +1. **Impressum und Datenschutz:** Geschäftsführer, Registergericht, HRB, USt-ID, vollständige Firmenanschrift, + Hosting-Anbieter und Löschfristen eintragen. 2. **Kontaktdaten:** `info@dilibworld.com` und Telefonnummer bestätigen oder in allen Dateien ersetzen. -3. **CSS-Framework:** Das Paket enthält ein schlankes lokales, Foundation-kompatibles Grid. Soll die vollständige offizielle Foundation-Distribution eingesetzt werden, kann `assets/css/foundation.min.css` durch den offiziellen Foundation-Build ersetzt werden. -4. **Kontaktformular:** Das Formular öffnet bewusst das lokale E-Mail-Programm und speichert keine Daten. Für serverseitigen Versand muss es an ein geprüftes Backend mit CSRF-, Spam- und Datenschutzschutz angebunden werden. +3. **CSS-Framework:** Das Paket enthält ein schlankes lokales, Foundation-kompatibles Grid. Soll die vollständige + offizielle Foundation-Distribution eingesetzt werden, kann `assets/css/foundation.min.css` durch den offiziellen + Foundation-Build ersetzt werden. +4. **Kontaktformular:** Das Formular sendet an `/api/contact`. Den Python-Dienst und Nginx-Proxy gemäß `backend/README.md` einrichten, bevor die aktualisierte Kontaktseite live geht. 5. **Rechtliche Prüfung:** Die Rechtstexte sind redaktionelle Vorlagen und keine Rechtsberatung. ## Deployment mit Nginx diff --git a/assets/css/app.css b/assets/css/app.css index 8065870..e019cc5 100644 --- a/assets/css/app.css +++ b/assets/css/app.css @@ -1,11 +1,1053 @@ -:root{ - --ink:#071b2e;--ink-2:#0d2944;--paper:#f6fbff;--white:#fff;--muted:#5d7185; - --cyan:#27d3dc;--cyan-2:#0697aa;--violet:#7057ff;--lime:#8de36c;--line:rgba(9,42,68,.12); - --shadow:0 24px 70px rgba(5,26,45,.14);--shadow-sm:0 12px 35px rgba(5,26,45,.10); - --radius:1.45rem;--radius-sm:.9rem;--header-h:5.25rem; +:root { + --ink: #071b2e; + --ink-2: #0d2944; + --paper: #f6fbff; + --white: #fff; + --muted: #5d7185; + --cyan: #27d3dc; + --cyan-2: #0697aa; + --violet: #7057ff; + --lime: #8de36c; + --line: rgba(9, 42, 68, .12); + --shadow: 0 24px 70px rgba(5, 26, 45, .14); + --shadow-sm: 0 12px 35px rgba(5, 26, 45, .10); + --radius: 1.45rem; + --radius-sm: .9rem; + --header-h: 5.25rem; } -html{scroll-behavior:smooth;background:var(--paper)}body{font-family:Inter,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;color:var(--ink);background:var(--paper);line-height:1.6;overflow-x:hidden} -a{color:var(--cyan-2);text-decoration:none}a:hover{color:var(--violet)}h1,h2,h3,h4{font-weight:760;line-height:1.08;letter-spacing:-.03em;color:var(--ink);margin-top:0}h1{font-size:clamp(2.7rem,7vw,5.8rem);max-width:13ch}h2{font-size:clamp(2rem,4.4vw,3.8rem)}h3{font-size:clamp(1.25rem,2vw,1.65rem)}p{margin-top:0}.lead{font-size:clamp(1.1rem,2vw,1.35rem);color:var(--muted);max-width:58ch}.eyebrow{display:inline-flex;align-items:center;gap:.55rem;text-transform:uppercase;letter-spacing:.14em;font-size:.76rem;font-weight:800;color:var(--cyan-2);margin-bottom:1.1rem}.eyebrow::before{content:"";width:1.8rem;height:2px;background:linear-gradient(90deg,var(--cyan),var(--violet))}.skip-link{position:fixed;left:1rem;top:-5rem;z-index:9999;background:var(--ink);color:white;padding:.7rem 1rem;border-radius:.5rem}.skip-link:focus{top:1rem}.site-header{position:sticky;top:0;z-index:1000;background:rgba(246,251,255,.86);backdrop-filter:blur(18px);border-bottom:1px solid rgba(9,42,68,.08)}.nav-shell{min-height:var(--header-h);display:flex;align-items:center;justify-content:space-between;gap:1rem}.brand{display:flex;align-items:center;gap:.72rem;color:var(--ink);font-weight:820;font-size:1.2rem;letter-spacing:-.03em}.brand img{width:3rem;height:3rem;object-fit:contain;filter:drop-shadow(0 6px 10px rgba(13,41,68,.15))}.brand small{display:block;font-size:.62rem;line-height:1.1;color:var(--muted);font-weight:700;letter-spacing:.11em;text-transform:uppercase}.desktop-nav{display:flex;align-items:center;gap:.2rem}.desktop-nav a{padding:.65rem .8rem;color:var(--ink-2);font-weight:700;font-size:.92rem;border-radius:.7rem}.desktop-nav a[aria-current="page"],.desktop-nav a:hover{background:white;color:var(--violet);box-shadow:0 6px 18px rgba(7,27,46,.06)}.lang-switch{display:inline-flex;border:1px solid var(--line);background:white;border-radius:999px;padding:.18rem}.lang-switch a{padding:.4rem .62rem;border-radius:999px;font-size:.76rem}.lang-switch a.active{background:var(--ink);color:white}.nav-cta{background:linear-gradient(135deg,var(--violet),#4e9cff)!important;color:white!important;padding:.68rem 1rem!important;box-shadow:0 10px 24px rgba(112,87,255,.25)}.menu-toggle{display:none;width:2.8rem;height:2.8rem;border:1px solid var(--line);border-radius:.8rem;background:white;align-items:center;justify-content:center;cursor:pointer}.menu-toggle span,.menu-toggle::before,.menu-toggle::after{display:block;content:"";width:1.25rem;height:2px;background:var(--ink);transition:.25s}.menu-toggle span{margin:.25rem 0}.menu-toggle.open span{opacity:0}.menu-toggle.open::before{transform:translateY(.375rem) rotate(45deg)}.menu-toggle.open::after{transform:translateY(-.375rem) rotate(-45deg)}.mobile-nav{display:none;padding:.5rem 0 1rem}.mobile-nav.open{display:block}.mobile-nav a{display:block;color:var(--ink);padding:.8rem 0;border-bottom:1px solid var(--line);font-weight:700}.hero{position:relative;min-height:calc(100vh - var(--header-h));display:flex;align-items:center;padding:5rem 0 4rem;overflow:hidden}.hero::before{content:"";position:absolute;inset:-20% -10%;background:radial-gradient(circle at 72% 25%,rgba(39,211,220,.25),transparent 29%),radial-gradient(circle at 16% 65%,rgba(112,87,255,.18),transparent 30%),linear-gradient(130deg,#f9fdff 20%,#eaf9ff 100%);z-index:0}.hero-grid{position:relative;z-index:1}.hero h1 .gradient{background:linear-gradient(100deg,var(--cyan-2),var(--violet));-webkit-background-clip:text;background-clip:text;color:transparent}.hero-actions{display:flex;flex-wrap:wrap;gap:.8rem;margin-top:2rem}.button.primary,.button.secondary,.button.ghost{border:0;border-radius:999px;padding:.95rem 1.35rem;font-weight:800;margin:0;transition:transform .2s,box-shadow .2s}.button.primary{background:linear-gradient(135deg,var(--violet),#3e9cff);box-shadow:0 14px 32px rgba(112,87,255,.30)}.button.secondary{background:var(--ink);color:white;box-shadow:0 14px 32px rgba(7,27,46,.20)}.button.ghost{background:rgba(255,255,255,.7);color:var(--ink);border:1px solid var(--line)}.button:hover{transform:translateY(-2px)}.trust-row{display:flex;flex-wrap:wrap;gap:1rem 1.5rem;margin-top:2.5rem;color:var(--muted);font-weight:700;font-size:.9rem}.trust-row span{display:flex;align-items:center;gap:.45rem}.trust-row span::before{content:"✓";display:grid;place-items:center;width:1.35rem;height:1.35rem;border-radius:50%;background:rgba(39,211,220,.18);color:#007f8f;font-weight:900}.hero-art{position:relative;padding:2rem}.hero-art img{width:100%;filter:drop-shadow(0 35px 70px rgba(7,27,46,.20));animation:float 8s ease-in-out infinite}.orbit-note{position:absolute;background:rgba(255,255,255,.88);backdrop-filter:blur(12px);border:1px solid rgba(255,255,255,.85);box-shadow:var(--shadow-sm);border-radius:1rem;padding:.75rem .9rem;font-weight:800;font-size:.82rem}.orbit-note.one{left:2%;top:16%}.orbit-note.two{right:0;bottom:18%}.orbit-note i{display:inline-block;width:.55rem;height:.55rem;border-radius:50%;background:var(--lime);box-shadow:0 0 0 6px rgba(141,227,108,.17);margin-right:.45rem}@keyframes float{0%,100%{transform:translateY(0) rotate(-.4deg)}50%{transform:translateY(-12px) rotate(.4deg)}}.section{padding:clamp(4rem,8vw,7.5rem) 0}.section.white{background:white}.section.dark{background:var(--ink);color:white;position:relative;overflow:hidden}.section.dark h2,.section.dark h3{color:white}.section.dark .lead,.section.dark p{color:#bfd1df}.section.dark::after{content:"";position:absolute;width:32rem;height:32rem;border-radius:50%;right:-12rem;top:-8rem;background:radial-gradient(circle,rgba(39,211,220,.19),transparent 70%)}.section-head{display:flex;align-items:end;justify-content:space-between;gap:2rem;margin-bottom:2.5rem}.section-head p{max-width:42rem}.solution-grid{display:grid;grid-template-columns:repeat(12,1fr);gap:1.25rem}.solution-card{position:relative;overflow:hidden;min-height:21rem;background:white;border:1px solid var(--line);border-radius:var(--radius);box-shadow:var(--shadow-sm);padding:1.8rem;transition:.3s}.solution-card:hover{transform:translateY(-6px);box-shadow:var(--shadow)}.solution-card.large{grid-column:span 7}.solution-card.small{grid-column:span 5}.solution-card.third{grid-column:span 4}.solution-card .icon{width:4rem;height:4rem;border-radius:1.1rem;display:grid;place-items:center;background:linear-gradient(135deg,rgba(39,211,220,.18),rgba(112,87,255,.14));margin-bottom:1.5rem}.solution-card .icon img{width:2.5rem;height:2.5rem}.solution-card p{color:var(--muted);max-width:42ch}.solution-card .card-link{position:absolute;bottom:1.5rem;left:1.8rem;font-weight:850;color:var(--ink)}.solution-card .card-link::after{content:" →";color:var(--violet)}.solution-card .glow{position:absolute;width:11rem;height:11rem;border-radius:50%;right:-4rem;top:-4rem;background:radial-gradient(circle,rgba(39,211,220,.27),transparent 70%)}.architecture{border:1px solid rgba(255,255,255,.12);background:rgba(255,255,255,.05);border-radius:var(--radius);padding:clamp(1.2rem,3vw,2.2rem);position:relative;z-index:2}.architecture img{width:100%}.feature-list{list-style:none;margin:1.5rem 0 0;padding:0}.feature-list li{position:relative;padding:.65rem 0 .65rem 2rem;border-bottom:1px solid var(--line);color:var(--muted)}.feature-list li::before{content:"";position:absolute;left:0;top:1.08rem;width:.7rem;height:.7rem;border-radius:50%;background:linear-gradient(135deg,var(--cyan),var(--violet));box-shadow:0 0 0 5px rgba(39,211,220,.12)}.dark .feature-list li{border-bottom-color:rgba(255,255,255,.12);color:#c8d8e5}.metric-strip{display:grid;grid-template-columns:repeat(4,1fr);gap:1rem;margin-top:2.5rem}.metric{padding:1.4rem;border-radius:1.1rem;background:rgba(255,255,255,.08);border:1px solid rgba(255,255,255,.11)}.metric strong{font-size:1.5rem;display:block;color:white}.metric span{font-size:.86rem;color:#aec4d5}.industry-card{height:100%;padding:1.5rem;border:1px solid var(--line);border-radius:var(--radius-sm);background:linear-gradient(180deg,#fff,#f7fcff)}.industry-card .num{font-size:.78rem;color:var(--violet);font-weight:900;letter-spacing:.12em}.industry-card p{color:var(--muted)}.process-steps{counter-reset:steps;display:grid;grid-template-columns:repeat(4,1fr);gap:1rem}.process-step{counter-increment:steps;padding:1.5rem;border:1px solid var(--line);border-radius:1.15rem;background:white}.process-step::before{content:"0" counter(steps);display:block;font-size:.78rem;letter-spacing:.12em;font-weight:900;color:var(--cyan-2);margin-bottom:1.8rem}.process-step p{color:var(--muted);font-size:.94rem}.quote{font-size:clamp(1.6rem,3.4vw,2.7rem);line-height:1.25;max-width:30ch;color:white}.cta-panel{position:relative;overflow:hidden;background:linear-gradient(135deg,var(--ink),#113d61);color:white;border-radius:2rem;padding:clamp(2rem,5vw,4rem);box-shadow:var(--shadow)}.cta-panel::after{content:"";position:absolute;width:20rem;height:20rem;border-radius:50%;right:-7rem;top:-8rem;background:radial-gradient(circle,rgba(39,211,220,.45),transparent 68%)}.cta-panel h2{color:white;position:relative;z-index:1}.cta-panel p{color:#c5d8e7;position:relative;z-index:1}.page-hero{padding:5rem 0 3rem;background:radial-gradient(circle at 85% 15%,rgba(39,211,220,.22),transparent 30%),linear-gradient(150deg,#f8fdff,#eaf7ff)}.page-hero h1{font-size:clamp(2.6rem,6vw,5rem);max-width:16ch}.product-row{padding:3rem 0;border-bottom:1px solid var(--line)}.product-row:last-child{border-bottom:0}.product-visual{background:linear-gradient(145deg,#edfaff,#f5f1ff);border:1px solid var(--line);border-radius:var(--radius);padding:2rem;min-height:22rem;display:grid;place-items:center}.product-visual img{max-height:18rem}.badge{display:inline-flex;padding:.35rem .7rem;border-radius:999px;background:rgba(112,87,255,.11);color:var(--violet);font-size:.76rem;font-weight:850;text-transform:uppercase;letter-spacing:.08em}.company-values{display:grid;grid-template-columns:repeat(3,1fr);gap:1rem}.value{padding:1.5rem;border-radius:1rem;background:white;border:1px solid var(--line)}.value strong{font-size:1.15rem}.contact-card{background:white;border:1px solid var(--line);border-radius:var(--radius);box-shadow:var(--shadow-sm);padding:clamp(1.5rem,4vw,2.6rem)}.contact-card input,.contact-card textarea,.contact-card select{border-radius:.75rem;border-color:#cbdbe7;background:#fbfdff;box-shadow:none}.contact-card input:focus,.contact-card textarea:focus,.contact-card select:focus{border-color:var(--violet);box-shadow:0 0 0 3px rgba(112,87,255,.12)}.form-grid{display:grid;grid-template-columns:1fr 1fr;gap:0 1rem}.form-grid .full{grid-column:1/-1}.checkbox-line{display:flex;align-items:flex-start;gap:.65rem;font-size:.9rem;color:var(--muted)}.checkbox-line input{width:auto;height:auto;margin-top:.3rem}.form-status{display:none;padding:.8rem 1rem;border-radius:.7rem;background:#eafbea;color:#216b2a;margin-top:1rem}.legal{max-width:56rem}.legal h2{font-size:1.7rem;margin-top:2.3rem}.legal h3{font-size:1.2rem;margin-top:1.7rem}.legal p,.legal li{color:#3f566b}.legal-note{border-left:4px solid #f1b842;background:#fff8df;padding:1rem 1.2rem;border-radius:.5rem;margin:1.5rem 0}.footer{background:#061625;color:#a9bfd1;padding:4rem 0 1.5rem}.footer h3,.footer strong{color:white}.footer-logo{display:flex;align-items:center;gap:.8rem;margin-bottom:1rem}.footer-logo img{width:3.2rem}.footer a{color:#c9dce9}.footer a:hover{color:var(--cyan)}.footer ul{list-style:none;margin:0;padding:0}.footer li{margin:.45rem 0}.footer-bottom{margin-top:3rem;padding-top:1.3rem;border-top:1px solid rgba(255,255,255,.1);display:flex;justify-content:space-between;gap:1rem;font-size:.85rem}.reveal-on-scroll{opacity:0;transform:translateY(22px);transition:opacity .65s ease,transform .65s ease}.reveal-on-scroll.visible{opacity:1;transform:none}.cookie-notice{position:fixed;z-index:2000;left:1rem;right:1rem;bottom:1rem;max-width:40rem;margin:auto;background:white;border:1px solid var(--line);border-radius:1rem;box-shadow:var(--shadow);padding:1rem 1.2rem;display:none}.cookie-notice.show{display:block}.cookie-actions{display:flex;gap:.6rem;flex-wrap:wrap;margin-top:.7rem}.cookie-actions button{border:0;border-radius:999px;padding:.55rem .9rem;font-weight:800;cursor:pointer}.cookie-actions .accept{background:var(--ink);color:white}.cookie-actions .decline{background:#edf3f7;color:var(--ink)} -@media(max-width:63.999em){.desktop-nav{display:none}.menu-toggle{display:block}.hero{min-height:auto}.hero-art{margin-top:2rem}.solution-card.large,.solution-card.small{grid-column:span 6}.solution-card.third{grid-column:span 6}.process-steps{grid-template-columns:repeat(2,1fr)}.metric-strip{grid-template-columns:repeat(2,1fr)}} -@media(max-width:39.999em){:root{--header-h:4.5rem}.grid-container{padding-left:1.1rem;padding-right:1.1rem}.brand img{width:2.6rem;height:2.6rem}.brand small{display:none}.hero{padding:3.2rem 0}.hero-art{padding:.5rem}.orbit-note{font-size:.72rem}.solution-card.large,.solution-card.small,.solution-card.third{grid-column:span 12;min-height:19rem}.section-head{display:block}.section-head .button{margin-top:1rem}.process-steps,.company-values,.metric-strip{grid-template-columns:1fr}.form-grid{grid-template-columns:1fr}.form-grid .full{grid-column:auto}.footer-bottom{display:block}.page-hero{padding:3rem 0 2rem}.product-row{padding:2rem 0}.product-visual{min-height:15rem;margin-bottom:1.5rem}.trust-row{display:block}.trust-row span{margin:.6rem 0}} -@media(prefers-reduced-motion:reduce){html{scroll-behavior:auto}*,*::before,*::after{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important}} + +html { + scroll-behavior: smooth; + background: var(--paper) +} + +body { + font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; + color: var(--ink); + background: var(--paper); + line-height: 1.6; + overflow-x: hidden +} + +a { + color: var(--cyan-2); + text-decoration: none +} + +a:hover { + color: var(--violet) +} + +h1, h2, h3, h4 { + font-weight: 760; + line-height: 1.08; + letter-spacing: -.03em; + color: var(--ink); + margin-top: 0 +} + +h1 { + font-size: clamp(2.7rem, 7vw, 5.8rem); + max-width: 13ch +} + +h2 { + font-size: clamp(2rem, 4.4vw, 3.8rem) +} + +h3 { + font-size: clamp(1.25rem, 2vw, 1.65rem) +} + +p { + margin-top: 0 +} + +.lead { + font-size: clamp(1.1rem, 2vw, 1.35rem); + color: var(--muted); + max-width: 58ch +} + +.eyebrow { + display: inline-flex; + align-items: center; + gap: .55rem; + text-transform: uppercase; + letter-spacing: .14em; + font-size: .76rem; + font-weight: 800; + color: var(--cyan-2); + margin-bottom: 1.1rem +} + +.eyebrow::before { + content: ""; + width: 1.8rem; + height: 2px; + background: linear-gradient(90deg, var(--cyan), var(--violet)) +} + +.skip-link { + position: fixed; + left: 1rem; + top: -5rem; + z-index: 9999; + background: var(--ink); + color: white; + padding: .7rem 1rem; + border-radius: .5rem +} + +.skip-link:focus { + top: 1rem +} + +.site-header { + position: sticky; + top: 0; + z-index: 1000; + background: rgba(246, 251, 255, .86); + backdrop-filter: blur(18px); + border-bottom: 1px solid rgba(9, 42, 68, .08) +} + +.nav-shell { + min-height: var(--header-h); + display: flex; + align-items: center; + justify-content: space-between; + gap: 1rem +} + +.brand { + display: flex; + align-items: center; + gap: .72rem; + color: var(--ink); + font-weight: 820; + font-size: 1.2rem; + letter-spacing: -.03em +} + +.brand img { + width: 3rem; + height: 3rem; + object-fit: contain; + filter: drop-shadow(0 6px 10px rgba(13, 41, 68, .15)) +} + +.brand small { + display: block; + font-size: .62rem; + line-height: 1.1; + color: var(--muted); + font-weight: 700; + letter-spacing: .11em; + text-transform: uppercase +} + +.desktop-nav { + display: flex; + align-items: center; + gap: .2rem +} + +.desktop-nav a { + padding: .65rem .8rem; + color: var(--ink-2); + font-weight: 700; + font-size: .92rem; + border-radius: .7rem +} + +.desktop-nav a[aria-current="page"], .desktop-nav a:hover { + background: white; + color: var(--violet); + box-shadow: 0 6px 18px rgba(7, 27, 46, .06) +} + +.lang-switch { + display: inline-flex; + border: 1px solid var(--line); + background: white; + border-radius: 999px; + padding: .18rem +} + +.lang-switch a { + padding: .4rem .62rem; + border-radius: 999px; + font-size: .76rem +} + +.lang-switch a.active { + background: var(--ink); + color: white +} + +.nav-cta { + background: linear-gradient(135deg, var(--violet), #4e9cff) !important; + color: white !important; + padding: .68rem 1rem !important; + box-shadow: 0 10px 24px rgba(112, 87, 255, .25) +} + +.menu-toggle { + display: none; + width: 2.8rem; + height: 2.8rem; + border: 1px solid var(--line); + border-radius: .8rem; + background: white; + align-items: center; + justify-content: center; + cursor: pointer +} + +.menu-toggle span, .menu-toggle::before, .menu-toggle::after { + display: block; + content: ""; + width: 1.25rem; + height: 2px; + background: var(--ink); + transition: .25s +} + +.menu-toggle span { + margin: .25rem 0 +} + +.menu-toggle.open span { + opacity: 0 +} + +.menu-toggle.open::before { + transform: translateY(.375rem) rotate(45deg) +} + +.menu-toggle.open::after { + transform: translateY(-.375rem) rotate(-45deg) +} + +.mobile-nav { + display: none; + padding: .5rem 0 1rem +} + +.mobile-nav.open { + display: block +} + +.mobile-nav a { + display: block; + color: var(--ink); + padding: .8rem 0; + border-bottom: 1px solid var(--line); + font-weight: 700 +} + +.hero { + position: relative; + min-height: calc(100vh - var(--header-h)); + display: flex; + align-items: center; + padding: 5rem 0 4rem; + overflow: hidden +} + +.hero::before { + content: ""; + position: absolute; + inset: -20% -10%; + background: radial-gradient(circle at 72% 25%, rgba(39, 211, 220, .25), transparent 29%), radial-gradient(circle at 16% 65%, rgba(112, 87, 255, .18), transparent 30%), linear-gradient(130deg, #f9fdff 20%, #eaf9ff 100%); + z-index: 0 +} + +.hero-grid { + position: relative; + z-index: 1 +} + +.hero h1 .gradient { + background: linear-gradient(100deg, var(--cyan-2), var(--violet)); + -webkit-background-clip: text; + background-clip: text; + color: transparent +} + +.hero-actions { + display: flex; + flex-wrap: wrap; + gap: .8rem; + margin-top: 2rem +} + +.button.primary, .button.secondary, .button.ghost { + border: 0; + border-radius: 999px; + padding: .95rem 1.35rem; + font-weight: 800; + margin: 0; + transition: transform .2s, box-shadow .2s +} + +.button.primary { + background: linear-gradient(135deg, var(--violet), #3e9cff); + box-shadow: 0 14px 32px rgba(112, 87, 255, .30) +} + +.button.secondary { + background: var(--ink); + color: white; + box-shadow: 0 14px 32px rgba(7, 27, 46, .20) +} + +.button.ghost { + background: rgba(255, 255, 255, .7); + color: var(--ink); + border: 1px solid var(--line) +} + +.button:hover { + transform: translateY(-2px) +} + +.trust-row { + display: flex; + flex-wrap: wrap; + gap: 1rem 1.5rem; + margin-top: 2.5rem; + color: var(--muted); + font-weight: 700; + font-size: .9rem +} + +.trust-row span { + display: flex; + align-items: center; + gap: .45rem +} + +.trust-row span::before { + content: "✓"; + display: grid; + place-items: center; + width: 1.35rem; + height: 1.35rem; + border-radius: 50%; + background: rgba(39, 211, 220, .18); + color: #007f8f; + font-weight: 900 +} + +.hero-art { + position: relative; + padding: 2rem +} + +.hero-art img { + width: 100%; + filter: drop-shadow(0 35px 70px rgba(7, 27, 46, .20)); + animation: float 8s ease-in-out infinite +} + +.orbit-note { + position: absolute; + background: rgba(255, 255, 255, .88); + backdrop-filter: blur(12px); + border: 1px solid rgba(255, 255, 255, .85); + box-shadow: var(--shadow-sm); + border-radius: 1rem; + padding: .75rem .9rem; + font-weight: 800; + font-size: .82rem +} + +.orbit-note.one { + left: 2%; + top: 16% +} + +.orbit-note.two { + right: 0; + bottom: 18% +} + +.orbit-note i { + display: inline-block; + width: .55rem; + height: .55rem; + border-radius: 50%; + background: var(--lime); + box-shadow: 0 0 0 6px rgba(141, 227, 108, .17); + margin-right: .45rem +} + +@keyframes float { + 0%, 100% { + transform: translateY(0) rotate(-.4deg) + } + 50% { + transform: translateY(-12px) rotate(.4deg) + } +} + +.section { + padding: clamp(4rem, 8vw, 7.5rem) 0 +} + +.section.white { + background: white +} + +.section.dark { + background: var(--ink); + color: white; + position: relative; + overflow: hidden +} + +.section.dark h2, .section.dark h3 { + color: white +} + +.section.dark .lead, .section.dark p { + color: #bfd1df +} + +.section.dark::after { + content: ""; + position: absolute; + width: 32rem; + height: 32rem; + border-radius: 50%; + right: -12rem; + top: -8rem; + background: radial-gradient(circle, rgba(39, 211, 220, .19), transparent 70%) +} + +.section-head { + display: flex; + align-items: end; + justify-content: space-between; + gap: 2rem; + margin-bottom: 2.5rem +} + +.section-head p { + max-width: 42rem +} + +.solution-grid { + display: grid; + grid-template-columns:repeat(12, 1fr); + gap: 1.25rem +} + +.solution-card { + position: relative; + overflow: hidden; + min-height: 21rem; + background: white; + border: 1px solid var(--line); + border-radius: var(--radius); + box-shadow: var(--shadow-sm); + padding: 1.8rem; + transition: .3s +} + +.solution-card:hover { + transform: translateY(-6px); + box-shadow: var(--shadow) +} + +.solution-card.large { + grid-column: span 7 +} + +.solution-card.small { + grid-column: span 5 +} + +.solution-card.third { + grid-column: span 4 +} + +.solution-card .icon { + width: 4rem; + height: 4rem; + border-radius: 1.1rem; + display: grid; + place-items: center; + background: linear-gradient(135deg, rgba(39, 211, 220, .18), rgba(112, 87, 255, .14)); + margin-bottom: 1.5rem +} + +.solution-card .icon img { + width: 2.5rem; + height: 2.5rem +} + +.solution-card p { + color: var(--muted); + max-width: 42ch +} + +.solution-card .card-link { + position: absolute; + bottom: 1.5rem; + left: 1.8rem; + font-weight: 850; + color: var(--ink) +} + +.solution-card .card-link::after { + content: " →"; + color: var(--violet) +} + +.solution-card .glow { + position: absolute; + width: 11rem; + height: 11rem; + border-radius: 50%; + right: -4rem; + top: -4rem; + background: radial-gradient(circle, rgba(39, 211, 220, .27), transparent 70%) +} + +.architecture { + border: 1px solid rgba(255, 255, 255, .12); + background: rgba(255, 255, 255, .05); + border-radius: var(--radius); + padding: clamp(1.2rem, 3vw, 2.2rem); + position: relative; + z-index: 2 +} + +.architecture img { + width: 100% +} + +.feature-list { + list-style: none; + margin: 1.5rem 0 0; + padding: 0 +} + +.feature-list li { + position: relative; + padding: .65rem 0 .65rem 2rem; + border-bottom: 1px solid var(--line); + color: var(--muted) +} + +.feature-list li::before { + content: ""; + position: absolute; + left: 0; + top: 1.08rem; + width: .7rem; + height: .7rem; + border-radius: 50%; + background: linear-gradient(135deg, var(--cyan), var(--violet)); + box-shadow: 0 0 0 5px rgba(39, 211, 220, .12) +} + +.dark .feature-list li { + border-bottom-color: rgba(255, 255, 255, .12); + color: #c8d8e5 +} + +.metric-strip { + display: grid; + grid-template-columns:repeat(4, 1fr); + gap: 1rem; + margin-top: 2.5rem +} + +.metric { + padding: 1.4rem; + border-radius: 1.1rem; + background: rgba(255, 255, 255, .08); + border: 1px solid rgba(255, 255, 255, .11) +} + +.metric strong { + font-size: 1.5rem; + display: block; + color: white +} + +.metric span { + font-size: .86rem; + color: #aec4d5 +} + +.industry-card { + height: 100%; + padding: 1.5rem; + border: 1px solid var(--line); + border-radius: var(--radius-sm); + background: linear-gradient(180deg, #fff, #f7fcff) +} + +.industry-card .num { + font-size: .78rem; + color: var(--violet); + font-weight: 900; + letter-spacing: .12em +} + +.industry-card p { + color: var(--muted) +} + +.process-steps { + counter-reset: steps; + display: grid; + grid-template-columns:repeat(4, 1fr); + gap: 1rem +} + +.process-step { + counter-increment: steps; + padding: 1.5rem; + border: 1px solid var(--line); + border-radius: 1.15rem; + background: white +} + +.process-step::before { + content: "0" counter(steps); + display: block; + font-size: .78rem; + letter-spacing: .12em; + font-weight: 900; + color: var(--cyan-2); + margin-bottom: 1.8rem +} + +.process-step p { + color: var(--muted); + font-size: .94rem +} + +.quote { + font-size: clamp(1.6rem, 3.4vw, 2.7rem); + line-height: 1.25; + max-width: 30ch; + color: white +} + +.cta-panel { + position: relative; + overflow: hidden; + background: linear-gradient(135deg, var(--ink), #113d61); + color: white; + border-radius: 2rem; + padding: clamp(2rem, 5vw, 4rem); + box-shadow: var(--shadow) +} + +.cta-panel::after { + content: ""; + position: absolute; + width: 20rem; + height: 20rem; + border-radius: 50%; + right: -7rem; + top: -8rem; + background: radial-gradient(circle, rgba(39, 211, 220, .45), transparent 68%) +} + +.cta-panel h2 { + color: white; + position: relative; + z-index: 1 +} + +.cta-panel p { + color: #c5d8e7; + position: relative; + z-index: 1 +} + +.page-hero { + padding: 5rem 0 3rem; + background: radial-gradient(circle at 85% 15%, rgba(39, 211, 220, .22), transparent 30%), linear-gradient(150deg, #f8fdff, #eaf7ff) +} + +.page-hero h1 { + font-size: clamp(2.6rem, 6vw, 5rem); + max-width: 16ch +} + +.product-row { + padding: 3rem 0; + border-bottom: 1px solid var(--line) +} + +.product-row:last-child { + border-bottom: 0 +} + +.product-visual { + background: linear-gradient(145deg, #edfaff, #f5f1ff); + border: 1px solid var(--line); + border-radius: var(--radius); + padding: 2rem; + min-height: 22rem; + display: grid; + place-items: center +} + +.product-visual img { + max-height: 18rem +} + +.badge { + display: inline-flex; + padding: .35rem .7rem; + border-radius: 999px; + background: rgba(112, 87, 255, .11); + color: var(--violet); + font-size: .76rem; + font-weight: 850; + text-transform: uppercase; + letter-spacing: .08em +} + +.company-values { + display: grid; + grid-template-columns:repeat(3, 1fr); + gap: 1rem +} + +.value { + padding: 1.5rem; + border-radius: 1rem; + background: white; + border: 1px solid var(--line) +} + +.value strong { + font-size: 1.15rem +} + +.contact-card { + background: white; + border: 1px solid var(--line); + border-radius: var(--radius); + box-shadow: var(--shadow-sm); + padding: clamp(1.5rem, 4vw, 2.6rem) +} + +.contact-card input, .contact-card textarea, .contact-card select { + border-radius: .75rem; + border-color: #cbdbe7; + background: #fbfdff; + box-shadow: none +} + +.contact-card input:focus, .contact-card textarea:focus, .contact-card select:focus { + border-color: var(--violet); + box-shadow: 0 0 0 3px rgba(112, 87, 255, .12) +} + +.form-grid { + display: grid; + grid-template-columns:1fr 1fr; + gap: 0 1rem +} + +.form-grid .full { + grid-column: 1/-1 +} + +.checkbox-line { + display: flex; + align-items: flex-start; + gap: .65rem; + font-size: .9rem; + color: var(--muted) +} + +.checkbox-line input { + width: auto; + height: auto; + margin-top: .3rem +} + +.form-status { + display: none; + padding: .8rem 1rem; + border-radius: .7rem; + background: #eafbea; + color: #216b2a; + margin-top: 1rem +} + +.legal { + max-width: 56rem +} + +.legal h2 { + font-size: 1.7rem; + margin-top: 2.3rem +} + +.legal h3 { + font-size: 1.2rem; + margin-top: 1.7rem +} + +.legal p, .legal li { + color: #3f566b +} + +.legal-note { + border-left: 4px solid #f1b842; + background: #fff8df; + padding: 1rem 1.2rem; + border-radius: .5rem; + margin: 1.5rem 0 +} + +.footer { + background: #061625; + color: #a9bfd1; + padding: 4rem 0 1.5rem +} + +.footer h3, .footer strong { + color: white +} + +.footer-logo { + display: flex; + align-items: center; + gap: .8rem; + margin-bottom: 1rem +} + +.footer-logo img { + width: 3.2rem +} + +.footer a { + color: #c9dce9 +} + +.footer a:hover { + color: var(--cyan) +} + +.footer ul { + list-style: none; + margin: 0; + padding: 0 +} + +.footer li { + margin: .45rem 0 +} + +.footer-bottom { + margin-top: 3rem; + padding-top: 1.3rem; + border-top: 1px solid rgba(255, 255, 255, .1); + display: flex; + justify-content: space-between; + gap: 1rem; + font-size: .85rem +} + +.reveal-on-scroll { + opacity: 0; + transform: translateY(22px); + transition: opacity .65s ease, transform .65s ease +} + +.reveal-on-scroll.visible { + opacity: 1; + transform: none +} + +.cookie-notice { + position: fixed; + z-index: 2000; + left: 1rem; + right: 1rem; + bottom: 1rem; + max-width: 40rem; + margin: auto; + background: white; + border: 1px solid var(--line); + border-radius: 1rem; + box-shadow: var(--shadow); + padding: 1rem 1.2rem; + display: none +} + +.cookie-notice.show { + display: block +} + +.cookie-actions { + display: flex; + gap: .6rem; + flex-wrap: wrap; + margin-top: .7rem +} + +.cookie-actions button { + border: 0; + border-radius: 999px; + padding: .55rem .9rem; + font-weight: 800; + cursor: pointer +} + +.cookie-actions .accept { + background: var(--ink); + color: white +} + +.cookie-actions .decline { + background: #edf3f7; + color: var(--ink) +} + +@media (max-width: 63.999em) { + .desktop-nav { + display: none + } + + .menu-toggle { + display: block + } + + .hero { + min-height: auto + } + + .hero-art { + margin-top: 2rem + } + + .solution-card.large, .solution-card.small { + grid-column: span 6 + } + + .solution-card.third { + grid-column: span 6 + } + + .process-steps { + grid-template-columns:repeat(2, 1fr) + } + + .metric-strip { + grid-template-columns:repeat(2, 1fr) + } +} + +@media (max-width: 39.999em) { + :root { + --header-h: 4.5rem + } + + .grid-container { + padding-left: 1.1rem; + padding-right: 1.1rem + } + + .brand img { + width: 2.6rem; + height: 2.6rem + } + + .brand small { + display: none + } + + .hero { + padding: 3.2rem 0 + } + + .hero-art { + padding: .5rem + } + + .orbit-note { + font-size: .72rem + } + + .solution-card.large, .solution-card.small, .solution-card.third { + grid-column: span 12; + min-height: 19rem + } + + .section-head { + display: block + } + + .section-head .button { + margin-top: 1rem + } + + .process-steps, .company-values, .metric-strip { + grid-template-columns:1fr + } + + .form-grid { + grid-template-columns:1fr + } + + .form-grid .full { + grid-column: auto + } + + .footer-bottom { + display: block + } + + .page-hero { + padding: 3rem 0 2rem + } + + .product-row { + padding: 2rem 0 + } + + .product-visual { + min-height: 15rem; + margin-bottom: 1.5rem + } + + .trust-row { + display: block + } + + .trust-row span { + margin: .6rem 0 + } +} + +@media (prefers-reduced-motion: reduce) { + html { + scroll-behavior: auto + } + + *, *::before, *::after { + animation-duration: .01ms !important; + animation-iteration-count: 1 !important; + transition-duration: .01ms !important + } +} + +/* Visually hidden bot trap; never accept it as a visible form field. */ +.contact-card .honeypot { position: absolute; left: -10000px; width: 1px; height: 1px; overflow: hidden; } +.form-status.error { background: #fff1f0; color: #8c2424; } diff --git a/assets/img/hero-architecture.svg b/assets/img/hero-architecture.svg index c337981..3fba0f2 100644 --- a/assets/img/hero-architecture.svg +++ b/assets/img/hero-architecture.svg @@ -1 +1,63 @@ -dilib SystemarchitekturVernetzte Module für künstliche Intelligenz, Datentransfer, Stammdaten und Prozesssteuerung.TRANSFERMASTERDATAPROCESSIDX / OCR \ No newline at end of file + + dilib Systemarchitektur + Vernetzte Module für künstliche Intelligenz, Datentransfer, Stammdaten und Prozesssteuerung. + + + + + + + + + + + + + + + + + + + + + + + + + + + + TRANSFER + + + + + + MASTERDATA + + + + + + PROCESS + + + + + + + IDX / OCR + + + + + + + + + + diff --git a/assets/img/og-cover.svg b/assets/img/og-cover.svg index 461751c..935e03e 100644 --- a/assets/img/og-cover.svg +++ b/assets/img/og-cover.svg @@ -1 +1,32 @@ -dilibworldGMBHIntelligent. Secure. Connected.Local AI and data platforms for critical business processes. \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + dilibworld + + GMBH + + Intelligent. Secure. + Connected. + + Local AI and data platforms for critical + business processes. + + diff --git a/assets/img/platform-architecture.svg b/assets/img/platform-architecture.svg index 52ec1c2..fda46a7 100644 --- a/assets/img/platform-architecture.svg +++ b/assets/img/platform-architecture.svg @@ -1 +1,60 @@ -Modulare dilib PlattformPartner & SystemeREST · JSON · XML · CSVdilib Data PlatformTransfer · Masterdata · ProcessLokale SystemeERP · CRM · DMS · ShopdilibAIlokal · privat · kontrolliertdilib IDXOCR · Index · VolltextGovernanceRechte · Audit · Monitoring \ No newline at end of file + + Modulare dilib Plattform + + + + + + + + + + + + + + + + + + + + + Partner & Systeme + REST · JSON · XML · CSV + + + + dilib Data Platform + Transfer · Masterdata · Process + + + + Lokale Systeme + ERP · CRM · DMS · Shop + + + + dilibAI + lokal · privat · kontrolliert + + + + dilib IDX + OCR · Index · Volltext + + + + Governance + Rechte · Audit · Monitoring + + + + + + + + + + + diff --git a/assets/img/product-ai.svg b/assets/img/product-ai.svg index eb73132..709d4d0 100644 --- a/assets/img/product-ai.svg +++ b/assets/img/product-ai.svg @@ -1 +1,15 @@ - \ No newline at end of file + + + + + + + + + + + + + + diff --git a/assets/img/product-idx.svg b/assets/img/product-idx.svg index edc7da1..78f2469 100644 --- a/assets/img/product-idx.svg +++ b/assets/img/product-idx.svg @@ -1 +1,12 @@ - \ No newline at end of file + + + + + + + + + + + + diff --git a/assets/img/product-masterdata.svg b/assets/img/product-masterdata.svg index 1bf09f6..ef89d44 100644 --- a/assets/img/product-masterdata.svg +++ b/assets/img/product-masterdata.svg @@ -1 +1,12 @@ - \ No newline at end of file + + + + + + + + + + + diff --git a/assets/img/product-process.svg b/assets/img/product-process.svg index 2798cae..010daa6 100644 --- a/assets/img/product-process.svg +++ b/assets/img/product-process.svg @@ -1 +1,12 @@ - \ No newline at end of file + + + + + + + + + + + + diff --git a/assets/img/product-transfer.svg b/assets/img/product-transfer.svg index 68b2e5e..48041a1 100644 --- a/assets/img/product-transfer.svg +++ b/assets/img/product-transfer.svg @@ -1 +1,12 @@ - \ No newline at end of file + + + + + + + + + + + diff --git a/assets/js/app.js b/assets/js/app.js index 98dcc7f..1039c64 100644 --- a/assets/js/app.js +++ b/assets/js/app.js @@ -1,50 +1,75 @@ (() => { - const menuButton = document.querySelector('[data-menu-toggle]'); - const mobileNav = document.querySelector('[data-mobile-nav]'); - if (menuButton && mobileNav) { - menuButton.addEventListener('click', () => { - const open = mobileNav.classList.toggle('open'); - menuButton.classList.toggle('open', open); - menuButton.setAttribute('aria-expanded', String(open)); + const menuButton = document.querySelector('[data-menu-toggle]'); + const mobileNav = document.querySelector('[data-mobile-nav]'); + if (menuButton && mobileNav) { + menuButton.addEventListener('click', () => { + const open = mobileNav.classList.toggle('open'); + menuButton.classList.toggle('open', open); + menuButton.setAttribute('aria-expanded', String(open)); + }); + mobileNav.querySelectorAll('a').forEach(a => a.addEventListener('click', () => { + mobileNav.classList.remove('open'); + menuButton.classList.remove('open'); + menuButton.setAttribute('aria-expanded', 'false'); + })); + } + + const observer = 'IntersectionObserver' in window ? new IntersectionObserver(entries => { + entries.forEach(entry => { + if (entry.isIntersecting) { + entry.target.classList.add('visible'); + observer.unobserve(entry.target); + } + }); + }, {threshold: .12}) : null; + document.querySelectorAll('.reveal-on-scroll').forEach(el => observer ? observer.observe(el) : el.classList.add('visible')); + + document.querySelectorAll('[data-contact-form]').forEach(form => { + let challengePromise = fetch('/api/contact', {credentials: 'same-origin', cache: 'no-store'}).then(r => { + if (!r.ok) throw new Error('challenge'); + return r.json(); + }).catch(() => null); + form.addEventListener('submit', async event => { + event.preventDefault(); + if (!form.reportValidity()) return; + const fd = new FormData(form); + const lang = document.documentElement.lang || 'de'; + const status = form.querySelector('.form-status'); + const button = form.querySelector('button[type="submit"]'); + button.disabled = true; + status.style.display = 'block'; + status.textContent = lang === 'de' ? 'Nachricht wird gesendet …' : 'Sending message …'; + try { + const challenge = await challengePromise; + if (!challenge?.token) throw new Error('challenge'); + const {token} = challenge; + const payload = Object.fromEntries(fd.entries()); + payload.token = token; + payload.lang = lang; + const response = await fetch('/api/contact', { + method: 'POST', credentials: 'same-origin', + headers: {'Content-Type': 'application/json'}, + body: JSON.stringify(payload) + }); + if (!response.ok) throw new Error('send'); + status.textContent = lang === 'de' ? 'Vielen Dank. Ihre Nachricht wurde übermittelt.' : 'Thank you. Your message has been submitted.'; + form.reset(); + challengePromise = fetch('/api/contact', {credentials: 'same-origin', cache: 'no-store'}).then(r => r.json()).catch(() => null); + } catch (_) { + status.textContent = lang === 'de' ? 'Die Nachricht konnte nicht gesendet werden. Bitte versuchen Sie es später erneut oder schreiben Sie an info@dilibworld.com.' : 'Your message could not be sent. Please try again later or email info@dilibworld.com.'; + } finally { + button.disabled = false; + } + }); }); - mobileNav.querySelectorAll('a').forEach(a => a.addEventListener('click', () => { - mobileNav.classList.remove('open'); menuButton.classList.remove('open'); - menuButton.setAttribute('aria-expanded', 'false'); + + const notice = document.querySelector('[data-cookie-notice]'); + const choice = localStorage.getItem('dilibworld-cookie-choice'); + if (notice && !choice) notice.classList.add('show'); + document.querySelectorAll('[data-cookie-choice]').forEach(btn => btn.addEventListener('click', () => { + localStorage.setItem('dilibworld-cookie-choice', btn.dataset.cookieChoice); + notice?.classList.remove('show'); })); - } - const observer = 'IntersectionObserver' in window ? new IntersectionObserver(entries => { - entries.forEach(entry => { - if (entry.isIntersecting) { entry.target.classList.add('visible'); observer.unobserve(entry.target); } - }); - }, {threshold: .12}) : null; - document.querySelectorAll('.reveal-on-scroll').forEach(el => observer ? observer.observe(el) : el.classList.add('visible')); - - document.querySelectorAll('[data-mailto-form]').forEach(form => { - form.addEventListener('submit', event => { - event.preventDefault(); - if (!form.reportValidity()) return; - const fd = new FormData(form); - const lang = document.documentElement.lang || 'de'; - const lines = []; - for (const [key, value] of fd.entries()) { - if (key !== 'privacy' && key !== 'website') lines.push(`${key}: ${value}`); - } - const subject = lang === 'de' ? 'Anfrage über dilibworld.com' : 'Enquiry via dilibworld.com'; - const email = form.dataset.recipient || 'info@dilibworld.com'; - window.location.href = `mailto:${email}?subject=${encodeURIComponent(subject)}&body=${encodeURIComponent(lines.join('\n'))}`; - const status = form.querySelector('.form-status'); - if (status) { status.style.display = 'block'; } - }); - }); - - const notice = document.querySelector('[data-cookie-notice]'); - const choice = localStorage.getItem('dilibworld-cookie-choice'); - if (notice && !choice) notice.classList.add('show'); - document.querySelectorAll('[data-cookie-choice]').forEach(btn => btn.addEventListener('click', () => { - localStorage.setItem('dilibworld-cookie-choice', btn.dataset.cookieChoice); - notice?.classList.remove('show'); - })); - - document.querySelectorAll('[data-current-year]').forEach(el => el.textContent = new Date().getFullYear()); -})(); \ No newline at end of file + document.querySelectorAll('[data-current-year]').forEach(el => el.textContent = new Date().getFullYear()); +})(); diff --git a/backend/README.md b/backend/README.md new file mode 100644 index 0000000..d450810 --- /dev/null +++ b/backend/README.md @@ -0,0 +1,11 @@ +# Kontaktformular mit Microsoft 365 + +Den Ordner `backend/` vorzugsweise außerhalb des Nginx-Webroots installieren. Wenn das ganze Projekt als Webroot dient, muss die beigefügte Nginx-Regel `/backend/` sperren. Die statischen Seiten bleiben bei Nginx. Nur `/api/contact` wird an den lokalen Python-WSGI-Dienst weitergeleitet. + +1. In Microsoft Entra eine eigene App registrieren, Microsoft Graph **Anwendungsberechtigung** `Mail.Send` erteilen und Administratorzustimmung geben. Die Sendeberechtigung in Exchange Online auf das vorgesehene Postfach einschränken (Application RBAC). Der Absender muss ein vorhandenes Exchange-Online-Postfach sein. Für das Formular kann `info@dilibworld.com` zugleich Absender und Empfänger sein; die Besuchermail steht in `Reply-To`. +2. `contact.env.example` als nicht öffentlich erreichbare Environment-Datei außerhalb des Webroots ablegen. `CONTACT_FORM_SECRET` mit `openssl rand -hex 32` erzeugen. IDs, Secret und Absender eintragen. Die Secret-Datei mit restriktiven Rechten schützen und **nie** in Git oder den Webroot legen. +3. Python-Umgebung anlegen: `python3 -m venv /opt/dilibworld-contact-venv` und `/opt/dilibworld-contact-venv/bin/pip install -r backend/requirements.txt`. Dienst mit einer Gunicorn-Worker-Instanz starten: `gunicorn --workers 1 --bind 127.0.0.1:8091 app:application` (Arbeitsverzeichnis `backend/`, Environment-Datei durch systemd `EnvironmentFile=` einlesen). Nur localhost binden. Bei mehreren Workern muss der einmalige Formularschlüssel in einem gemeinsamen Speicher verwaltet werden. +4. Die beiden Snippets aus `nginx-contact.conf.example` an den angegebenen Stellen in die bestehende HTTPS-Konfiguration aufnehmen. HTTP nach HTTPS umleiten. `nginx -t` ausführen und Nginx neu laden. Wenn `www.dilibworld.com` erreichbar ist, auf `dilibworld.com` umleiten, damit die Origin-Prüfung passt. +5. Nach Einrichtung eine echte Anfrage senden und Empfang sowie `Reply-To` prüfen. Ein gefülltes Feld `website` wird still verworfen. Bei Mailfehlern erscheint eine Fehlermeldung im Formular. Die Datenschutzvorlagen enthalten noch auszufüllende Angaben. + +Der Server prüft Origin, Formularalter, Honeypot, Pflichtfelder, Inhaltstyp und Länge. Nginx begrenzt Anfragen pro IP. Es werden keine Tokens oder Mailinhalte protokolliert. Microsoft Graph bestätigt eine angenommene Nachricht mit HTTP 202; die tatsächliche Zustellung ist damit noch nicht garantiert. diff --git a/backend/app.py b/backend/app.py new file mode 100644 index 0000000..080f0db --- /dev/null +++ b/backend/app.py @@ -0,0 +1,132 @@ +"""Small WSGI contact endpoint. Run behind HTTPS and the Nginx rate limit.""" +import base64 +import binascii +import hashlib +import hmac +import json +import logging +import os +import re +import secrets +import time +import urllib.error +import urllib.parse +import urllib.request + +LOG = logging.getLogger(__name__) +ORIGIN = os.environ.get('CONTACT_ORIGIN', 'https://dilibworld.com').rstrip('/') +SECRET = os.environ.get('CONTACT_FORM_SECRET', '').encode() +SENDER = os.environ.get('GRAPH_SENDER', 'info@dilibworld.com') +RECIPIENT = os.environ.get('CONTACT_RECIPIENT', 'info@dilibworld.com') +FIELDS = { + 'de': ('Vorname', 'Nachname', 'Unternehmen', 'E-Mail', 'Telefon', 'Thema', 'Nachricht'), + 'en': ('First name', 'Last name', 'Company', 'Email', 'Phone', 'Topic', 'Message'), +} +USED = {} + + +def reply(start_response, status, data): + body = json.dumps(data).encode() + start_response(status, [('Content-Type', 'application/json; charset=utf-8'), + ('Content-Length', str(len(body))), ('Cache-Control', 'no-store'), + ('X-Content-Type-Options', 'nosniff')]) + return [body] + + +def token(): + value = f'{int(time.time())}:{secrets.token_urlsafe(18)}' + signature = hmac.new(SECRET, value.encode(), hashlib.sha256).hexdigest() + return base64.urlsafe_b64encode(f'{value}:{signature}'.encode()).decode() + + +def valid_token(value): + try: + raw = base64.urlsafe_b64decode(value.encode()).decode() + timestamp, nonce, signature = raw.split(':') + signed = f'{timestamp}:{nonce}' + age = time.time() - int(timestamp) + digest = hmac.new(SECRET, signed.encode(), hashlib.sha256).hexdigest() + if not (3 <= age <= 3600 and hmac.compare_digest(digest, signature)): + return False + now = time.time() + for key, expiry in list(USED.items()): + if expiry < now: + del USED[key] + if signature in USED: + return False + USED[signature] = now + 3600 + return True + except (ValueError, UnicodeError, TypeError, binascii.Error): + return False + + +def graph_send(values, lang): + tenant = os.environ['GRAPH_TENANT_ID'] + app_id = os.environ['GRAPH_CLIENT_ID'] + client_secret = os.environ['GRAPH_CLIENT_SECRET'] + form = urllib.parse.urlencode({'client_id': app_id, 'client_secret': client_secret, + 'scope': 'https://graph.microsoft.com/.default', + 'grant_type': 'client_credentials'}).encode() + url = f'https://login.microsoftonline.com/{urllib.parse.quote(tenant, safe="")}/oauth2/v2.0/token' + request = urllib.request.Request(url, form, {'Content-Type': 'application/x-www-form-urlencoded'}) + with urllib.request.urlopen(request, timeout=10) as response: + access_token = json.load(response)['access_token'] + labels = FIELDS[lang] + content = '\n'.join(f'{label}: {values.get(label, "")}' for label in labels) + email = values[labels[3]] + message = {'message': { + 'subject': 'Kontaktanfrage über dilibworld.com', + 'body': {'contentType': 'Text', 'content': content}, + 'toRecipients': [{'emailAddress': {'address': RECIPIENT}}], + 'replyTo': [{'emailAddress': {'address': email}}], + }, 'saveToSentItems': True} + endpoint = 'https://graph.microsoft.com/v1.0/users/' + urllib.parse.quote(SENDER, safe='@') + '/sendMail' + request = urllib.request.Request(endpoint, json.dumps(message).encode(), + {'Content-Type': 'application/json', 'Authorization': f'Bearer {access_token}'}) + with urllib.request.urlopen(request, timeout=15) as response: + if response.status != 202: + raise RuntimeError('Graph did not accept the message') + + +def application(environ, start_response): + if environ.get('PATH_INFO') != '/api/contact': + return reply(start_response, '404 Not Found', {'error': 'not_found'}) + if not SECRET or not all(os.environ.get(key) for key in ('GRAPH_TENANT_ID', 'GRAPH_CLIENT_ID', 'GRAPH_CLIENT_SECRET')): + LOG.error('Contact service configuration incomplete') + return reply(start_response, '503 Service Unavailable', {'error': 'unavailable'}) + method = environ.get('REQUEST_METHOD') + if method == 'GET': + return reply(start_response, '200 OK', {'token': token()}) + if method != 'POST': + return reply(start_response, '405 Method Not Allowed', {'error': 'method'}) + if environ.get('HTTP_ORIGIN') != ORIGIN or environ.get('CONTENT_TYPE', '').split(';')[0] != 'application/json': + return reply(start_response, '403 Forbidden', {'error': 'origin'}) + try: + length = int(environ.get('CONTENT_LENGTH', '0')) + if not 0 < length <= 12000: + raise ValueError('length') + data = json.loads(environ['wsgi.input'].read(length)) + lang = data.get('lang') + if lang not in FIELDS or not isinstance(data.get('website'), str) or not isinstance(data.get('token'), str): + raise ValueError('fields') + if data['website']: + return reply(start_response, '200 OK', {'ok': True}) + if not valid_token(data['token']): + raise ValueError('token') + labels = FIELDS[lang] + values = {key: data.get(key, '') for key in labels} + if any(not isinstance(v, str) or len(v) > (5000 if key == labels[6] else 200) for key, v in values.items()): + raise ValueError('field length') + if not all(values[key].strip() for key in (labels[0], labels[1], labels[3], labels[6])): + raise ValueError('required') + if not re.fullmatch(r'[^\s@\r\n]+@[^\s@\r\n]+\.[^\s@\r\n]+', values[labels[3]]) or len(values[labels[3]]) > 254: + raise ValueError('email') + if data.get('privacy') not in ('akzeptiert', 'accepted'): + raise ValueError('privacy') + graph_send(values, lang) + except (ValueError, TypeError, KeyError, json.JSONDecodeError): + return reply(start_response, '400 Bad Request', {'error': 'invalid'}) + except (urllib.error.URLError, TimeoutError, RuntimeError): + LOG.exception('Contact delivery failed') + return reply(start_response, '502 Bad Gateway', {'error': 'delivery'}) + return reply(start_response, '200 OK', {'ok': True}) diff --git a/backend/contact.env b/backend/contact.env new file mode 100644 index 0000000..6201a7e --- /dev/null +++ b/backend/contact.env @@ -0,0 +1,7 @@ +CONTACT_ORIGIN=https://dilibworld.com +CONTACT_FORM_SECRET=REPLACE_WITH_RANDOM_SECRET +GRAPH_TENANT_ID=e966b988-0d5e-446c-9d7d-7ebd2b751546 +GRAPH_CLIENT_ID=9876e61a-b2ff-4b31-90c9-39e583b3cf73 +GRAPH_CLIENT_SECRET=JXA8Q~QMOKIXy~waf~OCJGz2M3QUu5~qBgr5vb0V +GRAPH_SENDER=info@dilibworld.com +CONTACT_RECIPIENT=info@dilibworld.com diff --git a/backend/contact.env.example b/backend/contact.env.example new file mode 100644 index 0000000..efee72b --- /dev/null +++ b/backend/contact.env.example @@ -0,0 +1,7 @@ +CONTACT_ORIGIN=https://dilibworld.com +CONTACT_FORM_SECRET=REPLACE_WITH_RANDOM_SECRET +GRAPH_TENANT_ID=REPLACE_WITH_TENANT_GUID +GRAPH_CLIENT_ID=REPLACE_WITH_APP_GUID +GRAPH_CLIENT_SECRET=REPLACE_WITH_SECRET_VALUE +GRAPH_SENDER=info@dilibworld.com +CONTACT_RECIPIENT=info@dilibworld.com diff --git a/backend/nginx-contact.conf.example b/backend/nginx-contact.conf.example new file mode 100644 index 0000000..9eb565c --- /dev/null +++ b/backend/nginx-contact.conf.example @@ -0,0 +1,14 @@ +# Add limit_req_zone in the nginx http {} context (not inside server {}): +limit_req_zone $binary_remote_addr zone=contact_form:10m rate=3r/m; + +# Add this location inside the existing HTTPS server for dilibworld.com: +location = /api/contact { + client_max_body_size 12k; + limit_req zone=contact_form burst=5 nodelay; + proxy_set_header Host $host; + proxy_set_header X-Forwarded-Proto https; + proxy_pass http://127.0.0.1:8091; +} + +# If the project directory itself is the Nginx document root, deny backend code: +location ^~ /backend/ { return 404; } diff --git a/backend/requirements.txt b/backend/requirements.txt new file mode 100644 index 0000000..bf1b27c --- /dev/null +++ b/backend/requirements.txt @@ -0,0 +1 @@ +gunicorn>=23,<24 diff --git a/de/datenschutz.html b/de/datenschutz.html index 44227af..c085e6e 100644 --- a/de/datenschutz.html +++ b/de/datenschutz.html @@ -1,11 +1,135 @@ -Datenschutz | dilibworld GmbH -
Datenschutz

Datenschutzerklärung

- + + + + + + Datenschutz | dilibworld GmbH + + + + + + + + + + + + + + + + +
+
+
Datenschutz +

Datenschutzerklärung

+
+
+ +
+
+ + + + + diff --git a/de/kontakt.html b/de/kontakt.html index a8a1f9d..13af7a5 100644 --- a/de/kontakt.html +++ b/de/kontakt.html @@ -1,11 +1,143 @@ -Kontakt | dilibworld GmbH -
Kontakt

Lassen Sie uns Ihren Anwendungsfall verstehen.

Ein gutes Projekt beginnt nicht mit einem Produkt, sondern mit einem klaren Problem, den richtigen Daten und einem messbaren Ziel.

Direkter Austausch.

Beschreiben Sie kurz, welche Systeme, Daten oder Prozesse verbunden, automatisiert oder mit lokaler KI unterstützt werden sollen.

Das Formular öffnet Ihr lokales E-Mail-Programm. Es werden keine Formulardaten auf dieser Website gespeichert.

Ihr E-Mail-Programm wurde geöffnet. Bitte prüfen und senden Sie die Nachricht dort.
- + + + + + + Kontakt | dilibworld GmbH + + + + + + + + + + + + + + + + +
+
+
Kontakt +

Lassen Sie uns Ihren Anwendungsfall verstehen.

+

Ein gutes Projekt beginnt nicht mit einem Produkt, sondern mit einem klaren Problem, den + richtigen Daten und einem messbaren Ziel.

+
+
+
+
+

Direkter Austausch.

+

Beschreiben Sie kurz, welche Systeme, Daten oder Prozesse verbunden, automatisiert + oder mit lokaler KI unterstützt werden sollen.

+ +

Ihre Anfrage wird verschlüsselt übermittelt und per Microsoft 365 an uns gesendet.

+
+
+
+
+ +
Vielen Dank. Ihre Nachricht wurde übermittelt. +
+
+
+
+
+
+
+
+
+ + + + + diff --git a/de/loesungen.html b/de/loesungen.html index f0cddb5..e46ee3b 100644 --- a/de/loesungen.html +++ b/de/loesungen.html @@ -1,11 +1,210 @@ -Lösungen | dilibworld GmbH -
Die dilib Plattform

Modular entwickelt. Gemeinsam stark.

Die Module der dilib Plattform greifen ineinander und können dennoch schrittweise eingeführt werden. So entsteht aus konkreten Anwendungsfällen eine belastbare, unternehmensweite Architektur.

dilibAI

Lokale KI. Vertrauliches Wissen. Volle Kontrolle.

dilibAI bringt Sprachmodelle und datenbasierte Assistenz in die eigene Infrastruktur. Interne Dokumente, Prompts und Geschäftsgeheimnisse müssen das Unternehmen nicht verlassen.

  • Wissensassistenten für Fachbereiche
  • Analyse von Dokumenten und Unternehmensdaten
  • Planung passender Server- und GPU-Infrastruktur
  • Berechtigungen, Quellenbezug und kontrollierte Nutzung
dilib Transfer

Die sichere Brücke zwischen Systemen.

dilib Transfer verbindet interne und externe Systeme über moderne Schnittstellen. Neben REST und JSON lassen sich XML, CSV, Excel und individuell vereinbarte Formate zuverlässig verarbeiten.

  • RESTful Services und APIs
  • Dateibasierte Importe und Exporte
  • Validierung, Fehlerbehandlung und Wiederholung
  • Partner-, Kunden- und Lieferantenintegration
dilib Masterdata

Unterschiedliche Daten werden gemeinsam nutzbar.

Eingehende Daten werden zunächst unverändert übernommen, fachlich normalisiert und anschließend passend für jedes Zielsystem strukturiert. Veränderungen und Zuordnungen bleiben nachvollziehbar.

  • Normalisierung und Mapping
  • Dublettenerkennung und Datenqualität
  • Zielsystemspezifische Aufbereitung
  • Protokollierung fachlicher Änderungen
dilib Process

Automatisierung im Herzen der Plattform.

Der Prozessserver steuert zeit-, ereignis- oder regelabhängige Aufgaben. Er überwacht Ausführungen, behandelt Fehler und sorgt dafür, dass wiederkehrende Arbeiten zuverlässig laufen.

  • Zeitpläne, Ereignisse und Regeln
  • Monitoring und Statusmeldungen
  • Wiederholungen und kontrollierte Fehlerpfade
  • Ressourcenschonende Hintergrundverarbeitung
dilib IDX

Dokumente werden zu nutzbarem Wissen.

dilib IDX verbindet OCR, Indexierung, Metadaten und Volltextsuche. Dokumente können automatisiert übernommen, getrennt, klassifiziert und für berechtigte Nutzer schnell auffindbar gemacht werden.

  • OCR und durchsuchbare PDFs
  • Metadaten- und Volltextindex
  • Automatische Dokumentenverarbeitung
  • Rollen- und Berechtigungskonzepte

Die passende Kombination beginnt mit Ihrem Prozess.

Wir identifizieren die Module, die den größten sicheren und wirtschaftlichen Nutzen erzeugen.

Anforderungen besprechen
- + + + + + + Lösungen | dilibworld GmbH + + + + + + + + + + + + + + + + +
+
+
Die dilib Plattform +

Modular entwickelt. Gemeinsam stark.

+

Die Module der dilib Plattform greifen ineinander und können dennoch schrittweise eingeführt + werden. So entsteht aus konkreten Anwendungsfällen eine belastbare, unternehmensweite Architektur.

+
+
+
+
+
+
+
+
+
+
+
dilibAI +

Lokale KI. Vertrauliches Wissen. Volle Kontrolle.

+

dilibAI bringt Sprachmodelle und datenbasierte Assistenz in die eigene + Infrastruktur. Interne Dokumente, Prompts und Geschäftsgeheimnisse müssen das Unternehmen + nicht verlassen.

+
    +
  • Wissensassistenten für Fachbereiche
  • +
  • Analyse von Dokumenten und Unternehmensdaten
  • +
  • Planung passender Server- und GPU-Infrastruktur
  • +
  • Berechtigungen, Quellenbezug und kontrollierte Nutzung
  • +
+
+
+
+
+
+
dilib Transfer +

Die sichere Brücke zwischen Systemen.

+

dilib Transfer verbindet interne und externe Systeme über moderne + Schnittstellen. Neben REST und JSON lassen sich XML, CSV, Excel und individuell vereinbarte + Formate zuverlässig verarbeiten.

+
    +
  • RESTful Services und APIs
  • +
  • Dateibasierte Importe und Exporte
  • +
  • Validierung, Fehlerbehandlung und Wiederholung
  • +
  • Partner-, Kunden- und Lieferantenintegration
  • +
+
+
+
+
+
+
+
+
+
+
+
+
dilib Masterdata +

Unterschiedliche Daten werden gemeinsam nutzbar.

+

Eingehende Daten werden zunächst unverändert übernommen, fachlich normalisiert + und anschließend passend für jedes Zielsystem strukturiert. Veränderungen und Zuordnungen + bleiben nachvollziehbar.

+
    +
  • Normalisierung und Mapping
  • +
  • Dublettenerkennung und Datenqualität
  • +
  • Zielsystemspezifische Aufbereitung
  • +
  • Protokollierung fachlicher Änderungen
  • +
+
+
+
+
+
+
dilib Process +

Automatisierung im Herzen der Plattform.

+

Der Prozessserver steuert zeit-, ereignis- oder regelabhängige Aufgaben. Er + überwacht Ausführungen, behandelt Fehler und sorgt dafür, dass wiederkehrende Arbeiten + zuverlässig laufen.

+
    +
  • Zeitpläne, Ereignisse und Regeln
  • +
  • Monitoring und Statusmeldungen
  • +
  • Wiederholungen und kontrollierte Fehlerpfade
  • +
  • Ressourcenschonende Hintergrundverarbeitung
  • +
+
+
+
+
+
+
+
+
+
+
+
+
+
dilib IDX +

Dokumente werden zu nutzbarem Wissen.

+

dilib IDX verbindet OCR, Indexierung, Metadaten und Volltextsuche. Dokumente + können automatisiert übernommen, getrennt, klassifiziert und für berechtigte Nutzer schnell + auffindbar gemacht werden.

+
    +
  • OCR und durchsuchbare PDFs
  • +
  • Metadaten- und Volltextindex
  • +
  • Automatische Dokumentenverarbeitung
  • +
  • Rollen- und Berechtigungskonzepte
  • +
+
+
+
+
+
+
+
+

Die passende Kombination beginnt mit Ihrem Prozess.

+

Wir identifizieren die Module, die den größten sicheren und wirtschaftlichen Nutzen + erzeugen.

Anforderungen besprechen
+
+
+
+ + + + + diff --git a/de/unternehmen.html b/de/unternehmen.html index 323524d..20b46d8 100644 --- a/de/unternehmen.html +++ b/de/unternehmen.html @@ -1,11 +1,150 @@ -Unternehmen | dilibworld GmbH -
dilibworld GmbH

Digitale Freiheit für Unternehmen.

Wir entwickeln sichere Softwareplattformen, die Daten, Prozesse und künstliche Intelligenz unter der Kontrolle unserer Kunden zusammenführen.

Aus Erfahrung mit komplexen und schutzbedürftigen Daten.

Die technologische Basis von dilib entstand aus langjähriger Arbeit an anspruchsvollen Integrations-, Dokumenten- und Verfahrenssystemen. Daraus wurde eine modulare Plattform für Unternehmen, die mehr benötigen als einzelne Schnittstellen oder isolierte KI-Werkzeuge.

dilib steht für digital liberty: Unternehmen sollen ihre Systeme modernisieren können, ohne die Kontrolle über Daten, Wissen und geschäftskritische Abläufe abzugeben. Deshalb verbinden wir offene Integration mit lokalem Betrieb, klaren Berechtigungen und nachvollziehbarer Automatisierung.

dilibworld Plattform
Unsere Grundsätze

Technologie muss Vertrauen verdienen.

Souveränität

Datenhaltung, Modelle und Betriebsform werden passend zur Organisation geplant.

Integration

Bestehende Investitionen werden eingebunden, statt funktionierende Systeme pauschal zu ersetzen.

Wirtschaftlichkeit

Projekte beginnen mit klaren Zielen, messbarem Nutzen und einem realistischen Einführungspfad.

Wofür wir stehen

„Künstliche Intelligenz wird erst dann zu einem Unternehmenswert, wenn Daten, Prozesse und Verantwortung zusammen gedacht werden.“

Partnerschaftlich von der Analyse bis zum Betrieb.

  • Fachliche und technische Anforderungsanalyse
  • Architektur, Integration und individuelle Erweiterungen
  • Lokaler, eigener oder betreuter Betrieb
  • Dokumentation, Übergabe und langfristige Weiterentwicklung
- + + + + + + Unternehmen | dilibworld GmbH + + + + + + + + + + + + + + + + +
+
+
dilibworld GmbH +

Digitale Freiheit für Unternehmen.

+

Wir entwickeln sichere Softwareplattformen, die Daten, Prozesse und künstliche Intelligenz + unter der Kontrolle unserer Kunden zusammenführen.

+
+
+
+
+

Aus Erfahrung mit komplexen und schutzbedürftigen Daten.

+

Die technologische Basis von dilib entstand aus langjähriger Arbeit an + anspruchsvollen Integrations-, Dokumenten- und Verfahrenssystemen. Daraus wurde eine modulare + Plattform für Unternehmen, die mehr benötigen als einzelne Schnittstellen oder isolierte + KI-Werkzeuge.

+

dilib steht für digital liberty: Unternehmen sollen ihre Systeme modernisieren + können, ohne die Kontrolle über Daten, Wissen und geschäftskritische Abläufe abzugeben. Deshalb + verbinden wir offene Integration mit lokalem Betrieb, klaren Berechtigungen und + nachvollziehbarer Automatisierung.

+
+
dilibworld Plattform
+
+
+
+
+
+
Unsere Grundsätze +

Technologie muss Vertrauen verdienen.

+
+
Souveränität +

Datenhaltung, Modelle und Betriebsform werden passend zur Organisation geplant.

+
Integration +

Bestehende Investitionen werden eingebunden, statt funktionierende Systeme pauschal zu + ersetzen.

+
Wirtschaftlichkeit +

Projekte beginnen mit klaren Zielen, messbarem Nutzen und einem realistischen + Einführungspfad.

+
+
+
+
+
+
+
Wofür wir stehen +

„Künstliche Intelligenz wird erst dann zu einem Unternehmenswert, wenn Daten, + Prozesse und Verantwortung zusammen gedacht werden.“

+

Partnerschaftlich von der Analyse bis zum Betrieb.

+
    +
  • Fachliche und technische Anforderungsanalyse
  • +
  • Architektur, Integration und individuelle Erweiterungen
  • +
  • Lokaler, eigener oder betreuter Betrieb
  • +
  • Dokumentation, Übergabe und langfristige Weiterentwicklung
  • +
+
+
+
+
+
+ + + + + diff --git a/en/company.html b/en/company.html index 1f3d345..31012ae 100644 --- a/en/company.html +++ b/en/company.html @@ -1,11 +1,146 @@ -Company | dilibworld GmbH -
dilibworld GmbH

Digital liberty for enterprises.

We develop secure software platforms that bring data, processes and artificial intelligence together under our customers' control.

Built on experience with complex and sensitive data.

The technological foundation of dilib grew from years of work on demanding integration, document and procedural systems. It has evolved into a modular platform for organisations that need more than isolated interfaces or stand-alone AI tools.

dilib stands for digital liberty: enterprises should be able to modernise their systems without surrendering control of data, knowledge and business-critical operations. We therefore combine open integration with local deployment, clear permissions and traceable automation.

dilibworld platform
Our principles

Technology must earn trust.

Sovereignty

Data storage, models and operating model are planned around the organisation.

Integration

Existing investments are connected instead of replacing working systems by default.

Commercial value

Projects begin with clear objectives, measurable outcomes and a realistic adoption path.

What we believe

“Artificial intelligence becomes an enterprise asset only when data, processes and responsibility are designed together.”

A collaborative path from analysis to operations.

  • Business and technical requirements analysis
  • Architecture, integration and custom extensions
  • Local, customer-operated or managed deployment
  • Documentation, handover and long-term evolution
- + + + + + + Company | dilibworld GmbH + + + + + + + + + + + + + + + + +
+
+
dilibworld GmbH +

Digital liberty for enterprises.

+

We develop secure software platforms that bring data, processes and artificial intelligence + together under our customers' control.

+
+
+
+
+

Built on experience with complex and sensitive data.

+

The technological foundation of dilib grew from years of work on demanding + integration, document and procedural systems. It has evolved into a modular platform for + organisations that need more than isolated interfaces or stand-alone AI tools.

+

dilib stands for digital liberty: enterprises should be able to modernise their + systems without surrendering control of data, knowledge and business-critical operations. We + therefore combine open integration with local deployment, clear permissions and traceable + automation.

+
+
dilibworld platform
+
+
+
+
+
+
Our principles +

Technology must earn trust.

+
+
Sovereignty +

Data storage, models and operating model are planned around the organisation.

+
Integration +

Existing investments are connected instead of replacing working systems by default.

+
Commercial value +

Projects begin with clear objectives, measurable outcomes and a realistic adoption path.

+
+
+
+
+
+
+
+
What we believe +

“Artificial intelligence becomes an enterprise asset only when data, processes and + responsibility are designed together.”

+

A collaborative path from analysis to operations.

+
    +
  • Business and technical requirements analysis
  • +
  • Architecture, integration and custom extensions
  • +
  • Local, customer-operated or managed deployment
  • +
  • Documentation, handover and long-term evolution
  • +
+
+
+
+
+
+ + + + + diff --git a/en/contact.html b/en/contact.html index 35a7f14..a1a97de 100644 --- a/en/contact.html +++ b/en/contact.html @@ -1,11 +1,141 @@ -Contact | dilibworld GmbH -
Contact

Let us understand your use case.

A strong project does not start with a product. It starts with a clear problem, the right data and a measurable objective.

A direct conversation.

Briefly describe which systems, data or processes should be connected, automated or supported by local AI.

The form opens your local email application. No form data is stored on this website.

Your email application has been opened. Please review and send the message there.
- + + + + + + Contact | dilibworld GmbH + + + + + + + + + + + + + + + + +
+
+
Contact +

Let us understand your use case.

+

A strong project does not start with a product. It starts with a clear problem, the right + data and a measurable objective.

+
+
+
+
+

A direct conversation.

+

Briefly describe which systems, data or processes should be connected, automated or + supported by local AI.

+ +

Your enquiry is transmitted securely and sent to us through Microsoft 365.

+
+
+
+
+ +
Thank you. Your message has been submitted. +
+
+
+
+
+
+
+
+
+ + + + + diff --git a/en/privacy.html b/en/privacy.html index b5ce59e..2bbeb2c 100644 --- a/en/privacy.html +++ b/en/privacy.html @@ -69,9 +69,7 @@ attacks on the basis of legitimate interests under Article 6(1)(f) GDPR.

[add hosting provider, location and retention period]

4. Contact

-

The contact form opens the user's local email application. The entered content is not transmitted to or - stored by this website. When the email is sent, the data is processed by the participating email - systems. The legal basis is Article 6(1)(b) or (f) GDPR depending on the content.

+

When you use the contact form, we process the contact details and message you provide to respond to your enquiry. The information is sent securely to our server and then through Microsoft 365 to our mailbox. A hidden field, a time-limited form token and request limits help prevent spam. This backend does not retain the form submission; the email remains in the mailbox and possibly Sent Items. Depending on your request, the legal basis is Article 6(1)(b) or (f) GDPR. [Complete Microsoft 365 processing, retention period and hosting details before publication.]

5. Cookies and local storage

The website does not use analytics or marketing cookies. A technically necessary choice is stored only in the browser's local storage to hide the privacy notice. It contains no personal profile data and is not diff --git a/en/solutions.html b/en/solutions.html index 64264f5..16570b6 100644 --- a/en/solutions.html +++ b/en/solutions.html @@ -1,11 +1,205 @@ -Solutions | dilibworld GmbH -

The dilib platform

Modular by design. Stronger together.

The modules of the dilib platform work together while still allowing a phased introduction. Concrete use cases grow into a robust enterprise-wide architecture.

dilibAI

Local AI. Confidential knowledge. Full control.

dilibAI brings language models and data-driven assistance into your own infrastructure. Internal documents, prompts and business secrets do not need to leave the organisation.

  • Knowledge assistants for specialist teams
  • Analysis of documents and enterprise data
  • Planning suitable server and GPU infrastructure
  • Permissions, source references and controlled use
dilib Transfer

The secure bridge between systems.

dilib Transfer connects internal and external systems through modern interfaces. In addition to REST and JSON, XML, CSV, Excel and agreed custom formats can be processed reliably.

  • RESTful services and APIs
  • File-based imports and exports
  • Validation, error handling and retries
  • Partner, customer and supplier integration
dilib Masterdata

Different data becomes usable together.

Incoming data is initially accepted as received, normalised for business use and structured for each target system. Changes and mappings remain traceable.

  • Normalisation and mapping
  • Duplicate detection and data quality
  • Target-system-specific preparation
  • Logging of business changes
dilib Process

Automation at the heart of the platform.

The process server controls time-, event- and rule-driven tasks. It monitors execution, handles errors and keeps recurring work running reliably.

  • Schedules, events and rules
  • Monitoring and status messages
  • Retries and controlled error paths
  • Resource-efficient background processing
dilib IDX

Documents become usable knowledge.

dilib IDX combines OCR, indexing, metadata and full-text search. Documents can be ingested, split, classified and made quickly discoverable for authorised users.

  • OCR and searchable PDFs
  • Metadata and full-text index
  • Automated document processing
  • Role and permission concepts

The right combination starts with your process.

We identify the modules that create the greatest secure and commercial value.

Discuss requirements
- + + + + + + Solutions | dilibworld GmbH + + + + + + + + + + + + + + + + +
+
+
The dilib platform +

Modular by design. Stronger together.

+

The modules of the dilib platform work together while still allowing a phased introduction. + Concrete use cases grow into a robust enterprise-wide architecture.

+
+
+
+
+
+
+
+
+
+
dilibAI +

Local AI. Confidential knowledge. Full control.

+

dilibAI brings language models and data-driven assistance into your own + infrastructure. Internal documents, prompts and business secrets do not need to leave the + organisation.

+
    +
  • Knowledge assistants for specialist teams
  • +
  • Analysis of documents and enterprise data
  • +
  • Planning suitable server and GPU infrastructure
  • +
  • Permissions, source references and controlled use
  • +
+
+
+
+
+
+
dilib Transfer +

The secure bridge between systems.

+

dilib Transfer connects internal and external systems through modern interfaces. + In addition to REST and JSON, XML, CSV, Excel and agreed custom formats can be processed + reliably.

+
    +
  • RESTful services and APIs
  • +
  • File-based imports and exports
  • +
  • Validation, error handling and retries
  • +
  • Partner, customer and supplier integration
  • +
+
+
+
+
+
+
+
+
+
+
+
+
dilib Masterdata +

Different data becomes usable together.

+

Incoming data is initially accepted as received, normalised for business use and + structured for each target system. Changes and mappings remain traceable.

+
    +
  • Normalisation and mapping
  • +
  • Duplicate detection and data quality
  • +
  • Target-system-specific preparation
  • +
  • Logging of business changes
  • +
+
+
+
+
+
+
dilib Process +

Automation at the heart of the platform.

+

The process server controls time-, event- and rule-driven tasks. It monitors + execution, handles errors and keeps recurring work running reliably.

+
    +
  • Schedules, events and rules
  • +
  • Monitoring and status messages
  • +
  • Retries and controlled error paths
  • +
  • Resource-efficient background processing
  • +
+
+
+
+
+
+
+
+
+
+
+
+
+
dilib IDX +

Documents become usable knowledge.

+

dilib IDX combines OCR, indexing, metadata and full-text search. Documents can + be ingested, split, classified and made quickly discoverable for authorised users.

+
    +
  • OCR and searchable PDFs
  • +
  • Metadata and full-text index
  • +
  • Automated document processing
  • +
  • Role and permission concepts
  • +
+
+
+
+
+
+
+
+

The right combination starts with your process.

+

We identify the modules that create the greatest secure and commercial value.

Discuss requirements
+
+
+
+ + + + + diff --git a/index.html b/index.html index aa7977b..745b1ea 100644 --- a/index.html +++ b/index.html @@ -1 +1,12 @@ -dilibworld GmbH

Deutsch · English

\ No newline at end of file + + + + + + dilibworld GmbH + + + +

Deutsch · English

+ diff --git a/sitemap.xml b/sitemap.xml index dcc2a5c..8c98ff0 100644 --- a/sitemap.xml +++ b/sitemap.xml @@ -1,15 +1,39 @@ - https://dilibworld.com/de/ - https://dilibworld.com/en/ - https://dilibworld.com/de/loesungen.html - https://dilibworld.com/en/solutions.html - https://dilibworld.com/de/unternehmen.html - https://dilibworld.com/en/company.html - https://dilibworld.com/de/kontakt.html - https://dilibworld.com/en/contact.html - https://dilibworld.com/de/impressum.html - https://dilibworld.com/en/legal-notice.html - https://dilibworld.com/de/datenschutz.html - https://dilibworld.com/en/privacy.html + + https://dilibworld.com/de/ + + + https://dilibworld.com/en/ + + + https://dilibworld.com/de/loesungen.html + + + https://dilibworld.com/en/solutions.html + + + https://dilibworld.com/de/unternehmen.html + + + https://dilibworld.com/en/company.html + + + https://dilibworld.com/de/kontakt.html + + + https://dilibworld.com/en/contact.html + + + https://dilibworld.com/de/impressum.html + + + https://dilibworld.com/en/legal-notice.html + + + https://dilibworld.com/de/datenschutz.html + + + https://dilibworld.com/en/privacy.html +