Files
Key-service-Server/Website/templates/base.html
T
Aiirondev_dev 9468a1333e Enhance website templates for Invario services and pricing
- Updated dienstleistungen.html to improve layout and content clarity, including new service descriptions and a refined CSS style for better visual appeal.
- Revamped inventarsystem.html with a focus on key features and pricing, adding a structured layout and enhancing the user experience with new design elements.
- Modified main.html to reflect updated pricing information and improve SEO with enhanced meta descriptions and structured data for better search visibility.
- Revised preise.html to clearly present pricing details, including new pricing pills and comparison cards for better user understanding of offerings.
2026-05-11 14:42:35 +02:00

804 lines
28 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0, user-scalable=yes, viewport-fit=cover">
<meta name="mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<title>{% block title %}Digitale Inventarverwaltung für Schulen{% endblock %}</title>
{# Basic SEO meta tags, can be overridden per-template by setting `meta_description` #}
<meta name="description" content="{{ meta_description|default('Invario: Schul-Inventarverwaltung für 250 €/Jahr oder Bibliothekssystem für 100 €/Jahr – entwickelt mit der Grundschule Albert-Schweitzer-Straße.') }}">
<meta name="robots" content="index, follow">
<link rel="canonical" href="{{ request.url_root.rstrip('/') }}{{ request.path }}">
<!-- OpenGraph / Twitter -->
<meta property="og:site_name" content="Invario">
<meta property="og:title" content="{{ meta_title|default('Digitale Inventarverwaltung für Schulen') }}">
<meta property="og:description" content="{{ meta_description|default('Invario: Schul-Inventarverwaltung für 250 €/Jahr oder Bibliothekssystem für 100 €/Jahr – entwickelt mit der Grundschule Albert-Schweitzer-Straße.') }}">
<meta property="og:type" content="website">
<meta property="og:url" content="{{ request.url_root.rstrip('/') }}{{ request.path }}">
<meta property="og:image" content="{{ url_for('static', filename='images/logo-1.jpeg') }}">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="{{ meta_title|default('Digitale Inventarverwaltung für Schulen') }}">
<meta name="twitter:description" content="{{ meta_description|default('Invario: Schul-Inventarverwaltung für 250 €/Jahr oder Bibliothekssystem für 100 €/Jahr – entwickelt mit der Grundschule Albert-Schweitzer-Straße.') }}">
<meta name="twitter:image" content="{{ url_for('static', filename='images/logo-1.jpeg') }}">
{% block head %}
<link rel="preconnect" href="https://api.fontshare.com">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://api.fontshare.com/v2/css?f[]=satoshi@400,500,700,900&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet">
<style>
:root {
--bg-main: #f4f6f4;
--bg-soft: #e6ebe6;
--surface: #ffffff;
--text-main: #102126;
--text-soft: #42565d;
--line: #c9d4d0;
--brand: #0f5d69;
--brand-strong: #0a3d45;
--accent: #a85c24;
--radius-md: 14px;
--shadow-sm: 0 10px 30px rgba(18, 40, 44, 0.08);
--shell-gutter: clamp(12px, 2.2vw, 34px);
--shell-max-width: 1240px;
}
* { box-sizing: border-box; }
:focus-visible {
outline: 3px solid #0f5d69;
outline-offset: 3px;
}
/* Verhinderung von iOS Auto-Zoom bei Inputs */
input, textarea, select, button {
font-family: inherit;
font-size: 16px;
}
html,
body {
margin: 0;
padding: 0;
padding-bottom: env(safe-area-inset-bottom);
padding-left: env(safe-area-inset-left);
padding-right: env(safe-area-inset-right);
min-height: 100%;
font-family: "Inter", system-ui, sans-serif;
color: var(--text-main);
background:
radial-gradient(circle at 88% -8%, rgba(15, 93, 105, 0.08) 0%, transparent 34%),
radial-gradient(circle at -5% 58%, rgba(168, 92, 36, 0.08) 0%, transparent 40%),
var(--bg-main);
}
body {
min-height: 100vh;
display: flex;
flex-direction: column;
}
h1 {
margin: 0;
font-family: "Satoshi", "Inter", system-ui, sans-serif;
line-height: 1.16;
font-size: clamp(1.85rem, 4vw, 3.5rem);
}
h2 {
margin: 0;
font-family: "Satoshi", "Inter", system-ui, sans-serif;
line-height: 1.2;
font-size: clamp(1.5rem, 3vw, 2.5rem);
}
h3 {
margin: 0;
font-family: "Satoshi", "Inter", system-ui, sans-serif;
line-height: 1.24;
font-size: clamp(1.2rem, 2vw, 1.8rem);
}
h4 {
margin: 0;
font-family: "Satoshi", "Inter", system-ui, sans-serif;
line-height: 1.24;
font-size: clamp(1rem, 1.8vw, 1.5rem);
}
p {
margin: 0;
line-height: 1.6;
color: var(--text-soft);
font-size: clamp(1rem, 1.15vw, 1.12rem);
}
a {
color: inherit;
text-decoration: none;
}
img {
max-width: 100%;
display: block;
}
.site-shell {
width: min(var(--shell-max-width), calc(100% - (var(--shell-gutter) * 2)));
margin: 0 auto;
}
.site-nav {
position: sticky;
top: 0;
z-index: 30;
backdrop-filter: blur(12px);
background: rgba(245, 242, 234, 0.9);
border-bottom: 1px solid var(--line);
}
.site-nav-inner {
min-height: 80px;
padding: 0.5rem 0;
display: flex;
align-items: center;
justify-content: space-between;
gap: 1rem;
}
.brand {
display: inline-flex;
align-items: center;
margin: 0;
padding: 0;
}
.brand img {
height: 85px;
width: auto;
max-width: 250px;
object-fit: contain;
display: block;
transform: scale(1.7) translateY(6px);
transform-origin: left center;
}
.nav-links {
display: flex;
align-items: center;
gap: 1.1rem;
flex-wrap: wrap;
font-weight: 600;
color: var(--text-soft);
font-size: 0.98rem;
}
.nav-links a {
white-space: nowrap;
transition: background 0.2s ease, color 0.2s ease;
}
.nav-links a:hover {
color: var(--brand);
}
.nav-links .nav-user-link,
.nav-links .nav-mobile-action {
display: none;
}
.nav-actions {
display: flex;
align-items: center;
gap: 0.65rem;
}
.nav-toggle {
display: none;
border: none;
background: transparent;
color: var(--text-main);
cursor: pointer;
align-items: center;
justify-content: center;
width: 44px;
height: 44px;
border-radius: 14px;
transition: background 0.2s ease;
}
.nav-toggle:hover,
.nav-toggle:focus-visible {
background: rgba(28, 90, 99, 0.08);
}
.nav-toggle svg {
width: 1.1rem;
height: 1.1rem;
}
.nav-btn {
display: inline-flex;
align-items: center;
justify-content: center;
border-radius: 999px;
border: 1px solid #bcd0de;
padding: 0.52rem 0.98rem;
font-weight: 700;
color: #1b4b52;
background: #ffffff;
transition: transform 0.18s ease, box-shadow 0.18s ease, background 0.18s ease;
}
.nav-btn:hover {
transform: translateY(-1px);
box-shadow: 0 8px 20px rgba(20, 53, 58, 0.14);
}
.nav-btn.primary {
color: #ffffff;
border-color: #184f57;
background: linear-gradient(120deg, #286f78 0%, #194f56 100%);
}
.nav-btn.primary:hover {
background: linear-gradient(120deg, #2d7882 0%, #1a5660 100%);
}
.nav-dropdown {
position: relative;
}
.nav-dropdown > summary {
list-style: none;
cursor: pointer;
}
.nav-dropdown > summary::-webkit-details-marker {
display: none;
}
.nav-dropdown > summary::after {
content: "▾";
margin-left: 0.45rem;
font-size: 0.72rem;
color: #5f747a;
}
.nav-dropdown[open] > summary::after {
content: "▴";
}
.dropdown-menu {
position: absolute;
right: 0;
top: calc(100% + 0.45rem);
min-width: 220px;
padding: 0.5rem;
border-radius: 12px;
border: 1px solid #ccd4cc;
background: #ffffff;
box-shadow: 0 12px 24px rgba(26, 45, 48, 0.14);
display: grid;
gap: 0.35rem;
z-index: 40;
}
.dropdown-menu a {
padding: 0.5rem 0.65rem;
border-radius: 8px;
font-weight: 600;
color: #214f55;
}
.dropdown-menu a:hover {
background: #f2f6f3;
}
.main-wrap {
flex: 1 0 auto;
padding: 2.2rem 0 3.5rem;
}
.flashes {
margin-bottom: 1rem;
display: grid;
gap: 0.75rem;
}
.flash {
padding: 0.8rem 1rem;
border-radius: 10px;
border: 1px solid var(--line);
background: var(--surface);
box-shadow: var(--shadow-sm);
font-weight: 600;
}
.flash.success { border-left: 5px solid #0e9f6e; }
.flash.error { border-left: 5px solid #d3413e; }
.flash.info { border-left: 5px solid var(--brand); }
.cookie-banner {
position: fixed;
left: 50%;
bottom: 1rem;
transform: translateX(-50%);
width: min(900px, calc(100% - 1.5rem));
border: 1px solid #c6d0c7;
border-radius: 14px;
background: rgba(255, 255, 255, 0.98);
box-shadow: 0 16px 32px rgba(26, 45, 48, 0.2);
padding: 0.95rem;
z-index: 70;
display: flex;
align-items: center;
justify-content: space-between;
gap: 0.8rem;
animation: cookieEnter 0.35s ease;
}
.cookie-banner p {
margin: 0;
color: #315055;
font-size: 0.92rem;
}
.cookie-banner a {
color: #1b5b62;
text-decoration: underline;
font-weight: 700;
}
.cookie-actions {
display: inline-flex;
align-items: center;
gap: 0.5rem;
flex-shrink: 0;
}
.cookie-btn {
border: 1px solid #1c5a63;
border-radius: 999px;
background: linear-gradient(120deg, #286f78 0%, #194f56 100%);
color: #ffffff;
font-weight: 700;
padding: 0.45rem 0.85rem;
cursor: pointer;
}
.cookie-btn.secondary {
border-color: #ccd5cc;
background: #ffffff;
color: #315055;
}
.cookie-banner.hidden {
display: none;
}
@keyframes cookieEnter {
from {
opacity: 0;
transform: translateX(-50%) translateY(14px);
}
to {
opacity: 1;
transform: translateX(-50%) translateY(0);
}
}
@media (max-width: 820px) {
.site-nav-inner {
min-height: 64px;
flex-wrap: wrap;
align-items: center;
gap: 0.8rem;
}
.nav-toggle {
display: inline-flex;
}
.nav-links {
position: absolute;
left: 50%;
top: calc(100% + 0.6rem);
transform: translateX(-50%) translateY(-10px);
width: min(100%, calc(100% - 1.5rem));
max-width: 520px;
background: rgba(255, 255, 255, 0.98);
border: 1px solid #d8dfdb;
border-radius: 20px;
padding: 0.9rem;
display: grid;
gap: 0.6rem;
z-index: 25;
opacity: 0;
visibility: hidden;
pointer-events: none;
box-shadow: 0 18px 40px rgba(23, 44, 57, 0.12);
transition: opacity 0.2s ease, transform 0.2s ease, visibility 0.2s ease;
}
.nav-links.open {
opacity: 1;
visibility: visible;
pointer-events: auto;
transform: translateX(-50%) translateY(0);
}
.nav-links a {
display: block;
width: 100%;
padding: 1rem 1rem;
border-radius: 16px;
background: #f7f5f0;
color: var(--text-main);
font-weight: 700;
}
.nav-links a:hover,
.nav-links a:focus-visible {
background: #e7f0ec;
}
.nav-links .nav-user-link,
.nav-links .nav-mobile-action {
display: block;
}
.nav-links .nav-user-link {
padding-left: 1rem;
border-left: 3px solid rgba(28, 90, 99, 0.18);
background: #f1f6f4;
}
.nav-links .nav-mobile-action {
border: 1px solid #bcd0de;
background: #ffffff;
color: #1b4b52;
}
.nav-actions {
display: none;
}
.main-wrap {
padding: 1.4rem 0 2.2rem;
}
.cookie-banner {
flex-direction: column;
align-items: flex-start;
}
.cookie-actions {
width: 100%;
}
.cookie-btn {
width: 100%;
}
.dropdown-menu {
right: auto;
left: 0;
min-width: 200px;
}
}
@media (max-width: 520px) {
.site-shell {
width: min(100%, calc(100% - 1rem));
}
.nav-links {
top: calc(100% + 0.6rem);
padding: 0.9rem;
}
.nav-actions {
justify-content: stretch;
}
.nav-actions .nav-btn {
width: 100%;
}
.nav-links .nav-user-link {
display: block;
}
}
</style>
{% endblock %}
</head>
<body>
<nav class="site-nav" role="navigation" aria-label="Hauptnavigation">
<div class="site-shell site-nav-inner">
<a class="brand" href="{{ url_for('default') }}">
<img src="{{ url_for('static', filename='logos/Logo ohne Background .png') }}" alt="Invario Logo">
</a>
<button type="button" class="nav-toggle" id="mobileMenuToggle" aria-expanded="false" aria-controls="mainNav" aria-label="Navigation öffnen">
<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false">
<path d="M4 7h16M4 12h16M4 17h16" stroke="currentColor" stroke-width="2" stroke-linecap="round"></path>
</svg>
</button>
<div class="nav-links" id="mainNav" aria-label="Main Navigation" aria-hidden="true">
<a href="{{ url_for('default') }}">Start</a>
<a href="{{ url_for('dienstleistungen') }}">Für Schulen</a>
<a href="{{ url_for('team') }}">Team</a>
<a href="{{ url_for('kontakt') }}">Kontakt</a>
{% if session.get('is_admin') %}
<a class="nav-user-link" href="{{ url_for('admin_invoices') }}">Rechnungsverwaltung</a>
<a class="nav-user-link" href="{{ url_for('admin_blog') }}">Blog verwalten</a>
<a class="nav-user-link" href="{{ url_for('admin_team') }}">Team Cards</a>
<a class="nav-user-link" href="{{ url_for('admin_chats') }}">Admin-Chat</a>
<a class="nav-user-link" href="{{ url_for('admin_tickets') }}">Support-Center</a>
<a class="nav-user-link" href="{{ url_for('admin_system_tools') }}">System-Tools</a>
{% elif 'username' in session %}
<a class="nav-user-link" href="{{ url_for('my_invoices') }}">Meine Rechnungen</a>
<a class="nav-user-link" href="{{ url_for('my_instance_management') }}">Meine Instanz</a>
<a class="nav-user-link" href="{{ url_for('user_chat') }}">Chat mit Admin</a>
<a class="nav-user-link" href="{{ url_for('user_tickets') }}">Support Tickets</a>
<a class="nav-user-link" href="{{ url_for('logout') }}">Abmelden</a>
{% else %}
<a class="nav-mobile-action nav-btn primary" href="{{ url_for('login') }}">Login</a>
<a class="nav-mobile-action nav-btn" href="{{ url_for('register') }}">Registrieren</a>
{% endif %}
</div>
<div class="nav-actions">
<a class="nav-btn primary" href="{{ url_for('preise') }}">Preise</a>
{% if session.get('is_admin') %}
<details class="nav-dropdown">
<summary class="nav-btn">Admin</summary>
<div class="dropdown-menu">
<a href="{{ url_for('admin_users') }}">Userverwaltung</a>
<a href="{{ url_for('admin_invoices') }}">Rechnungsverwaltung</a>
<a href="{{ url_for('admin_chats') }}">Admin-Chat</a>
<a href="{{ url_for('admin_tickets') }}">Support-Center</a>
<a href="{{ url_for('admin_system_tools') }}">System-Tools</a>
<a href="{{ url_for('admin_blog') }}">Blog verwalten</a>
<a href="{{ url_for('admin_team') }}">Team Cards</a>
<a href="{{ url_for('admin_instances') }}">Schul-Instanzen</a>
</div>
</details>
<a class="nav-btn" href="{{ url_for('logout') }}">Logout</a>
{% elif 'username' in session %}
<details class="nav-dropdown">
<summary class="nav-btn">Nutzerbereich</summary>
<div class="dropdown-menu">
<a href="{{ url_for('my_invoices') }}">Meine Rechnungen</a>
<a href="{{ url_for('my_instance_management') }}">Meine Instanz</a>
<a href="{{ url_for('user_chat') }}">Chat mit Admin</a>
<a href="{{ url_for('user_tickets') }}">Support Tickets</a>
</div>
</details>
<a class="nav-btn" href="{{ url_for('logout') }}">Logout</a>
{% else %}
<a class="nav-btn" href="{{ url_for('login') }}">Login</a>
<a class="nav-btn" href="{{ url_for('register') }}">Registrieren</a>
{% endif %}
</div>
</div>
</nav>
<main class="site-shell main-wrap" role="main">
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
<div class="flashes">
{% for category, message in messages %}
<div class="flash {{ category }}">{{ message }}</div>
{% endfor %}
</div>
{% endif %}
{% endwith %}
{% block content %}{% endblock %}
</main>
<footer class="site-footer">
<div class="site-shell footer-inner">
<div class="footer-content">
<div class="footer-section">
<h4>Über uns</h4>
<p>Digitale Verwaltungsabläufe für Bildungseinrichtungen in Deutschland.</p>
</div>
<div class="footer-section">
<h4>Schnelllinks</h4>
<ul class="footer-links">
<li><a href="{{ url_for('default') }}">Start</a></li>
<li><a href="{{ url_for('dienstleistungen') }}">Leistungsübersicht</a></li>
<li><a href="{{ url_for('team') }}">Team</a></li>
<li><a href="{{ url_for('blog') }}">Neuigkeiten</a></li>
<li><a href="{{ url_for('preise') }}">Preise</a></li>
</ul>
</div>
<div class="footer-section">
<h4>Rechtliches</h4>
<ul class="footer-links">
<li><a href="{{ url_for('datenschutz') }}">Datenschutz</a></li>
<li><a href="{{ url_for('impressum') }}">Impressum</a></li>
<li><a href="{{ url_for('nutzungsbedingungen') }}">Nutzungsbedingungen</a></li>
</ul>
</div>
</div>
<div class="footer-bottom">
<p>&copy; 2026 Invario. Alle Rechte vorbehalten.</p>
</div>
</div>
<style>
.site-footer {
background: linear-gradient(135deg, var(--brand-strong) 0%, #1c5a63 100%);
color: #ffffff;
margin-top: auto;
padding: 3rem 0 1.5rem;
border-top: 1px solid var(--line);
}
.footer-inner {
position: relative;
z-index: 1;
display: grid;
gap: 2rem;
margin-bottom: 2rem;
}
.footer-content {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 2rem;
}
.footer-section {
display: flex;
flex-direction: column;
gap: 0.75rem;
}
.footer-section h4 {
font-size: 1rem;
font-weight: 700;
color: #ffffff;
}
.footer-section p {
color: rgba(255, 255, 255, 0.8);
font-size: 0.95rem;
}
.footer-links {
list-style: none;
margin: 0;
padding: 0;
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.footer-links a {
color: rgba(255, 255, 255, 0.8);
font-size: 0.95rem;
}
.footer-links a:hover {
color: #ffffff;
}
.footer-bottom {
text-align: center;
padding-top: 1.5rem;
border-top: 1px solid rgba(255, 255, 255, 0.1);
}
.footer-bottom p {
color: rgba(255, 255, 255, 0.7);
font-size: 0.9rem;
margin: 0;
}
@media (max-width: 700px) {
.footer-inner {
gap: 1.5rem;
}
.footer-content {
grid-template-columns: 1fr;
gap: 1.5rem;
}
}
</style>
</footer>
<div class="cookie-banner hidden" id="cookieBanner" role="dialog" aria-live="polite" aria-label="Cookie Hinweis">
<p>Wir verwenden Cookies, um die Website sicher und benutzerfreundlich zu betreiben. Mit "Cookies akzeptieren" wird die Nutzung bestätigt. Details in <a href="{{ url_for('datenschutz') }}">Datenschutz</a>.</p>
<div class="cookie-actions">
<button type="button" class="cookie-btn" id="cookieAcceptBtn">Cookies akzeptieren</button>
<button type="button" class="cookie-btn secondary" id="cookieDeclineBtn">Ablehnen und zu Ecosia</button>
</div>
</div>
<!-- Mobile compatibility scripts -->
<script src="{{ url_for('static', filename='js/mobile_compatibility.js') }}"></script>
<script src="{{ url_for('static', filename='js/ios_fixes.js') }}"></script>
<script>
(function () {
var menuToggle = document.getElementById('mobileMenuToggle');
var navLinks = document.getElementById('mainNav');
if (menuToggle && navLinks) {
menuToggle.addEventListener('click', function () {
var isExpanded = this.getAttribute('aria-expanded') === 'true';
this.setAttribute('aria-expanded', String(!isExpanded));
navLinks.classList.toggle('open');
navLinks.setAttribute('aria-hidden', String(isExpanded));
});
navLinks.querySelectorAll('a').forEach(function (link) {
link.addEventListener('click', function () {
if (navLinks.classList.contains('open')) {
menuToggle.setAttribute('aria-expanded', 'false');
navLinks.classList.remove('open');
navLinks.setAttribute('aria-hidden', 'true');
}
});
});
document.addEventListener('click', function (event) {
if (!navLinks.contains(event.target) && !menuToggle.contains(event.target) && navLinks.classList.contains('open')) {
menuToggle.setAttribute('aria-expanded', 'false');
navLinks.classList.remove('open');
navLinks.setAttribute('aria-hidden', 'true');
}
});
navLinks.querySelectorAll('a').forEach(function (link) {
link.addEventListener('click', function () {
if (navLinks.classList.contains('open')) {
menuToggle.setAttribute('aria-expanded', 'false');
navLinks.classList.remove('open');
navLinks.setAttribute('aria-hidden', 'true');
}
});
});
window.addEventListener('resize', function () {
if (window.innerWidth > 820 && navLinks.classList.contains('open')) {
menuToggle.setAttribute('aria-expanded', 'false');
navLinks.classList.remove('open');
navLinks.removeAttribute('aria-hidden');
}
});
}
var banner = document.getElementById("cookieBanner");
var acceptBtn = document.getElementById("cookieAcceptBtn");
var declineBtn = document.getElementById("cookieDeclineBtn");
if (!banner || !acceptBtn || !declineBtn) {
return;
}
var consentKey = "cookie_consent_v1";
function hasConsent() {
return window.localStorage.getItem(consentKey) === "accepted" || document.cookie.indexOf("cookie_consent=accepted") !== -1;
}
function setConsent() {
window.localStorage.setItem(consentKey, "accepted");
document.cookie = "cookie_consent=accepted; Max-Age=" + (60 * 60 * 24 * 365) + "; Path=/; SameSite=Strict";
}
if (!hasConsent()) {
banner.classList.remove("hidden");
}
acceptBtn.addEventListener("click", function () {
setConsent();
banner.classList.add("hidden");
});
declineBtn.addEventListener("click", function () {
window.location.href = "https://www.ecosia.org";
});
})();
</script>
</body>
</html>