Trauerfall-Sofortleiste mit erster Anleitung
Die Nummer auf jeder Seite, dazu „Was ist jetzt zu tun?“ nach Sterbeort, eine Checkliste zum Drucken und ein Rückruf, der nur verspricht, was das Haus hält.
Startseite und alle Seiten eines Bestattungshauses: die Nummer immer sichtbar, die Anleitung als Feld unter der Leiste (Telefon: darüber).
Eine schmale Leiste auf jeder Seite: „Im Trauerfall · Tag und Nacht“, die Nummer als tel:-Link und der Knopf „Was ist jetzt zu tun?“. Am Desktop steht sie oben, auf dem Telefon unten in der Daumenzone. Der Knopf öffnet eine Anleitung nach Sterbeort (zu Hause; Krankenhaus, Heim, Hospiz; unerwartet oder Unfall; im Ausland) mit drei bis fünf nummerierten Schritten und dem Satz „Sie haben Zeit.“. Dazu eine Unterlagen-Checkliste mit echten Checkboxen zum Drucken und ein Rückruf mit zwei Feldern. Die Rückrufzeit steht nur da, wenn das Haus sie wirklich hält.
Wer gerade einen Menschen verloren hat, sucht nicht im Menü. Er braucht eine Nummer, unter der jemand abnimmt, und die Antwort auf „Was muss ich jetzt tun?“. Die Leiste gibt beides auf jeder Seite, ohne Werbung davor. Die Weiche nach Sterbeort nimmt Fragen vorweg, die am Telefon sonst zuerst kommen: Wer stellt den Tod fest, wen rufe ich wann an, was lege ich bereit.
Wann einsetzen
Bestattungshaus, Trauerbegleitung mit Bereitschaft, Bestattungswald oder Friedhofsverwaltung (dort mit dem Hinweis, zuerst ein Bestattungshaus zu beauftragen). Übertragbar auf andere Lagen mit Bereitschaft: Notdienst einer Praxis, Tierarzt-Notdienst, Pflegedienst.
Wann nicht
Wenn nachts niemand abnimmt: dann keine „Tag und Nacht“-Zeile, sondern die echten Zeiten der Rufbereitschaft. Nicht für Trauerredner ohne Bereitschaft (dort Erreichbarkeit und Rückruf). Nie als blinkender Störer, nie mit Countdown oder Verkaufsbotschaft.
Varianten
- Leiste: Desktop oben (sticky), Telefon unten in der Daumenzone, Anleitung als aufklappbares Feld darunter bzw. darüber
- Eigene Seite „Was ist jetzt zu tun?“ mit Reitern nach Sterbeort, Checkliste zum Drucken und Rückruf
- Waldbestattung: Nummer der Verwaltung mit echten Zeiten und der Hinweis, zuerst ein Bestattungshaus zu beauftragen
- Rufbereitschaft nachts statt „Tag und Nacht“ (ehrliche Zeitangabe, Rückrufzusage nur, wenn sie stimmt)
Umsetzung
Leiste als eigene Landmarke (<aside aria-label="Im Trauerfall">) mit Sprunglink am Seitenanfang. Am Desktop position: sticky; top: 0, auf dem Telefon position: fixed; bottom: 0 mit env(safe-area-inset-bottom). scroll-padding-top bzw. scroll-padding-bottom in Höhe der Leiste, damit Fokus und Sprungziele nie darunter liegen (WCAG 2.4.11). Ein Consent-Banner steht über der Leiste, nicht unter ihr. Der Knopf „Was ist jetzt zu tun?“ ist ein Disclosure (aria-expanded, aria-controls) und öffnet ein Feld mit Reitern nach Sterbeort (role=tablist, Pfeiltasten, Pos1/Ende, automatische Aktivierung). Checkliste als fieldset mit echten Checkboxen; Stand nur lokal (localStorage), nichts wird gesendet; „Liste drucken“ ruft window.print(), @media print zeigt nur Kopf mit Nummer und Liste. Rückruf: zwei Felder (Name, Telefon, autocomplete name/tel), Fehlerliste über dem Formular, Bestätigung mit Uhrzeit aus der echten Zusage des Hauses; bei Fehler die Nummer zum Anrufen. Die Zeile „Tag und Nacht“ kommt aus der Konfiguration und wird zur Rufbereitschaft, wenn nachts kein Mensch abnimmt.
Robust umsetzen
Telefon. Leiste unten in der Daumenzone mit „Anrufen“ und „Was tun?“. Die Anleitung öffnet sich darüber als Feld mit eigener Scrollfläche und Schließen-Knopf. Der Seiteninhalt bekommt unten Platz in Höhe der Leiste.
Ohne Bewegung. Das Feld öffnet und schließt ohne Übergang. Sonst bewegt sich nichts.
Barrierefrei. Eigene Landmarke mit Sprunglink. Reiter nach APG (Pfeiltasten, Pos1, Ende), Checkliste als fieldset mit legend, Zähler als Text. Fokus nie unter der Leiste (scroll-padding, WCAG 2.4.11). Knöpfe 48 px, Text ab 19 px, Sekundärtext 6,5 : 1. Rückruf mit Fehlerliste und verknüpften Fehlermeldungen (aria-describedby), Bestätigung in einer role=status-Region. Keine Bewegung außer Öffnen und Schließen.
Code
<!DOCTYPE html>
<!--
Trauerfall-Sofortleiste mit erster Anleitung
Fundus · Sektionen & Funktionen · https://cecodesign.de/lab/fundus/sektionen/trauerfall-sofortleiste/
Eigenständige Datei. Bilder liegen hier unter bilder/ – eigene einsetzen.
-->
<html lang="de">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Trauerfall-Sofortleiste mit erster Anleitung · Fundus-Demo</title>
<script>document.documentElement.classList.add('js');if(matchMedia('(prefers-reduced-motion: reduce)').matches)document.documentElement.classList.add('reduziert')</script>
<style>
@font-face { font-family: 'Source Serif 4'; src: url('https://cdn.jsdelivr.net/fontsource/fonts/source-serif-4:vf@latest/latin-opsz-normal.woff2') format('woff'); font-weight: 200 900; font-display: swap; }
@font-face { font-family: 'Commissioner'; src: url('https://cdn.jsdelivr.net/fontsource/fonts/commissioner:vf@latest/latin-full-normal.woff2') format('woff2-variations'); font-weight: 100 900; font-display: swap; }
:root {
/* Rezept bestattung-wuerdig */
--kalk: #f4f1eb; --text: #24221f; --sand: #e8e1d5; --schiefer: #2b2d2c;
--moos: #3f5b48; --moos-tief: #34503d; --moos-hell: #8fb59a; --moos-hell-hover: #a3c3ab;
--leise: #5a554d; --linie: #d3ccc0; --auf-schiefer: #f4f1eb; --auf-schiefer-leise: #c9c3b8;
--fehler: #8a2f1d;
--serif: 'Source Serif 4', Georgia, serif;
--sans: 'Commissioner', system-ui, sans-serif;
/* UI-Kurvenpaar (token-toggle-asymmetrisch, auf UI-Maß gekürzt) */
--auf-kurve: cubic-bezier(0.4, 0, 0.2, 1); --zu-kurve: cubic-bezier(0.4, 0, 1, 1);
--auf-dauer: 300ms; --zu-dauer: 200ms; --farbe-dauer: 150ms;
--leiste-h: 64px;
scroll-padding-top: calc(var(--leiste-h) + 16px);
}
* { box-sizing: border-box; margin: 0; }
html { background: var(--kalk); color: var(--text); font-family: var(--sans); font-variation-settings: 'FLAR' 0, 'VOLM' 0; font-size: 100%; -webkit-text-size-adjust: 100%; }
body { min-height: 100svh; font-size: 1.1875rem; line-height: 1.65; font-variant-numeric: tabular-nums; }
:focus-visible { outline: 3px solid var(--text); outline-offset: 3px; border-radius: 2px; }
.sofort :focus-visible, .dunkel :focus-visible { outline-color: var(--auf-schiefer); }
a { color: inherit; text-decoration-thickness: 1px; text-underline-offset: .35ex; }
button, input { font: inherit; color: inherit; }
button { cursor: pointer; background: none; border: 0; }
h1, h2, h3 { font-family: var(--serif); font-weight: 400; font-optical-sizing: auto; text-wrap: balance; }
h1 { font-size: clamp(2.25rem, 1.6rem + 2.6vw, 3.5rem); line-height: 1.12; letter-spacing: -.01em; }
h2 { font-size: clamp(1.75rem, 1.4rem + 1.4vw, 2.5rem); line-height: 1.15; }
h3 { font-size: 1.375rem; font-weight: 600; line-height: 1.3; }
p { max-width: 62ch; text-wrap: pretty; }
.nur-sr { position: absolute !important; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; }
.rubrik { font: 500 1rem/1.3 var(--sans); letter-spacing: .06em; text-transform: uppercase; color: var(--leise); }
.tel-nr { font-weight: 600; font-variant-numeric: tabular-nums; letter-spacing: .01em; white-space: nowrap; }
.platzhalter { display: inline-block; margin-top: .75rem; padding: .35rem .6rem; border: 1px dashed #8a8174; color: var(--leise); font-size: 1rem; line-height: 1.45; }
/* Sprunglinks */
.sprung { position: absolute; left: 12px; top: 8px; z-index: 60; display: flex; flex-wrap: wrap; gap: 8px; }
.sprung a { position: absolute; left: -9999px; padding: 10px 16px; background: var(--kalk); color: var(--text); font-weight: 600; font-size: 1rem; border: 1px solid var(--text); }
.sprung a:focus { position: static; }
/* ---------- Knöpfe (muster.button: button-zustaende + pfeil-icon-button Variante linie) ---------- */
.knopf { display: inline-flex; align-items: center; justify-content: center; gap: .55em; min-height: 48px; padding: 0 1.25rem; border-radius: 6px; font: 600 1.0625rem/1.2 var(--sans); text-decoration: none; transition: background-color var(--farbe-dauer) var(--auf-kurve), color var(--farbe-dauer) var(--auf-kurve), border-color var(--farbe-dauer) var(--auf-kurve); }
.knopf-moos { background: var(--moos); color: #fff; }
.knopf-moos:hover { background: var(--moos-tief); }
.knopf-hell { background: var(--moos-hell); color: var(--schiefer); }
.knopf-hell:hover { background: var(--moos-hell-hover); }
.knopf-rand { border: 1px solid currentColor; }
.knopf-rand:hover { background: rgba(36, 34, 31, .06); }
.sofort .knopf-rand:hover { background: rgba(244, 241, 235, .1); }
.knopf[aria-busy="true"] { pointer-events: none; }
.knopf[aria-busy="true"] .knopf-text::after { content: ' …'; }
.knopf svg { flex: none; }
.linie { display: inline-flex; align-items: center; gap: .45em; min-height: 44px; font-weight: 600; text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: .35ex; }
.linie .pfeil-schaft { opacity: 0; transition: opacity var(--farbe-dauer) var(--auf-kurve); }
.linie .pfeil-spitze { transition: transform var(--farbe-dauer) var(--auf-kurve); }
.linie:hover .pfeil-schaft, .linie:focus-visible .pfeil-schaft { opacity: 1; }
.linie:hover .pfeil-spitze, .linie:focus-visible .pfeil-spitze { transform: translateX(3px); }
/* ---------- Sofortleiste ---------- */
.sofort { position: sticky; top: 0; z-index: 30; background: var(--schiefer); color: var(--auf-schiefer); }
.sofort-zeile { max-width: 1200px; margin: 0 auto; min-height: var(--leiste-h); padding: 8px clamp(16px, 3vw, 40px); display: flex; flex-wrap: wrap; align-items: center; gap: 8px 24px; }
.sofort-lage { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 14px; margin-right: auto; }
.sofort-titel { font-size: 1rem; font-weight: 500; letter-spacing: .06em; text-transform: uppercase; }
.sofort-zeit { font-size: 1rem; color: var(--auf-schiefer-leise); }
.sofort-anruf { display: inline-flex; align-items: center; gap: .6em; min-height: 48px; color: var(--auf-schiefer); text-decoration: none; font-size: 1.5rem; }
.sofort-anruf:hover .tel-nr { text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: .3ex; }
.sofort-anruf svg { color: var(--moos-hell); }
.sofort-anruf .anruf-wort { display: none; }
.sofort-knopf .kurz { display: none; }
.sofort-knopf[aria-expanded="true"] .chevron { transform: rotate(180deg); }
.sofort-knopf .chevron { transition: transform var(--auf-dauer) var(--auf-kurve); }
.sofort-knopf[aria-current="page"] { background: transparent; color: var(--auf-schiefer); border: 1px solid var(--auf-schiefer-leise); }
/* Feld mit der Anleitung (Disclosure) */
.feld { position: absolute; left: 0; right: 0; top: 100%; background: var(--kalk); color: var(--text); border-bottom: 1px solid var(--linie); box-shadow: 0 18px 40px -24px rgba(36, 34, 31, .45); max-height: calc(100svh - var(--leiste-h)); overflow-y: auto; overscroll-behavior: contain;
opacity: 0; transform: translateY(-6px); transition: opacity var(--zu-dauer) var(--zu-kurve), transform var(--zu-dauer) var(--zu-kurve); }
.feld.auf { opacity: 1; transform: none; transition-duration: var(--auf-dauer); transition-timing-function: var(--auf-kurve); }
.feld[hidden] { display: none; }
.feld-innen { max-width: 1200px; margin: 0 auto; padding: 28px clamp(16px, 3vw, 40px) 32px; display: grid; grid-template-columns: minmax(0, 15rem) minmax(0, 1fr) minmax(0, 19rem); gap: 24px 40px; align-items: start; }
.feld-kopf { grid-column: 1 / -1; display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px 20px; padding-bottom: 18px; border-bottom: 1px solid var(--linie); }
.feld-kopf h2 { font-size: clamp(1.625rem, 1.3rem + 1vw, 2.125rem); margin-right: auto; }
.feld-kopf h2:focus { outline: none; }
.feld-kopf h2:focus-visible { outline: 3px solid var(--text); }
.zeit-satz { font-family: var(--serif); font-size: 1.375rem; line-height: 1.35; }
.schliessen { display: inline-flex; align-items: center; gap: .4em; min-height: 44px; padding: 0 .75rem; border-radius: 6px; font-size: 1rem; font-weight: 500; color: var(--text); }
.schliessen:hover { background: rgba(36, 34, 31, .06); }
.wald-hinweis { grid-column: 1 / -1; display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 4px 16px; padding: 16px 20px; background: var(--sand); border-left: 4px solid var(--schiefer); }
.wald-hinweis strong { font-family: var(--serif); font-size: 1.3125rem; font-weight: 600; line-height: 1.3; }
.wald-hinweis p { grid-column: 2; font-size: 1.0625rem; }
.wald-hinweis .zahl { grid-row: span 2; font: 400 2rem/1 var(--serif); color: var(--leise); }
/* Reiter */
.reiter { display: flex; flex-direction: column; gap: 2px; }
.reiter-frage { font-size: 1rem; font-weight: 500; color: var(--leise); margin-bottom: 6px; }
.reiter [role="tab"] { display: flex; align-items: center; min-height: 48px; padding: 8px 14px; text-align: left; line-height: 1.3; font-size: 1.0625rem; font-weight: 500; color: var(--leise); border-left: 3px solid transparent; border-radius: 0 6px 6px 0; transition: background-color var(--farbe-dauer) var(--auf-kurve), color var(--farbe-dauer) var(--auf-kurve); }
.reiter [role="tab"]:hover { color: var(--text); background: rgba(36, 34, 31, .05); }
.reiter [role="tab"][aria-selected="true"] { color: var(--text); font-weight: 600; background: var(--sand); border-left-color: var(--schiefer); }
.reiter-flaeche [role="tabpanel"]:focus-visible { outline-offset: 6px; }
.schritte { list-style: none; padding: 0; counter-reset: s; display: grid; gap: 18px; }
.schritte li { counter-increment: s; display: grid; grid-template-columns: 2.25rem minmax(0, 1fr); gap: 2px 14px; }
.schritte li::before { content: counter(s); grid-row: span 2; font: 400 2rem/1 var(--serif); color: var(--leise); padding-top: .1rem; }
.schritte strong { font-weight: 600; line-height: 1.4; }
.schritte p { color: var(--text); font-size: 1.0625rem; line-height: 1.6; }
.schritte a { font-weight: 600; white-space: nowrap; }
.panel-titel { font-family: var(--serif); font-weight: 600; font-size: 1.375rem; line-height: 1.3; margin-bottom: 14px; }
.wiederholung { margin-top: 22px; display: flex; flex-wrap: wrap; align-items: center; gap: 4px 14px; padding: 12px 16px; border: 1px solid var(--linie); border-radius: 6px; }
.wiederholung span { font-size: 1rem; color: var(--leise); }
.wiederholung a { font-size: 1.25rem; text-decoration: none; }
.wiederholung a:hover { text-decoration: underline; }
.feld-fuss { grid-column: 1 / -1; display: flex; flex-wrap: wrap; align-items: center; gap: 8px 28px; padding-top: 14px; border-top: 1px solid var(--linie); }
/* Rückruf */
.rueckruf { background: var(--sand); border-radius: 8px; padding: 20px 20px 18px; display: grid; gap: 10px; }
.rueckruf h3 { font-size: 1.25rem; }
.felder { display: grid; gap: 10px; }
.felder[hidden] { display: none; }
.zusage { font-size: 1.0625rem; line-height: 1.5; }
.rueckruf label { display: block; font-size: 1rem; font-weight: 500; margin-top: 4px; }
.rueckruf input { display: block; width: 100%; min-height: 48px; margin-top: 4px; padding: 10px 12px; border: 1px solid #8a8174; border-radius: 6px; background: #fbfaf7; font-size: 1.0625rem; }
.rueckruf input:focus-visible { outline: 3px solid var(--text); outline-offset: 1px; }
.rueckruf input[aria-invalid="true"] { border: 2px solid var(--fehler); }
.feldfehler { color: var(--fehler); font-size: 1rem; font-weight: 500; margin-top: 4px; }
.fehlerliste { border: 2px solid var(--fehler); border-radius: 6px; padding: 12px 14px; background: #fbfaf7; }
.fehlerliste:focus-visible { outline: 3px solid var(--text); outline-offset: 2px; }
.fehlerliste p { font-weight: 600; font-size: 1.0625rem; }
.fehlerliste ul { margin: 4px 0 0; padding-left: 1.1rem; }
.fehlerliste a { color: var(--fehler); font-weight: 500; font-size: 1rem; }
.rueckruf .knopf { margin-top: 6px; width: 100%; }
.klein { font-size: 1rem; line-height: 1.5; color: var(--leise); }
.antwort:empty { display: none; }
.antwort { display: grid; gap: 10px; }
.antwort:focus { outline: none; }
.antwort:focus-visible { outline: 3px solid var(--text); outline-offset: 4px; }
.antwort .bestaetigt { font-family: var(--serif); font-size: 1.375rem; line-height: 1.35; }
.antwort .fehlschlag { font-weight: 600; color: var(--fehler); }
.antwort .gross-tel { font-size: 1.5rem; text-decoration: none; }
.antwort .gross-tel:hover { text-decoration: underline; }
.antwort button { justify-self: start; width: auto !important; margin-top: 0 !important; }
.antwort:not(:empty) + .felder { padding-top: 12px; border-top: 1px solid var(--linie); }
/* ---------- Seite: Kopf und Hero ---------- */
.kopf { max-width: 1200px; margin: 0 auto; padding: 20px clamp(16px, 3vw, 40px); display: flex; flex-wrap: wrap; align-items: center; gap: 12px 32px; }
.marke { display: grid; gap: 0; text-decoration: none; margin-right: auto; }
.marke b { font: 400 1.75rem/1.1 var(--serif); letter-spacing: -.005em; }
.marke span { font-size: 1rem; color: var(--leise); line-height: 1.4; }
.navi ul { list-style: none; padding: 0; display: flex; flex-wrap: wrap; gap: 4px 22px; }
.navi a { display: inline-flex; align-items: center; min-height: 44px; font-size: 1rem; font-weight: 500; text-decoration: none; }
.navi a:hover, .navi a[aria-current] { text-decoration: underline; }
main { display: block; }
.huelle { max-width: 1200px; margin: 0 auto; padding: 0 clamp(16px, 3vw, 40px); }
.held { display: grid; grid-template-columns: minmax(0, 1.05fr) minmax(0, .95fr); gap: clamp(24px, 4vw, 64px); align-items: center; padding: clamp(16px, 3vw, 40px) 0 clamp(40px, 6vw, 80px); }
.held-text { display: grid; gap: 22px; align-content: start; }
.held-tel { display: grid; gap: 2px; padding: 16px 0; border-top: 1px solid var(--linie); border-bottom: 1px solid var(--linie); }
.held-tel a { font-size: clamp(1.75rem, 1.4rem + 1.2vw, 2.25rem); text-decoration: none; justify-self: start; line-height: 1.25; }
.held-tel a:hover { text-decoration: underline; text-decoration-thickness: 1px; }
.held-tel span { font-size: 1rem; color: var(--leise); }
.tueren { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
.tuer { display: grid; gap: 4px; align-content: start; min-height: 100%; padding: 18px 18px 16px; text-align: left; text-decoration: none; background: var(--sand); border: 1px solid transparent; border-radius: 8px; transition: border-color var(--farbe-dauer) var(--auf-kurve); }
.tuer:hover { border-color: var(--text); }
.tuer b { font: 400 1.375rem/1.25 var(--serif); }
.tuer span { font-size: 1rem; color: var(--leise); line-height: 1.45; }
.tuer .pfeil { margin-top: 6px; }
.bild { position: relative; border-radius: 4px; overflow: hidden; background: var(--sand); }
.bild svg { display: block; width: 100%; height: auto; }
.bild figcaption { padding: 10px 0 0; font-size: 1rem; color: var(--leise); background: var(--kalk); }
/* Seite „Was ist jetzt zu tun?“ */
.pfad { font-size: 1rem; color: var(--leise); padding-top: 8px; }
.pfad a { color: var(--leise); }
.seite-kopf { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 20rem); gap: 24px clamp(24px, 4vw, 64px); align-items: start; padding: 18px 0 34px; }
.seite-text { display: grid; gap: 18px; max-width: 46rem; }
.seite-text .platzhalter { justify-self: start; margin: 0; }
.kontakt-karte { display: grid; gap: 6px; padding: 20px; background: var(--sand); border-radius: 8px; }
.kontakt-karte .tel-nr { font-size: 1.75rem; text-decoration: none; justify-self: start; line-height: 1.3; }
.kontakt-karte .tel-nr:hover { text-decoration: underline; text-decoration-thickness: 1px; }
.kontakt-karte p:not(.rubrik):not(.klein) { font-size: 1.0625rem; line-height: 1.5; }
.uebernehmen ul { list-style: none; padding: 0; margin: 16px 0; display: grid; gap: 0; }
.uebernehmen li { display: grid; gap: 2px; padding: 12px 0; border-bottom: 1px solid var(--linie); }
.uebernehmen li b { font-weight: 600; }
.uebernehmen li span { font-size: 1.0625rem; line-height: 1.55; }
.seite-kopf .zeit-satz { font-size: clamp(1.375rem, 1.2rem + .6vw, 1.75rem); }
.anleitung-seite { border-top: 1px solid var(--linie); padding: 30px 0 46px; display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 20rem); gap: 32px clamp(24px, 4vw, 64px); align-items: start; }
.anleitung-seite .rueckruf-spalte { padding-top: 4px; }
.anleitung-seite .rueckruf-spalte h2 { font-size: 1.5rem; margin-bottom: 6px; }
.anleitung-seite .reiter-frage { font-size: 1.0625rem; }
.anleitung-seite .reiter { flex-direction: row; flex-wrap: wrap; gap: 8px; margin-bottom: 26px; }
.anleitung-seite .reiter [role="tab"] { border: 1px solid var(--linie); border-radius: 6px; padding: 8px 18px; }
.anleitung-seite .reiter [role="tab"][aria-selected="true"] { border-color: var(--schiefer); box-shadow: inset 0 -3px 0 var(--schiefer); background: var(--sand); }
.anleitung-seite .schritte { gap: 24px; max-width: 46rem; }
.anleitung-seite .schritte li::before { font-size: 2.5rem; }
.anleitung-seite .schritte li { grid-template-columns: 3rem minmax(0, 1fr); }
.anleitung-seite .schritte p { font-size: 1.1875rem; }
.zwei { display: grid; grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr); gap: clamp(24px, 4vw, 56px); padding: 40px 0 56px; border-top: 1px solid var(--linie); align-items: start; }
.unterlagen h2, .uebernehmen h2 { margin-bottom: 10px; }
.unterlagen fieldset { border: 0; padding: 0; margin: 20px 0 0; }
.unterlagen legend { font: 600 1.25rem/1.3 var(--serif); padding: 0; margin-bottom: 8px; }
.haken { display: grid; grid-template-columns: 28px minmax(0, 1fr); gap: 14px; align-items: start; padding: 10px 0; border-bottom: 1px solid var(--linie); cursor: pointer; }
.haken input { width: 26px; height: 26px; margin: 2px 0 0; accent-color: var(--schiefer); cursor: pointer; }
.haken span { line-height: 1.5; }
.haken small { display: block; font-size: 1rem; color: var(--leise); }
.haken:has(input:checked) span > b { text-decoration: line-through; text-decoration-thickness: 1px; text-decoration-color: var(--leise); }
.haken b { font-weight: 500; }
.stand { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 20px; margin-top: 20px; }
.stand-zahl { font-weight: 600; }
.lokal { margin-top: 10px; }
.druck-kopf { display: none; }
.druck-beenden { display: none; }
/* Fußzeile */
.fuss { background: var(--schiefer); color: var(--auf-schiefer); }
.fuss-innen { max-width: 1200px; margin: 0 auto; padding: 32px clamp(16px, 3vw, 40px); display: flex; flex-wrap: wrap; gap: 12px 40px; font-size: 1rem; }
.fuss-innen p { color: var(--auf-schiefer-leise); }
.fuss-innen a { color: var(--auf-schiefer); }
/* Consent-Banner (Demo-Zustand): liegt nie unter der Leiste */
.consent { position: fixed; left: 16px; bottom: 16px; z-index: 35; width: min(560px, calc(100vw - 32px)); background: var(--kalk); color: var(--text); border: 1px solid var(--text); border-radius: 8px; padding: 18px 18px 16px; display: grid; gap: 10px; box-shadow: 0 16px 40px -20px rgba(36, 34, 31, .5); }
.consent[hidden] { display: none; }
.consent h2 { font-size: 1.25rem; font-weight: 600; }
.consent p { font-size: 1rem; line-height: 1.5; }
.consent .reihe { display: flex; flex-wrap: wrap; gap: 8px; }
.consent .knopf { flex: 1 1 12rem; }
/* ---------- Demo-Pult ---------- */
.pult { position: fixed; right: 14px; bottom: 14px; z-index: 50; width: min(330px, calc(100vw - 28px)); display: grid; gap: 8px; padding: 12px 14px; background: rgba(43, 45, 44, .97); color: var(--auf-schiefer); border: 1px solid rgba(244, 241, 235, .3); border-radius: 8px; font: 500 .75rem/1.4 var(--sans); }
.pult .zeile { display: flex; flex-wrap: wrap; align-items: center; gap: 5px; }
.pult .zeile > span { width: 100%; letter-spacing: .06em; text-transform: uppercase; color: var(--auf-schiefer-leise); }
.pult button { min-height: 30px; padding: 0 9px; border: 1px solid rgba(244, 241, 235, .45); border-radius: 4px; font: inherit; color: var(--auf-schiefer); }
.pult button[aria-pressed="true"] { background: var(--auf-schiefer); color: var(--schiefer); }
.pult .werte { color: var(--auf-schiefer-leise); font-size: .75rem; line-height: 1.5; }
.pult [hidden] { display: none; }
/* ---------- Varianten ---------- */
[data-nur]:not([data-sichtbar]) { display: none !important; }
/* ---------- schmal ---------- */
@media (max-width: 1100px) {
.feld-innen { grid-template-columns: minmax(0, 14rem) minmax(0, 1fr); }
.feld-innen .rueckruf { grid-column: 1 / -1; }
.feld-innen .felder { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: 16px; }
.feld-innen .felder > * { grid-column: 1 / -1; }
.feld-innen .felder .feld-paar { grid-column: auto; }
.feld-innen .rueckruf .knopf { width: auto; justify-self: start; }
}
@media (max-width: 860px) {
.held { grid-template-columns: minmax(0, 1fr); }
.held .bild svg { height: clamp(14rem, 50vw, 22rem); }
.zwei, .seite-kopf, .anleitung-seite { grid-template-columns: minmax(0, 1fr); }
.navi { display: none; }
}
@media (max-width: 760px) {
:root { --leiste-h: 96px; scroll-padding-top: 16px; scroll-padding-bottom: calc(var(--leiste-h) + env(safe-area-inset-bottom) + 16px); }
body { padding-bottom: calc(var(--leiste-h) + env(safe-area-inset-bottom)); }
.sofort { position: fixed; left: 0; right: 0; top: auto; bottom: 0; padding-bottom: env(safe-area-inset-bottom); box-shadow: 0 -10px 30px -18px rgba(36, 34, 31, .5); }
.sofort-zeile { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 6px 8px; padding: 8px 12px 10px; min-height: 0; }
.sofort-lage { grid-column: 1 / -1; margin: 0; gap: 0 10px; }
.sofort-titel, .sofort-zeit { font-size: .9375rem; }
.sofort-anruf { display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: center; gap: 0 8px; min-height: 52px; padding: 4px 12px; border-radius: 6px; background: var(--moos-hell); color: var(--schiefer); font-size: 1rem; line-height: 1.2; }
.sofort-anruf svg { grid-row: span 2; color: var(--schiefer); }
.sofort-anruf .anruf-wort { display: block; font-weight: 600; }
.sofort-anruf .tel-nr { font-weight: 500; font-size: .9375rem; }
.sofort-anruf:hover .tel-nr { text-decoration: none; }
.sofort-knopf .lang { display: none; }
.sofort-knopf .kurz { display: inline; }
.sofort .sofort-knopf { min-height: 52px; padding: 0 10px; font-size: 1rem; background: transparent; color: var(--auf-schiefer); border: 1px solid var(--auf-schiefer-leise); }
.feld { top: auto; bottom: 100%; max-height: calc(100svh - var(--leiste-h) - 12px - env(safe-area-inset-bottom)); border-bottom: 0; border-top: 1px solid var(--linie); border-radius: 12px 12px 0 0; transform: translateY(6px); box-shadow: 0 -18px 40px -24px rgba(36, 34, 31, .5); }
.feld-innen { grid-template-columns: minmax(0, 1fr); padding-top: 0; gap: 20px; }
.feld-kopf { position: sticky; top: 0; z-index: 1; background: var(--kalk); padding-top: 14px; padding-bottom: 12px; }
.feld-kopf h2 { font-size: 1.5rem; }
.reiter { flex-direction: row; flex-wrap: wrap; gap: 6px; }
.reiter [role="tab"] { flex: 1 1 9.5rem; border: 1px solid var(--linie); border-radius: 6px; font-size: 1rem; }
.reiter [role="tab"][aria-selected="true"] { border-color: var(--schiefer); box-shadow: inset 0 -3px 0 var(--schiefer); }
.feld-innen .felder { grid-template-columns: minmax(0, 1fr); }
.feld-innen .felder .feld-paar { grid-column: 1 / -1; }
.feld-innen .rueckruf .knopf { width: 100%; }
.consent { left: 8px; right: 8px; width: auto; bottom: calc(var(--leiste-h) + env(safe-area-inset-bottom) + 8px); }
.pult { bottom: calc(var(--leiste-h) + env(safe-area-inset-bottom) + 10px); }
.tueren { grid-template-columns: minmax(0, 1fr); }
.kopf { padding-top: 14px; padding-bottom: 6px; }
}
@media (max-width: 360px) {
.sofort-zeile { grid-template-columns: minmax(0, 1fr); }
:root { --leiste-h: 150px; }
.anleitung-seite .schritte li, .schritte li { grid-template-columns: 2rem minmax(0, 1fr); gap: 2px 10px; }
.wald-hinweis { grid-template-columns: minmax(0, 1fr); }
.wald-hinweis p { grid-column: 1; }
.wald-hinweis .zahl { display: none; }
}
/* ---------- Druckansicht (window.print und Demo-Schalter) ---------- */
.druck body { background: #fff; padding-bottom: 0; }
.druck .sofort, .druck .sprung, .druck .kopf, .druck .fuss, .druck .consent, .druck .pfad, .druck .seite-kopf, .druck .anleitung-seite, .druck .uebernehmen, .druck .unterlagen .stand, .druck .unterlagen .lokal, .druck .unterlagen > h2, .druck .unterlagen > p { display: none !important; }
.druck .zwei { display: block; border: 0; padding: 0; }
.druck .unterlagen { max-width: 44rem; margin: 0 auto; padding: 32px 0; color: #000; }
.druck .druck-kopf { display: grid; gap: 6px; padding-bottom: 14px; margin-bottom: 8px; border-bottom: 1px solid #000; }
.druck .druck-kopf b { font: 400 1.75rem/1.1 var(--serif); }
.druck .haken { break-inside: avoid; border-color: #999; }
.druck .haken:has(input:checked) span > b { text-decoration: none; }
.druck .druck-beenden { display: inline-flex; margin-top: 18px; }
@media print {
.sofort, .sprung, .pult, .consent, fundus-pult-knopf, .druck-beenden { display: none !important; }
body { padding-bottom: 0; }
@page { margin: 18mm 16mm; }
}
:root.reduziert *, :root.reduziert *::before, :root.reduziert *::after { transition-duration: .01ms !important; animation-duration: .01ms !important; }
@media (hover: none) {
.linie .pfeil-schaft { opacity: 1; }
.tuer:hover { border-color: transparent; }
}
@media (forced-colors: active) {
button, [role=button], [role=tab], [role=switch], input, select, textarea { border: 1px solid ButtonText !important; }
.reiter [role="tab"][aria-selected="true"] { outline: 2px solid Highlight; }
.sofort { border-bottom: 1px solid CanvasText; }
.feld { border: 1px solid CanvasText; }
}
.vorschau body { overflow: hidden; }
.vorschau .sprung, .vorschau .consent { display: none !important; }
</style>
</head>
<body>
<div class="sprung"><a href="#trauerfall">Zu „Im Trauerfall“ springen</a><a href="#inhalt">Zum Inhalt springen</a></div>
<aside class="sofort" id="trauerfall" aria-label="Im Trauerfall" tabindex="-1">
<div class="sofort-zeile">
<p class="sofort-lage"><span class="sofort-titel">Im Trauerfall</span> <span class="sofort-zeit" id="sofort-zeit">Tag und Nacht</span></p>
<a class="sofort-anruf" id="sofort-anruf" href="tel:+498999998120">
<svg width="22" height="22" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M6.6 3.5h3l1.5 4-2 1.3a11 11 0 0 0 6.1 6.1l1.3-2 4 1.5v3a2 2 0 0 1-2.1 2A16.5 16.5 0 0 1 4.6 5.6 2 2 0 0 1 6.6 3.5Z" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linejoin="round"/></svg>
<span class="anruf-wort">Anrufen</span><span class="tel-nr" id="sofort-nr">089 99998 120</span>
</a>
<button class="knopf knopf-hell sofort-knopf" id="sofort-knopf" type="button" aria-expanded="false" aria-controls="feld">
<span class="knopf-text"><span class="lang">Was ist jetzt zu tun?</span><span class="kurz">Was ist zu tun?</span></span>
<svg class="chevron" width="16" height="16" viewBox="0 0 16 16" aria-hidden="true" focusable="false"><path d="M3.5 6 8 10.5 12.5 6" fill="none" stroke="currentColor" stroke-width="1.6"/></svg>
</button>
</div>
<section class="feld" id="feld" aria-labelledby="feld-titel" hidden>
<div class="feld-innen" id="feld-innen"></div>
</section>
</aside>
<header class="kopf" id="kopf"></header>
<main id="inhalt" tabindex="-1"></main>
<footer class="fuss dunkel">
<div class="fuss-innen" id="fuss"></div>
</footer>
<section class="consent" id="consent" aria-labelledby="consent-titel" hidden>
<h2 id="consent-titel">Ihre Privatsphäre</h2>
<p>Wir verwenden nur Cookies, die für die Seite nötig sind. Eine Statistik nutzen wir nur, wenn Sie zustimmen. Auf den Seiten zum Trauerfall gibt es keine Werbung.</p>
<div class="reihe">
<button class="knopf knopf-rand" type="button" data-consent>Nur notwendige</button>
<button class="knopf knopf-rand" type="button" data-consent>Statistik erlauben</button>
</div>
</section>
<div class="pult" role="group" aria-label="Steuerung der Demo">
<div class="zeile" role="group" aria-label="Variante"><span>Variante</span>
<button type="button" data-v="leiste" aria-pressed="true">Leiste</button>
<button type="button" data-v="seite" aria-pressed="false">Seite</button>
<button type="button" data-v="wald" aria-pressed="false">Wald</button>
</div>
<div class="zeile" role="group" aria-label="Erreichbarkeit nachts" id="pult-nacht"><span>Nachts</span>
<button type="button" data-nacht="tag" aria-pressed="true">Mensch am Telefon</button>
<button type="button" data-nacht="bereitschaft" aria-pressed="false">Rufbereitschaft</button>
</div>
<div class="zeile" role="group" aria-label="Zustände"><span>Zustand</span>
<button type="button" id="pult-fehler" aria-pressed="false">Rückruf scheitert</button>
<button type="button" id="pult-consent" aria-pressed="false">Consent-Banner</button>
<button type="button" id="pult-druck" aria-pressed="false">Druckansicht</button>
</div>
<p class="werte" id="pult-werte">Öffnen 300 ms (0.4, 0, 0.2, 1) · Schließen 200 ms (0.4, 0, 1, 1) · max. 6 px · sonst keine Bewegung</p>
</div>
<template id="t-held-steinlinde">
<div class="huelle">
<div class="held">
<div class="held-text">
<p class="rubrik">Bestattungshaus in Pasing</p>
<h1>Wir sind da, wenn ein Mensch stirbt. Und wenn Sie vorsorgen möchten.</h1>
<div class="held-tel">
<a href="tel:+498999998120" class="tel-nr" data-nr>089 99998 120</a>
<span data-erreichbar>Tag und Nacht erreichbar, auch am Wochenende</span>
</div>
<div class="tueren">
<button class="tuer" type="button" data-oeffne aria-controls="feld">
<b>Ein Mensch ist gestorben</b>
<span>Was jetzt zu tun ist, Schritt für Schritt</span>
<span class="pfeil" aria-hidden="true"><svg width="22" height="12" viewBox="0 0 22 12"><path d="M0 6h20M15 1l5 5-5 5" fill="none" stroke="#24221f" stroke-width="1.5"/></svg></span>
</button>
<a class="tuer" href="#">
<b>Ich möchte vorsorgen</b>
<span>Wünsche festlegen, Geld sicher hinterlegen</span>
<span class="pfeil" aria-hidden="true"><svg width="22" height="12" viewBox="0 0 22 12"><path d="M0 6h20M15 1l5 5-5 5" fill="none" stroke="#24221f" stroke-width="1.5"/></svg></span>
</a>
</div>
</div>
<figure class="bild">
<svg viewBox="0 0 600 640" role="img" aria-label="Abschiedsraum im Tageslicht: ein hohes Fenster zum Garten, ein Leinenvorhang, eine Holzbank an der Wand." preserveAspectRatio="xMidYMid slice">
<rect width="600" height="640" fill="#e8e1d5"/>
<rect y="486" width="600" height="154" fill="#d9cfbf"/>
<rect y="482" width="600" height="5" fill="#cfc6b6"/>
<polygon points="262,487 506,487 600,640 300,640" fill="#e4dccf"/>
<rect x="248" y="70" width="272" height="412" fill="#f4f1eb"/>
<rect x="264" y="86" width="240" height="380" fill="#dfe5dc"/>
<path d="M264 300c30-26 64-34 96-22 26-30 74-34 104-6 18-6 32-2 40 4v190H264Z" fill="#b5c8b8"/>
<path d="M264 360c22-18 52-22 74-10 20-22 56-26 80-8 24-14 64-12 86 6v118H264Z" fill="#8fb59a"/>
<path d="M264 418c40-14 90-12 120-2 36-14 86-14 120 0v50H264Z" fill="#6e8c76"/>
<rect x="380" y="86" width="8" height="380" fill="#f4f1eb"/>
<rect x="264" y="286" width="240" height="8" fill="#f4f1eb"/>
<rect x="248" y="466" width="272" height="16" fill="#ece6dc"/>
<path d="M196 60h52v426h-52c6-60 10-150 6-220-3-70-8-140-6-206Z" fill="#efe9df"/>
<path d="M210 64c-2 110 2 300 0 418M226 64c2 120-2 290 2 418M240 64c-1 140 1 280 0 418" fill="none" stroke="#ddd5c8" stroke-width="2"/>
<rect x="186" y="54" width="350" height="8" rx="4" fill="#cfc6b6"/>
<rect x="24" y="446" width="196" height="16" rx="2" fill="#9c8467"/>
<rect x="34" y="462" width="12" height="40" fill="#7d6a52"/>
<rect x="198" y="462" width="12" height="40" fill="#7d6a52"/>
<rect x="30" y="434" width="184" height="12" rx="6" fill="#cfc6b6"/>
<rect x="24" y="500" width="196" height="4" fill="#cfc6b6"/>
<rect x="540" y="370" width="30" height="116" rx="12" fill="#c9bfae"/>
<path d="M555 372c-6-60-20-110-38-150M556 372c4-70 2-120-6-170M557 372c10-50 24-90 40-120" fill="none" stroke="#6e7f6f" stroke-width="2"/>
</svg>
<figcaption>Unser Abschiedsraum zum Garten. Sie können sich hier in Ruhe verabschieden.</figcaption>
</figure>
</div>
</div>
</template>
<template id="t-held-wald">
<div class="huelle">
<div class="held">
<div class="held-text">
<p class="rubrik">Baumbestattung südlich von München</p>
<h1>Ein Platz unter Bäumen. Für Menschen, die im Wald ruhen möchten.</h1>
<div class="held-tel">
<a href="tel:+498999998340" class="tel-nr">089 99998 340</a>
<span>Verwaltung: Montag bis Freitag, 8 bis 16 Uhr</span>
</div>
<div class="tueren">
<button class="tuer" type="button" data-oeffne aria-controls="feld">
<b>Ein Mensch ist gestorben</b>
<span>Was jetzt zu tun ist und wer was übernimmt</span>
<span class="pfeil" aria-hidden="true"><svg width="22" height="12" viewBox="0 0 22 12"><path d="M0 6h20M15 1l5 5-5 5" fill="none" stroke="#24221f" stroke-width="1.5"/></svg></span>
</button>
<a class="tuer" href="#">
<b>Waldführung kennenlernen</b>
<span>Den Wald sehen und einen Platz aussuchen</span>
<span class="pfeil" aria-hidden="true"><svg width="22" height="12" viewBox="0 0 22 12"><path d="M0 6h20M15 1l5 5-5 5" fill="none" stroke="#24221f" stroke-width="1.5"/></svg></span>
</a>
</div>
</div>
<figure class="bild">
<svg viewBox="0 0 600 640" role="img" aria-label="Buchenwald im Herbstlicht: hohe glatte Stämme, ein heller Weg zwischen Moos, an einem Baum eine kleine Holztafel." preserveAspectRatio="xMidYMid slice">
<rect width="600" height="640" fill="#e6e7df"/>
<rect x="40" width="10" height="460" fill="#c4c6bc"/><rect x="120" width="8" height="450" fill="#c4c6bc"/><rect x="350" width="9" height="455" fill="#c4c6bc"/><rect x="470" width="7" height="450" fill="#c4c6bc"/><rect x="560" width="10" height="460" fill="#c4c6bc"/>
<rect x="80" width="20" height="490" fill="#9a9b90"/><rect x="250" width="16" height="480" fill="#9a9b90"/><rect x="420" width="18" height="485" fill="#9a9b90"/>
<rect y="440" width="600" height="200" fill="#b9c7b1"/>
<path d="M0 470c80-14 170-10 240 2 70-12 190-16 360-2v170H0Z" fill="#a6bba0"/>
<path d="M302 466c-4 50-34 110-92 174h264c-52-64-82-124-86-174Z" fill="#e8e1d5"/>
<ellipse cx="170" cy="560" rx="46" ry="7" fill="#97ab92"/>
<rect x="150" width="40" height="560" fill="#6e675d"/>
<ellipse cx="493" cy="590" rx="52" ry="8" fill="#97ab92"/>
<rect x="470" width="46" height="590" fill="#5a554d"/>
<rect x="478" y="388" width="30" height="20" rx="2" fill="#a08b6f"/>
<rect x="486" y="395" width="14" height="2" fill="#5a554d"/><rect x="486" y="400" width="10" height="2" fill="#5a554d"/>
<path d="M0 600c40-8 90-8 120 0v40H0Z" fill="#8fb59a"/><path d="M520 612c30-10 60-10 80-4v32h-80Z" fill="#8fb59a"/>
</svg>
<figcaption>Im Ruhewald am Hochanger. Jeder Platz liegt an einem Baum mit Nummer.</figcaption>
</figure>
</div>
</div>
</template>
<script>
(() => {
const h = document.documentElement;
const reduziert = () => h.classList.contains('reduziert');
const $ = (s, r = document) => r.querySelector(s);
const $$ = (s, r = document) => [...r.querySelectorAll(s)];
const q = new URLSearchParams(location.search);
const VARIANTEN = ['leiste', 'seite', 'wald'];
/* ---------- Daten (Texte vom Kunden prüfen lassen) ---------- */
const HAUS = {
steinlinde: {
tel: '089 99998 120', href: 'tel:+498999998120',
marke: 'Steinlinde', zusatz: 'Bestattungshaus · München-Pasing',
navi: ['Im Trauerfall', 'Bestattungsarten', 'Kosten', 'Vorsorge', 'Traueranzeigen', 'Über uns'],
fuss: '<p><b>Bestattungshaus Steinlinde</b><br>Steinlindenweg 4, 81241 München<br>Büro werktags 8 bis 18 Uhr</p><p>Impressum · Datenschutz · Erklärung zur Barrierefreiheit<br><span class="platzhalter" style="border-color:#8f897f;color:#c9c3b8;margin-top:6px">Platzhalter: Pflichtangaben vom Kunden prüfen lassen</span></p><p>Beispielseite: Haus, Personen und Adresse sind erfunden. Die Nummern stammen aus dem Bereich, den die Bundesnetzagentur für Medienproduktionen freihält.</p>'
},
wald: {
tel: '089 99998 340', href: 'tel:+498999998340',
marke: 'Ruhewald am Hochanger', zusatz: 'Baumbestattung · Landkreis München',
navi: ['Waldführung', 'Grabarten und Kosten', 'Beisetzung', 'Anfahrt', 'Im Trauerfall'],
fuss: '<p><b>Ruhewald am Hochanger</b> · Verwaltung<br>Forsthaus am Hochanger 1<br>Montag bis Freitag 8 bis 16 Uhr</p><p>Impressum · Datenschutz · Waldsatzung<br><span class="platzhalter" style="border-color:#8f897f;color:#c9c3b8;margin-top:6px">Platzhalter: Pflichtangaben und Satzung vom Kunden prüfen lassen</span></p><p>Beispielseite: Wald, Personen und Adresse sind erfunden. Die Nummern stammen aus dem Bereich, den die Bundesnetzagentur für Medienproduktionen freihält.</p>'
}
};
const ARZT = 'Rufen Sie die Hausarztpraxis an, nachts und am Wochenende den ärztlichen Bereitschaftsdienst unter <a href="tel:116117">116 117</a>.';
const ANLEITUNG = {
steinlinde: [
{ id: 'zuhause', reiter: 'Zu Hause', titel: 'Wenn der Mensch zu Hause gestorben ist', schritte: [
['Eine Ärztin oder einen Arzt rufen.', ARZT + ' Die Ärztin stellt den Tod fest (Leichenschau) und schreibt die Todesbescheinigung. Den Notruf <a href="tel:112">112</a> brauchen Sie nur, wenn Sie nicht sicher sind, ob der Mensch noch lebt.'],
['Uns anrufen, wenn Sie so weit sind.', 'Wir besprechen mit Ihnen, wann wir kommen. Sie müssen nichts vorbereiten. Wie lange der Verstorbene zu Hause bleiben darf, regelt das Land; wir sagen es Ihnen am Telefon.'],
['Abschied nehmen.', 'Bleiben Sie, so lange Sie möchten. Rufen Sie Menschen an, die sich verabschieden möchten. Das Zimmer darf so bleiben, wie es ist.'],
['Unterlagen bereitlegen.', 'Ausweis, Geburts- oder Eheurkunde; die ganze Liste steht in der Checkliste. Den Sterbefall melden wir beim Standesamt. Das muss bis zum dritten Werktag nach dem Tod geschehen.']
] },
{ id: 'haus', reiter: 'Krankenhaus, Heim, Hospiz', titel: 'Wenn der Mensch im Krankenhaus, im Heim oder im Hospiz gestorben ist', schritte: [
['Das Haus ruft die Ärztin.', 'Eine Ärztin des Hauses stellt den Tod fest und schreibt die Todesbescheinigung. Darum müssen Sie sich nicht kümmern.'],
['Sagen Sie, wer die Bestattung übernimmt.', 'Nennen Sie der Station oder der Pflege unseren Namen. Oder rufen Sie uns an: Wir melden uns beim Haus und vereinbaren, wann wir den Verstorbenen abholen.'],
['Nach einem Abschied vor Ort fragen.', 'Viele Häuser haben dafür einen ruhigen Raum. Sie können sich auch später bei uns verabschieden, in unserem Abschiedsraum.'],
['Unterlagen bereitlegen.', 'Was Sie brauchen, steht in der Checkliste. Persönliche Sachen bewahrt das Haus meist eine Weile auf.']
] },
{ id: 'unerwartet', reiter: 'Unerwartet oder Unfall', titel: 'Wenn der Tod unerwartet kam oder nach einem Unfall', schritte: [
['Im Zweifel den Notruf 112 wählen.', 'Wenn Sie nicht sicher sind, ob jemand noch lebt, rufen Sie <a href="tel:112">112</a>.'],
['Polizei und Ärztin klären die Ursache.', 'Bei einem plötzlichen Tod, einem Unfall oder wenn die Ursache unklar ist, wird die Polizei hinzugezogen. Das ist üblich und kein Verdacht gegen Sie.'],
['Uns anrufen, auch nur mit Fragen.', 'Bis die Behörden den Verstorbenen freigeben, kann es einige Tage dauern. Wir halten den Kontakt und sagen Ihnen, wann ein Abschied möglich ist.'],
['Sich Hilfe holen.', 'Sie müssen das nicht allein tragen. Die Telefonseelsorge ist rund um die Uhr erreichbar: <a href="tel:08001110111">0800 111 0 111</a>.']
] },
{ id: 'ausland', reiter: 'Im Ausland', titel: 'Wenn der Mensch im Ausland gestorben ist', schritte: [
['Die Papiere vor Ort geben lassen.', 'Eine ärztliche Bescheinigung oder die Sterbeurkunde des Landes. Die deutsche Botschaft oder das Konsulat hilft bei Fragen zu Papieren und Behörden.'],
['Uns anrufen.', 'Wir organisieren mit einem Partner vor Ort die Überführung nach München oder eine Einäscherung im Land. Was das kostet, sagen wir Ihnen vorher.'],
['Versicherungen prüfen.', 'Manche Reise- und Auslandskrankenversicherungen tragen die Überführung. Legen Sie die Police bereit; wir sprechen mit der Versicherung.'],
['Unterlagen bereitlegen.', 'Reisepass, Geburts- und Eheurkunde. Urkunden in fremder Sprache brauchen eine beglaubigte Übersetzung.']
] }
],
wald: [
{ id: 'platz', reiter: 'Es gibt schon einen Platz', titel: 'Wenn der Verstorbene schon einen Platz bei uns hat', schritte: [
['Den Tod feststellen lassen.', 'Wie bei jedem Sterbefall. ' + ARZT + ' Im Krankenhaus, Heim oder Hospiz übernimmt das Haus.'],
['Ein Bestattungshaus beauftragen.', 'Es holt den Verstorbenen ab und kümmert sich um Einäscherung und Papiere. Im Ruhewald werden nur Urnen beigesetzt. Sagen Sie dort, dass es einen Platz bei uns gibt.'],
['Die Platznummer weitergeben.', 'Sie steht auf der Urkunde über den Platz. Haben Sie die Urkunde nicht zur Hand, finden wir den Platz auch über den Namen.'],
['Den Tag der Beisetzung abstimmen.', 'Das Bestattungshaus meldet die Beisetzung bei uns an. Den Tag legen wir gemeinsam mit Ihnen fest.']
] },
{ id: 'neu', reiter: 'Noch kein Platz', titel: 'Wenn es noch keinen Platz gibt', schritte: [
['Den Tod feststellen lassen.', 'Wie bei jedem Sterbefall. ' + ARZT],
['Ein Bestattungshaus beauftragen.', 'Sagen Sie, dass Sie eine Beisetzung im Wald wünschen. Das Bestattungshaus kümmert sich um Abholung, Einäscherung und Papiere.'],
['Einen Platz aussuchen.', 'Eine Försterin geht mit Ihnen durch den Wald, und Sie wählen einen Baum. Den Termin dafür vereinbaren Sie mit uns.'],
['Den Tag der Beisetzung abstimmen.', 'Wie viel Zeit bis zur Beisetzung bleibt, regelt das Land. Das Bestattungshaus kennt die Fristen und stimmt den Tag mit uns ab.']
] }
]
};
const UNTERLAGEN = [
{ legend: 'Für das Standesamt', hinweis: 'Den Sterbefall melden in der Regel wir für Sie.', punkte: [
['todes', 'Todesbescheinigung', 'stellt die Ärztin aus; oft bringt sie das Haus oder die Ärztin mit'],
['ausweis', 'Personalausweis oder Reisepass der verstorbenen Person', ''],
['geburt', 'Geburtsurkunde oder Auszug aus dem Geburtenregister', ''],
['ehe', 'Urkunde der letzten Ehe oder Lebenspartnerschaft', 'nur, wenn es eine gab'],
['aufloesung', 'Scheidungsurteil oder Sterbeurkunde des Partners', 'nur bei geschiedener Ehe oder verwitweten Menschen']
] },
{ legend: 'Für die Bestattung und danach', hinweis: '', punkte: [
['kasse', 'Karte der Krankenkasse', ''],
['rente', 'Rentenbescheid oder Rentennummer', ''],
['vorsorge', 'Vorsorgevertrag oder Bestattungsverfügung', 'falls vorhanden'],
['grab', 'Unterlagen zum Grab', 'wenn es schon ein Familiengrab gibt'],
['police', 'Police einer Lebens- oder Sterbegeldversicherung', 'falls vorhanden']
] }
];
/* ---------- Zustand ---------- */
const zustand = {
v: VARIANTEN.includes(q.get('v')) ? q.get('v') : 'leiste',
nacht: 'tag', fehler: false, consent: false, druckSchalter: false,
offen: false, reiter: 0
};
const haus = () => zustand.v === 'wald' ? 'wald' : 'steinlinde';
const H = () => HAUS[haus()];
/* Ortszeit Europe/Berlin */
function berlin(d = new Date()) {
const t = Object.fromEntries(new Intl.DateTimeFormat('de-DE', { timeZone: 'Europe/Berlin', hourCycle: 'h23', weekday: 'short', hour: '2-digit', minute: '2-digit' }).formatToParts(d).map(p => [p.type, p.value]));
return { tag: t.weekday, std: +t.hour, min: +t.minute };
}
const uhr = d => new Intl.DateTimeFormat('de-DE', { timeZone: 'Europe/Berlin', hour: '2-digit', minute: '2-digit', hourCycle: 'h23' }).format(d).replace(':', '.');
const werktag = b => !['Sa', 'So'].includes(b.tag);
function besetzt(von, bis) { const b = berlin(); return werktag(b) && b.std >= von && b.std < bis; }
function naechsterWerktag() {
const fmt = new Intl.DateTimeFormat('de-DE', { timeZone: 'Europe/Berlin', weekday: 'long' });
const b = berlin(); let d = new Date();
if (werktag(b) && b.std < 8) return 'heute';
for (let i = 1; i < 8; i++) { d = new Date(Date.now() + i * 864e5); if (werktag(berlin(d))) return i === 1 ? 'morgen' : 'am ' + fmt.format(d); }
return 'am nächsten Werktag';
}
/* Die Zusage steht nur da, wenn das Haus sie hält: hier aus der Konfiguration */
function zusage() {
if (haus() === 'wald') {
return besetzt(8, 16)
? { satz: 'Während der Bürozeit rufen wir am selben Tag zurück, spätestens bis 16 Uhr.', bis: () => 'heute bis 16 Uhr' }
: { satz: 'Die Verwaltung ist gerade nicht besetzt. Wir rufen ' + naechsterWerktag() + ' ab 8 Uhr zurück.', bis: () => naechsterWerktag() + ' zwischen 8 und 12 Uhr' };
}
const min = zustand.nacht === 'tag' || besetzt(8, 18) ? 15 : 30;
return { satz: 'Wir rufen innerhalb von ' + min + ' Minuten zurück.', bis: () => 'bis ' + uhr(new Date(Date.now() + min * 6e4)) + ' Uhr' };
}
function zeitText() {
if (haus() === 'wald') return { kurz: 'Verwaltung Mo–Fr 8–16 Uhr', lang: 'Verwaltung: Montag bis Freitag, 8 bis 16 Uhr', wieder: 'Verwaltung, Montag bis Freitag 8 bis 16 Uhr' };
return zustand.nacht === 'tag'
? { kurz: 'Tag und Nacht', lang: 'Tag und Nacht erreichbar, auch am Wochenende', wieder: 'Tag und Nacht, auch am Wochenende' }
: { kurz: 'Werktags 8–18 Uhr, nachts Rufbereitschaft', lang: 'Werktags 8 bis 18 Uhr im Haus. Nachts und am Wochenende Rufbereitschaft: Sprechen Sie auf Band, wir rufen innerhalb von 30 Minuten zurück.', wieder: 'Werktags 8 bis 18 Uhr, nachts Rufbereitschaft mit Rückruf in 30 Minuten' };
}
/* ---------- Bausteine ---------- */
const pfeil = '<svg width="20" height="12" viewBox="0 0 20 12" aria-hidden="true" focusable="false"><path class="pfeil-schaft" d="M1 6h16" stroke="currentColor" stroke-width="1.5"/><path class="pfeil-spitze" d="M12 1.5 16.5 6 12 10.5" fill="none" stroke="currentColor" stroke-width="1.5"/></svg>';
function reiterHtml(p, groesse) {
const daten = ANLEITUNG[haus()];
const tabs = daten.map((r, i) => `<button type="button" role="tab" id="${p}-tab-${r.id}" aria-controls="${p}-panel-${r.id}" aria-selected="${i === zustand.reiter}" tabindex="${i === zustand.reiter ? 0 : -1}">${r.reiter}</button>`).join('');
const z = zeitText();
const panels = daten.map((r, i) => `<div role="tabpanel" id="${p}-panel-${r.id}" aria-labelledby="${p}-tab-${r.id}" tabindex="0"${i === zustand.reiter ? '' : ' hidden'}>
<${groesse} class="panel-titel">${r.titel}</${groesse}>
<ol class="schritte">${r.schritte.map(s => `<li><strong>${s[0]}</strong><p>${s[1]}</p></li>`).join('')}</ol>
<p class="wiederholung"><span>${z.wieder}</span> <a class="tel-nr" href="${H().href}">${H().tel}</a></p>
</div>`).join('');
return {
tabs: `<p class="reiter-frage" id="${p}-frage">${haus() === 'wald' ? 'Gibt es schon einen Platz im Wald?' : 'Wo ist der Mensch gestorben?'}</p><div class="reiter" role="tablist" aria-labelledby="${p}-frage" aria-orientation="${zustand.v === 'seite' ? 'horizontal' : 'vertical'}">${tabs}</div>`,
panels: `<div class="reiter-flaeche">${panels}</div>`
};
}
function rueckrufHtml(p, titel) {
return `<form class="rueckruf" id="${p}-form" novalidate aria-labelledby="${p}-titel">
${titel ? `<h3 id="${p}-titel">Lieber zurückgerufen werden?</h3>` : ''}
<p class="zusage" id="${p}-zusage">${zusage().satz}</p>
<div class="fehlerliste" id="${p}-fehler" tabindex="-1" hidden><p>Bitte prüfen Sie:</p><ul></ul></div>
<div class="antwort" id="${p}-antwort" role="status" tabindex="-1"></div>
<div class="felder">
<div class="feld-paar"><label for="${p}-name">Ihr Name</label><input id="${p}-name" name="name" autocomplete="name" aria-describedby="${p}-name-f"><p class="feldfehler" id="${p}-name-f" hidden></p></div>
<div class="feld-paar"><label for="${p}-tel">Ihre Telefonnummer</label><input id="${p}-tel" name="tel" type="tel" inputmode="tel" autocomplete="tel" aria-describedby="${p}-tel-f"><p class="feldfehler" id="${p}-tel-f" hidden></p></div>
<button class="knopf knopf-moos" type="submit"><span class="knopf-text">Rückruf anfordern</span></button>
<p class="klein">Wir nutzen Name und Nummer nur für diesen Rückruf. <span class="platzhalter">Platzhalter: Datenschutzhinweis vom Kunden prüfen lassen</span></p>
</div>
</form>`;
}
function unterlagenHtml() {
const gruppen = UNTERLAGEN.map((g, gi) => `<fieldset><legend>${g.legend}</legend>${g.hinweis ? `<p class="klein">${g.hinweis}</p>` : ''}
${g.punkte.map(pk => `<label class="haken"><input type="checkbox" name="${pk[0]}"><span><b>${pk[1]}</b>${pk[2] ? `<small>${pk[2]}</small>` : ''}</span></label>`).join('')}</fieldset>`).join('');
return `<section class="unterlagen" id="unterlagen" aria-labelledby="unt-titel">
<div class="druck-kopf"><b>Steinlinde · Bestattungshaus</b><span>Unterlagen für den Trauerfall · Tag und Nacht: ${HAUS.steinlinde.tel}</span></div>
<h2 id="unt-titel">Unterlagen bereitlegen</h2>
<p>Haken Sie ab, was Sie gefunden haben. Was fehlt, besorgen wir mit Ihnen.</p>
<form id="liste" onsubmit="return false">${gruppen}</form>
<div class="stand"><p class="stand-zahl" id="stand" aria-live="polite">0 von 10 bereit</p>
<button class="knopf knopf-rand" type="button" id="drucken"><svg width="18" height="18" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M7 9V3h10v6M7 17H4v-7h16v7h-3M7 14h10v7H7Z" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linejoin="round"/></svg><span class="knopf-text">Liste drucken</span></button>
<button class="knopf knopf-rand" type="button" id="leeren">Häkchen entfernen</button></div>
<p class="klein lokal">Ihre Häkchen bleiben nur auf diesem Gerät. Es wird nichts gesendet.</p>
<button class="knopf knopf-rand druck-beenden" type="button" id="druck-beenden">Druckansicht beenden</button>
</section>`;
}
/* ---------- Aufbau je Variante ---------- */
function aufbauen() {
const v = zustand.v, x = H(), z = zeitText();
document.body.dataset.v = v;
$('#sofort-zeit').textContent = z.kurz;
$('#sofort-nr').textContent = x.tel;
$('#sofort-anruf').href = x.href;
const knopf = $('#sofort-knopf');
if (v === 'seite') { knopf.setAttribute('aria-current', 'page'); knopf.removeAttribute('aria-expanded'); knopf.removeAttribute('aria-controls'); knopf.classList.remove('knopf-hell'); }
else { knopf.removeAttribute('aria-current'); knopf.setAttribute('aria-expanded', 'false'); knopf.setAttribute('aria-controls', 'feld'); knopf.classList.add('knopf-hell'); }
knopf.querySelector('.chevron').style.display = v === 'seite' ? 'none' : '';
$('#kopf').innerHTML = `<a class="marke" href="#"><b>${x.marke}</b><span>${x.zusatz}</span></a>
<nav class="navi" aria-label="Hauptmenü"><ul>${x.navi.map(n => `<li><a href="#"${v === 'seite' && n === 'Im Trauerfall' ? ' aria-current="page"' : ''}>${n}</a></li>`).join('')}</ul></nav>`;
$('#fuss').innerHTML = x.fuss;
const main = $('#inhalt'), feld = $('#feld-innen');
if (v === 'seite') {
const r = reiterHtml('s', 'h3');
main.innerHTML = `<div class="huelle">
<nav class="pfad" aria-label="Sie sind hier"><a href="#">Start</a> / <a href="#">Im Trauerfall</a> / <span aria-current="page">Was ist jetzt zu tun?</span></nav>
<div class="seite-kopf"><div class="seite-text"><h1 id="seite-titel" tabindex="-1">Was ist jetzt zu tun?</h1>
<p class="zeit-satz">Sie haben Zeit. Niemand erwartet, dass Sie jetzt alles wissen.</p>
<p>Diese Seite führt Sie durch die ersten Stunden. Wählen Sie unten, wo der Mensch gestorben ist.</p>
<span class="platzhalter">Platzhalter: Texte zu Ablauf und Fristen vom Kunden prüfen lassen (Landesrecht)</span></div>
<div class="kontakt-karte"><p class="rubrik">Lieber sprechen?</p><a class="tel-nr" href="${x.href}">${x.tel}</a><p>${z.lang}</p><p class="klein">Sie können auch nur Fragen stellen. Ein Gespräch verpflichtet zu nichts.</p></div></div>
<section class="anleitung-seite" id="anleitung" aria-labelledby="anl-titel"><h2 id="anl-titel" class="nur-sr">Erste Schritte nach Sterbeort</h2>
<div class="anleitung-haupt">${r.tabs}${r.panels}</div>
<section class="rueckruf-spalte" aria-labelledby="s-titel"><h2 id="s-titel">Lieber zurückgerufen werden?</h2><p class="klein" style="margin-bottom:12px">Zwei Angaben reichen. Sie müssen nichts erklären.</p>${rueckrufHtml('s', false)}</section></section>
<div class="zwei">${unterlagenHtml()}
<section class="uebernehmen" aria-labelledby="ue-titel"><h2 id="ue-titel">Was wir für Sie übernehmen</h2>
<ul><li><b>Standesamt</b><span>Wir melden den Sterbefall und holen die Sterbeurkunden.</span></li>
<li><b>Abholung</b><span>Wir kommen, wann es für Sie passt, auch nachts.</span></li>
<li><b>Friedhof und Termine</b><span>Wir stimmen Trauerfeier und Beisetzung mit Friedhof oder Krematorium ab.</span></li>
<li><b>Abmeldungen</b><span>Rente, Krankenkasse und Versicherungen, wenn Sie das möchten.</span></li></ul>
<p class="klein">Was jede Leistung kostet, steht vorher schriftlich fest.</p></section>
</div></div>`;
feld.innerHTML = ''; $('#feld').removeAttribute('aria-labelledby');
zustand.offen = false; $('#feld').hidden = true; $('#feld').classList.remove('auf');
} else {
main.innerHTML = $(v === 'wald' ? '#t-held-wald' : '#t-held-steinlinde').innerHTML;
$$('[data-erreichbar]', main).forEach(e => e.textContent = z.lang);
const r = reiterHtml('f', 'h3');
$('#feld').setAttribute('aria-labelledby', 'feld-titel');
feld.innerHTML = `<div class="feld-kopf"><h2 id="feld-titel" tabindex="-1">Was ist jetzt zu tun?</h2><p class="zeit-satz">Sie haben Zeit.</p>
<button class="schliessen" type="button" id="schliessen"><svg width="16" height="16" viewBox="0 0 16 16" aria-hidden="true" focusable="false"><path d="M3 3l10 10M13 3 3 13" stroke="currentColor" stroke-width="1.6"/></svg>Schließen</button></div>
${v === 'wald' ? `<div class="wald-hinweis"><span class="zahl" aria-hidden="true">!</span><strong>Bitte beauftragen Sie zuerst ein Bestattungshaus.</strong>
<p>Wir sind die Verwaltung des Waldes. Abholung, Einäscherung und Papiere übernimmt das Bestattungshaus Ihrer Wahl; es meldet die Beisetzung bei uns an. Nachts und am Wochenende erreichen Sie Ihr Bestattungshaus, unsere Verwaltung ist Montag bis Freitag von 8 bis 16 Uhr besetzt.</p></div>` : ''}
<div class="reiter-spalte">${r.tabs}</div>${r.panels}${rueckrufHtml('f', true)}
<div class="feld-fuss">${v === 'leiste' ? `<a class="linie" href="?v=seite" id="zur-seite">Unterlagen-Checkliste zum Drucken ${pfeil}</a>` : `<a class="linie" href="#">Bestattungshäuser in der Nähe ${pfeil}</a>`}
<span class="platzhalter" style="margin:0">Platzhalter: Texte vom Kunden prüfen lassen</span></div>`;
}
binden();
zeigeDruck();
pultZeigen();
}
/* ---------- Verhalten ---------- */
function reiterWaehlen(i, fokus) {
const liste = $('[role="tablist"]'); if (!liste) return;
const tabs = $$('[role="tab"]', liste);
i = (i + tabs.length) % tabs.length; zustand.reiter = i;
tabs.forEach((t, k) => {
const an = k === i;
t.setAttribute('aria-selected', an); t.tabIndex = an ? 0 : -1;
document.getElementById(t.getAttribute('aria-controls')).hidden = !an;
});
if (fokus) tabs[i].focus();
}
function feldAuf(fokus) {
if (zustand.v === 'seite') return;
const feld = $('#feld'); zustand.offen = true;
clearTimeout(feld._t); feld.hidden = false;
void feld.offsetWidth; feld.classList.add('auf');
$('#sofort-knopf').setAttribute('aria-expanded', 'true');
if (fokus) $('#feld-titel').focus({ preventScroll: true });
}
function feldZu(fokusZurueck) {
const feld = $('#feld'); if (!zustand.offen) return;
zustand.offen = false; feld.classList.remove('auf');
$('#sofort-knopf').setAttribute('aria-expanded', 'false');
feld._t = setTimeout(() => { if (!zustand.offen) feld.hidden = true; }, reduziert() ? 0 : 200);
if (fokusZurueck) $('#sofort-knopf').focus();
}
function stand() {
const boxen = $$('#liste input'); if (!boxen.length) return;
const n = boxen.filter(b => b.checked).length;
$('#stand').textContent = n + ' von ' + boxen.length + ' bereit';
try { localStorage.setItem('steinlinde-unterlagen', JSON.stringify(boxen.filter(b => b.checked).map(b => b.name))); } catch (e) {}
}
function zeigeDruck() { h.classList.toggle('druck', zustand.druckSchalter && zustand.v === 'seite'); }
function feldFehler(form, feld, text) {
const f = document.getElementById(feld.getAttribute('aria-describedby'));
if (text) { feld.setAttribute('aria-invalid', 'true'); f.textContent = text; f.hidden = false; }
else { feld.removeAttribute('aria-invalid'); f.textContent = ''; f.hidden = true; }
}
function absenden(form, auto) {
const p = form.id.split('-')[0];
const name = form.elements.name, tel = form.elements.tel, liste = $('#' + p + '-fehler');
const fehler = [];
const ziffern = tel.value.replace(/[^\d]/g, '');
feldFehler(form, name, name.value.trim() ? '' : 'Bitte geben Sie Ihren Namen an.');
if (!name.value.trim()) fehler.push([name, 'Bitte geben Sie Ihren Namen an.']);
const telText = !tel.value.trim() ? 'Bitte geben Sie Ihre Telefonnummer an.' : ziffern.length < 6 ? 'Die Nummer ist zu kurz. Bitte mit Vorwahl, zum Beispiel 0151 23456789.' : '';
feldFehler(form, tel, telText); if (telText) fehler.push([tel, telText]);
if (fehler.length) {
liste.querySelector('ul').innerHTML = fehler.map(f => `<li><a href="#${f[0].id}">${f[1]}</a></li>`).join('');
liste.hidden = false; if (!auto) liste.focus();
return;
}
liste.hidden = true;
const k = form.querySelector('[type="submit"]');
k.setAttribute('aria-busy', 'true'); k.querySelector('.knopf-text').textContent = 'Wird gesendet';
clearTimeout(form._t);
form._t = setTimeout(() => {
k.removeAttribute('aria-busy'); k.querySelector('.knopf-text').textContent = 'Rückruf anfordern';
const a = $('#' + p + '-antwort'), x = H();
if (zustand.fehler) {
a.innerHTML = `<p class="fehlschlag">Ihre Anfrage ist leider nicht bei uns angekommen.</p><p>Bitte rufen Sie uns direkt an. Wir sind da.</p><a class="tel-nr gross-tel" href="${x.href}">${x.tel}</a><button class="knopf knopf-rand" type="button" data-nochmal>Noch einmal senden</button>`;
} else {
const vorname = name.value.trim();
a.innerHTML = `<p class="bestaetigt">Danke, ${vorname.replace(/[<>&]/g, '')}. Wir rufen Sie ${zusage().bis()} an.</p><p class="klein">Unter ${tel.value.trim().replace(/[<>&]/g, '')}. Wenn Sie nicht warten möchten: <a class="tel-nr" href="${x.href}">${x.tel}</a></p><button class="knopf knopf-rand" type="button" data-nochmal>Angaben ändern</button>`;
form.querySelector('.felder').hidden = true; form.querySelector('.zusage').hidden = true;
}
if (!auto) a.focus();
}, 900);
}
function formZurueck(form) {
if (!form) return;
clearTimeout(form._t); form.reset();
form.querySelector('.felder').hidden = false; form.querySelector('.zusage').hidden = false;
form.querySelector('.antwort').innerHTML = '';
form.querySelector('.fehlerliste').hidden = true;
$$('input', form).forEach(i => feldFehler(form, i, ''));
const k = form.querySelector('[type="submit"]'); k.removeAttribute('aria-busy'); k.querySelector('.knopf-text').textContent = 'Rückruf anfordern';
}
function binden() {
const liste = $('[role="tablist"]');
if (liste) {
$$('[role="tab"]', liste).forEach((t, i) => t.addEventListener('click', () => reiterWaehlen(i, true)));
liste.addEventListener('keydown', e => {
const tabs = $$('[role="tab"]', liste), i = tabs.indexOf(document.activeElement);
if (i < 0) return;
const m = { ArrowRight: 1, ArrowDown: 1, ArrowLeft: -1, ArrowUp: -1 }[e.key];
if (m) { e.preventDefault(); reiterWaehlen(i + m, true); }
else if (e.key === 'Home') { e.preventDefault(); reiterWaehlen(0, true); }
else if (e.key === 'End') { e.preventDefault(); reiterWaehlen(tabs.length - 1, true); }
});
}
$$('.rueckruf').forEach(form => {
form.addEventListener('submit', e => { e.preventDefault(); absenden(form); });
form.addEventListener('click', e => {
const n = e.target.closest('[data-nochmal]'); if (!n) return;
const war = n.textContent === 'Noch einmal senden';
if (war) { form.querySelector('.antwort').innerHTML = ''; absenden(form); }
else { const name = form.elements.name.value, tel = form.elements.tel.value; formZurueck(form); form.elements.name.value = name; form.elements.tel.value = tel; form.elements.name.focus(); }
});
form.addEventListener('input', e => { if (e.target.getAttribute('aria-invalid')) feldFehler(form, e.target, ''); });
});
$$('[data-oeffne]').forEach(b => b.addEventListener('click', () => { if (zustand.offen) $('#feld-titel').focus(); else feldAuf(true); }));
const s = $('#schliessen'); if (s) s.addEventListener('click', () => feldZu(true));
const zs = $('#zur-seite'); if (zs) zs.addEventListener('click', e => { e.preventDefault(); setzeVariante('seite', true); $('#seite-titel').focus(); });
const boxen = $$('#liste input');
if (boxen.length) {
let gespeichert = [];
try { gespeichert = JSON.parse(localStorage.getItem('steinlinde-unterlagen') || '[]'); } catch (e) {}
boxen.forEach(b => { b.checked = gespeichert.includes(b.name); b.addEventListener('change', stand); });
stand();
$('#drucken').addEventListener('click', () => window.print());
$('#leeren').addEventListener('click', () => { boxen.forEach(b => b.checked = false); stand(); });
$('#druck-beenden').addEventListener('click', () => { zustand.druckSchalter = false; zeigeDruck(); pultZeigen(); $('#pult-druck').focus(); });
}
}
/* Sofortleiste: Knopf, Escape, Fokus verlässt die Leiste */
$('#sofort-knopf').addEventListener('click', () => {
if (zustand.v === 'seite') { scrollTo({ top: 0 }); $('#seite-titel').focus({ preventScroll: true }); return; }
zustand.offen ? feldZu(false) : feldAuf(true);
});
$('#trauerfall').addEventListener('keydown', e => { if (e.key === 'Escape' && zustand.offen) { e.preventDefault(); feldZu(true); } });
$('#trauerfall').addEventListener('focusout', e => { if (zustand.offen && e.relatedTarget && !e.currentTarget.contains(e.relatedTarget) && !e.relatedTarget.closest('[data-oeffne], [data-fundus-pult], fundus-pult-knopf')) feldZu(false); });
addEventListener('beforeprint', () => h.classList.add('druck'));
addEventListener('afterprint', zeigeDruck);
$$('[data-consent]').forEach(b => b.addEventListener('click', () => { zustand.consent = false; $('#consent').hidden = true; pultZeigen(); }));
/* ---------- Pult ---------- */
function setzeVariante(v, schreiben) {
zustand.v = v; zustand.reiter = 0; zustand.offen = false; zustand.druckSchalter = false;
$('#feld').hidden = true; $('#feld').classList.remove('auf');
aufbauen();
if (schreiben) { const p = new URLSearchParams(location.search); p.set('v', v); history.replaceState(null, '', '?' + p.toString().replace(/=(?=&|$)/g, '')); }
}
function pultZeigen() {
$$('[data-v]').forEach(b => b.setAttribute('aria-pressed', b.dataset.v === zustand.v));
$$('[data-nacht]').forEach(b => b.setAttribute('aria-pressed', b.dataset.nacht === zustand.nacht));
$('#pult-nacht').hidden = zustand.v === 'wald';
$('#pult-fehler').setAttribute('aria-pressed', zustand.fehler);
$('#pult-consent').setAttribute('aria-pressed', zustand.consent);
$('#pult-druck').setAttribute('aria-pressed', zustand.druckSchalter);
$('#pult-druck').hidden = zustand.v !== 'seite';
$('#consent').hidden = !zustand.consent;
}
$$('[data-v]').forEach(b => b.addEventListener('click', () => { stopp(); setzeVariante(b.dataset.v, true); }));
$$('[data-nacht]').forEach(b => b.addEventListener('click', () => { zustand.nacht = b.dataset.nacht; const o = zustand.offen, r = zustand.reiter; aufbauen(); zustand.reiter = r; reiterWaehlen(r); if (o) feldAuf(false); }));
$('#pult-fehler').addEventListener('click', () => { zustand.fehler = !zustand.fehler; pultZeigen(); });
$('#pult-consent').addEventListener('click', () => { zustand.consent = !zustand.consent; pultZeigen(); });
$('#pult-druck').addEventListener('click', () => { zustand.druckSchalter = !zustand.druckSchalter; zeigeDruck(); pultZeigen(); scrollTo({ top: 0 }); });
/* ---------- Vorführung ---------- */
let schritte = [], pos = 0, uhrwerk = null, laeuft = false;
function tippe(feld, text) { feld.value = text; feld.dispatchEvent(new Event('input', { bubbles: true })); }
function ablauf() {
const form = () => $('.rueckruf');
if (zustand.v === 'seite') {
return [
[1200, () => { const a = $('#anleitung'); scrollTo({ top: a.getBoundingClientRect().top + scrollY - 80 }); }],
[1400, () => reiterWaehlen(1)], [2200, () => reiterWaehlen(2)], [2200, () => reiterWaehlen(3)],
[2000, () => tippe(form().elements.name, 'Agnes Wiedl')],
[800, () => tippe(form().elements.tel, '0151 23456789')],
[900, () => absenden(form(), true)],
[3000, () => { reiterWaehlen(0); const z = $('.zwei'); scrollTo({ top: z.getBoundingClientRect().top + scrollY - 80 }); }],
[1000, () => { $$('#liste input')[0].checked = true; stand(); }],
[900, () => { $$('#liste input')[1].checked = true; stand(); }],
[900, () => { $$('#liste input')[2].checked = true; stand(); }],
[900, () => { $$('#liste input')[5].checked = true; stand(); }],
[3000, () => neustart()]
];
}
const s = [[1000, () => feldAuf(false)], [2200, () => reiterWaehlen(1)]];
if (zustand.v === 'leiste') s.push([2200, () => reiterWaehlen(2)], [2200, () => reiterWaehlen(3)]);
s.push([2000, () => { const f = $('#feld'), r = form(); if (r.getBoundingClientRect().bottom > innerHeight) f.scrollTop = r.offsetTop - 24; }],
[900, () => tippe(form().elements.name, 'Agnes Wiedl')], [800, () => tippe(form().elements.tel, '0151 23456789')],
[900, () => absenden(form(), true)], [3600, () => feldZu(false)], [1600, () => neustart()]);
return s;
}
function takt() {
if (!laeuft) return;
if (pos >= schritte.length) { schritte = ablauf(); pos = 0; }
const [warte, tu] = schritte[pos];
uhrwerk = setTimeout(() => { if (!laeuft) return; tu(); pos++; takt(); }, warte);
}
function stopp() { laeuft = false; clearTimeout(uhrwerk); h.classList.remove('vorfuehrung'); }
function neustart() {
zustand.reiter = 0;
const feld = $('#feld');
if (zustand.offen) { zustand.offen = false; feld.classList.remove('auf'); feld.hidden = true; $('#sofort-knopf').setAttribute('aria-expanded', 'false'); }
feld.scrollTop = 0;
reiterWaehlen(0);
formZurueck($('.rueckruf'));
$$('#liste input').forEach(b => b.checked = false); stand();
scrollTo({ top: 0 });
}
function vorfuehren() {
stopp(); neustart();
laeuft = true; h.classList.add('vorfuehrung');
schritte = ablauf(); pos = 0; takt();
}
function pause() { laeuft = false; clearTimeout(uhrwerk); }
function weiter() { if (laeuft) return; if (!schritte.length) return vorfuehren(); laeuft = true; takt(); }
aufbauen();
})();
</script>
</body>
</html>