This commit is contained in:
breitenbach76 2026-06-09 15:37:54 +02:00
parent 864936382b
commit 6376e8365a
2 changed files with 169 additions and 3 deletions

View file

@ -334,6 +334,24 @@
.roleChip { background:var(--soft); color:var(--ink); }
.navBackdrop { background:rgba(0,0,0,.55); }
@keyframes akteFlash { 0%,55%{ background:rgba(255,206,84,.22); } 100%{ background:transparent; } }
/* Service-Beschreibung (Modal/Popup) */
.svcModal{position:fixed;inset:0;z-index:40;display:none;align-items:flex-start;justify-content:center;padding:max(24px,5vh) 16px;overflow:auto;background:rgba(0,0,0,.6)}
body.svcOpen .svcModal{display:flex}
.svcModalInner{background:var(--panel);border:1px solid var(--line);border-radius:16px;box-shadow:var(--shadow);max-width:820px;width:100%;padding:20px 24px 26px}
.svcModalInner .navTop b{font-size:13px}
.svcTabs{display:flex;flex-wrap:wrap;gap:6px;margin:10px 0 6px}
.svcTab{font-size:12px;padding:6px 11px;border:1px solid var(--line);border-radius:999px;background:var(--soft);color:var(--muted);cursor:pointer}
.svcTab:hover{border-color:#c9d2dd}
.svcTab.sel{border-color:var(--accent);color:var(--ink);font-weight:700;box-shadow:0 0 0 2px rgba(226,0,26,.12)}
.svcModalTitle{font-size:22px;font-weight:800;margin:12px 0 4px;line-height:1.2}
.svcDesc{color:var(--muted);margin:0 0 6px}
.svcH{margin:16px 0 6px;font-size:12px;text-transform:uppercase;letter-spacing:.6px;color:var(--accent)}
.svcList{margin:0;padding-left:20px}
.svcList li{margin:6px 0;line-height:1.5}
.runCardWrap{display:flex;flex-direction:column;gap:6px}
#runCard{cursor:zoom-in}
.svcHintRow{font-size:12px;color:var(--muted);text-align:center}
</style>
</head>
<body>
@ -342,6 +360,7 @@
<span class="tag">v0.9</span>
<div id="cardBadge" class="cardBadge"></div>
<div class="spacer"></div>
<button class="ghost" id="svcBtn" title="Ausführliche Service-Beschreibungen">&nbsp;Service-Info</button>
<button class="ghost" id="akteBtn" title="Service-Akte (gesammelte Artefakte)">📁&nbsp;Service-Akte</button>
<button class="ghost" id="rollenBtn" title="Rollen-Glossar (RACI)">👥&nbsp;Rollen</button>
<button class="ghost" id="stationsBtn" title="Stationsübersicht">&nbsp;Stationen</button>
@ -356,6 +375,7 @@
<div id="rollenList"></div>
<main><div class="card" id="panel"></div></main>
</div>
<div id="svcModal" class="svcModal"><div class="svcModalInner"></div></div>
<script>
/* Empfohlener Einstiegspunkt je Change-Typ (didaktische Auflösung in Schritt 2).
@ -524,6 +544,25 @@ const DECK_ORDER = [[2,1],[0,3],[4,0],[1,2],[5,3],[3,0],[0,1],[2,3],[4,2],[1,0],
const USE_CASES = [
{ service:"Zentrale VDI (Virtual-Desktop-Infrastructure)",
desc:"Bereitstellung von virtuellen Windows-Desktops über das interne Rechenzentrum.",
detail:{
nutzen:[
"<b>Einheitliche Arbeitsumgebung</b> — alle Fachamt-Mitarbeitenden erhalten denselben, zentral verwalteten Windows-Desktop.",
"<b>Datensicherheit</b> — Daten verbleiben im Rechenzentrum, keine lokalen Kopien; reduziert Verlust- und Diebstahlrisiko.",
"<b>Flexibler Zugriff</b> — Nutzung von Thin-Clients, Laptops oder Tablets über RDP/HTML5 von überall.",
"<b>Schnelle Bereitstellung</b> — neue Anwendungen und Updates werden zentral ausgerollt, kein lokaler Installationsaufwand.",
"<b>Kostenersparnis</b> — geringerer Wartungs- und Lizenzaufwand für Einzelgeräte."
],
aufgaben:[
"<b>Desktop-Image-Management</b> — Erstellung und Pflege standardisierter Windows-10-Images (MSIX-Packaging).",
"<b>VDI-Host-Provisionierung</b> — VM-Hosts (VMware vSphere/Hyper-V), Storage-Pools und Connection-Broker (Horizon oder Citrix).",
"<b>Netzwerk- und QoS-Einrichtung</b> — VLAN-Segmente, Priorisierung von VDI-Traffic, Load-Balancing der Broker-Server.",
"<b>Automatisierte Image-Pipelines</b> — Build- und Deploy-Automatisierung (Packer + Ansible, Blue-Green-Deploy).",
"<b>Identity-Integration</b> — AD-basiertes RBAC, Conditional Access, MFA für alle Nutzer.",
"<b>Patch- und Update-Management</b> — regelmäßige OS- und Applikations-Patches über zentrale Tools.",
"<b>Service-Monitoring</b> — SLA = 99 % Uptime, 4-Stunden-Reaktionszeit, Monitoring von Session-Count und Host-Health (Grafana + Prometheus).",
"<b>Support & Schulung</b> — 2nd-Level-Help-Desk, Benutzerhandbuch, Schulungen für Fachamt-IT-Support."
]
},
changes:[
{titel:"Open Source von oben!", text:"Der OB gibt die Richtung vor: Die proprietäre VDI-Lösung soll auf eine Open-Source-Alternative (OpenStack + Thin-Client) umgestellt werden."},
{titel:"Tapetenwechsel", text:"Die Stadt bekommt ein neues Logo — der Desktop-Hintergrund aller virtuellen Arbeitsplätze muss angepasst werden."},
@ -532,6 +571,24 @@ const USE_CASES = [
]},
{ service:"Managed VPN-Access Service",
desc:"Zentral verwalteter VPN-Dienst, der Mitarbeitenden der Fachämter sicheren Remote-Zugriff auf interne Systeme (Intranet, Fachanwendungen, Datenbanken) ermöglicht.",
detail:{
nutzen:[
"<b>Sicherer Remote-Zugriff</b> — verschlüsselte Tunnel ermöglichen Zugriff auf interne Systeme von zu Hause oder unterwegs.",
"<b>Zentralisierte Authentifizierung</b> — Single-Sign-On über AD, MFA und ggf. FIDO2-Security-Keys.",
"<b>Compliance-Erfüllung</b> — erfüllt DSGVO- und IT-Security-Vorgaben (Protokollierung, Zugriffskontrolle).",
"<b>Flexibilität für Mitarbeitende</b> — Arbeiten von jedem Gerät aus, ohne Sicherheitskompromisse.",
"<b>Transparente Überwachung</b> — vollständige Log- und Audit-Funktion für alle Verbindungen."
],
aufgaben:[
"<b>VPN-Appliance-Bereitstellung</b> — Installation hochverfügbarer VPN-VMs (FortiGate, Cisco ASA o. Ä.) inkl. Load-Balancing.",
"<b>Netzwerk- und Policy-Design</b> — VPN-Subnetze, Split-Tunnel-Regeln, Firewall-Policies (nur Port 443/8443).",
"<b>Identity-Integration</b> — SAML/AD-Anbindung, Conditional Access, MFA-Durchsetzung, optional FIDO2-Support.",
"<b>Client-Provisionierung</b> — automatisierte Verteilung von VPN-Profilen via Intune/SCCM, Dokumentation für End-User.",
"<b>Firmware- und Sicherheits-Updates</b> — regelmäßige Patch-Cycles, IPS/IDS-Monitoring, tägliche Log-Analyse.",
"<b>Monitoring & SLA-Management</b> — 99,8 % Uptime, 1-Stunden-Reaktionszeit, Dashboard (Grafana + Prometheus).",
"<b>Incident- und Change-Management</b> — 24/7-Support, Notfall-Deaktivierung bei Sicherheitsvorfällen, Dokumentation aller Änderungen."
]
},
changes:[
{titel:"Brüssel ruft!", text:"Eine neue EU-weite IT-Sicherheitsverordnung zwingt dazu, die gesamte VPN-Architektur neu aufzustellen."},
{titel:"Heimvorteil", text:"Ein neues Intranet-Portal soll in die Split-Tunnel-Liste, damit Mitarbeitende auch aus dem Homeoffice darauf zugreifen."},
@ -540,6 +597,25 @@ const USE_CASES = [
]},
{ service:"Online-Bürgerportal für Meldungen & Anträge",
desc:"Zentrales Web-Portal, über das Bürger*innen Meldungen (z. B. Straßenreparatur, Lärm) und Anträge (z. B. Baugenehmigung, Personalausweis) digital einreichen und den Status verfolgen.",
detail:{
nutzen:[
"<b>24/7-Zugang</b> — Bürger*innen können Meldungen (Straßenreparatur, Lärm) und Anträge (Baugenehmigung, Personalausweis) jederzeit online einreichen.",
"<b>Automatisierte Weiterleitung</b> — Eingaben werden sofort an das zuständige Fachamt geroutet, Bearbeitungszeiten sinken.",
"<b>Status-Tracking</b> — Antragsteller*innen sehen den Bearbeitungsstand in Echtzeit; reduziert Rückfragen und Telefonaufkommen.",
"<b>Digitale Signatur & revisionssichere Protokollierung</b> — erfüllt gesetzliche Vorgaben (DSGVO, OZG) und erhöht die Rechtssicherheit.",
"<b>Transparenz & Bürgernähe</b> — öffentliche Infos zu Bearbeitungszeiten und Service-Statistiken stärken das Vertrauen."
],
aufgaben:[
"<b>Anforderungsanalyse & Fachkonzept</b> — gemeinsam mit den Fachämtern (Bau, Bürger-Service, IT-Security).",
"<b>Entwicklung/Anpassung</b> der Web-Applikation (z. B. Node.js + Vue, Formular-Engine, Workflow-Engine).",
"<b>Betrieb von HA-Infrastruktur</b> — VM-Cluster, Load-Balancer, PostgreSQL-HA, tägliche Backups, Disaster-Recovery-Plan.",
"<b>Sicherheitsintegration</b> — SAML-basiertes SSO, rollenbasiertes Access-Control, MFA, WAF-Regeln, regelmäßige OWASP-Scans.",
"<b>DMZ-Einrichtung & Netzwerk-Segmente</b> — HTTPS-Only, IP-Whitelisting fürs interne Fachämter-Netz, DDoS-Schutz.",
"<b>CI/CD-Pipeline</b> (GitLab CI, Blue-Green-Deploy) für schnelle, kontrollierte Releases.",
"<b>Service-Management</b> — SLA = 99,5 % Verfügbarkeit, 2-Stunden-Reaktionszeit, Monitoring (Prometheus + Grafana), 2nd-Level-Help-Desk.",
"<b>Dokumentation & Schulungen</b> — Benutzerhandbuch, FAQ, Schulungen für Fachamt-Mitarbeitende, Knowledge-Base-Einträge."
]
},
changes:[
{titel:"Mitreden, Pflicht!", text:"Ein neues Landesgesetz schreibt digitale Bürgerbeteiligung vor — das Portal muss um komplette Beteiligungs-Module erweitert werden."},
{titel:"Licht an!", text:"Das Amt für öffentliche Ordnung möchte eine neue Mängel-Kategorie „Beleuchtung und Strom“ zu den bestehenden Kategorien hinzufügen."},
@ -548,6 +624,23 @@ const USE_CASES = [
]},
{ service:"Zentrales Dokumenten-Management-System (DMS)",
desc:"Elektronisches Archiv, das alle ein- und ausgehenden Dokumente (PDF, Scans, E-Mails) zentral speichert, versioniert und revisionssicher archiviert.",
detail:{
nutzen:[
"<b>Revisionssichere Archivierung</b> — gesetzeskonforme Aufbewahrung von Eingangs-, Ausgangs- und Vorgangsdokumenten (1030 Jahre).",
"<b>Schnelle Volltext-Suche</b> — Metadaten- und Volltext-Index ermöglichen sofortiges Auffinden aller Unterlagen.",
"<b>Automatisierte Workflows</b> — Dokumente werden automatisch an die zuständigen Fachämter weitergeleitet, Freigabe-Ketten gesteuert.",
"<b>Platz- und Kostenersparnis</b> — Wegfall von Papierarchiven, reduzierte Lager- und Verwaltungskosten.",
"<b>Transparenz & Nachvollziehbarkeit</b> — lückenlose Protokollierung aller Zugriffe und Änderungen für Audits."
],
aufgaben:[
"<b>Systemauswahl & Anpassung</b> — Installation und Konfiguration einer DMS-Lösung (z. B. Alfresco, SharePoint) inkl. Metadaten-Schema und OCR-Engine.",
"<b>Infrastruktur-Bereitstellung</b> — HA-VM-Cluster, verschlüsselter SAN-Storage (TB-Scale), tägliche Snapshots und Langzeit-Backups.",
"<b>Sicherheits- und Identity-Integration</b> — AD-basiertes RBAC, MFA, Verschlüsselung at-rest und in-transit, Audit-Log-Management.",
"<b>Workflow-Engine-Implementierung</b> — Automatisierung von Dokumenten-Freigabe- und Weiterleitungsprozessen für alle Fachämter.",
"<b>Monitoring & Performance</b> — Index-Health-Checks, Speicher-Auslastungs-Monitoring, SLA = 99,8 % Verfügbarkeit (Grafana + Prometheus).",
"<b>Support & Schulung</b> — 2nd-Level-Help-Desk, Benutzerhandbuch, Fachschulungen für Sachbearbeiter und Archivare, laufende Doku-Updates."
]
},
changes:[
{titel:"Datendiät", text:"Eine DSGVO-Ergänzung zur Datenminimierung erzwingt die komplette Neugestaltung von Metadaten-Modell und Archivierungs-Policies."},
{titel:"Dropdown-Wunsch", text:"Das Finanzamt bittet um ein neues Metadaten-Feld „Kostenstelle“ als Auswahlliste."},
@ -556,6 +649,22 @@ const USE_CASES = [
]},
{ service:"Kommunales GIS-Portal (Geoinformations-System)",
desc:"Web-basiertes Karten- und Analyse-Portal, das Fachämtern (Bau, Umwelt, Verkehr) räumliche Daten (Flurstücke, Infrastruktur, Umweltzonen) und bearbeitbare Layer bereitstellt.",
detail:{
nutzen:[
"<b>Zentraler Daten-Hub</b> — einheitlicher Zugriff auf Flurstücke, Infrastruktur- und Umwelt-Daten für alle Fachämter.",
"<b>Interaktive Karten & Analysen</b> — web-basierte Visualisierung, Layer-Management und räumliche Auswertungen.",
"<b>Transparenz für Bürger*innen</b> — öffentliche Karten-Ansichten erhöhen das Vertrauen in kommunale Entscheidungen.",
"<b>Verbesserte Planungsqualität</b> — schnellere, datenbasierte Entscheidungen in Bau-, Umwelt- und Verkehrs-Planung.",
"<b>Skalierbarkeit</b> — Unterstützung großer Datenmengen (TB-Scale) und hoher Nutzerzahlen."
],
aufgaben:[
"<b>GIS-Server-Installation</b> — Deployment von GeoServer oder ArcGIS Server, Konfiguration von OGC-Services (WMS/WFS).",
"<b>Infrastruktur-Provisionierung</b> — GPU-beschleunigte Rendering-Nodes, redundanter Storage-Pool (RAID 6/SSD), Hochdurchsatz-Netz (10 GbE).",
"<b>Daten-Ingestion-Pipelines</b> — ETL-Prozesse (CityGML → 3-D-Tiles, Raster-Import) automatisiert via Python-Scripts/Docker.",
"<b>Netz- und CDN-Einbindung</b> — optimierte Auslieferung öffentlicher Karten, Edge-Caching, DDoS-Schutz.",
"<b>Security & Identity</b> — AD-basiertes RBAC, OAuth-2.0-Token-Auth, regelmäßige Pen-Tests, Verschlüsselung in-transit."
]
},
changes:[
{titel:"Norm-Zwang", text:"Eine bundesweite Vorgabe zu EU-Standards erzwingt die komplette Migration des GIS-Stacks auf konforme Services und Datenmodelle."},
{titel:"Grün dazu!", text:"Das Umweltamt möchte im Analyse-Modul „Klimarisiko-Analyse“ eine weitere Datenquelle zu städtischen Grünflächen anbinden."},
@ -564,6 +673,24 @@ const USE_CASES = [
]},
{ service:"Beschaffungs- und Vertrags-System für Fachämter",
desc:"Web-Applikation, über die Fachämter interne Beschaffungen (Material, Dienstleistungen) anlegen, prüfen und Verträge digital verwalten.",
detail:{
nutzen:[
"<b>Vollständig digitaler Beschaffungs-Workflow</b> — von Bedarfsermittlung über Ausschreibung bis Vertragsarchivierung.",
"<b>Automatisierte Genehmigungs-Ketten</b> — rollenbasierte Freigaben reduzieren Durchlaufzeiten und Fehler.",
"<b>Kosten- und Compliance-Kontrolle</b> — Echtzeit-Auswertungen, Einhaltung von Haushalts- und Vergaberegeln.",
"<b>Revisionssichere Archivierung</b> — gesetzeskonforme Aufbewahrung von Verträgen (1030 Jahre).",
"<b>Reduzierter Papierverbrauch</b> — umweltfreundlich und effizienter."
],
aufgaben:[
"<b>System-Selection & Customizing</b> — Implementierung einer e-Procurement-Lösung (SAP SRM, Odoo Purchase) inkl. Workflow-Engine und E-Signatur.",
"<b>HA-Infrastruktur-Betrieb</b> — VM-Cluster, MariaDB-Galera-Datenbank, tägliche Backups, Disaster-Recovery-Strategie.",
"<b>Identity & Access Management</b> — AD-basiertes RBAC, SAML-SSO, MFA für alle Nutzergruppen (Anforderer, Genehmiger, Finanz).",
"<b>Sicherheits- und Netzwerk-Design</b> — DMZ-Zone, HTTPS-Only, Firewall-Regeln für externe Lieferanten-Portale, IPS/IDS-Monitoring.",
"<b>Patch- und Update-Management</b> — regelmäßige Sicherheits-Patches, automatisierte CI/CD-Deployments.",
"<b>Monitoring & SLA-Erfüllung</b> — 99,5 % Uptime, 2-Stunden-Reaktionszeit, Dashboard (ELK-Stack + Grafana).",
"<b>Support & Schulung</b> — 2nd-Level-Help-Desk, Benutzerhandbuch, Fachschulungen für Einkauf- und Fachabteilungen."
]
},
changes:[
{titel:"Vergabe neu!", text:"Eine neue EU-Vergaberichtlinie zwingt zur Einführung von E-Invoicing und erweiterten Transparenz-Reports."},
{titel:"Format-Wechsel", text:"Die Verträge der Fachämter liegen wegen aktualisierter Sicherheitsrichtlinien in einem neuen Dateiformat vor — die Schnittstellen der Web-Applikation müssen entsprechend angepasst werden."},
@ -1142,7 +1269,7 @@ function defaultState(){
classifyDone:false, classifyWrong:null,
freigabeDone:false, freigabeWrong:null,
entryDone:false, entryWrong:null,
bonusReveal:false, bonusDone:{}, servicesDone:{}, akteFlash:null,
bonusReveal:false, bonusDone:{}, servicesDone:{}, akteFlash:null, svcModalSel:null,
index:0, stage:"discuss", quizIndex:0, gateDeciderDone:false, gateCrit:0,
actStep:0, actReveal:false, actDone:false, arteWrong:null,
picks:{}, done:{}, akte:{},
@ -1236,11 +1363,43 @@ function renderRollen(){
const c = $("#rollenClose"); if(c) c.onclick = ()=> document.body.classList.remove("rollenOpen");
}
/* ====================== RENDER: SERVICE-BESCHREIBUNG (Modal/Popup) ====================== */
function serviceDetailHtml(si){
const u = USE_CASES[si]; const d = (u && u.detail) || {};
const nutzen = (d.nutzen||[]).map(x=>`<li>${x}</li>`).join("");
const aufgaben = (d.aufgaben||[]).map(x=>`<li>${x}</li>`).join("");
return `<p class="svcDesc">${u.desc}</p>`
+ (nutzen?`<h4 class="svcH">Kundennutzen</h4><ul class="svcList">${nutzen}</ul>`:``)
+ (aufgaben?`<h4 class="svcH">Aufgaben des IT-Providers</h4><ul class="svcList">${aufgaben}</ul>`:``);
}
function openSvcModal(si){
S.svcModalSel = (si!=null) ? si : (S.service!=null ? S.service : 0);
document.body.classList.remove("navOpen","akteOpen","rollenOpen");
document.body.classList.add("svcOpen"); save(); renderSvcModal();
}
function renderSvcModal(){
const inner = document.querySelector("#svcModal .svcModalInner");
if(!inner) return;
const sel = (S.svcModalSel!=null) ? S.svcModalSel : (S.service!=null ? S.service : 0);
const tabs = USE_CASES.map((u,si)=>
`<button class="svcTab ${si===sel?'sel':''}" data-si="${si}">${u.service}</button>`).join("");
inner.innerHTML = `
<div class="navTop"><b> Service-Beschreibung</b><button id="svcClose" title="Schließen"></button></div>
<div class="svcTabs">${tabs}</div>
<h3 class="svcModalTitle">${USE_CASES[sel].service}</h3>
${serviceDetailHtml(sel)}`;
const c = inner.querySelector("#svcClose"); if(c) c.onclick = ()=> document.body.classList.remove("svcOpen");
inner.querySelectorAll(".svcTab[data-si]").forEach(el=>{
el.onclick = ()=>{ S.svcModalSel=+el.dataset.si; save(); renderSvcModal(); };
});
}
/* ====================== VIEW DISPATCH ====================== */
function draw(){
document.body.classList.toggle("runMode", S.view==="run");
if(S.view!=="run"){ document.body.classList.remove("navOpen","akteOpen","rollenOpen"); }
renderCardBadge();
renderSvcModal();
if(S.view==="deck") return renderDeck();
if(S.view==="mainIntro") return renderMainIntro();
if(S.view==="classify") return renderClassify();
@ -1302,6 +1461,7 @@ function renderMainIntro(){
<div class="recBox"><h4>Worum geht's</h4>
<p style="margin:0 0 8px">${card.text}</p>
<p style="margin:0;color:var(--muted)">Als <b>Major Change</b> wird der Service <b>neu eingeführt</b> und durchläuft den <b>kompletten Lifecycle ab Design</b>. Die Freigaben fallen unterwegs an den <b>Gates</b> (SOR bzw. Service Owner) an — hier müsst ihr nichts einordnen. Das Einordnen (Change-Art · Freigabe · Einstieg) kommt danach bei den <b>Bonus-Varianten</b>.</p></div>
<div class="recBox"><h4>Service-Beschreibung</h4>${serviceDetailHtml(S.service)}</div>
</div>
</div>
<div class="actions">
@ -1649,7 +1809,10 @@ function renderRun(){
const loopBanner = (S.loopback && S.index < S.loopback.untilIdx)
? `<div class="tourBanner"><b>Nacharbeit nach Gate ${S.loopback.gateNr}</b> — überarbeitet die folgenden Stationen; danach wird das Gate erneut vorgelegt und entscheidet neu.</div>`
: ``;
const cardBig = `<img class="classifyCard" src="cards/s${S.service}-c${S.change}.png" alt="${acard(S.service,S.change).titel}">`;
const cardBig = `<div class="runCardWrap">
<img id="runCard" class="classifyCard" src="cards/s${S.service}-c${S.change}.png" alt="${acard(S.service,S.change).titel}" title="Tippen für die ausführliche Service-Beschreibung">
<div class="svcHintRow"> Tippen für Service-Beschreibung</div>
</div>`;
const stepBody = st.typ==="gate"
? (S.stage==="gateDone" ? renderGateDone(st) : renderGate(st))
: renderActivity(st);
@ -1877,6 +2040,7 @@ function renderGateDone(st){
/* ====================== WIRING ====================== */
function wire(st){
const b = id => $("#"+id);
const rc = $("#runCard"); if(rc) rc.onclick = ()=> openSvcModal(S.service);
if(b("actReveal")) b("actReveal").onclick = ()=>{ S.actReveal=true; save(); draw(); };
if(b("actNext")) b("actNext").onclick = ()=>{ S.actStep=(S.actStep||0)+1; S.actReveal=false; save(); draw(); };
if(b("actToDone")) b("actToDone").onclick = ()=>{ S.actDone=true; S.akteFlash=null; document.body.classList.remove("akteOpen"); save(); draw(); };
@ -1944,6 +2108,8 @@ function renderEnd(){
$("#akteBtn").onclick = ()=>{ const o=document.body.classList.contains("akteOpen"); closeOverlays(); if(!o) document.body.classList.add("akteOpen"); };
$("#rollenBtn").onclick = ()=>{ const o=document.body.classList.contains("rollenOpen"); closeOverlays(); if(!o) document.body.classList.add("rollenOpen"); };
$("#navBackdrop").onclick = closeOverlays;
$("#svcBtn").onclick = ()=> openSvcModal(S.service);
$("#svcModal").onclick = (e)=>{ if(e.target.id==="svcModal") document.body.classList.remove("svcOpen"); };
draw();
})();

View file

@ -1,5 +1,5 @@
/* Service Worker — SLC-Workshop Companion (App-Shell, offline-first) */
const CACHE = "slc-companion-v29";
const CACHE = "slc-companion-v30";
const SHELL = ["./", "index.html", "manifest.webmanifest", "icon.svg"];
// Action-Card-Grafiken (cards/s<service>-c<change>.png) fuer Offline vorab cachen (alle 24).
const CARDS = [];