Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 13 additions & 5 deletions CLAUDE.md

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ Die App selbst bleibt abhängigkeitsfrei; für die Tests wird einmalig Playwrigh
```bash
npm install # nur Dev: @playwright/test
npx playwright install chromium
npm test # 371 Tests, ~145 s
npm test # 376 Tests, ~150 s
npm run test:ui # interaktiver Modus
```

Expand Down Expand Up @@ -309,7 +309,7 @@ datenlotse/
│ ├── sample-landesbehoerde.csv # Beispiel: fiktive Landesebene (12 Datensätze)
│ ├── sample-verein.csv # Beispiel: fiktiver gemeinnütziger Träger (12 Datensätze)
│ └── template.csv # Leere Vorlage zum eigenen Befüllen
├── tests/ # Playwright-End-to-End-Tests (371 Tests in 14 Dateien)
├── tests/ # Playwright-End-to-End-Tests (376 Tests in 14 Dateien)
│ ├── helpers.js # openApp/loadSample/Download-Helfer
│ ├── smoke.spec.js # Views, Routing, Dashboard, HTML-Validität, Anrede
│ ├── import.spec.js # CSV-Parser, Ableitung, Formel-Injection
Expand Down
56 changes: 52 additions & 4 deletions css/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,39 @@ a { color: var(--c-accent); }
max-width: 620px;
margin: 0 auto;
}
/* ── „So kommen Sie zu offenen Daten" ────────────────────────────
Eigener Abschnitt unter dem Hero. Vorher steckten Logo, Titel, Einleitung,
Chips, Zusage, Aktion und Import-Zeile alle im Hero-Container – sieben
Bausteine, die einander die Aufmerksamkeit nahmen. */
.steps-section {
max-width: 940px;
margin: var(--home-gap) auto 0;
padding: 0 24px;
text-align: center;
}
.steps-panel {
background: #fff;
border: 1px solid var(--glass-border);
border-radius: 18px;
box-shadow: var(--shadow-md);
padding: 32px 32px 30px;
}
.steps-title {
font-size: 21px;
font-weight: 800;
color: var(--c-accent);
margin: 0 0 8px;
letter-spacing: -0.4px;
}
.steps-title i { margin-right: 8px; }
.steps-lead {
font-size: 14.5px;
color: var(--c-muted);
line-height: 1.6;
max-width: 560px;
margin: 0 auto;
}

/* Die vier Schritte als scannbare Chips statt eines langen grauen Fließtexts.
Jeder Chip springt direkt in den passenden Baustein. */
.hero-steps {
Expand All @@ -155,7 +188,7 @@ a { color: var(--c-accent); }
flex-wrap: wrap;
justify-content: center;
gap: 10px;
margin: 30px auto 0;
margin: 24px auto 0;
max-width: 760px;
}
.hero-step {
Expand Down Expand Up @@ -1418,17 +1451,29 @@ a { color: var(--c-accent); }
}
.tour-hint-close:hover { background: rgba(66, 0, 147, 0.07); color: var(--c-accent); }

