{
 "$schema": "../../schema.json",
 "schema": "fundus/1",
 "id": "programm-kalender",
 "name": "Programm-Kalender mit Liste und Monat",
 "name_en": "Event programme with list and month view, category filter and ICS export",
 "kurz": "Programm eines Kulturhauses als Liste und Monat mit Rubrik-Filter, echter .ics-Datei je Termin, gedimmter Vergangenheit und Ausverkauft-Zustand.",
 "kategorie": "Sektionen & Funktionen",
 "kategorie_slug": "sektionen",
 "kategorie_nr": 16,
 "bau_chat": "D",
 "prioritaet": "D",
 "trendstatus": "etabliert",
 "belegstatus": "belegt",
 "website_belege": 2,
 "stimmung": [
  "präzise",
  "experimentell"
 ],
 "stimmung_roh": [
  "sachlich",
  "grafisch",
  "funktional"
 ],
 "technik": [
  "css",
  "vanilla-js",
  "intl",
  "css-grid"
 ],
 "technik_gruppen": [
  "css",
  "js"
 ],
 "leistungskosten": "niedrig",
 "steckbrief": {
  "beschreibung": "Das Programm eines Hauses als eine Sektion mit zwei Ansichten: eine Liste nach Datum zum Überfliegen und eine Monatsansicht zum Planen. Ein Umschalter wechselt die Ansicht, Rubrik-Filter wirken in beiden. Jeder Termin zeigt Datum, Uhrzeit, Ort, Rubrik als Text und Farbe, Preis und Ticket-Status. „In Kalender“ erzeugt im Browser eine echte .ics-Datei und lädt sie herunter. Vergangene Termine bleiben sichtbar, aber gedimmt und einzeilig. Ausverkaufte Termine sind als Text gekennzeichnet und bieten die Warteliste an. Ist ein Filter leer, zeigt die Sektion einen Ausweg statt einer leeren Fläche.",
  "warum_es_wirkt": "Besucher suchen zuerst Datum, Uhrzeit und Ticket, erst dann das Bild. Die Liste beantwortet „Was läuft bald?“, der Monat „Was passt in meine Woche?“. Ein gemeinsamer Filter für beide Ansichten spart Wege. Der Kalender-Export macht aus Interesse einen festen Termin.",
  "wann_einsetzen": "Kulturhaus, Kunsthalle, Festival, Theater, Kino, Kursanbieter mit festen Terminen, Restaurant oder Hotel mit Veranstaltungen. Ab etwa acht Terminen im Monat.",
  "wann_nicht": "Bei zwei oder drei Terminen im Jahr reicht eine einfache Liste. Liefert das Ticketsystem (Spektrix, Enviso u. a.) eine eigene Programmseite, die Sektion nur als Teaser bauen und dorthin verlinken. Dauerangebote (Ausstellung täglich geöffnet) gehören nicht als Einzeltermine in den Monat.",
  "varianten": [
   "Liste und Monat mit Umschalter, Filter nach Rubrik (Programmseite eines Hauses)",
   "Tagesleiste: Tage als Reiter, darunter die Termine des Tages (Festival, Kino, Messe)",
   "Teaser „Nächste Termine“ mit drei Karten und Link zum Programm (Startseite)",
   "Kursprogramm mit freien Plätzen und Warteliste statt Ticketpreis"
  ],
  "umsetzung": "Daten als Liste von Terminen (id, tag, zeit, dauer, rubrik, titel, ort, preis, status). Ein Filterzustand, je Ansicht eine Render-Funktion. Kalenderrechnung in UTC (Date.UTC), damit die Zeitzone des Geräts keine Tage verschiebt; Anzeige mit Intl.DateTimeFormat('de-DE', { timeZone: 'UTC' }).\n\nListe: <ol> der Tage, je Tag eine <ol> der Termine. Datum und Uhrzeit in Mono mit tabular-nums. Vergangene Tage kompakt und gedimmt, „Heute“ als Marke.\n\nMonat: <ol> mit 7 Spalten, Montag zuerst, Tage mit Terminen als <button aria-pressed> mit vollständigem Datum im zugänglichen Namen. Darunter die Termine des gewählten Tages in derselben Darstellung wie die Liste.\n\nLinien: Fallback mit gap: 1px auf Linienfarbe. Verbesserung: @supports (row-rule: 1px solid) { .raster { background: none; column-rule: 1px solid; row-rule: 1px solid; rule-break: intersection; rule-inset-junction: 5px } }. Gap Decorations sind rein dekorativ.\n\nICS: Zeilen mit CRLF, Faltung nach 75 Oktetten (TextEncoder, UTF-8 nie zerteilen), Text maskieren (Backslash, Semikolon, Komma, Zeilenumbruch mit vorangestelltem Backslash), VTIMEZONE für Europe/Berlin mitliefern, DTSTART/DTEND;TZID=Europe/Berlin als Wandzeit, DTSTAMP in UTC, stabile UID. new Blob([text], { type: 'text/calendar;charset=utf-8' }), URL.createObjectURL, <a download>, danach revokeObjectURL. Eine Datei kann mehrere VEVENT enthalten (z. B. „Auswahl in den Kalender“).\n\nIm Einsatz: Jetzt aus new Date() in Europe/Berlin, Programm aus dem CMS oder dem Ticketsystem, Filter und Ansicht in der URL (?rubrik=musik&ansicht=monat), damit Links teilbar sind.",
  "mobil": "Rubriken als wischbare Leiste. Der Monat wird zur Punkt-Übersicht, ein Tipp auf den Tag zeigt die Termine darunter. Vergangene Termine einzeilig. Tagesleiste wischbar mit Scroll-Snap.",
  "reduzierte_bewegung": "Ansichten und Listen erscheinen ohne Einblenden, die Segment-Pille springt. Zustände und Texte bleiben gleich.",
  "barrierefreiheit": "Rubrik nie nur über Farbe: immer ein Text-Label auf weißer Schrift (AA auf jeder Spartenfarbe). Filter als Schalter mit aria-pressed, Anzahl je Rubrik mit Label. Ansicht als Radiogruppe in fieldset mit legend. Trefferzahl und Monatsname in aria-live. Tage im Monat als Knöpfe mit vollständigem Datum und Terminzahl im Namen. „Ausverkauft“, „Vorbei“ und „Heute“ als Text, nicht nur als Dimmen oder Farbe. Der Kalender-Knopf nennt Titel und Datum im zugänglichen Namen. Bei sehr vielen Tagen im Monat roving tabindex mit Pfeiltasten erwägen."
 },
 "messwerte": {
  "easing": "cubic-bezier(0.215, 0.61, 0.355, 1)",
  "dauer_ms": "150–250 UI, 300–350 Ansichtswechsel",
  "stagger_ms": "",
  "distanz": "",
  "sonstiges": "Kurve und Dauern aus dem Rezept kultur-programm-haltung (Stedelijk .2s/.35s, Barbican .1–.3s)",
  "herkunft": "eigene Festlegung",
  "quelle": "Rezept kultur-programm-haltung"
 },
 "kurve": {
  "bezier": [
   0.215,
   0.61,
   0.355,
   1.0
  ],
  "css": "cubic-bezier(0.215, 0.61, 0.355, 1)",
  "name": "eigene Kurve",
  "dauer_ms": 200
 },
 "gesehen_bei": [
  {
   "seite": "Brücke-Museum Berlin",
   "url": "https://www.bruecke-museum.de/en/programm/veranstaltungen/2137.ics",
   "auszeichnung": "",
   "beobachtung": "Jede Veranstaltung hat eine eigene .ics-Datei: VCALENDAR 2.0, DTSTART;TZID=Europe/Berlin:20221204T110000, SUMMARY mit Hausname. LOCATION und URL fehlen in dieser Datei (am 01.11.2026 abgerufen).",
   "art": "website"
  },
  {
   "seite": "Barbican",
   "url": "https://www.barbican.org.uk/",
   "auszeichnung": "",
   "beobachtung": "Spartenfarben als System (#d14900, #5778a2, #946f2e, #402f79, #e60077, #017e9d, #20882a), Startseite aus Reihen je Rubrik, Merkliste „Saved events“, Ticketing über Spektrix (Rezept-Recherche 31.10.2026).",
   "art": "website"
  },
  {
   "seite": "Chrome for Developers: Gap decorations",
   "url": "https://developer.chrome.com/blog/gap-decorations-stable",
   "auszeichnung": "",
   "beobachtung": "Gap Decorations ab Chrome und Edge 149: column-rule und row-rule auch in Grid und Flex, rule-break, rule-inset, rule-visibility-items. Rein dekorativ; ohne Unterstützung bleiben die Lücken leer.",
   "art": "artikel"
  },
  {
   "seite": "DEV Community: hand-rolled iCalendar writer",
   "url": "https://dev.to/daniel_pertu/we-hand-rolled-an-icalendar-writer-in-164-lines-and-its-three-sharp-edges-are-crlf-75-octets-and-570a",
   "auszeichnung": "",
   "beobachtung": "Drei Stolperstellen beim eigenen ICS-Export: Zeilenende CRLF, Zeilen höchstens 75 Oktette (nicht Zeichen, UTF-8 nicht zerteilen), DTEND bei ganztägigen Terminen exklusiv.",
   "art": "artikel"
  }
 ],
 "tutorials": [
  {
   "titel": "RFC 5545: iCalendar",
   "url": "https://www.rfc-editor.org/rfc/rfc5545"
  },
  {
   "titel": "Chrome for Developers: Gap decorations",
   "url": "https://developer.chrome.com/blog/gap-decorations-stable"
  }
 ],
 "kombinierbar_mit": [
  "flip-zustandswechsel",
  "gleitender-indikator",
  "sticky-shrink-header",
  "toast-stapel"
 ],
 "urls": {
  "detail": "https://cecodesign.de/lab/fundus/sektionen/programm-kalender/",
  "meta": "https://cecodesign.de/lab/fundus/sektionen/programm-kalender/meta.json",
  "demo": "https://cecodesign.de/lab/fundus/sektionen/programm-kalender/demo"
 },
 "herkunft": {
  "quelldateien": [
   "DEF-Recherche 01.11.2026"
  ],
  "pruefnotizen": [
   "ICS-Beleg Brücke-Museum am 01.11.2026 per WebFetch abgerufen. Barbican aus der Rezept-Recherche vom 31.10.2026.",
   "Kurve und Dauern sind aus dem Rezept übernommen, keine eigene Messung am Muster."
  ]
 },
 "bau": {
  "status": "fertig",
  "kurz": "Programm eines Kulturhauses als Liste und Monat mit Rubrik-Filter, echter .ics-Datei je Termin, gedimmter Vergangenheit und Ausverkauft-Zustand.",
  "demo": true,
  "abhaengigkeiten": [],
  "werte": {
   "easing": "cubic-bezier(0.215, 0.61, 0.355, 1) (easeOutCubic aus dem Rezept kultur-programm-haltung)",
   "dauer_ms": {
    "ui": 200,
    "segment_pille": 250,
    "ansichtswechsel": 320,
    "toast": 250,
    "knopf_druck": 150
   },
   "stagger_ms": "24 je Tagesblock beim Neuaufbau der Liste",
   "distanz": "Einblenden translateY 8px → 0 mit Deckkraft 0 → 1",
   "segment": "zwei gleich breite Felder, Pille translate 0 → 100 %, 3px Innenabstand",
   "vergangen": "Tagesblock kompakt (eine Zeile, Datum 1.5rem), Text #6b6862 statt Deckkraft, Chip color-mix(Spartenfarbe 50 %, #6b6862); im Monat Zelle Text #6b6862, Farbbalken Deckkraft .5",
   "ausverkauft": "Liste: Feld „Ausverkauft“ mit 45°-Schraffur und gestricheltem Rand plus Knopf „Auf die Warteliste“; Monat: Farbbalken gestrichelt (3px/2px) und „· ausverkauft“ hinter der Uhrzeit",
   "monatsraster": "7 Spalten, Montag zuerst, Zeilen minmax(104px, auto); Telefon 58px mit Punkten 7px statt Titeln",
   "linien": "@supports (row-rule: 1px solid): column-rule und row-rule 1px rgba(11,11,11,.16), rule-break: intersection, rule-inset-junction 5px; sonst gap 1px auf Linienfarbe",
   "ics": "VCALENDAR 2.0, PRODID, METHOD:PUBLISH, VTIMEZONE Europe/Berlin (CET/CEST mit RRULE), je Termin UID, DTSTAMP (UTC), DTSTART/DTEND;TZID=Europe/Berlin, SUMMARY, LOCATION, DESCRIPTION, CATEGORIES, URL; Maskierung von \\ ; , und Zeilenumbruch; Faltung nach 75 Oktetten; CRLF; Blob text/calendar;charset=utf-8 + <a download>",
   "farben": "Grund #efede9, Fläche #e4e1db, Tinte #0b0b0b, leise #55524c; Musik #c4421a, Bühne #3d5f9a, Kunst #2f7d4a, Film #b0186b (immer weiße Schrift auf Farbfläche plus Text-Label)",
   "schriften": "Schibsted Grotesk 850 (h1 clamp(2.75rem, 7vw, 7rem), -0.02em), Atkinson Hyperlegible Next (Text 1.0625–1.125rem), IBM Plex Mono 400/500 für Datum, Uhrzeit, Labels (tabular-nums)",
   "demo_stand": "fest Di 10.11.2026, 17:00 (im Einsatz new Date())",
   "vorfuehrung": "Zeiger 620 ms gleiche Kurve; Musik filtern, In Kalender, Monat, Film dazu, Tag 14. wählen, Filter auf Kunst, Dezember (Leerzustand); Schleife"
  },
  "ausloeser": "klick",
  "touch": "Rubriken als waagerecht wischbare Leiste mit 44px hohen Schaltern. Monat wird zur Punkt-Übersicht (ein Quadrat je Termin in Spartenfarbe); Antippen eines Tages zeigt dessen Termine darunter. Vergangene Termine einzeilig ohne Aktionen. Hover-Farben entfallen.",
  "reduziert": "Kein Einblenden der Liste, kein Gleiten der Segment-Pille, Toast nur mit Deckkraft in 150 ms, Zeiger der Vorführung springt. Alle Zustände bleiben gleich.",
  "korrekturen": {
   "beschreibung": "Das Programm eines Hauses als eine Sektion mit zwei Ansichten: eine Liste nach Datum zum Überfliegen und eine Monatsansicht zum Planen. Ein Umschalter wechselt die Ansicht, Rubrik-Filter wirken in beiden. Jeder Termin zeigt Datum, Uhrzeit, Ort, Rubrik als Text und Farbe, Preis und Ticket-Status. „In Kalender“ erzeugt im Browser eine echte .ics-Datei und lädt sie herunter. Vergangene Termine bleiben sichtbar, aber gedimmt und einzeilig. Ausverkaufte Termine sind als Text gekennzeichnet und bieten die Warteliste an. Ist ein Filter leer, zeigt die Sektion einen Ausweg statt einer leeren Fläche.",
   "warum_es_wirkt": "Besucher suchen zuerst Datum, Uhrzeit und Ticket, erst dann das Bild. Die Liste beantwortet „Was läuft bald?“, der Monat „Was passt in meine Woche?“. Ein gemeinsamer Filter für beide Ansichten spart Wege. Der Kalender-Export macht aus Interesse einen festen Termin.",
   "wann_einsetzen": "Kulturhaus, Kunsthalle, Festival, Theater, Kino, Kursanbieter mit festen Terminen, Restaurant oder Hotel mit Veranstaltungen. Ab etwa acht Terminen im Monat.",
   "wann_nicht": "Bei zwei oder drei Terminen im Jahr reicht eine einfache Liste. Liefert das Ticketsystem (Spektrix, Enviso u. a.) eine eigene Programmseite, die Sektion nur als Teaser bauen und dorthin verlinken. Dauerangebote (Ausstellung täglich geöffnet) gehören nicht als Einzeltermine in den Monat.",
   "varianten": [
    "Liste und Monat mit Umschalter, Filter nach Rubrik (Programmseite eines Hauses)",
    "Tagesleiste: Tage als Reiter, darunter die Termine des Tages (Festival, Kino, Messe)",
    "Teaser „Nächste Termine“ mit drei Karten und Link zum Programm (Startseite)",
    "Kursprogramm mit freien Plätzen und Warteliste statt Ticketpreis"
   ],
   "umsetzung": "Daten als Liste von Terminen (id, tag, zeit, dauer, rubrik, titel, ort, preis, status). Ein Filterzustand, je Ansicht eine Render-Funktion. Kalenderrechnung in UTC (Date.UTC), damit die Zeitzone des Geräts keine Tage verschiebt; Anzeige mit Intl.DateTimeFormat('de-DE', { timeZone: 'UTC' }).\n\nListe: <ol> der Tage, je Tag eine <ol> der Termine. Datum und Uhrzeit in Mono mit tabular-nums. Vergangene Tage kompakt und gedimmt, „Heute“ als Marke.\n\nMonat: <ol> mit 7 Spalten, Montag zuerst, Tage mit Terminen als <button aria-pressed> mit vollständigem Datum im zugänglichen Namen. Darunter die Termine des gewählten Tages in derselben Darstellung wie die Liste.\n\nLinien: Fallback mit gap: 1px auf Linienfarbe. Verbesserung: @supports (row-rule: 1px solid) { .raster { background: none; column-rule: 1px solid; row-rule: 1px solid; rule-break: intersection; rule-inset-junction: 5px } }. Gap Decorations sind rein dekorativ.\n\nICS: Zeilen mit CRLF, Faltung nach 75 Oktetten (TextEncoder, UTF-8 nie zerteilen), Text maskieren (Backslash, Semikolon, Komma, Zeilenumbruch mit vorangestelltem Backslash), VTIMEZONE für Europe/Berlin mitliefern, DTSTART/DTEND;TZID=Europe/Berlin als Wandzeit, DTSTAMP in UTC, stabile UID. new Blob([text], { type: 'text/calendar;charset=utf-8' }), URL.createObjectURL, <a download>, danach revokeObjectURL. Eine Datei kann mehrere VEVENT enthalten (z. B. „Auswahl in den Kalender“).\n\nIm Einsatz: Jetzt aus new Date() in Europe/Berlin, Programm aus dem CMS oder dem Ticketsystem, Filter und Ansicht in der URL (?rubrik=musik&ansicht=monat), damit Links teilbar sind.",
   "mobil": "Rubriken als wischbare Leiste. Der Monat wird zur Punkt-Übersicht, ein Tipp auf den Tag zeigt die Termine darunter. Vergangene Termine einzeilig. Tagesleiste wischbar mit Scroll-Snap.",
   "reduzierte_bewegung": "Ansichten und Listen erscheinen ohne Einblenden, die Segment-Pille springt. Zustände und Texte bleiben gleich.",
   "barrierefreiheit": "Rubrik nie nur über Farbe: immer ein Text-Label auf weißer Schrift (AA auf jeder Spartenfarbe). Filter als Schalter mit aria-pressed, Anzahl je Rubrik mit Label. Ansicht als Radiogruppe in fieldset mit legend. Trefferzahl und Monatsname in aria-live. Tage im Monat als Knöpfe mit vollständigem Datum und Terminzahl im Namen. „Ausverkauft“, „Vorbei“ und „Heute“ als Text, nicht nur als Dimmen oder Farbe. Der Kalender-Knopf nennt Titel und Datum im zugänglichen Namen. Bei sehr vielen Tagen im Monat roving tabindex mit Pfeiltasten erwägen."
  },
  "geprueft": "02.11.2026",
  "notiz": "Welt: Rezept kultur-programm-haltung, erfundenes Kulturhaus Elbsalon im alten Kesselhaus am Winterhafen, Magdeburg (Adresse und Domain elbsalon.example erfunden). Schibsted Grotesk, Atkinson Hyperlegible Next, IBM Plex Mono, vier Spartenfarben aus dem Rezept. 25 Termine im November und Dezember 2026, Demo-Stand fest auf Di 10.11.2026, 17:00, damit vergangene Termine und „Heute“ stabil bleiben. Zustände: vergangen, heute, wenige Plätze, ausverkauft mit Warteliste, ohne Anmeldung, Leerzustand (Kunst im Dezember) mit Ausweg. ICS ist echt (Blob, RFC 5545 mit VTIMEZONE); in der Vorführung wird nur die Datei erzeugt, nicht heruntergeladen. Ticket und Warteliste sind nicht verbunden (Hinweis im Toast). Monatslinien per Gap Decorations mit Unterbrechung an Kreuzungen, sonst 1px-Lücken. Referenzen: bruecke-museum.de (.ics je Termin), barbican.org.uk, developer.chrome.com, dev.to. AD-Review 02.11.2026: Note 5. Vorspann ohne „Liste und Monat“, weil die Tagesleiste den Umschalter nicht hat. Zugang 02.11.2026: Vergangene Termine über Farbe statt Deckkraft gedämpft (Text #6B6862, 4,7:1; Chip Spartenfarbe 50 % mit #6B6862, Weiß darauf ≥ 5,4:1; Tagesleiste und Monat ebenso), „Wenige Plätze“ #B83E18 (4,8:1), kompakte Titel brechen am Telefon um statt Auslassungspunkten, Knopfrahmen im Kontrastmodus.",
  "varianten": [
   {
    "id": "programm",
    "name": "Liste und Monat",
    "wann": "Programmseite eines Hauses mit vielen Terminen über Wochen (Kulturhaus, Theater, Kursanbieter).",
    "werte": {
     "ansichten": "Liste und Monat mit Segment-Umschalter",
     "start": "Liste, Monat des Demo-Stands"
    }
   },
   {
    "id": "tage",
    "name": "Tagesleiste",
    "wann": "Festival, Kinowoche oder Messe, bei denen Besucher Tag für Tag planen.",
    "werte": {
     "ansichten": "nur Tagesleiste, Segment-Umschalter entfällt",
     "tagesleiste": "Reiter min. 76px breit, Tageszahl Schibsted 800 1.625rem, Punkte 6px je Termin in Spartenfarbe, Scroll-Snap x proximity",
     "start": "heute bzw. nächster Tag mit Terminen"
    }
   }
  ]
 }
}
