Zum Inhalt
← Sektionen & Funktionen

FAQ-Seite mit Suche

Eine ganze FAQ-Seite: Suchfeld mit Treffermarkierung per Custom Highlight, Themen als Filter mit Zahl, exklusives Akkordeon aus details mit name, Direktlink je Frage, Rückruf mit dem Suchwort bei null Treffern und FAQPage-JSON-LD nur auf Wunsch.

Ab etwa acht Fragen in mehreren Themen: Pflege, Praxis, Fahrschule, Kurs, IT-Dienstleister.

Eine eigene Seite für häufige Fragen. Oben ein Suchfeld, darunter Themen als Filter mit Trefferzahl. Die Fragen stehen als Akkordeon aus details und summary, je Thema mit name, sodass nur eine Antwort offen ist. Jede Frage hat eine eigene Adresse (#frage-…), die sie öffnet; ein Knopf kopiert den Link. Treffer werden im Text markiert. Gibt es keinen Treffer, nennt die Seite Telefon und Rückruf statt einer leeren Liste. FAQPage-JSON-LD gibt es nur, wo es Sinn ergibt.

Angehörige, Patient:innen oder Kund:innen kommen mit einer konkreten Frage. Eine Suche mit Markierung findet sie schneller als Scrollen durch zwanzig Einträge. Direktlinks lassen sich im Telefonat oder per E-Mail weitergeben („Schauen Sie unter Kosten nach“). Der Weg zum Menschen am Ende fängt alles auf, was die Seite nicht beantwortet.

Wann einsetzen

Ab etwa acht Fragen in mehreren Themen: Pflege, Praxis, Fahrschule, Kurs, Fitness, Apotheke, IT-Dienstleister, Umzug. Als eigene Seite zusätzlich zu kurzen FAQ-Blöcken auf den Leistungsseiten.

Wann nicht

Nicht bei drei bis fünf Fragen: dann reicht akkordeon-hoehe-auto auf der Leistungsseite. Nicht als Ablage für Inhalte, die eine eigene Seite verdienen (Kosten, Ablauf). FAQPage-JSON-LD nicht als Trick für Rich Results: Google zeigt FAQ-Ergebnisse seit August 2023 nur noch für bekannte Behörden- und Gesundheitsseiten; Markup muss genau dem sichtbaren Text entsprechen.

Varianten

  • Ausführlich: Suche, Themen-Filter mit Zahl, Direktlinks, Treffermarkierung, Rückruf bei null Treffern
  • Kurz: wenige Fragen ohne Suche, nur Themen als Sprunglinks
  • Mit „Antwort geändert am“ für Fragen zu Kosten und Fristen

Umsetzung

Fragen als details mit summary in Abschnitten je Thema; alle details eines Themas tragen dasselbe name (exklusives Akkordeon). Während einer Suche wird name entfernt, damit mehrere Treffer offen stehen dürfen. Jede Frage hat eine id; beim Laden und bei hashchange öffnet die passende details, scrollt mit scroll-margin-top und setzt den Fokus auf summary. Ein kleiner Knopf je Antwort kopiert location mit #id (navigator.clipboard, Rückmeldung in aria-live). Suche: input type=search mit 120 ms Entprellung, Umlaute und ß normalisiert, alle Wörter müssen vorkommen; Treffer öffnen sich bis zu drei, Zahl in aria-live=polite, Wert in ?q= per history.replaceState. Markierung über CSS Custom Highlight API (CSS.highlights, ::highlight) ohne DOM-Eingriff, ohne Unterstützung ohne Markierung. Themen als Knöpfe mit aria-pressed und Zahl. Null Treffer: eigener Zustand mit Telefon, Rückruf und dem Suchwort als Formulartext. Die Browser-Suche findet geschlossene details-Inhalte in Chromium und öffnet sie. JSON-LD FAQPage nur aus dem sichtbaren Text erzeugen und nur, wenn die Seite wirklich Fragen und Antworten des Betriebs enthält.

Robust umsetzen

Telefon. Suchfeld groß oben, Themen als umbrechende Knopfreihe. Fragen in voller Breite mit großen Tippzielen (mindestens 56 px). Link-kopieren-Knopf sichtbar in der offenen Antwort. Telefon am Ende als großer Knopf.

Ohne Bewegung. Antworten öffnen und schließen ohne Übergang, Sprünge ohne weiches Scrollen.

Barrierefrei. summary ist der native Knopf, keine eigene Rolle nötig. Suchfeld mit sichtbarem Label, Trefferzahl per aria-live. Themen-Knöpfe mit aria-pressed. Markierung nicht nur über Farbe (zusätzlich Unterstreichung im ::highlight). Nach einem Direktlink liegt der Fokus auf der Frage. Null-Treffer-Zustand als Text mit Ausweg.

Code

<!DOCTYPE html>
<!--
  FAQ-Seite mit Suche
  Fundus · Sektionen & Funktionen · https://cecodesign.de/lab/fundus/sektionen/faq-seite-suche/
  Eigenständige Datei. Bilder liegen hier unter bilder/ – eigene einsetzen.
-->
<html lang="de" data-v="suche">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>FAQ-Seite mit Suche · 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: 'Literata'; src: url('https://cdn.jsdelivr.net/fontsource/fonts/literata:vf@latest/latin-full-normal.woff2') format('woff2-variations'); font-weight: 200 900; font-display: swap; }
@font-face { font-family: 'Hanken Grotesk'; src: url('https://cdn.jsdelivr.net/fontsource/fonts/hanken-grotesk:vf@latest/latin-wght-normal.woff2') format('woff2-variations'); font-weight: 100 900; font-style: normal; font-display: swap; }
@font-face { font-family: 'Geist Mono'; src: url('https://cdn.jsdelivr.net/fontsource/fonts/geist-mono:vf@latest/latin-wght-normal.woff2') format('woff2-variations'); font-weight: 100 900; font-display: swap; }