.tour-layer.hidden { display: none; }
.tour-layer {
/* Das Abdunkeln liegt UNTER der hervorgehobenen Stelle (1201) und deshalb
an body::before, nicht am Layer: `position: fixed` macht den Layer zum
eigenen Stapelkontext, aus dem die Karte nicht herauskommt – sie stünde
sonst dauerhaft unter dem Zielelement. */
body.tour-on::before {
content: '';
position: fixed;
inset: 0;
z-index: 1200;
background: rgba(30, 27, 46, 0.42);
pointer-events: none;
}
.tour-layer.hidden { display: none; }
.tour-layer {
position: fixed;
inset: 0;
/* über der hervorgehobenen Stelle: sonst zeichnet das Zielelement in die Karte */
z-index: 1202;
display: flex;
align-items: flex-end;
justify-content: center;
padding: 20px;
/* Der Layer dunkelt ab, blockiert aber nicht die hervorgehobene Stelle */
/* Der Layer blockiert die hervorgehobene Stelle nicht – nur die Karte fängt Klicks */
pointer-events: none;
}
.tour-card {
Expand Down Expand Up @@ -2547,6 +2592,9 @@ details[open] > .about-summary .about-caret { transform: rotate(180deg); }
/* Auf schmalen Geräten wird die Luft im Container zur Platzverschwendung */
.hero { padding: 26px 16px 4px; }
.hero-panel { padding: 26px 18px 24px; border-radius: 14px; }
.steps-section { padding: 0 16px; }
.steps-panel { padding: 22px 18px 22px; border-radius: 14px; }
.steps-title { font-size: 18px; }
.view-hero { padding: 22px 18px 20px; margin: 22px 0 22px; border-radius: 14px; }
.view-hero .inventory-title { font-size: 27px; }
.view-hero .inventory-hint { padding-top: 14px; margin-top: 16px; }
Expand Down
12 changes: 10 additions & 2 deletions datenschutz/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
}
</script>
<link rel="stylesheet" href="/assets/fonts/inter/inter.css">
<link rel="stylesheet" href="/assets/fonts/fa/icons.min.css?v=65">
<link rel="stylesheet" href="/assets/fonts/fa/icons.min.css?v=66">
<link rel="stylesheet" href="/css/tokens.css">
<link rel="stylesheet" href="/css/styles.css">
</head>
Expand Down Expand Up @@ -164,12 +164,20 @@ <h1 class="static-title">Datenschutzerklärung</h1>

</main>

<footer class="footer">
<footer class="site-footer">
<a class="footer-brand" href="https://nozilla.de/" target="_blank" rel="noopener">nozilla | bits &amp; bytes mit ❤</a>
<nav class="footer-links">
<a href="/">Werkzeug</a>
<span class="footer-sep">·</span>
<a href="/wissen/">Wissen &amp; Methodik</a>
<span class="footer-sep">·</span>
<a href="https://nozilla.de/impressum/" target="_blank" rel="noopener">Impressum</a>
<span class="footer-sep">·</span>
<a href="/datenschutz/">Datenschutz</a>
<span class="footer-sep">·</span>
<a href="https://nozilla.de/kontakt/" target="_blank" rel="noopener">Kontakt</a>
<span class="footer-sep">·</span>
<a href="https://github.com/daimpad/datenlotse" target="_blank" rel="noopener" title="GitHub Repository" aria-label="DatenLotse auf GitHub"><svg class="footer-github" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" aria-hidden="true" focusable="false"><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27s1.36.09 2 .27c1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.01 8.01 0 0 0 16 8c0-4.42-3.58-8-8-8Z"/></svg></a>
</nav>
</footer>
</body>
Expand Down
79 changes: 44 additions & 35 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>DatenLotse – Von der Datenökosystem-Map zur Open-Data-Umsetzung</title>
<meta name="description" content="DatenLotse führt Organisationen von der kartierten Datenökosystem-Map zur operativen Umsetzung: Dateninventar nach DCAT-AP.de, Risiko-Clearing und datenschutzkonforme Pseudonymisierung – lokal im Browser.">
<meta name="description" content="DatenLotse führt Organisationen von der kartierten Datenökosystem-Map zur Veröffentlichung als Open Data: Dateninventar nach DCAT-AP.de, Risiko-Clearing und datenschutzkonforme Pseudonymisierung – lokal im Browser.">
<meta name="author" content="nozilla">
<meta name="robots" content="index, follow">

Expand All @@ -21,7 +21,7 @@

<!-- Open Graph -->
<meta property="og:title" content="DatenLotse – Von der Map zur Open-Data-Umsetzung">
<meta property="og:description" content="Dateninventar nach DCAT-AP.de, Risiko-Clearing und datenschutzkonforme Pseudonymisierung – lokal im Browser, ohne Server.">
<meta property="og:description" content="Daten öffnen statt nur verwalten: Dateninventar nach DCAT-AP.de, Risiko-Clearing und datenschutzkonforme Pseudonymisierung – lokal im Browser, ohne Server.">
<meta property="og:type" content="website">
<meta property="og:url" content="https://datenlotse.nozilla.net/">
<meta property="og:image" content="https://datenlotse.nozilla.net/social-preview.png">
Expand All @@ -35,7 +35,7 @@
<!-- Twitter Card -->
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="DatenLotse – Von der Map zur Open-Data-Umsetzung">
<meta name="twitter:description" content="Dateninventar nach DCAT-AP.de, Risiko-Clearing und datenschutzkonforme Pseudonymisierung – lokal im Browser, ohne Server.">
<meta name="twitter:description" content="Daten öffnen statt nur verwalten: Dateninventar nach DCAT-AP.de, Risiko-Clearing und datenschutzkonforme Pseudonymisierung – lokal im Browser, ohne Server.">
<meta name="twitter:image" content="https://datenlotse.nozilla.net/social-preview.png">
<meta name="twitter:image:alt" content="DatenLotse – Von der Map zur Open-Data-Umsetzung">

Expand Down Expand Up @@ -125,10 +125,10 @@
<link rel="stylesheet" href="assets/fonts/inter/inter.css">
<!-- Zugeschnitten auf die verwendeten Icons (tools/build-icons.py) – das
vollstaendige all.min.css bleibt als Quelle im Repo, wird aber nicht geladen. -->
<link rel="stylesheet" href="assets/fonts/fa/icons.min.css?v=65">
<link rel="stylesheet" href="assets/fonts/fa/icons.min.css?v=66">

<link rel="stylesheet" href="css/tokens.css?v=65">
<link rel="stylesheet" href="css/styles.css?v=65">
<link rel="stylesheet" href="css/tokens.css?v=66">
<link rel="stylesheet" href="css/styles.css?v=66">
</head>
<body>

Expand Down Expand Up @@ -181,32 +181,11 @@
<main id="main-content" tabindex="-1">

<!-- ── Hero ──────────────────────────────────────────────────── -->
<section class="hero" id="hero">
<section class="hero home-only" id="hero">
<div class="hero-panel">
<img src="logo.svg" alt="DatenLotse" class="hero-logo">
<h1 class="hero-headline">DatenLotse: Datenmanagement verstehen, aufbauen, vertiefen</h1>
<p class="hero-sub">Der <strong>DatenLotse</strong> begleitet Ihre Organisation dabei, ein umfassendes <strong>Datenmanagement zu verstehen</strong> und <strong>aufzubauen</strong> – und den <strong>Ist-Zustand</strong> Ihrer Datenlandschaft vertiefend einzusehen.</p>

<ol class="hero-steps" aria-label="Die vier Schritte des DatenLotsen">
<li><button class="hero-step" data-go="kompass">
<span class="hero-step-ic"><i class="fas fa-compass"></i></span>
<span class="hero-step-text"><strong>Überblick</strong><span>Daten-Kompass</span></span>
</button></li>
<li><button class="hero-step" data-go="inventory">
<span class="hero-step-ic"><i class="fas fa-boxes-stacked"></i></span>
<span class="hero-step-text"><strong>Inventar</strong><span>nach DCAT-AP.de</span></span>
</button></li>
<li><button class="hero-step" data-go="clearing">
<span class="hero-step-ic"><i class="fas fa-traffic-light"></i></span>
<span class="hero-step-text"><strong>Risiko-Clearing</strong><span>Rot · Gelb · Grün</span></span>
</button></li>
<li><button class="hero-step" data-go="pseudo">
<span class="hero-step-ic"><i class="fas fa-user-shield"></i></span>
<span class="hero-step-text"><strong>Pseudonymisierung</strong><span>Texte bereinigen</span></span>
</button></li>
</ol>

<p class="hero-trust"><i class="fas fa-lock"></i> Ihre Daten bleiben im Browser · kein Konto · keine Übertragung von Inhalten</p>
<h1 class="hero-headline">DatenLotse: Daten verstehen, ordnen und als Open Data ver&ouml;ffentlichen</h1>
<p class="hero-sub">Vom <strong>Ist-Zustand</strong> Ihrer Datenlandschaft bis zur Ver&ouml;ffentlichung als <strong>Open Data</strong>: Welche Best&auml;nde lassen sich <strong>&ouml;ffnen</strong>, wie werden sie nach dem Standard <strong>DCAT-AP.de</strong> beschrieben &ndash; und was muss vorher gekl&auml;rt oder gesch&uuml;tzt werden?</p>

<button class="btn btn-primary hero-cta" id="hero-kompass-btn"><i class="fas fa-compass"></i> Daten-Kompass starten</button>
<p class="hero-from-graf">
Expand All @@ -216,6 +195,36 @@ <h1 class="hero-headline">DatenLotse: Datenmanagement verstehen, aufbauen, verti
</div>
</section>

<!-- ── Der Weg in vier Schritten ──────────────────────────────
Bewusst ein eigener Abschnitt statt eines weiteren Blocks im Hero:
Logo, Titel, Einleitung, Chips, Zusage, Aktion und Import-Zeile
standen sonst als sieben Bausteine in einem Container. -->
<section class="steps-section home-only" id="hero-steps">
<div class="steps-panel">
<h2 class="steps-title"><i class="fas fa-route"></i> So kommen Sie zu offenen Daten</h2>
<p class="steps-lead">Vier Schritte, jeder f&uuml;r sich nutzbar. Wenn Sie nicht wissen, wo Sie anfangen sollen: Der Daten-Kompass sagt es Ihnen.</p>
<ol class="hero-steps" aria-label="Die vier Schritte des DatenLotsen">
<li><button class="hero-step" data-go="kompass">
<span class="hero-step-ic"><i class="fas fa-compass"></i></span>
<span class="hero-step-text"><strong>Überblick</strong><span>Daten-Kompass</span></span>
</button></li>
<li><button class="hero-step" data-go="inventory">
<span class="hero-step-ic"><i class="fas fa-boxes-stacked"></i></span>
<span class="hero-step-text"><strong>Inventar</strong><span>nach DCAT-AP.de</span></span>
</button></li>
<li><button class="hero-step" data-go="clearing">
<span class="hero-step-ic"><i class="fas fa-traffic-light"></i></span>
<span class="hero-step-text"><strong>Risiko-Clearing</strong><span>Rot · Gelb · Grün</span></span>
</button></li>
<li><button class="hero-step" data-go="pseudo">
<span class="hero-step-ic"><i class="fas fa-user-shield"></i></span>
<span class="hero-step-text"><strong>Pseudonymisierung</strong><span>Texte bereinigen</span></span>
</button></li>
</ol>
<p class="hero-trust"><i class="fas fa-lock"></i> Ihre Daten bleiben im Browser · kein Konto · keine &Uuml;bertragung von Inhalten</p>
</div>
</section>

<!-- ── Akkordeon: Über den DatenLotsen ───────────────────────── -->
<div class="tour-hint hidden" id="tour-hint">
<span class="tour-hint-text"><i class="fas fa-route"></i> Zum ersten Mal hier? Ein kurzer Rundgang zeigt, wof&uuml;r die Bausteine da sind.</span>
Expand All @@ -225,7 +234,7 @@ <h1 class="hero-headline">DatenLotse: Datenmanagement verstehen, aufbauen, verti
</span>
</div>

<section class="about-accordion" id="about-accordion">
<section class="about-accordion home-only" id="about-accordion">
<details class="about-details">
<summary class="about-summary">
<span><i class="fas fa-compass"></i> Mehr über den DatenLotsen erfahren</span>
Expand Down Expand Up @@ -281,7 +290,7 @@ <h2 class="dashboard-title" id="dashboard-title"><i class="fas fa-gauge-high"></
</section>

<!-- ── Modul-Grid ────────────────────────────────────────────── -->
<section class="module-grid" id="module-grid">
<section class="module-grid home-only" id="module-grid">

<!-- Modul 1 – Governance -->
<article class="module-card">
Expand Down Expand Up @@ -858,7 +867,7 @@ <h3 class="view-next-title"><i class="fas fa-diagram-successor"></i> Woraus ents
</section>

<!-- ── Beratungs-CTA (Phase 4–5) ─────────────────────────────── -->
<section class="consult-cta">
<section class="consult-cta home-only">
<div class="consult-cards">
<div class="consult-card consult-card-info">
<h2 class="consult-card-headline">Phase 4 &amp; 5: Pipeline &amp; zirkuläres Ökosystem</h2>
Expand Down Expand Up @@ -893,7 +902,7 @@ <h2 class="consult-card-headline">Umsetzung besprechen</h2>
Brands-Familie und h&auml;tte daf&uuml;r 116 KB Schrift nachgeladen. -->
<a href="https://github.com/daimpad/datenlotse" target="_blank" rel="noopener" title="GitHub Repository" aria-label="DatenLotse auf GitHub"><svg class="footer-github" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" aria-hidden="true" focusable="false"><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27s1.36.09 2 .27c1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.01 8.01 0 0 0 16 8c0-4.42-3.58-8-8-8Z"/></svg></a>
</nav>
<span class="footer-version">v65</span>
<span class="footer-version">v66</span>
</footer>

<!-- ── FAQ-Modal ─────────────────────────────────────────────── -->
Expand Down Expand Up @@ -1109,7 +1118,7 @@ <h2 id="license-title"><i class="fas fa-id-card"></i> Lizenz-Wegweiser</h2>
</div>
</div>

<script src="js/app.js?v=65"></script>
<script src="js/app.js?v=66"></script>

<!-- Anonyme Seitenzählung (GoatCounter). Der EINZIGE externe Aufruf der
Seite: keine Cookies, kein LocalStorage, keine Kennung, kein
Expand Down
18 changes: 10 additions & 8 deletions js/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -515,7 +515,7 @@ function clearState() {
Teile defensiv. grafRows wird mitgesichert (anders als im
LocalStorage), damit der Import-Kontext vollständig ist. */
const PROJECT_SCHEMA = 1;
const APP_VERSION = 'v65';
const APP_VERSION = 'v66';

function buildProjectJSON() {
return JSON.stringify({
Expand Down Expand Up @@ -1019,11 +1019,13 @@ function startTour() {
tour.i = 0;
tour.active = true;
document.getElementById('tour-layer')?.classList.remove('hidden');
document.body.classList.add('tour-on');
renderTour();
}
function endTour() {
tour.active = false;
document.getElementById('tour-layer')?.classList.add('hidden');
document.body.classList.remove('tour-on');
document.querySelectorAll('.tour-highlight').forEach(el => el.classList.remove('tour-highlight'));
closeSidebar();
markTourSeen();
Expand Down Expand Up @@ -2950,20 +2952,20 @@ document.addEventListener('keydown', e => {

/* ── View-Umschaltung (home / inventory / governance / pseudo) ── */
function showView(name) {
['hero', 'about-accordion', 'module-grid'].forEach(id => {
const el = document.getElementById(id);
if (el) el.style.display = (name === 'home') ? '' : 'none';
// Alles, was nur auf die Startseite gehört, trägt `.home-only` – vorher stand
// dafür eine Liste von IDs plus ein Sonderfall für `.consult-cta`; ein neuer
// Startseiten-Abschnitt wäre auf den Unterseiten stehen geblieben.
document.querySelectorAll('.home-only').forEach(el => {
el.style.display = (name === 'home') ? '' : 'none';
});
document.getElementById('inventory-view')?.classList.toggle('hidden', name !== 'inventory');
document.getElementById('governance-view')?.classList.toggle('hidden', name !== 'governance');
document.getElementById('pseudo-view')?.classList.toggle('hidden', name !== 'pseudo');
document.getElementById('kompass-view')?.classList.toggle('hidden', name !== 'kompass');
document.getElementById('wissen-view')?.classList.toggle('hidden', name !== 'wissen');
document.getElementById('vorlagen-view')?.classList.toggle('hidden', name !== 'vorlagen');
// Der Phase-4&5-Beratungsblock gehört auf die Startseite; Unterseiten bekommen
// stattdessen ihren eigenen, kontextpassenden „Wie geht es weiter?"-Block.
const cta = document.querySelector('.consult-cta');
if (cta) cta.style.display = (name === 'home') ? '' : 'none';
// Der Phase-4&5-Beratungsblock (`.consult-cta`) trägt dieselbe Klasse: Unterseiten
// bekommen stattdessen ihren eigenen, kontextpassenden „Wie geht es weiter?"-Block.
if (name === 'home') { refreshDashboard(); refreshTourHint(); }
else { const dash = document.getElementById('dashboard'); if (dash) dash.classList.add('hidden'); }
window.scrollTo({ top: 0 });
Expand Down
Loading
Loading