{
 "$schema": "../../schema.json",
 "schema": "fundus/1",
 "id": "buchungsleiste-datumsbereich",
 "name": "Buchungsleiste mit Datumsbereich",
 "name_en": "Booking bar with date range picker and guests",
 "kurz": "Anreise und Abreise in einem Kalender mit Belegung und Mindestaufenthalt, Gäste mit Kinderalter, am Desktop als verankertes Popover, auf dem Telefon als Bottom-Sheet; Übergabe an die Engine erst nach zweitem Klick.",
 "kategorie": "Sektionen & Funktionen",
 "kategorie_slug": "sektionen",
 "kategorie_nr": 16,
 "bau_chat": "D",
 "prioritaet": "D",
 "trendstatus": "etabliert",
 "belegstatus": "belegt",
 "website_belege": 3,
 "stimmung": [
  "ruhig",
  "präzise",
  "luxuriös"
 ],
 "stimmung_roh": [
  "hochwertig",
  "ruhig",
  "funktional"
 ],
 "technik": [
  "css",
  "vanilla-js",
  "popover",
  "anchor-positioning",
  "dialog",
  "intl",
  "form"
 ],
 "technik_gruppen": [
  "css",
  "js"
 ],
 "leistungskosten": "niedrig",
 "steckbrief": {
  "beschreibung": "Die Leiste direkt unter dem Hero fragt nur, was die Booking-Engine braucht: Anreise und Abreise in einem Kalender, die Zahl der Nächte, Erwachsene und Kinder mit Alter. Belegte Tage und Mindestaufenthalt stehen schon im Kalender. Am Desktop öffnen Kalender und Gäste als Popover, per Anchor Positioning an der Leiste verankert. Auf dem Telefon wird die Leiste zur festen unteren Zeile, die ein Bottom-Sheet (dialog) öffnet. Die Daten gehen erst nach einem zweiten Klick mit Datenschutz-Hinweis an die Booking-Engine, als Parameter in der URL.",
  "warum_es_wirkt": "Die Website ist das Foyer, die Buchungsleiste die Rezeption. Wer schon weiß, wann er kommt, will Verfügbarkeit sehen, ohne erst die fremde Buchungsseite zu laden. Ein eigener Kalender passt zur Marke, zeigt Regeln früh und lädt keine fremden Skripte, bevor der Gast es will.",
  "wann_einsetzen": "Hotel, Pension, Ferienwohnung, Campingplatz; abgewandelt für Tischreservierung (ein Datum, Uhrzeit, Personen), Kursbuchung oder Verleih.",
  "wann_nicht": "Wenn die Booking-Engine ohne URL-Parameter arbeitet und alles im eigenen Widget abfragt: dann reicht ein klarer Knopf „Zimmer buchen“. Bei Häusern mit nur einer Wohnung und wenigen Anfragen ist ein Anfrageformular ehrlicher.",
  "varianten": [
   "Leiste unter dem Hero, mobil feste untere Zeile mit Bottom-Sheet",
   "Buchungskarte auf der Zimmerseite, sticky neben Fotos und Ausstattung, mit Ab-Preis pro Nacht",
   "Tischreservierung: ein Datum, Uhrzeit in Slots, Personen",
   "Ohne JS: native date-Inputs und Selects im selben Formular"
  ],
  "umsetzung": "Grundlage ist ein echtes form method=get mit action = Engine-URL und den Feldern arrival, departure (type=date, required), adults, children und childAges; ohne JS funktioniert es so. JS setzt noValidate, blendet die nativen Felder aus und zeigt Knöpfe, die einen eigenen Kalender öffnen. Kalender: zwei Tabellen mit role=grid, Zellen mit data-d und Roving tabindex; erster Klick Anreise, zweiter Abreise, beim Zeigen eine gestrichelte Bereichsvorschau. Regeln aus der Engine (belegte Nächte, Mindestaufenthalt je Anreisetag) sperren Tage mit Grund im aria-label. Desktop: popover mit position-anchor an der Leiste und position-try-fallbacks (--oben, --rechts, --rechts-oben) plus position-try-order: most-height; geöffnet per showPopover({ source }). Ohne Anchor Positioning rechnet JS die Lage aus getBoundingClientRect. Telefon: dieselben Knoten (Kalender, Gäste) wandern in ein dialog-Bottom-Sheet (showModal, closedby=any). Übergabe in zwei Schritten: Klick 1 prüft (Daten fehlen → Kalender öffnet mit Hinweis; Kinderalter fehlt → Gäste öffnen mit Fehler) und zeigt Zusammenfassung und Datenschutz-Hinweis; erst Klick 2 baut die URL und öffnet die Engine (window.open oder iFrame-src erst jetzt). Parameternamen hängen von der Engine ab, bei Mews z. B. mewsStart, mewsEnd, mewsAdultCount, mewsChildCount. In der Demo zeigt ein Dialog die URL statt sie zu öffnen.",
  "mobil": "Feste untere Zeile mit Zusammenfassung und „Prüfen“. Bottom-Sheet mit zwei Monaten untereinander, Tagen in 44 px, Gästen und festem Fuß mit Nächten und Weiter-Knopf.",
  "reduzierte_bewegung": "Popover und Sheet erscheinen ohne Weg, nur mit kurzem Einblenden oder sofort; die Bereichsvorschau springt.",
  "barrierefreiheit": "Kalender nach dem APG-Beispiel Date Picker Dialog: Pfeiltasten (Tag, Woche), Bild auf/ab (Monat), Pos1/Ende (Woche), Enter/Leertaste wählt; nach der Abreise springt der Fokus auf „Übernehmen“, Esc schließt und gibt den Fokus an das Feld zurück. Jeder Tag trägt den vollen Namen, gesperrte Tage nennen den Grund („nicht wählbar: Mindestaufenthalt 2 Nächte“, „ausgebuchte Nacht dazwischen“), der Hinweis über dem Kalender ist aria-live. Wochentage mit abbr. Stepper-Knöpfe mit Namen („Kinder: eines mehr“), Zahl als output mit aria-live, Plus gesperrt bei voller Belegung mit Erklärung. Fehlendes Kinderalter: Feld markiert, Fokus springt hin, Fehlertext. Datenschutz-Hinweis zur Weitergabe und Preisangaben vom Kunden prüfen lassen."
 },
 "messwerte": {
  "easing": "auf cubic-bezier(0.16, 1, 0.3, 1), zu cubic-bezier(0.4, 0, 0.2, 1)",
  "dauer_ms": "300 auf, 200 zu, 150 Auswahl",
  "stagger_ms": "",
  "distanz": "Popover 8 px, Bottom-Sheet 100 %",
  "sonstiges": "token-toggle-asymmetrisch laut Rezept boutique-hotel-gastgeber (öffnen ca. 300 ms, schließen ca. 200 ms; UI 150–250 ms mit cubic-bezier(0.4, 0, 0.2, 1))",
  "herkunft": "eigene Festlegung",
  "quelle": "Rezept boutique-hotel-gastgeber (bewegung, regeln)"
 },
 "kurve": {
  "bezier": [
   0.16,
   1.0,
   0.3,
   1.0
  ],
  "css": "cubic-bezier(0.16, 1, 0.3, 1)",
  "name": "expo.out",
  "dauer_ms": 300
 },
 "gesehen_bei": [
  {
   "seite": "Michelberger Hotel (Berlin)",
   "url": "https://www.michelbergerhotel.com/",
   "auszeichnung": "",
   "beobachtung": "Laut Rezept-Recherche (live geprüft 31.10.2026): eigene Datumsauswahl auf der Seite mit Zuständen CalendarDay__blocked_minimum_nights und __blocked_out_of_range; der Mindestaufenthalt ist im Kalender sichtbar.",
   "art": "website"
  },
  {
   "seite": "The Hoxton",
   "url": "https://thehoxton.com/",
   "auszeichnung": "",
   "beobachtung": "Laut Rezept-Recherche (live geprüft 31.10.2026): Section „irnmn-booking-system“ als Buchungsleiste direkt nach dem Hero, zusätzlich eine Leisten-Variante; Navigation mit „Why Book With Us?“.",
   "art": "website"
  },
  {
   "seite": "Aman",
   "url": "https://www.aman.com/",
   "auszeichnung": "",
   "beobachtung": "Laut Rezept-Recherche (live geprüft 31.10.2026): erste Section „aman-booking-bar-section“, Übergänge 0.4 s und Expo-Out cubic-bezier(0.19, 1, 0.22, 1).",
   "art": "website"
  },
  {
   "seite": "Mews Booking Engine: Deeplinks",
   "url": "https://docs.mews.com/booking-engine-guide/booking-engine-standalone/deeplinks",
   "auszeichnung": "",
   "beobachtung": "Per WebFetch am 01.11.2026 gelesen: Die Engine nimmt Anreise und Abreise als ISO-Datum (mewsStart, mewsEnd), Erwachsene und Kinder (mewsAdultCount, mewsChildCount), Sprache und Gutscheincode als URL-Parameter. So kann die eigene Leiste die Auswahl übergeben.",
   "art": "artikel"
  },
  {
   "seite": "WAI-ARIA APG: Date Picker Dialog",
   "url": "https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/examples/datepicker-dialog/",
   "auszeichnung": "",
   "beobachtung": "Kalender als Tabelle mit role=grid, Roving tabindex, aria-selected am gewählten Tag; Pfeiltasten für Tage und Wochen, Bild auf/ab für Monate, Home/Ende für die Woche, Esc schließt und gibt den Fokus an den Knopf zurück.",
   "art": "demo"
  }
 ],
 "tutorials": [
  {
   "titel": "WAI-ARIA APG: Date Picker Dialog Example",
   "url": "https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/examples/datepicker-dialog/"
  },
  {
   "titel": "Mews: Booking Engine Deeplinks",
   "url": "https://docs.mews.com/booking-engine-guide/booking-engine-standalone/deeplinks"
  },
  {
   "titel": "Chrome Developers: Introducing the CSS anchor positioning API",
   "url": "https://developer.chrome.com/blog/anchor-positioning-api"
  }
 ],
 "kombinierbar_mit": [
  "cinematic-video-hero",
  "native-popover-dropdowns",
  "einblenden-starting-style",
  "token-toggle-asymmetrisch",
  "mobile-bottom-navigation",
  "animiertes-select",
  "slideshow-innere-gegenparallaxe"
 ],
 "urls": {
  "detail": "https://cecodesign.de/lab/fundus/sektionen/buchungsleiste-datumsbereich/",
  "meta": "https://cecodesign.de/lab/fundus/sektionen/buchungsleiste-datumsbereich/meta.json",
  "demo": "https://cecodesign.de/lab/fundus/sektionen/buchungsleiste-datumsbereich/demo"
 },
 "herkunft": {
  "quelldateien": [
   "DEF-Recherche 01.11.2026"
  ],
  "pruefnotizen": [
   "Michelberger, Hoxton und Aman stammen aus der Rezept-Recherche boutique-hotel-gastgeber (live geprüft 31.10.2026), hier nicht erneut abgerufen. Mews-Deeplinks und APG-Beispiel per WebFetch am 01.11.2026 gelesen.",
   "Preisangaben (inkl. MwSt., Gästetaxe) und Datenschutz-Hinweis zur Weitergabe an den Buchungspartner vom Kunden prüfen lassen."
  ]
 },
 "bau": {
  "status": "fertig",
  "kurz": "Anreise und Abreise in einem Kalender mit Belegung und Mindestaufenthalt, Gäste mit Kinderalter, am Desktop als verankertes Popover, auf dem Telefon als Bottom-Sheet; Übergabe an die Engine erst nach zweitem Klick.",
  "demo": true,
  "abhaengigkeiten": [],
  "werte": {
   "easing": "auf cubic-bezier(0.16, 1, 0.3, 1), zu cubic-bezier(0.4, 0, 0.2, 1) (token-toggle-asymmetrisch laut Rezept boutique-hotel-gastgeber)",
   "dauer_ms": "300 auf, 200 zu, 150 Auswahl und Hover",
   "popover": "opacity 0 → 1, translate 0 8px → 0; @starting-style; Exit mit overlay und display allow-discrete; die Dauer wechselt mit :popover-open (auf 300 ms) gegenüber dem Grundzustand (zu 200 ms)",
   "anker": "Kalender: position-anchor --datum, top: anchor(bottom), left: anchor(left), 10px Abstand, position-try-fallbacks: --oben, --rechts, --rechts-oben, position-try-order: most-height; Gäste: --gaeste; Zusammenfassung: --los, rechtsbündig",
   "bottom_sheet": "dialog.showModal(), closedby=any, translate 0 100% → 0 in 300 ms, zu 200 ms; ::backdrop rgba(30,28,26,.45); max-height 92svh; ab 640px Breite abwärts",
   "kalender": "zwei Monate, Zelle 38px (Sheet 46px), Kreis 36px (Sheet 44px), Band #e8ddcf hinter dem Bereich, Vorschau mit gestrichelter Kante 1px #b9ab98, Anfang und Ende #3e3a37",
   "regeln": "Mindestaufenthalt 2 Nächte bei Anreise Fr/Sa, 3 Nächte 24.–31.12.; ausgebuchte Nacht sperrt Anreise und jede Abreise dahinter, ist aber als Abreisetag wählbar; Anreise gesperrt, wenn der Mindestaufenthalt ab dem Tag nicht frei ist; höchstens 21 Nächte",
   "gaeste": "Erwachsene 1–4, Kinder 0–3, zusammen höchstens 4 (Zimmerseite 3); Alter je Kind 0–13 Pflicht",
   "richtpreis": "168 € So–Do, 198 € Fr/Sa, 228 € 24.–31.12. je Nacht, Summe als „ab“",
   "uebergabe": "Klick 1 (Verfügbarkeit prüfen): Zusammenfassung mit Datenschutz-Hinweis im Popover; Klick 2 (Weiter zur Buchung): URL ?arrival=JJJJ-MM-TT&departure=JJJJ-MM-TT&adults=2&children=1&childAges=6&lang=de",
   "datum": "Intl de-AT (Jänner), Heute in Europe/Vienna, Rechnung auf UTC-Mittag",
   "farben": "Grund #f3eee7, Leiste #fef2e3, Popover #fffaf3, Text #3e3a37, leise #6b6d68, Linien #d5d1c8, Haus #6e5a47",
   "schrift": "Newsreader (Werte 1.375rem, h1 300 clamp(2.5rem, 1.5rem + 4vw, 5.5rem), opsz 72), Mona Sans (Labels 0.75rem, wdth 118, Laufweite 0.06em, versal)",
   "hero_bild": "einmaliges Zurückskalieren 1.06 → 1 in 1200 ms cubic-bezier(0.37, 0, 0.63, 1)",
   "vorfuehrung_runde_ms": 15400
  },
  "ausloeser": "klick",
  "touch": "Unter 640 px wird die Leiste zur festen unteren Zeile (Zusammenfassung „10. Dez. – 13. Dez. · 3 Gäste“ und Knopf „Prüfen“). Tippen öffnet ein Bottom-Sheet (dialog) mit zwei Monaten untereinander, Tagen in 44 px, den Gästen darunter und festem Fuß mit Nächten, Richtpreis und Weiter-Knopf. Die Zusammenfassung vor der Übergabe kommt ebenfalls als Blatt von unten.",
  "reduziert": "Popover, Sheet und Dialog erscheinen ohne Weg (Übergänge auf 1 ms), das Hero-Bild skaliert nicht. Auswahl und Bereich wechseln ohne Übergang.",
  "korrekturen": {
   "umsetzung": "Grundlage ist ein echtes form method=get mit action = Engine-URL und den Feldern arrival, departure (type=date, required), adults, children und childAges; ohne JS funktioniert es so. JS setzt noValidate, blendet die nativen Felder aus und zeigt Knöpfe, die einen eigenen Kalender öffnen. Kalender: zwei Tabellen mit role=grid, Zellen mit data-d und Roving tabindex; erster Klick Anreise, zweiter Abreise, beim Zeigen eine gestrichelte Bereichsvorschau. Regeln aus der Engine (belegte Nächte, Mindestaufenthalt je Anreisetag) sperren Tage mit Grund im aria-label. Desktop: popover mit position-anchor an der Leiste und position-try-fallbacks (--oben, --rechts, --rechts-oben) plus position-try-order: most-height; geöffnet per showPopover({ source }). Ohne Anchor Positioning rechnet JS die Lage aus getBoundingClientRect. Telefon: dieselben Knoten (Kalender, Gäste) wandern in ein dialog-Bottom-Sheet (showModal, closedby=any). Übergabe in zwei Schritten: Klick 1 prüft (Daten fehlen → Kalender öffnet mit Hinweis; Kinderalter fehlt → Gäste öffnen mit Fehler) und zeigt Zusammenfassung und Datenschutz-Hinweis; erst Klick 2 baut die URL und öffnet die Engine (window.open oder iFrame-src erst jetzt). Parameternamen hängen von der Engine ab, bei Mews z. B. mewsStart, mewsEnd, mewsAdultCount, mewsChildCount. In der Demo zeigt ein Dialog die URL statt sie zu öffnen.",
   "barrierefreiheit": "Kalender nach dem APG-Beispiel Date Picker Dialog: Pfeiltasten (Tag, Woche), Bild auf/ab (Monat), Pos1/Ende (Woche), Enter/Leertaste wählt; nach der Abreise springt der Fokus auf „Übernehmen“, Esc schließt und gibt den Fokus an das Feld zurück. Jeder Tag trägt den vollen Namen, gesperrte Tage nennen den Grund („nicht wählbar: Mindestaufenthalt 2 Nächte“, „ausgebuchte Nacht dazwischen“), der Hinweis über dem Kalender ist aria-live. Wochentage mit abbr. Stepper-Knöpfe mit Namen („Kinder: eines mehr“), Zahl als output mit aria-live, Plus gesperrt bei voller Belegung mit Erklärung. Fehlendes Kinderalter: Feld markiert, Fokus springt hin, Fehlertext. Datenschutz-Hinweis zur Weitergabe und Preisangaben vom Kunden prüfen lassen.",
   "mobil": "Feste untere Zeile mit Zusammenfassung und „Prüfen“. Bottom-Sheet mit zwei Monaten untereinander, Tagen in 44 px, Gästen und festem Fuß mit Nächten und Weiter-Knopf."
  },
  "geprueft": "02.11.2026",
  "notiz": "Welt: Rezept boutique-hotel-gastgeber, erfundenes Haus Seeweite in Bregenz (Bodensee), Newsreader und Mona Sans, Sand #f3eee7, Creme #fef2e3, Holz #6e5a47; Buchungssystem „Quartierbuch“ erfunden. Hero-Bild selbst gerechnet (numpy: Dämmerung über dem See, Pfänder-Silhouette, Mole mit Laternen und Spiegelungen) als medien/buchungsleiste-datumsbereich-see.webp (18 KB) und -see-klein.webp. Belegung aus einem Hash des Datums, damit die Demo in jedem Monat Belegung zeigt; Datumsformat de-AT (Jänner), heute in Europe/Vienna. Pult: Variante Leiste unter dem Hero oder Zimmerseite (?v=leiste|zimmer), „Ohne JS“ zeigt die nativen Felder im selben Formular. Vorführung: Kalender öffnet über der Leiste, Anreise Donnerstag, Vorschau, Abreise nach drei Nächten, Kind mit 6 Jahren, Prüfen, Zusammenfassung, Übergabe-Dialog mit URL. Tastatur und Sheet per Playwright geprüft (Mindestaufenthalt, belegte Nacht dazwischen, Fokus zurück). Referenzen: michelbergerhotel.com (Mindestaufenthalt im Kalender), thehoxton.com und aman.com (Leiste nach dem Hero), docs.mews.com (Deeplinks), w3.org (APG Date Picker). AD-Review 02.11.2026: Note 4.",
  "varianten": [
   {
    "id": "leiste",
    "name": "Leiste unter dem Hero",
    "wann": "Startseite von Hotel, Pension oder Ferienwohnungen: die Leiste liegt halb über dem Hero, der Kalender öffnet nach oben, wenn unten kein Platz ist.",
    "werte": {
     "lage": "margin-top −46px über dem Hero, max. 1180px breit, Raster 2.2fr / 1.1fr / auto, Höhe 92px",
     "kalender": "öffnet je nach Platz unter oder über der Leiste (most-height)",
     "gaeste_max": 4,
     "telefon": "feste untere Zeile"
    }
   },
   {
    "id": "zimmer",
    "name": "Buchungskarte auf der Zimmerseite",
    "wann": "Zimmer- oder Wohnungsseite mit Fotos und Ausstattung: Karte rechts sticky mit Ab-Preis pro Nacht, Felder untereinander, Gesamtpreis unter dem Formular.",
    "werte": {
     "lage": "aside sticky top 24px, Spalte minmax(320px, 4.2fr)",
     "kalender": "rechtsbündig an der Karte (Fallback --rechts), ragt über die Zimmerfotos",
     "gaeste_max": 3,
     "preis": "ab 168 € pro Nacht, Gesamt „3 Nächte · ab 564 € gesamt“"
    }
   }
  ]
 }
}