/* Rezept pflege-dienst-naehe: warmes Weiß, Pflaume, Sonnengelb nur für Anrufen und Anfragen */
:root {
  --grund: #faf7f2; --karte: #ffffff; --text: #1f1b16; --leise: #4a443d; --linie: #d8d0c4;
  --pflaume: #5b2a4a; --pflaume-tief: #47203a; --pflaume-hell: #f3e9ef; --gelb: #ffc845; --hinweis: #fff1cc; --treffer: #ffe08a;
  --ph-grund: #f6ecc4; --ph-kante: #7a6410; --ph-text: #3d3205;
  --auf: cubic-bezier(0.16, 1, 0.3, 1); --zu: cubic-bezier(0.7, 0, 0.84, 0);
  --hover: 150ms; --oeffnen: 300ms; --schliessen: 200ms;
  --h: 'Literata', Georgia, serif; --t: 'Hanken Grotesk', system-ui, sans-serif;
  --r: 12px; --r-klein: 8px;
  interpolate-size: allow-keywords;
}
* { box-sizing: border-box; margin: 0; padding: 0; }
html { background: var(--grund); color: var(--text); font-family: var(--t); -webkit-font-smoothing: antialiased; }
:root:has(:focus-visible) { scroll-behavior: auto; }
body { font-size: 20px; line-height: 1.6; }
a { color: inherit; text-underline-offset: 3px; text-decoration-thickness: 1px; }
button, input, textarea { font: inherit; color: inherit; }
button { background: none; border: 0; cursor: pointer; }
:focus-visible { outline: 3px solid var(--text); outline-offset: 3px; }
.vh { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
.vh:focus { position: fixed; left: 12px; top: 12px; width: auto; height: auto; clip-path: none; white-space: normal; z-index: 100; padding: 10px 14px; background: #fff; color: #111; outline: 3px solid #111; }
.ziffern { font-variant-numeric: tabular-nums lining-nums; }
.huelle { max-width: 1180px; margin: 0 auto; padding: 0 clamp(18px, 3.4vw, 44px); }
h1, h2, h3 { font-family: var(--h); font-weight: 600; letter-spacing: -.01em; line-height: 1.1; color: var(--pflaume); text-wrap: balance; }
p { text-wrap: pretty; }

/* Kopf */
.kopf { border-bottom: 1px solid var(--linie); background: var(--karte); }
.kopf .huelle { display: flex; align-items: center; gap: 22px; min-height: 76px; flex-wrap: wrap; padding-top: 8px; padding-bottom: 8px; }
.marke { display: flex; align-items: center; gap: 12px; text-decoration: none; margin-right: auto; }
.marke svg { width: 38px; height: 38px; flex: none; }
.marke b { display: block; font: 600 21px/1.1 var(--h); color: var(--pflaume); }
.marke small { display: block; font-size: 16px; color: var(--leise); }
.kopf nav ul { display: flex; gap: 20px; list-style: none; }
.kopf nav a { text-decoration: none; font-size: 17px; color: var(--leise); }
.kopf nav a:hover, .kopf nav a[aria-current] { color: var(--text); text-decoration: underline; text-decoration-thickness: 2px; text-underline-offset: 6px; }
.tel-gross { text-decoration: none; line-height: 1.15; text-align: right; }
.tel-gross b { display: block; font-size: 24px; font-weight: 700; font-variant-numeric: tabular-nums; }
.tel-gross small { font-size: 16px; color: var(--leise); }
.gelb { display: inline-flex; align-items: center; justify-content: center; gap: 10px; min-height: 56px; padding: 0 22px; background: var(--gelb); color: var(--text); border: 2px solid var(--text); border-radius: var(--r-klein); font-weight: 600; font-size: 20px; text-decoration: none; white-space: nowrap; transition: background-color var(--hover) var(--auf); }
.gelb:hover { background: #ffd56b; }
.gelb svg { width: 20px; height: 20px; flex: none; }

.krumen { padding: 18px 0 0; font-size: 16px; color: var(--leise); }
.krumen ol { display: flex; flex-wrap: wrap; list-style: none; }
.krumen li + li::before { content: '›'; margin: 0 9px; }

/* Kopf der Seite */
.titel { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 360px); gap: clamp(22px, 4vw, 60px); padding: clamp(24px, 3.4vw, 44px) 0 clamp(20px, 2.4vw, 30px); align-items: end; }
h1 { font-size: clamp(2.5rem, 1.8rem + 3vw, 4rem); }
h1:focus { outline: none; }
.titel p { margin-top: 14px; max-width: 34em; }
.kurzweg { background: var(--pflaume); color: #fff; border-radius: var(--r); padding: 20px 22px; }
.kurzweg p { margin: 0; font-size: 17px; color: rgba(255, 255, 255, .9); }
.kurzweg a { display: block; font-size: 26px; font-weight: 700; text-decoration: none; margin-top: 4px; font-variant-numeric: tabular-nums; }
.kurzweg :focus-visible { outline-color: #fff; }

/* Suche und Themen */
.suche { position: sticky; top: 0; z-index: 10; background: var(--grund); padding: 14px 0 12px; border-bottom: 1px solid var(--linie); }
.suchfeld { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 10px; align-items: end; }
.suchfeld label { display: grid; gap: 6px; font-weight: 600; font-size: 17px; }
.eingabe { position: relative; }
.eingabe svg { position: absolute; left: 16px; top: 50%; width: 22px; height: 22px; transform: translateY(-50%); color: var(--leise); pointer-events: none; }
.eingabe input { width: 100%; min-height: 60px; padding: 0 52px 0 50px; border: 2px solid var(--text); border-radius: var(--r-klein); background: var(--karte); font-size: 20px; }
.eingabe input::placeholder { color: #6c655c; }
.eingabe input::-webkit-search-cancel-button { display: none; }
.leeren { position: absolute; right: 8px; top: 50%; transform: translateY(-50%); width: 44px; height: 44px; display: grid; place-items: center; border-radius: var(--r-klein); }
.leeren[hidden] { display: none; }
.leeren:hover { background: var(--pflaume-hell); }
.leeren svg { position: static; transform: none; width: 18px; height: 18px; color: var(--text); }
.zahl { font-size: 17px; color: var(--leise); padding-bottom: 16px; white-space: nowrap; }
.zahl b { color: var(--text); }
.themen { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
.themen button, .themen a { display: inline-flex; align-items: center; gap: 8px; min-height: 44px; padding: 0 16px; border: 1.5px solid var(--linie); border-radius: 999px; background: var(--karte); font-size: 17px; text-decoration: none; transition: background-color var(--hover) var(--auf), border-color var(--hover) var(--auf), color var(--hover) var(--auf); }
.themen button:hover, .themen a:hover { border-color: var(--pflaume); }
.themen button[aria-pressed="true"] { background: var(--pflaume); border-color: var(--pflaume); color: #fff; }
.themen .n { font-variant-numeric: tabular-nums; font-size: 15px; opacity: .8; }
.themen button[disabled] { opacity: .5; cursor: default; }

/* Fragen */
.liste { padding: clamp(22px, 3vw, 40px) 0 clamp(40px, 5vw, 72px); display: grid; gap: clamp(28px, 3.6vw, 48px); }
.thema { display: grid; grid-template-columns: minmax(0, 260px) minmax(0, 1fr); gap: clamp(16px, 3vw, 48px); scroll-margin-top: 170px; }
.thema[hidden] { display: none; }
.thema > h2 { font-size: clamp(1.6rem, 1.3rem + 1vw, 2.1rem); position: sticky; top: 190px; align-self: start; }
.thema > h2 small { display: block; font: 500 16px/1.4 var(--t); color: var(--leise); margin-top: 6px; letter-spacing: 0; }
.fragen { display: grid; border-top: 2px solid var(--pflaume); }
details.frage { border-bottom: 1px solid var(--linie); scroll-margin-top: 180px; }
details.frage[hidden] { display: none; }
.frage summary { list-style: none; display: grid; grid-template-columns: minmax(0, 1fr) 36px; gap: 16px; align-items: center; min-height: 64px; padding: 14px 4px 14px 0; cursor: pointer; font-weight: 600; font-size: 20px; line-height: 1.35; }
.frage summary::-webkit-details-marker { display: none; }
.frage summary:hover { color: var(--pflaume); }
.frage summary .zeichen { width: 36px; height: 36px; border-radius: 50%; border: 2px solid var(--pflaume); position: relative; justify-self: end; }
.frage summary .zeichen::before, .frage summary .zeichen::after { content: ''; position: absolute; left: 50%; top: 50%; width: 14px; height: 2px; margin: -1px 0 0 -7px; background: var(--pflaume); transition: transform var(--schliessen) var(--zu); }
.frage summary .zeichen::after { transform: rotate(90deg); }
.frage[open] summary .zeichen { background: var(--pflaume); }
.frage[open] summary .zeichen::before, .frage[open] summary .zeichen::after { background: #fff; transition: transform var(--oeffnen) var(--auf); }
.frage[open] summary .zeichen::after { transform: rotate(0deg); }
.frage summary:focus-visible { outline-offset: -3px; border-radius: 4px; }
.frage::details-content { block-size: 0; overflow: hidden; transition: block-size var(--schliessen) var(--zu), content-visibility var(--schliessen) var(--zu) allow-discrete; }
.frage[open]::details-content { block-size: auto; transition: block-size var(--oeffnen) var(--auf), content-visibility var(--oeffnen) var(--auf) allow-discrete; }
.antwort { padding: 0 52px 22px 0; max-width: 64ch; }
.antwort p + p, .antwort p + table, .antwort table + p { margin-top: .7em; }
.antwort ul { margin: .5em 0 0 1.1em; }
.antwort .fuss-zeile { display: flex; flex-wrap: wrap; gap: 8px 18px; align-items: center; margin-top: 16px; font-size: 16px; color: var(--leise); }
.link-kopieren { display: inline-flex; align-items: center; gap: 8px; min-height: 44px; padding: 0 12px; border: 1.5px solid var(--linie); border-radius: var(--r-klein); font-size: 16px; font-weight: 600; color: var(--text); transition: border-color var(--hover) var(--auf); }
.link-kopieren:hover, .link-kopieren.druck { border-color: var(--pflaume); }
.link-kopieren svg { width: 16px; height: 16px; }
.antwort table { border-collapse: collapse; width: 100%; max-width: 30em; font-size: 18px; }
.antwort th, .antwort td { text-align: left; padding: 8px 10px; border-bottom: 1px solid var(--linie); }
.antwort thead th { background: var(--hinweis); font-size: 16px; }
mark.platzhalter { background: repeating-linear-gradient(-45deg, var(--ph-grund) 0 7px, #f1e3ad 7px 14px); color: var(--ph-text); padding: 1px 5px; border: 1px dashed var(--ph-kante); font-weight: 500; font-size: .9em; -webkit-box-decoration-break: clone; box-decoration-break: clone; }
::highlight(faq-treffer) { background-color: var(--treffer); color: var(--text); text-decoration: underline 2px var(--pflaume); }
.ziel-blink { animation: ziel 1200ms var(--auf); }
@keyframes ziel { 0% { background: var(--hinweis); } 100% { background: transparent; } }

/* Null Treffer */
.liste[hidden] { display: none; }
.nichts { display: none; padding: clamp(28px, 4vw, 48px) 0 clamp(48px, 6vw, 80px); }
.nichts.an { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 420px); gap: clamp(22px, 4vw, 60px); align-items: start; }
.nichts h2 { font-size: clamp(1.8rem, 1.4rem + 1.4vw, 2.5rem); }
.nichts p { margin-top: 12px; max-width: 34em; }
.nichts .vorschlaege { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 16px; }
.nichts .vorschlaege button { min-height: 44px; padding: 0 16px; border: 1.5px solid var(--linie); border-radius: 999px; background: var(--karte); font-size: 17px; }
.nichts .vorschlaege button:hover { border-color: var(--pflaume); }
.rueckruf { background: var(--karte); border: 1px solid var(--linie); border-radius: var(--r); padding: 22px; display: grid; gap: 14px; }
.rueckruf h3 { font-size: 1.5rem; }
.rueckruf label { display: grid; gap: 4px; font-weight: 600; font-size: 17px; }
.rueckruf input, .rueckruf textarea { width: 100%; padding: 12px 14px; border: 2px solid var(--text); border-radius: var(--r-klein); background: #fff; font-size: 19px; }
.rueckruf textarea { min-height: 96px; resize: vertical; }
.rueckruf .gelb { width: 100%; }
.rueckruf .klein { font-size: 16px; color: var(--leise); }
.danke { display: none; padding: 14px; border-radius: var(--r-klein); background: var(--hinweis); font-size: 18px; }
.rueckruf.gesendet .danke { display: block; }
.rueckruf.gesendet form { display: none; }

/* Nicht dabei */
.nicht-dabei { border-top: 1px solid var(--linie); padding: clamp(30px, 4vw, 52px) 0 clamp(48px, 6vw, 80px); display: grid; grid-template-columns: 96px minmax(0, 1fr) auto; gap: 18px 26px; align-items: center; }
.nicht-dabei .bild { width: 96px; aspect-ratio: 1; border-radius: var(--r); background: var(--pflaume-hell); display: grid; place-items: center; font: 600 30px/1 var(--h); color: var(--pflaume); position: relative; }
.nicht-dabei .bild small { position: absolute; bottom: 6px; font: 500 9px/1 'Geist Mono', monospace; letter-spacing: .1em; text-transform: uppercase; color: var(--leise); }
.nicht-dabei h2 { font-size: clamp(1.5rem, 1.2rem + 1vw, 2rem); }
.nicht-dabei p { margin-top: 6px; }

/* JSON-LD */
.daten-panel { display: none; padding-bottom: 48px; }
:root[data-ld] .daten-panel { display: block; }
.daten-panel .hinweis { background: var(--hinweis); border-left: 4px solid var(--gelb); padding: 14px 16px; font-size: 17px; margin-bottom: 12px; }
.daten-panel pre { padding: 18px 20px; border-radius: var(--r-klein); background: #241c20; color: #efe6ea; font: 400 12.5px/1.6 'Geist Mono', monospace; overflow-x: auto; max-height: 340px; }

.fuss { background: var(--pflaume); color: rgba(255, 255, 255, .88); font-size: 17px; padding: 40px 0 48px; }
.fuss .huelle { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(210px, 100%), 1fr)); gap: 20px 36px; }
.fuss b { color: #fff; display: block; margin-bottom: 6px; }
.fuss a { color: #fff; }
.fuss ul { list-style: none; display: grid; gap: 6px; }
.fuss :focus-visible { outline-color: #fff; }

.meldung { position: fixed; left: 50%; bottom: 24px; z-index: 30; transform: translate(-50%, 8px); opacity: 0; background: var(--text); color: #fff; padding: 12px 18px; border-radius: var(--r-klein); font-size: 17px; font-weight: 600; pointer-events: none; transition: opacity var(--schliessen) var(--zu), transform var(--schliessen) var(--zu); max-width: calc(100vw - 32px); }
.meldung.an { opacity: 1; transform: translate(-50%, 0); transition: opacity var(--oeffnen) var(--auf), transform var(--oeffnen) var(--auf); }

/* Kurz: wenige Fragen, ohne Suche */
:root[data-v="kurz"] .suchfeld { display: none; }
:root[data-v="kurz"] .suche { position: static; border-bottom: 0; padding-top: 0; }
:root[data-v="kurz"] .themen { margin-top: 0; }

.pult { position: fixed; right: 14px; bottom: 14px; z-index: 40; width: 250px; padding: 12px; display: grid; gap: 9px; background: rgba(31, 27, 22, .95); color: #faf7f2; border-radius: 10px; box-shadow: 0 12px 34px rgba(0, 0, 0, .24); }
.pult .mono { font: 500 10.5px/1.4 'Geist Mono', ui-monospace, monospace; letter-spacing: .14em; text-transform: uppercase; color: rgba(250, 247, 242, .72); }
.pult .reihe { display: grid; grid-template-columns: 1fr 1fr; border: 1px solid rgba(250, 247, 242, .24); border-radius: 6px; overflow: hidden; }
.pult button { padding: 8px 6px; font: 500 11.5px/1.2 'Geist Mono', monospace; color: rgba(250, 247, 242, .84); transition: background-color var(--hover) var(--auf), color var(--hover) var(--auf); }
.pult .reihe button + button { border-left: 1px solid rgba(250, 247, 242, .24); }
.pult button[aria-pressed="true"] { background: #faf7f2; color: #1f1b16; }
.pult .einzeln { border: 1px solid rgba(250, 247, 242, .24); border-radius: 6px; text-align: left; padding: 8px 10px; display: flex; justify-content: space-between; }
.pult :focus-visible { outline: 2px solid #fff; outline-offset: 2px; }
.pult .werte { font: 400 10.5px/1.5 'Geist Mono', monospace; color: rgba(250, 247, 242, .72); }

@media (max-width: 1040px) { .kopf nav { display: none; } }
@media (max-width: 860px) {
  .titel { grid-template-columns: minmax(0, 1fr); }
  .thema { grid-template-columns: minmax(0, 1fr); scroll-margin-top: 200px; }
  .thema > h2 { position: static; }
  .nichts.an { grid-template-columns: minmax(0, 1fr); }
  .nicht-dabei { grid-template-columns: 72px minmax(0, 1fr); }
  .nicht-dabei .bild { width: 72px; }
  .nicht-dabei .gelb { grid-column: 1 / -1; }
}
@media (max-width: 640px) {
  body { font-size: 19px; }
  .kopf .gelb, .tel-gross small { display: none; }
  .tel-gross b { font-size: 20px; }
  .suchfeld { grid-template-columns: minmax(0, 1fr); }
  .zahl { padding-bottom: 0; }
  .suche { position: static; }
  .themen { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; margin-right: -18px; padding-right: 18px; }
  .themen button, .themen a { flex: none; }
  .antwort { padding-right: 0; }
  .frage summary { font-size: 19px; }
  details.frage, .thema { scroll-margin-top: 16px; }
}
@media (max-width: 360px) { .marke small { display: none; } }
.vorschau body { overflow: hidden; }
.vorschau .meldung { display: none; }

.reduziert *, .reduziert *::before, .reduziert *::after, .reduziert .frage::details-content { animation: none !important; transition-duration: .01ms !important; }
@media (forced-colors: active) {
  button, [role=button], [role=tab], [role=switch], input, select, textarea, .gelb { border: 1px solid ButtonText !important; }
  .themen button[aria-pressed="true"] { outline: 3px solid Highlight; }
  ::highlight(faq-treffer) { background-color: Highlight; color: HighlightText; }
}
</style>
</head>
<body>
<a class="vh" href="#suchfeld">Zur Suche springen</a>
<header class="kopf"><div class="huelle">
  <a class="marke" href="#" aria-label="Ambulante Pflege Weidenhof, Startseite">
    <svg viewBox="0 0 38 38" aria-hidden="true"><rect width="38" height="38" rx="10" fill="#5b2a4a"/><path d="M19 29V13M19 18c-4-1-7-4-7-8 4 0 7 3 7 8zm0 3c4-1 7-4 7-8-4 0-7 3-7 8z" stroke="#ffc845" stroke-width="2.2" fill="none" stroke-linejoin="round"/></svg>
    <span><b>Pflege Weidenhof</b><small>Ambulanter Dienst · Neumarkt</small></span>
  </a>
  <nav aria-label="Hauptmenü"><ul><li><a href="#">Leistungen</a></li><li><a href="#">Kosten</a></li><li><a href="#" aria-current="page">Fragen</a></li><li><a href="#">Arbeiten bei uns</a></li></ul></nav>
  <a class="tel-gross" href="tel:+4991812964010"><b>09181 29 64 010</b><small>Mo bis Fr 8 bis 17 Uhr</small></a>
  <a class="gelb" href="#">Pflege anfragen</a>
</div></header>

<main>
  <div class="huelle">
    <nav class="krumen" aria-label="Brotkrumen"><ol><li><a href="#">Startseite</a></li><li><span aria-current="page">Häufige Fragen</span></li></ol></nav>
    <div class="titel">
      <div>
        <h1 id="titel" tabindex="-1">Häufige Fragen</h1>
        <p id="einleitung"></p>
      </div>
      <div class="kurzweg"><p>Lieber gleich mit uns sprechen?</p><a href="tel:+4991812964010">09181 29 64 010</a><p>Nadine Gebhardt, Pflegedienstleitung</p></div>
    </div>
  </div>
  <div class="suche"><div class="huelle">
    <div class="suchfeld" role="search">
      <label for="suchfeld">Frage oder Stichwort
        <span class="eingabe"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" aria-hidden="true"><circle cx="10.5" cy="10.5" r="6.5"/><path d="m20 20-4.8-4.8"/></svg><input type="search" id="suchfeld" placeholder="zum Beispiel Kosten, Wochenende, Pflegegrad" autocomplete="off" enterkeyhint="search"><button type="button" class="leeren" id="leeren" aria-label="Suche leeren" hidden><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M6 6l12 12M18 6 6 18"/></svg></button></span>
      </label>
      <p class="zahl" id="zahl" aria-live="polite"></p>
    </div>
    <div class="themen" id="themen" role="group" aria-label="Themen"></div>
  </div></div>
  <div class="huelle">
    <div class="liste" id="liste"></div>
    <section class="nichts" id="nichts" aria-labelledby="nichts-titel">
      <div>
        <h2 id="nichts-titel" tabindex="-1"></h2>
        <p>Vielleicht steht es unter einem anderen Wort. Oder Sie fragen uns direkt, das geht oft schneller.</p>
        <div class="vorschlaege" id="vorschlaege"></div>
      </div>
      <div class="rueckruf" id="rueckruf">
        <h3>Wir rufen Sie zurück</h3>
        <form id="rueckruf-form" novalidate>
          <div style="display:grid;gap:14px">
            <label>Ihr Name<input id="rr-name" autocomplete="name" required></label>
            <label>Telefon<input id="rr-tel" type="tel" autocomplete="tel" inputmode="tel" required></label>
            <label>Ihre Frage<textarea id="rr-frage"></textarea></label>
            <p class="klein" id="rr-fehler" role="alert" hidden></p>
            <button type="submit" class="gelb">Rückruf anfragen</button>
            <p class="klein">Wir rufen werktags bis 17 Uhr zurück, meist am selben Tag.</p>
          </div>
        </form>
        <p class="danke" id="rr-danke" tabindex="-1"></p>
      </div>
    </section>
  </div>
  <div class="huelle">
    <section class="nicht-dabei" aria-labelledby="nd-titel">
      <span class="bild" aria-hidden="true">NG<small>Foto</small></span>
      <div><h2 id="nd-titel">Ihre Frage war nicht dabei?</h2><p>Nadine Gebhardt beantwortet sie am Telefon. Wenn sie öfter kommt, schreiben wir sie hier dazu.</p></div>
      <a class="gelb" href="tel:+4991812964010"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" aria-hidden="true"><path d="M5 4h4l2 5-2.5 1.5a11 11 0 0 0 5 5L15 13l5 2v4a2 2 0 0 1-2 2A16 16 0 0 1 3 6a2 2 0 0 1 2-2"/></svg>Anrufen</a>
    </section>
  </div>
  <section class="huelle daten-panel" aria-label="Strukturierte Daten">
    <p class="hinweis">FAQPage nur aus dem sichtbaren Text und nur, wenn die Seite echte Fragen des Betriebs beantwortet. Rich Results zeigt Google seit August 2023 fast nur noch für bekannte Behörden- und Gesundheitsseiten. Das Markup schadet nicht, bringt aber meist keine Darstellung.</p>
    <pre id="ld-zeigen"></pre>
  </section>
</main>

<footer class="fuss"><div class="huelle">
  <div><b>Ambulante Pflege Weidenhof</b>Weidenhof 3<br>92318 Neumarkt in der Oberpfalz</div>
  <div><b>Erreichbar</b>Büro Mo bis Fr 8 bis 17 Uhr<br>Pflege täglich 6 bis 21 Uhr</div>
  <div><b>Einsatzgebiet</b>Neumarkt, Berg, Pölling, Sengenthal, Postbauer-Heng, Deining</div>
  <ul><li><a href="#">Impressum</a></li><li><a href="#">Datenschutz</a></li><li><a href="#">Barrierefreiheit</a></li></ul>
</div></footer>
<div class="meldung" id="meldung" role="status" aria-live="polite"></div>

<div class="pult" aria-label="Steuerung der Demo" role="group">
  <span class="mono">Umfang</span>
  <div class="reihe" id="pult-v">
    <button type="button" data-v="suche" aria-pressed="true">Mit Suche</button>
    <button type="button" data-v="kurz" aria-pressed="false">Kurz</button>
  </div>
  <button type="button" class="einzeln" id="pult-ld" aria-pressed="false"><span>JSON-LD FAQPage</span><span aria-hidden="true">aus</span></button>
  <p class="werte" id="pult-werte">details name je Thema · öffnen 300 ms (0.16,1,0.3,1), zu 200 ms (0.7,0,0.84,0) · Suche 120 ms entprellt · ::highlight</p>
</div>

<script>
(() => {
  const h = document.documentElement;
  const reduziert = () => h.classList.contains('reduziert');
  const $ = (s, w = document) => w.querySelector(s);
  const $$ = (s, w = document) => [...w.querySelectorAll(s)];
  const P = t => `<mark class="platzhalter">[${t}]</mark>`;
  const KOPIE = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" aria-hidden="true"><path d="M10 14a4 4 0 0 0 5.7 0l3-3a4 4 0 0 0-5.7-5.7l-1 1M14 10a4 4 0 0 0-5.7 0l-3 3a4 4 0 0 0 5.7 5.7l1-1"/></svg>';

  /* Fragen und Antworten des Betriebs. Beträge und Fristen als Platzhalter: vom Kunden mit Quelle und Stand eintragen. */
  const THEMEN = [
    { id: 'anfang', t: 'Erster Kontakt', u: 'Bevor es losgeht', fragen: [
      ['wie-schnell', 'Wie schnell können Sie anfangen?', `<p>Meist innerhalb von ${P('Zahl')} Werktagen nach dem ersten Gespräch. Ist es dringend, etwa nach einem Krankenhaus-Aufenthalt, rufen Sie bitte an. Dann suchen wir gemeinsam eine Lösung.</p>`, true],
      ['erstgespraech', 'Kommen Sie zu uns nach Hause, bevor etwas feststeht?', '<p>Ja. Das erste Gespräch ist bei Ihnen zu Hause und kostet nichts. Es dauert etwa eine Stunde. Danach wissen Sie, was wir tun können und was es kostet.</p>', true],
      ['orte', 'In welche Orte fahren Sie?', '<p>Neumarkt und die Orte rundherum: Berg, Pölling, Sengenthal, Postbauer-Heng und Deining. Wohnen Sie woanders, rufen Sie bitte an. Manchmal geht es trotzdem.</p>'],
      ['mitbringen', 'Was brauchen Sie beim ersten Besuch von uns?', '<ul><li>die Versichertenkarte</li><li>den Medikamentenplan, falls es einen gibt</li><li>den Bescheid über den Pflegegrad, falls schon da</li><li>die Verordnung vom Arzt, wenn wir Spritzen geben oder Verbände wechseln sollen</li></ul>']
    ] },
    { id: 'kosten', t: 'Kosten und Kasse', u: 'Was Sie zahlen, was die Kasse zahlt', fragen: [
      ['pflegekasse', 'Was zahlt die Pflegekasse?', `<p>Das hängt vom Pflegegrad ab. Für Pflege durch einen Dienst wie uns gibt es Geld von der Pflegekasse (Pflegesachleistung). Wir rechnen direkt mit ihr ab.</p><table><caption class="vh">Pflegesachleistung je Pflegegrad im Monat</caption><thead><tr><th scope="col">Pflegegrad</th><th scope="col">Im Monat bis zu</th></tr></thead><tbody>${[2, 3, 4, 5].map(g => `<tr><th scope="row">${g}</th><td>${P('Betrag laut Pflegekasse')}</td></tr>`).join('')}</tbody></table>`, true, `Stand: ${P('Monat Jahr, Quelle')}`],
      ['ohne-pflegegrad', 'Was kostet es, wenn noch kein Pflegegrad da ist?', `<p>Dann zahlen Sie selbst. Vorher sagen wir Ihnen, was jeder Einsatz kostet: ${P('Link zur Preisliste')}. Gleichzeitig helfen wir beim Antrag auf einen Pflegegrad.</p>`],
      ['behandlungspflege', 'Wer zahlt, wenn Sie Spritzen geben oder Verbände wechseln?', '<p>Das ist Pflege auf Anweisung vom Arzt (Behandlungspflege). Sie braucht eine Verordnung. Dann rechnen wir mit der Krankenkasse ab, nicht mit der Pflegekasse.</p>'],
      ['rechnung', 'Bekomme ich eine Rechnung?', '<p>Ja, jeden Monat. Darauf steht jeder Einsatz mit Datum und Uhrzeit. Was die Kasse übernimmt, ist schon abgezogen.</p>'],
      ['kuendigen', 'Kann ich den Vertrag kündigen?', `<p>Ja. Die Frist steht im Pflegevertrag: ${P('Frist laut Vertrag')}. Bei einem Umzug ins Heim oder ins Krankenhaus melden Sie sich einfach bei uns.</p>`, false, `Stand: ${P('Datum')}`]
    ] },
    { id: 'alltag', t: 'Pflege im Alltag', u: 'Wer kommt, wann und wie oft', fragen: [
      ['dieselbe', 'Kommt immer dieselbe Pflegekraft?', '<p>Meist ein festes kleines Team aus zwei bis drei Personen. So kennt man sich, und im Urlaub kommt trotzdem jemand Bekanntes.</p>'],
      ['wochenende', 'Kommen Sie auch am Wochenende und an Feiertagen?', '<p>Ja. Wir pflegen jeden Tag von 6 bis 21 Uhr, auch an Feiertagen. Das Büro ist Montag bis Freitag von 8 bis 17 Uhr erreichbar.</p>', true],
      ['tuer', 'Was passiert, wenn niemand die Tür öffnet?', '<p>Dann rufen wir zuerst an. Meldet sich niemand, rufen wir die Person aus Ihrer Notfall-Liste an. Haben wir einen Schlüssel, gehen wir hinein und sehen nach.</p>'],
      ['haushalt', 'Helfen Sie auch beim Einkaufen oder Putzen?', `<p>Ja, als Hilfe im Haushalt. Das bezahlen viele über den Entlastungsbetrag der Pflegekasse: ${P('Betrag und Stand')}.</p>`],
      ['hausnotruf', 'Können Sie einen Hausnotruf einrichten?', '<p>Wir vermitteln einen Anbieter und sind auf Wunsch die Stelle, die im Notfall kommt. Das klären wir im ersten Gespräch.</p>']
    ] },
    { id: 'angehoerige', t: 'Für Angehörige', u: 'Wenn Sie sich kümmern', fragen: [
      ['weit-weg', 'Ich wohne weit weg. Wie erfahre ich, wie es meiner Mutter geht?', '<p>Mit Einverständnis Ihrer Mutter rufen wir Sie an, wenn sich etwas ändert. Und Sie können jederzeit im Büro nachfragen. Wir notieren jeden Besuch in der Pflegemappe.</p>', true],
      ['lernen', 'Kann ich lernen, selbst mit anzupacken?', '<p>Ja. Wir zeigen Ihnen zu Hause, wie Sie beim Aufstehen oder Waschen helfen, ohne sich den Rücken zu verderben. Auf Wunsch auch in einem Kurs.</p>'],
      ['pause', 'Ich brauche selbst eine Pause. Gibt es Hilfe?', `<p>Ja. Wenn Sie verreisen oder krank sind, übernehmen wir die Pflege (Verhinderungspflege). Die Pflegekasse zahlt dafür einen Betrag im Jahr: ${P('Betrag und Stand')}.</p>`],
      ['ansprechperson', 'Wer ist meine feste Ansprechperson?', '<p>Nadine Gebhardt, unsere Pflegedienstleitung. Sie erreichen sie unter 09181 29 64 010, Montag bis Freitag von 8 bis 17 Uhr.</p>', true]
    ] }
  ];
  const KURZ = ['wie-schnell', 'erstgespraech', 'pflegekasse', 'wochenende', 'weit-weg', 'ansprechperson'];

  let v = new URLSearchParams(location.search).get('v');
  if (!['suche', 'kurz'].includes(v)) v = 'suche';
  let thema = 'alle', suchwort = '', entprell = null, meldTimer = null;

  const norm = s => s.toLowerCase().replace(/[äàá]/g, 'a').replace(/[öó]/g, 'o').replace(/[üú]/g, 'u'); // gleich lang: Markierung bleibt deckungsgleich
  function melden(t) { const m = $('#meldung'); m.textContent = t; m.classList.add('an'); clearTimeout(meldTimer); meldTimer = setTimeout(() => m.classList.remove('an'), 2000); }

  function zeichne() {
    h.dataset.v = v;
    const kurz = v === 'kurz';
    const themen = THEMEN.map(th => ({ ...th, fragen: th.fragen.filter(f => !kurz || KURZ.includes(f[0])) })).filter(th => th.fragen.length);
    const anzahl = themen.reduce((n, th) => n + th.fragen.length, 0);
    $('#einleitung').innerHTML = kurz ? `Die ${anzahl} Fragen, die uns Angehörige am häufigsten stellen. In einfachen Worten.` : `${anzahl} Antworten für Angehörige und Pflegebedürftige, in einfachen Worten. Suchen Sie ein Wort oder wählen Sie ein Thema.`;
    $('#liste').innerHTML = themen.map(th => `<section class="thema" id="${th.id}" aria-labelledby="${th.id}-t"><h2 id="${th.id}-t">${th.t}<small>${th.u}</small></h2><div class="fragen">${th.fragen.map(([id, q, a, _top, stand]) => `<details class="frage" id="frage-${id}" name="${th.id}" data-thema="${th.id}"><summary><span>${q}</span><span class="zeichen" aria-hidden="true"></span></summary><div class="antwort">${a}<div class="fuss-zeile">${stand ? `<span>${stand}</span>` : ''}<button type="button" class="link-kopieren" data-link="frage-${id}">${KOPIE}Link zu dieser Frage kopieren</button></div></div></details>`).join('')}</div></section>`).join('');
    // Themen: im Kurz-Modus Sprunglinks, sonst Filter mit Zahl
    $('#themen').innerHTML = kurz
      ? themen.map(th => `<a href="#${th.id}">${th.t}</a>`).join('')
      : `<button type="button" data-thema="alle" aria-pressed="true">Alle <span class="n"></span></button>` + themen.map(th => `<button type="button" data-thema="${th.id}" aria-pressed="false">${th.t} <span class="n"></span></button>`).join('');
    $$('#themen button').forEach(b => b.addEventListener('click', () => { thema = b.dataset.thema; filtern(); }));
    $$('[data-link]').forEach(b => b.addEventListener('click', () => kopieren(b)));
    $('#suchfeld').value = suchwort;
    filtern(true);
    jsonLd();
  }

  function treffer(det, woerter) { if (!det._text) { const k = det.cloneNode(true); k.querySelectorAll('.fuss-zeile button').forEach(x => x.remove()); det._text = norm(k.textContent + ' ' + det.closest('.thema').querySelector('h2').textContent); } return woerter.every(w => det._text.includes(w)); }
  function filtern(still) {
    // einfache Stammform: „kosten“ findet auch „kostet“, „wochenende“ auch „Wochenenden“
    const woerter = norm(suchwort).split(/\s+/).filter(w => w.length > 1).map(w => w.length >= 5 ? w.replace(/(en|er|es|et|e|n|s)$/, '') : w);
    const alle = $$('details.frage');
    let n = 0; const proThema = {};
    alle.forEach(d => {
      const passt = !woerter.length || treffer(d, woerter);
      if (passt) proThema[d.dataset.thema] = (proThema[d.dataset.thema] || 0) + 1;
      const sichtbar = passt && (thema === 'alle' || d.dataset.thema === thema);
      d.hidden = !sichtbar; if (sichtbar) n++;
      // während der Suche dürfen mehrere offen sein
      if (woerter.length) d.removeAttribute('name'); else d.setAttribute('name', d.dataset.thema);
    });
    $$('.thema').forEach(s => { s.hidden = !$$('details.frage', s).some(d => !d.hidden); });
    $$('#themen button').forEach(b => {
      const z = b.dataset.thema === 'alle' ? Object.values(proThema).reduce((a, c) => a + c, 0) : (proThema[b.dataset.thema] || 0);
      b.querySelector('.n').textContent = z; b.setAttribute('aria-pressed', b.dataset.thema === thema);
      b.disabled = z === 0 && b.dataset.thema !== thema && b.dataset.thema !== 'alle';
    });
    // bis zu drei Treffer öffnen
    if (woerter.length) { const sicht = alle.filter(d => !d.hidden); sicht.forEach((d, i) => { d.open = i < 3 && sicht.length <= 6; }); }
    const nichts = $('#nichts');
    const leer = n === 0 && woerter.length > 0;
    nichts.classList.toggle('an', leer);
    $('#liste').hidden = leer;
    if (leer) {
      $('#nichts-titel').textContent = `Zu „${suchwort.trim()}“ haben wir noch keine Antwort aufgeschrieben.`;
      $('#rr-frage').value = `Ich habe eine Frage zu: ${suchwort.trim()}`;
      $('#vorschlaege').innerHTML = ['Kosten', 'Wochenende', 'Pflegegrad', 'Angehörige'].map(w => `<button type="button" data-wort="${w}">${w}</button>`).join('');
      $$('#vorschlaege button').forEach(b => b.addEventListener('click', () => { suchwort = b.dataset.wort; $('#suchfeld').value = suchwort; thema = 'alle'; filtern(); $('#suchfeld').focus(); }));
    }
    $('#zahl').innerHTML = woerter.length ? (leer ? 'Keine Treffer' : `<b>${n}</b> ${n === 1 ? 'Treffer' : 'Treffer'}`) : `<b>${n}</b> Fragen`;
    $('#leeren').hidden = !suchwort;
    markieren(woerter);
    if (!still) { const q = new URLSearchParams(location.search); if (suchwort) q.set('q', suchwort); else q.delete('q'); history.replaceState(null, '', location.pathname + (q.toString() ? '?' + q : '') + location.hash); }
  }
  function markieren(woerter) {
    if (!window.CSS || !CSS.highlights || typeof Highlight === 'undefined') return;
    CSS.highlights.delete('faq-treffer');
    if (!woerter.length) return;
    const bereiche = [];
    $$('details.frage:not([hidden])').forEach(d => {
      const tw = document.createTreeWalker(d, NodeFilter.SHOW_TEXT, { acceptNode: n => n.parentElement.closest('button') ? NodeFilter.FILTER_REJECT : NodeFilter.FILTER_ACCEPT });
      let k; while ((k = tw.nextNode())) {
        const t = norm(k.nodeValue);
        woerter.forEach(w => { let i = t.indexOf(w); while (i > -1) { const r = new Range(); r.setStart(k, i); r.setEnd(k, i + w.length); bereiche.push(r); i = t.indexOf(w, i + w.length); } });
      }
    });
    CSS.highlights.set('faq-treffer', new Highlight(...bereiche));
  }
  function kopieren(b) {
    const url = location.href.split('#')[0] + '#' + b.dataset.link;
    const fertig = () => melden('Link kopiert. Sie können ihn per E-Mail oder Nachricht weitergeben.');
    if (navigator.clipboard && window.isSecureContext) navigator.clipboard.writeText(url).then(fertig, fertig); else fertig();
  }
  function oeffneHash(fokus = true) {
    const id = decodeURIComponent(location.hash.slice(1)); if (!id) return;
    const el = document.getElementById(id); if (!el) return;
    if (el.matches('details.frage')) {
      if (el.hidden) { suchwort = ''; thema = 'alle'; $('#suchfeld').value = ''; filtern(true); }
      el.open = true;
      el.scrollIntoView({ block: 'start', behavior: reduziert() ? 'auto' : 'smooth' });
      if (fokus) el.querySelector('summary').focus({ preventScroll: true });
      const a = el.querySelector('.antwort'); a.classList.remove('ziel-blink'); void a.offsetWidth; if (!reduziert()) a.classList.add('ziel-blink');
    }
  }
  addEventListener('hashchange', () => oeffneHash());

  function jsonLd() {
    const fragen = $$('details.frage').map(d => ({ '@type': 'Question', name: d.querySelector('summary span').textContent, acceptedAnswer: { '@type': 'Answer', text: d.querySelector('.antwort').cloneNode(true).textContent.replace('Link zu dieser Frage kopieren', '').replace(/\s+/g, ' ').trim() } }));
    const ld = { '@context': 'https://schema.org', '@type': 'FAQPage', mainEntity: fragen };
    $('#ld-zeigen').textContent = JSON.stringify(ld, null, 2);
    let s = $('#ld');
    if (h.hasAttribute('data-ld')) { if (!s) { s = document.createElement('script'); s.type = 'application/ld+json'; s.id = 'ld'; document.head.appendChild(s); } s.textContent = JSON.stringify(ld); }
    else if (s) s.remove();
  }

  $('#suchfeld').addEventListener('input', e => { clearTimeout(entprell); entprell = setTimeout(() => { suchwort = e.target.value; filtern(); }, 120); });
  $('#suchfeld').addEventListener('keydown', e => { if (e.key === 'Escape' && suchwort) { e.preventDefault(); suchwort = ''; e.target.value = ''; filtern(); } });
  $('#leeren').addEventListener('click', () => { suchwort = ''; $('#suchfeld').value = ''; filtern(); $('#suchfeld').focus(); });
  addEventListener('keydown', e => { if (e.key === '/' && v === 'suche' && !/INPUT|TEXTAREA/.test(document.activeElement.tagName)) { e.preventDefault(); $('#suchfeld').focus(); } });
  $('#rueckruf-form').addEventListener('submit', e => {
    e.preventDefault();
    const name = $('#rr-name'), tel = $('#rr-tel'), f = $('#rr-fehler');
    const fehlt = [!name.value.trim() && 'Ihren Namen', !/\d{5,}/.test(tel.value.replace(/\D/g, '')) && 'eine Telefonnummer'].filter(Boolean);
    [name, tel].forEach(x => x.removeAttribute('aria-invalid'));
    if (fehlt.length) { f.hidden = false; f.textContent = `Bitte tragen Sie noch ${fehlt.join(' und ')} ein.`; (fehlt[0] === 'Ihren Namen' ? name : tel).setAttribute('aria-invalid', 'true'); (fehlt[0] === 'Ihren Namen' ? name : tel).focus(); return; }
    f.hidden = true;
    $('#rr-danke').textContent = `Danke, ${name.value.trim()}. Wir rufen Sie unter ${tel.value.trim()} zurück, werktags bis 17 Uhr.`;
    $('#rueckruf').classList.add('gesendet'); $('#rr-danke').focus();
  });

  function setzeV(neu, schreiben) {
    v = neu; thema = 'alle'; if (v === 'kurz') suchwort = '';
    $$('#pult-v button').forEach(b => b.setAttribute('aria-pressed', b.dataset.v === v));
    if (schreiben) { const q = new URLSearchParams(location.search); q.set('v', v); q.delete('q'); history.replaceState(null, '', location.pathname + '?' + q); }
    zeichne();
  }
  $$('#pult-v button').forEach(b => b.addEventListener('click', () => setzeV(b.dataset.v, true)));
  $('#pult-ld').addEventListener('click', () => { const b = $('#pult-ld'), an = b.getAttribute('aria-pressed') !== 'true'; b.setAttribute('aria-pressed', an); b.lastElementChild.textContent = an ? 'an' : 'aus'; h.toggleAttribute('data-ld', an); jsonLd(); });

  const q0 = new URLSearchParams(location.search);
  if (q0.get('q') && v === 'suche') suchwort = q0.get('q');
  if (q0.has('ld')) { h.setAttribute('data-ld', ''); $('#pult-ld').setAttribute('aria-pressed', 'true'); $('#pult-ld').lastElementChild.textContent = 'an'; }
  setzeV(v, false);
  if (location.hash) setTimeout(() => oeffneHash(), 60);

  /* Vorführung: tippen, Treffer markieren, Thema filtern, null Treffer, Direktlink */
  let uhren = [];
  const spaeter = (f, ms) => uhren.push(setTimeout(f, ms));
  function stopp() { uhren.forEach(clearTimeout); uhren = []; }
  function tippe(wort, start) { for (let i = 1; i <= wort.length; i++) spaeter(() => { suchwort = wort.slice(0, i); $('#suchfeld').value = suchwort; if (i === wort.length || i % 2 === 0) filtern(true); }, start + i * 90); return start + wort.length * 90; }
  function neustart() { stopp(); suchwort = ''; thema = 'alle'; zeichne(); scrollTo(0, 0); }
  function vorfuehren() {
    neustart();
    h.classList.add('vorfuehrung');
    if (v === 'kurz') {
      const ids = ['frage-wie-schnell', 'frage-pflegekasse', 'frage-wochenende', 'frage-weit-weg'];
      ids.forEach((id, i) => spaeter(() => { const d = document.getElementById(id); if (d) d.open = true; }, 1000 + i * 1500));
      spaeter(vorfuehren, 1000 + ids.length * 1500 + 1200);
      return;
    }
    let t = tippe('Kosten', 900);
    spaeter(() => { thema = 'kosten'; filtern(true); }, t + 1600);
    spaeter(() => { thema = 'alle'; suchwort = ''; $('#suchfeld').value = ''; filtern(true); }, t + 3200);
    t = tippe('Hund', t + 3600);
    spaeter(() => { suchwort = ''; $('#suchfeld').value = ''; filtern(true); const d = $('#frage-wochenende'); if (d) { d.open = true; const a = d.querySelector('.antwort'); if (!reduziert()) { a.classList.remove('ziel-blink'); void a.offsetWidth; a.classList.add('ziel-blink'); } } }, t + 2400);
    spaeter(vorfuehren, t + 5200);
  }
  function pause() { stopp(); h.classList.remove('vorfuehrung'); }
  function weiter() { vorfuehren(); }

})();
</script>
</body>
</html>