<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="de">
	<id>https://www.muenster4you.de/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Maintenance+script</id>
	<title>MediaWiki - Benutzerbeiträge [de]</title>
	<link rel="self" type="application/atom+xml" href="https://www.muenster4you.de/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Maintenance+script"/>
	<link rel="alternate" type="text/html" href="https://www.muenster4you.de/w/index.php?title=Spezial:Beitr%C3%A4ge/Maintenance_script"/>
	<updated>2026-10-28T15:19:10Z</updated>
	<subtitle>Benutzerbeiträge</subtitle>
	<generator>MediaWiki 1.46.2</generator>
	<entry>
		<id>https://www.muenster4you.de/w/index.php?title=Widget:StartseitenBild&amp;diff=1196</id>
		<title>Widget:StartseitenBild</title>
		<link rel="alternate" type="text/html" href="https://www.muenster4you.de/w/index.php?title=Widget:StartseitenBild&amp;diff=1196"/>
		<updated>2026-10-28T10:20:37Z</updated>

		<summary type="html">&lt;p&gt;Maintenance script: Sicherheitskorrektur bei Widget-Wiederherstellung: URL- und HTML-Kontexte&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;&lt;br /&gt;
&amp;lt;style type=&amp;quot;text/css&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
.fsb-container {&lt;br /&gt;
  position: relative;&lt;br /&gt;
  width: 100%;&lt;br /&gt;
  display: inline-block;&lt;br /&gt;
  background-size: cover;&lt;br /&gt;
  background-position: center;&lt;br /&gt;
  min-height:300px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.fsb-content {&lt;br /&gt;
  position: absolute;&lt;br /&gt;
  top: 50%; /* Position des Widgets */&lt;br /&gt;
  left: 50%;&lt;br /&gt;
  transform: translate(-50%, -50%);&lt;br /&gt;
  color: white; /* Textfarbe: Weiß */&lt;br /&gt;
  background-color: #00308D; /* Hintergrundfarbe: Blau */&lt;br /&gt;
  border-radius: 15px; /* Abgerundete Ecken */&lt;br /&gt;
  padding: 20px;&lt;br /&gt;
  text-align: center;&lt;br /&gt;
  width: 65%; /* Breite des Widgets, kannst du anpassen */&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.fsb-content a {&lt;br /&gt;
  color:white;&lt;br /&gt;
  margin: 10px 0; /* Abstand zwischen den Textabsätzen */&lt;br /&gt;
}&lt;br /&gt;
.fsb-content .headline-text {&lt;br /&gt;
  font-size: 1.5em; /* Größerer Schriftzug */&lt;br /&gt;
  font-weight: bold; /* Dickere Schrift */&lt;br /&gt;
  margin: 10px 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.fsb-container .fsb-image { position:absolute; inset:0; width:100%; height:100%; object-fit:cover; z-index:0; }&lt;br /&gt;
.fsb-container .fsb-content { z-index:1; }&lt;br /&gt;
&amp;lt;/style&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;fsb-container&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;img class=&amp;quot;fsb-image&amp;quot; src=&amp;quot;&amp;lt;!--{$bildUrl|allowedprefixes:&#039;https://,http://,/w/images/&#039;|escape:&#039;html&#039;}--&amp;gt;&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;div class=&amp;quot;fsb-content&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;a href=&amp;quot;&amp;lt;!--{$link|allowedprefixes:&#039;https://,http://,/wiki/,/w/&#039;|escape:&#039;html&#039;}--&amp;gt;&amp;quot; class=&amp;quot;headline-text&amp;quot;&amp;gt;&amp;lt;!--{$text|escape:&#039;html&#039;}--&amp;gt;&amp;lt;/a&amp;gt;&lt;br /&gt;
  &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/includeonly&amp;gt;&lt;/div&gt;</summary>
		<author><name>Maintenance script</name></author>
	</entry>
	<entry>
		<id>https://www.muenster4you.de/w/index.php?title=Widget:StartseitenSuche&amp;diff=1195</id>
		<title>Widget:StartseitenSuche</title>
		<link rel="alternate" type="text/html" href="https://www.muenster4you.de/w/index.php?title=Widget:StartseitenSuche&amp;diff=1195"/>
		<updated>2026-10-28T10:20:36Z</updated>

		<summary type="html">&lt;p&gt;Maintenance script: Sicherheitskorrektur bei Widget-Wiederherstellung: URL- und HTML-Kontexte&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;&lt;br /&gt;
&amp;lt;div id=&amp;quot;chat-widget&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;div id=&amp;quot;chat-messages&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
  &amp;lt;div id=&amp;quot;chat-sources-panel&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
  &amp;lt;form id=&amp;quot;chat-form&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;input type=&amp;quot;text&amp;quot; id=&amp;quot;chat-input&amp;quot; placeholder=&amp;quot;Stelle mir deine Frage …&amp;quot; autocomplete=&amp;quot;off&amp;quot; /&amp;gt;&lt;br /&gt;
    &amp;lt;button type=&amp;quot;submit&amp;quot; id=&amp;quot;chat-send&amp;quot;&amp;gt;Fragen&amp;lt;/button&amp;gt;&lt;br /&gt;
  &amp;lt;/form&amp;gt;&lt;br /&gt;
  &amp;lt;div id=&amp;quot;chat-footer&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;span id=&amp;quot;chat-status&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
    &amp;lt;button id=&amp;quot;chat-new&amp;quot; type=&amp;quot;button&amp;quot;&amp;gt;Neue Unterhaltung&amp;lt;/button&amp;gt;&lt;br /&gt;
  &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;style&amp;gt;&lt;br /&gt;
.overlay-container {&lt;br /&gt;
  position: relative;&lt;br /&gt;
  width: 100%;&lt;br /&gt;
  min-height: 400px;&lt;br /&gt;
  padding: 24px;&lt;br /&gt;
  display: flex;&lt;br /&gt;
  align-items: center;&lt;br /&gt;
  justify-content: center;&lt;br /&gt;
  overflow: hidden;&lt;br /&gt;
  border-radius: 12px;&lt;br /&gt;
  background-color: #2f3e46;&lt;br /&gt;
  background-image: url(&amp;quot;/w/images/a/a9/Schloss-Muenster-Philipp-Foelting-CC-BY-SA.jpg&amp;quot;);&lt;br /&gt;
  background-size: cover;&lt;br /&gt;
  background-position: center;&lt;br /&gt;
  background-repeat: no-repeat;&lt;br /&gt;
  box-sizing: border-box;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.overlay-container::before {&lt;br /&gt;
  content: &amp;quot;&amp;quot;;&lt;br /&gt;
  position: absolute;&lt;br /&gt;
  inset: 0;&lt;br /&gt;
  background: rgba(0, 0, 0, 0.38);&lt;br /&gt;
  z-index: 1;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.overlay-content {&lt;br /&gt;
  position: relative;&lt;br /&gt;
  z-index: 2;&lt;br /&gt;
  width: 100%;&lt;br /&gt;
  max-width: 860px;&lt;br /&gt;
  padding: 0px;&lt;br /&gt;
  border-radius: 12px;&lt;br /&gt;
  background: rgba(255, 255, 255, 0.92);&lt;br /&gt;
  backdrop-filter: blur(4px);&lt;br /&gt;
  -webkit-backdrop-filter: blur(4px);&lt;br /&gt;
  box-sizing: border-box;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#chat-widget {&lt;br /&gt;
  max-width: 800px;&lt;br /&gt;
  margin: 0 auto;&lt;br /&gt;
  font-family: -apple-system, &amp;quot;system-ui&amp;quot;, &amp;quot;Segoe UI&amp;quot;, Roboto, &amp;quot;Helvetica Neue&amp;quot;, Arial, sans-serif;&lt;br /&gt;
  color: #212529;&lt;br /&gt;
  display: flex;&lt;br /&gt;
  flex-direction: column;&lt;br /&gt;
}&lt;br /&gt;
#chat-messages {&lt;br /&gt;
  min-height: 120px;&lt;br /&gt;
  max-height: 500px;&lt;br /&gt;
  overflow-y: auto;&lt;br /&gt;
  padding: 8px 0;&lt;br /&gt;
  display: flex;&lt;br /&gt;
  flex-direction: column;&lt;br /&gt;
  gap: 12px;&lt;br /&gt;
}&lt;br /&gt;
#chat-messages:empty::before {&lt;br /&gt;
  content: &amp;quot;Stelle eine Frage und erhalte Antworten basierend auf dem Münster Wiki und ausgewählten Web-Inhalten für Münster. Beachte: KI-Suche kann Fehler machen. Prüfe deine Ergebnisse sorgfältig. Verwende keine personenbezogenen Daten.&amp;quot;;&lt;br /&gt;
  display: block;&lt;br /&gt;
  text-align: center;&lt;br /&gt;
  color: #999;&lt;br /&gt;
  font-size: 14px;&lt;br /&gt;
  padding: 40px 16px;&lt;br /&gt;
}&lt;br /&gt;
.chat-msg {&lt;br /&gt;
  max-width: 85%;&lt;br /&gt;
  padding: 10px 14px;&lt;br /&gt;
  border-radius: 10px;&lt;br /&gt;
  font-size: 14.5px;&lt;br /&gt;
  line-height: 1.55;&lt;br /&gt;
  word-wrap: break-word;&lt;br /&gt;
}&lt;br /&gt;
.chat-msg-user {&lt;br /&gt;
  align-self: flex-end;&lt;br /&gt;
  background: #00308D;&lt;br /&gt;
  color: #fff;&lt;br /&gt;
  border-bottom-right-radius: 3px;&lt;br /&gt;
}&lt;br /&gt;
.chat-msg-assistant {&lt;br /&gt;
  align-self: flex-start;&lt;br /&gt;
  background: #f0f2f5;&lt;br /&gt;
  color: #212529;&lt;br /&gt;
  border-bottom-left-radius: 3px;&lt;br /&gt;
}&lt;br /&gt;
.chat-msg-assistant p {&lt;br /&gt;
  margin: 0 0 8px 0;&lt;br /&gt;
}&lt;br /&gt;
.chat-msg-assistant p:last-child {&lt;br /&gt;
  margin-bottom: 0;&lt;br /&gt;
}&lt;br /&gt;
@keyframes chatDots {&lt;br /&gt;
  0%, 80%, 100% { opacity: 0.3; }&lt;br /&gt;
  40% { opacity: 1; }&lt;br /&gt;
}&lt;br /&gt;
.chat-loading-dots span {&lt;br /&gt;
  display: inline-block;&lt;br /&gt;
  width: 7px;&lt;br /&gt;
  height: 7px;&lt;br /&gt;
  margin: 0 2px;&lt;br /&gt;
  background: #999;&lt;br /&gt;
  border-radius: 50%;&lt;br /&gt;
  animation: chatDots 1.2s ease-in-out infinite;&lt;br /&gt;
}&lt;br /&gt;
.chat-loading-dots span:nth-child(2) { animation-delay: 0.15s; }&lt;br /&gt;
.chat-loading-dots span:nth-child(3) { animation-delay: 0.3s; }&lt;br /&gt;
#chat-sources-panel {&lt;br /&gt;
  display: none;&lt;br /&gt;
}&lt;br /&gt;
#chat-sources-panel.visible {&lt;br /&gt;
  display: block;&lt;br /&gt;
  margin: 4px 0 8px 0;&lt;br /&gt;
}&lt;br /&gt;
.chat-sources-toggle {&lt;br /&gt;
  background: none;&lt;br /&gt;
  border: 1px solid #ddd;&lt;br /&gt;
  border-radius: 6px;&lt;br /&gt;
  padding: 6px 12px;&lt;br /&gt;
  font-size: 12px;&lt;br /&gt;
  color: #555;&lt;br /&gt;
  cursor: pointer;&lt;br /&gt;
  transition: background 0.15s;&lt;br /&gt;
}&lt;br /&gt;
.chat-sources-toggle:hover {&lt;br /&gt;
  background: #f5f5f5;&lt;br /&gt;
}&lt;br /&gt;
.chat-sources-list {&lt;br /&gt;
  display: none;&lt;br /&gt;
  margin-top: 8px;&lt;br /&gt;
}&lt;br /&gt;
.chat-sources-list.open {&lt;br /&gt;
  display: block;&lt;br /&gt;
}&lt;br /&gt;
.chat-source-item {&lt;br /&gt;
  padding: 10px 12px;&lt;br /&gt;
  margin-bottom: 6px;&lt;br /&gt;
  border: 1px solid #e0e0e0;&lt;br /&gt;
  border-radius: 6px;&lt;br /&gt;
  background: #fff;&lt;br /&gt;
  transition: border-color 0.15s;&lt;br /&gt;
}&lt;br /&gt;
.chat-source-item:hover {&lt;br /&gt;
  border-color: #b0b8c1;&lt;br /&gt;
}&lt;br /&gt;
.chat-source-item h5 {&lt;br /&gt;
  margin: 0 0 3px 0;&lt;br /&gt;
  font-size: 14px;&lt;br /&gt;
  font-weight: 600;&lt;br /&gt;
}&lt;br /&gt;
.chat-source-item h5 a {&lt;br /&gt;
  color: #00308D;&lt;br /&gt;
  text-decoration: none;&lt;br /&gt;
}&lt;br /&gt;
.chat-source-item h5 a:hover {&lt;br /&gt;
  text-decoration: underline;&lt;br /&gt;
}&lt;br /&gt;
.chat-source-item .chat-source-snippet {&lt;br /&gt;
  font-size: 12.5px;&lt;br /&gt;
  line-height: 1.45;&lt;br /&gt;
  color: #666;&lt;br /&gt;
  margin: 0;&lt;br /&gt;
}&lt;br /&gt;
.chat-source-item .chat-source-meta {&lt;br /&gt;
  font-size: 11px;&lt;br /&gt;
  color: #999;&lt;br /&gt;
  margin-top: 3px;&lt;br /&gt;
}&lt;br /&gt;
#chat-form {&lt;br /&gt;
  display: flex;&lt;br /&gt;
  margin-top: 8px;&lt;br /&gt;
}&lt;br /&gt;
#chat-input {&lt;br /&gt;
  flex: 1;&lt;br /&gt;
  padding: 10px 14px;&lt;br /&gt;
  font-size: 15px;&lt;br /&gt;
  border: 1px solid #ccc;&lt;br /&gt;
  border-right: none;&lt;br /&gt;
  border-radius: 4px 0 0 4px;&lt;br /&gt;
  outline: none;&lt;br /&gt;
  transition: border-color 0.2s;&lt;br /&gt;
  color: #212529;&lt;br /&gt;
  background: #fff;&lt;br /&gt;
}&lt;br /&gt;
#chat-input:focus {&lt;br /&gt;
  border-color: #4CAF50;&lt;br /&gt;
}&lt;br /&gt;
#chat-input:disabled {&lt;br /&gt;
  background: #f5f5f5;&lt;br /&gt;
  color: #999;&lt;br /&gt;
}&lt;br /&gt;
#chat-send {&lt;br /&gt;
  padding: 10px 20px;&lt;br /&gt;
  font-size: 15px;&lt;br /&gt;
  font-weight: 500;&lt;br /&gt;
  cursor: pointer;&lt;br /&gt;
  background: #4CAF50;&lt;br /&gt;
  color: #fff;&lt;br /&gt;
  border: none;&lt;br /&gt;
  border-radius: 0 4px 4px 0;&lt;br /&gt;
  transition: background 0.2s;&lt;br /&gt;
  white-space: nowrap;&lt;br /&gt;
}&lt;br /&gt;
#chat-send:hover {&lt;br /&gt;
  background: #43A047;&lt;br /&gt;
}&lt;br /&gt;
#chat-send:disabled {&lt;br /&gt;
  background: #a5d6a7;&lt;br /&gt;
  cursor: not-allowed;&lt;br /&gt;
}&lt;br /&gt;
#chat-footer {&lt;br /&gt;
  display: flex;&lt;br /&gt;
  align-items: center;&lt;br /&gt;
  justify-content: space-between;&lt;br /&gt;
  margin-top: 8px;&lt;br /&gt;
  min-height: 28px;&lt;br /&gt;
}&lt;br /&gt;
#chat-status {&lt;br /&gt;
  font-size: 12px;&lt;br /&gt;
  color: #888;&lt;br /&gt;
}&lt;br /&gt;
#chat-new {&lt;br /&gt;
  display: none;&lt;br /&gt;
  background: none;&lt;br /&gt;
  border: 1px solid #ccc;&lt;br /&gt;
  border-radius: 4px;&lt;br /&gt;
  padding: 4px 12px;&lt;br /&gt;
  font-size: 12px;&lt;br /&gt;
  color: #555;&lt;br /&gt;
  cursor: pointer;&lt;br /&gt;
  transition: background 0.15s;&lt;br /&gt;
}&lt;br /&gt;
#chat-new:hover {&lt;br /&gt;
  background: #f5f5f5;&lt;br /&gt;
}&lt;br /&gt;
#chat-new.visible {&lt;br /&gt;
  display: inline-block;&lt;br /&gt;
}&lt;br /&gt;
.chat-msg-error {&lt;br /&gt;
  align-self: center;&lt;br /&gt;
  background: #fef2f2;&lt;br /&gt;
  color: #b00;&lt;br /&gt;
  border: 1px solid #fca5a5;&lt;br /&gt;
  font-size: 13px;&lt;br /&gt;
  padding: 8px 14px;&lt;br /&gt;
  border-radius: 6px;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/style&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;script&amp;gt;&lt;br /&gt;
(function() {&lt;br /&gt;
  var form = document.getElementById(&#039;chat-form&#039;);&lt;br /&gt;
  var input = document.getElementById(&#039;chat-input&#039;);&lt;br /&gt;
  var sendBtn = document.getElementById(&#039;chat-send&#039;);&lt;br /&gt;
  var messagesEl = document.getElementById(&#039;chat-messages&#039;);&lt;br /&gt;
  var sourcesPanel = document.getElementById(&#039;chat-sources-panel&#039;);&lt;br /&gt;
  var statusEl = document.getElementById(&#039;chat-status&#039;);&lt;br /&gt;
  var newBtn = document.getElementById(&#039;chat-new&#039;);&lt;br /&gt;
  var apiHost = &#039;api.&#039; + location.hostname.split(&#039;.&#039;).slice(1).join(&#039;.&#039;);&lt;br /&gt;
&lt;br /&gt;
  var conversationId = null;&lt;br /&gt;
  var isLoading = false;&lt;br /&gt;
&lt;br /&gt;
  function escapeHtml(str) {&lt;br /&gt;
    var d = document.createElement(&#039;div&#039;);&lt;br /&gt;
    d.textContent = str;&lt;br /&gt;
    return d.innerHTML.replace(/&amp;quot;/g, &amp;quot;&amp;amp;quot;&amp;quot;).replace(/&#039;/g, &amp;quot;&amp;amp;#39;&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function truncate(str, len) {&lt;br /&gt;
    if (str.length &amp;lt;= len) return str;&lt;br /&gt;
    return str.substring(0, len).replace(/\s+\S*$/, &#039;&#039;) + &#039;\u2026&#039;;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function formatAnswer(text) {&lt;br /&gt;
    var html = escapeHtml(text);&lt;br /&gt;
    html = html.replace(/\*\*(.+?)\*\*/g, &#039;&amp;lt;strong&amp;gt;$1&amp;lt;/strong&amp;gt;&#039;);&lt;br /&gt;
    var paragraphs = html.split(/\n{2,}/);&lt;br /&gt;
    if (paragraphs.length &amp;gt; 1) {&lt;br /&gt;
      html = paragraphs.map(function(p) { return &#039;&amp;lt;p&amp;gt;&#039; + p.replace(/\n/g, &#039;&amp;lt;br&amp;gt;&#039;) + &#039;&amp;lt;/p&amp;gt;&#039;; }).join(&#039;&#039;);&lt;br /&gt;
    } else {&lt;br /&gt;
      html = html.replace(/\n/g, &#039;&amp;lt;br&amp;gt;&#039;);&lt;br /&gt;
    }&lt;br /&gt;
    return html;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function addUserMessage(text) {&lt;br /&gt;
    var div = document.createElement(&#039;div&#039;);&lt;br /&gt;
    div.className = &#039;chat-msg chat-msg-user&#039;;&lt;br /&gt;
    div.textContent = text;&lt;br /&gt;
    messagesEl.appendChild(div);&lt;br /&gt;
    scrollToBottom();&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function addAssistantMessage(text) {&lt;br /&gt;
    var div = document.createElement(&#039;div&#039;);&lt;br /&gt;
    div.className = &#039;chat-msg chat-msg-assistant&#039;;&lt;br /&gt;
    div.innerHTML = formatAnswer(text);&lt;br /&gt;
    messagesEl.appendChild(div);&lt;br /&gt;
    scrollToBottom();&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function addLoadingIndicator() {&lt;br /&gt;
    var div = document.createElement(&#039;div&#039;);&lt;br /&gt;
    div.className = &#039;chat-msg chat-msg-assistant chat-loading-dots&#039;;&lt;br /&gt;
    div.id = &#039;chat-loading&#039;;&lt;br /&gt;
    div.innerHTML = &#039;&amp;lt;span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt;&amp;lt;/span&amp;gt;&#039;;&lt;br /&gt;
    messagesEl.appendChild(div);&lt;br /&gt;
    scrollToBottom();&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function removeLoadingIndicator() {&lt;br /&gt;
    var el = document.getElementById(&#039;chat-loading&#039;);&lt;br /&gt;
    if (el) el.remove();&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function addError(msg) {&lt;br /&gt;
    var div = document.createElement(&#039;div&#039;);&lt;br /&gt;
    div.className = &#039;chat-msg chat-msg-error&#039;;&lt;br /&gt;
    div.textContent = msg;&lt;br /&gt;
    messagesEl.appendChild(div);&lt;br /&gt;
    scrollToBottom();&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function scrollToBottom() {&lt;br /&gt;
    messagesEl.scrollTop = messagesEl.scrollHeight;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function renderSources(sources) {&lt;br /&gt;
    if (!sources || sources.length === 0) {&lt;br /&gt;
      sourcesPanel.className = &#039;&#039;;&lt;br /&gt;
      sourcesPanel.innerHTML = &#039;&#039;;&lt;br /&gt;
      return;&lt;br /&gt;
    }&lt;br /&gt;
    sourcesPanel.className = &#039;visible&#039;;&lt;br /&gt;
    var listId = &#039;src-list-&#039; + Date.now();&lt;br /&gt;
    var html = &#039;&amp;lt;button class=&amp;quot;chat-sources-toggle&amp;quot; onclick=&amp;quot;var l=document.getElementById(\&#039;&#039; + listId + &#039;\&#039;);l.classList.toggle(\&#039;open\&#039;);this.textContent=l.classList.contains(\&#039;open\&#039;)?\&#039;▲ Quellen verbergen\&#039;:\&#039;▼ &#039; + sources.length + &#039; Quellen anzeigen\&#039;&amp;quot;&amp;gt;&#039;&lt;br /&gt;
      + &#039;▼ &#039; + sources.length + &#039; Quellen anzeigen&amp;lt;/button&amp;gt;&#039;;&lt;br /&gt;
    html += &#039;&amp;lt;div class=&amp;quot;chat-sources-list&amp;quot; id=&amp;quot;&#039; + listId + &#039;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
    sources.forEach(function(s) {&lt;br /&gt;
      var pct = Math.round((s.score || 0) * 100);&lt;br /&gt;
      var url = s.url || &#039;&#039;;&lt;br /&gt;
      try {&lt;br /&gt;
        var parsedSourceUrl = new URL(url, location.origin);&lt;br /&gt;
        if (parsedSourceUrl.protocol !== &#039;https:&#039; &amp;amp;&amp;amp; parsedSourceUrl.protocol !== &#039;http:&#039;) url = &#039;#&#039;;&lt;br /&gt;
      } catch (invalidSourceUrl) { url = &#039;#&#039;; }&lt;br /&gt;
      var title = &#039;&#039;;&lt;br /&gt;
      if (url) {&lt;br /&gt;
        var seg = url.split(&#039;/&#039;).pop();&lt;br /&gt;
        try { seg = decodeURIComponent(seg); } catch (e) {}&lt;br /&gt;
        title = seg.replace(/_/g, &#039; &#039;);&lt;br /&gt;
      }&lt;br /&gt;
      html += &#039;&amp;lt;div class=&amp;quot;chat-source-item&amp;quot;&amp;gt;&#039;&lt;br /&gt;
        + &#039;&amp;lt;h5&amp;gt;&amp;lt;a href=&amp;quot;&#039; + escapeHtml(url) + &#039;&amp;quot;&amp;gt;&#039; + escapeHtml(title) + &#039;&amp;lt;/a&amp;gt;&amp;lt;/h5&amp;gt;&#039;&lt;br /&gt;
        + &#039;&amp;lt;p class=&amp;quot;chat-source-snippet&amp;quot;&amp;gt;&#039; + escapeHtml(truncate(s.content || &#039;&#039;, 150)) + &#039;&amp;lt;/p&amp;gt;&#039;&lt;br /&gt;
        + &#039;&amp;lt;div class=&amp;quot;chat-source-meta&amp;quot;&amp;gt;Relevanz: &#039; + pct + &#039;% · &#039; + escapeHtml(s.source || &#039;&#039;) + &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
        + &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
    });&lt;br /&gt;
    html += &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
    sourcesPanel.innerHTML = html;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function setLoading(loading) {&lt;br /&gt;
    isLoading = loading;&lt;br /&gt;
    input.disabled = loading;&lt;br /&gt;
    sendBtn.disabled = loading;&lt;br /&gt;
    if (loading) {&lt;br /&gt;
      addLoadingIndicator();&lt;br /&gt;
    } else {&lt;br /&gt;
      removeLoadingIndicator();&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function updateStatus(remaining) {&lt;br /&gt;
    if (remaining &amp;gt; 0) {&lt;br /&gt;
      statusEl.textContent = remaining + &#039; R\u00fcckfrage&#039; + (remaining !== 1 ? &#039;n&#039; : &#039;&#039;) + &#039; verbleibend&#039;;&lt;br /&gt;
    } else if (remaining === 0) { if (conversationId) {&lt;br /&gt;
      statusEl.textContent = &#039;Keine R\u00fcckfragen mehr m\u00f6glich&#039;;&lt;br /&gt;
      input.disabled = true;&lt;br /&gt;
      sendBtn.disabled = true;&lt;br /&gt;
      input.placeholder = &#039;Starte eine neue Unterhaltung&#039;;&lt;br /&gt;
    } }&lt;br /&gt;
    newBtn.className = conversationId ? &#039;visible&#039; : &#039;&#039;;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function resetConversation() {&lt;br /&gt;
    conversationId = null;&lt;br /&gt;
    messagesEl.innerHTML = &#039;&#039;;&lt;br /&gt;
    sourcesPanel.className = &#039;&#039;;&lt;br /&gt;
    sourcesPanel.innerHTML = &#039;&#039;;&lt;br /&gt;
    statusEl.textContent = &#039;&#039;;&lt;br /&gt;
    newBtn.className = &#039;&#039;;&lt;br /&gt;
    input.disabled = false;&lt;br /&gt;
    sendBtn.disabled = false;&lt;br /&gt;
    input.placeholder = &#039;Stelle eine Frage \u00fcber M\u00fcnster \u2026&#039;;&lt;br /&gt;
    input.focus();&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  newBtn.addEventListener(&#039;click&#039;, resetConversation);&lt;br /&gt;
&lt;br /&gt;
  form.addEventListener(&#039;submit&#039;, function(e) {&lt;br /&gt;
    e.preventDefault();&lt;br /&gt;
    if (isLoading) return;&lt;br /&gt;
    var message = input.value.trim();&lt;br /&gt;
    if (!message) return;&lt;br /&gt;
&lt;br /&gt;
    input.value = &#039;&#039;;&lt;br /&gt;
    addUserMessage(message);&lt;br /&gt;
    setLoading(true);&lt;br /&gt;
&lt;br /&gt;
    var body = { message: message };&lt;br /&gt;
    if (conversationId) {&lt;br /&gt;
      body.conversation_id = conversationId;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    var url = location.protocol + &#039;//&#039; + apiHost + &#039;/chat&#039;;&lt;br /&gt;
&lt;br /&gt;
    fetch(url, {&lt;br /&gt;
      method: &#039;POST&#039;,&lt;br /&gt;
      headers: { &#039;Content-Type&#039;: &#039;application/json&#039; },&lt;br /&gt;
      body: JSON.stringify(body)&lt;br /&gt;
    })&lt;br /&gt;
      .then(function(res) {&lt;br /&gt;
        if (!res.ok) {&lt;br /&gt;
          return res.json().then(function(data) {&lt;br /&gt;
            throw new Error(data.detail || &#039;HTTP &#039; + res.status);&lt;br /&gt;
          });&lt;br /&gt;
        }&lt;br /&gt;
        return res.json();&lt;br /&gt;
      })&lt;br /&gt;
      .then(function(data) {&lt;br /&gt;
        setLoading(false);&lt;br /&gt;
        conversationId = data.conversation_id;&lt;br /&gt;
        addAssistantMessage(data.answer);&lt;br /&gt;
        renderSources(data.sources);&lt;br /&gt;
        updateStatus(data.remaining_followups);&lt;br /&gt;
        input.focus();&lt;br /&gt;
      })&lt;br /&gt;
      .catch(function(err) {&lt;br /&gt;
        setLoading(false);&lt;br /&gt;
        addError(&#039;Fehler: &#039; + err.message);&lt;br /&gt;
        input.focus();&lt;br /&gt;
      });&lt;br /&gt;
  });&lt;br /&gt;
})();&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;/includeonly&amp;gt;&lt;/div&gt;</summary>
		<author><name>Maintenance script</name></author>
	</entry>
	<entry>
		<id>https://www.muenster4you.de/w/index.php?title=Widget:ChatBox&amp;diff=1194</id>
		<title>Widget:ChatBox</title>
		<link rel="alternate" type="text/html" href="https://www.muenster4you.de/w/index.php?title=Widget:ChatBox&amp;diff=1194"/>
		<updated>2026-10-28T10:20:36Z</updated>

		<summary type="html">&lt;p&gt;Maintenance script: Sicherheitskorrektur bei Widget-Wiederherstellung: URL- und HTML-Kontexte&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;&lt;br /&gt;
&amp;lt;div id=&amp;quot;chat-widget&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;div id=&amp;quot;chat-messages&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
  &amp;lt;div id=&amp;quot;chat-sources-panel&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
  &amp;lt;form id=&amp;quot;chat-form&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;input type=&amp;quot;text&amp;quot; id=&amp;quot;chat-input&amp;quot; placeholder=&amp;quot;Stelle eine Frage über Münster …&amp;quot; autocomplete=&amp;quot;off&amp;quot; /&amp;gt;&lt;br /&gt;
    &amp;lt;button type=&amp;quot;submit&amp;quot; id=&amp;quot;chat-send&amp;quot;&amp;gt;Fragen&amp;lt;/button&amp;gt;&lt;br /&gt;
  &amp;lt;/form&amp;gt;&lt;br /&gt;
  &amp;lt;div id=&amp;quot;chat-footer&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;span id=&amp;quot;chat-status&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
    &amp;lt;button id=&amp;quot;chat-new&amp;quot; type=&amp;quot;button&amp;quot;&amp;gt;Neue Unterhaltung&amp;lt;/button&amp;gt;&lt;br /&gt;
  &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;style&amp;gt;&lt;br /&gt;
#chat-widget {&lt;br /&gt;
  max-width: 800px;&lt;br /&gt;
  margin: 0 auto;&lt;br /&gt;
  font-family: -apple-system, &amp;quot;system-ui&amp;quot;, &amp;quot;Segoe UI&amp;quot;, Roboto, &amp;quot;Helvetica Neue&amp;quot;, Arial, sans-serif;&lt;br /&gt;
  color: #212529;&lt;br /&gt;
  display: flex;&lt;br /&gt;
  flex-direction: column;&lt;br /&gt;
}&lt;br /&gt;
#chat-messages {&lt;br /&gt;
  min-height: 120px;&lt;br /&gt;
  max-height: 500px;&lt;br /&gt;
  overflow-y: auto;&lt;br /&gt;
  padding: 8px 0;&lt;br /&gt;
  display: flex;&lt;br /&gt;
  flex-direction: column;&lt;br /&gt;
  gap: 12px;&lt;br /&gt;
}&lt;br /&gt;
#chat-messages:empty::before {&lt;br /&gt;
  content: &amp;quot;Stelle eine Frage und erhalte Antworten basierend auf dem Münster Wiki und ausgewählten Web-Inhalten für Münster. Beachte: KI-Suche kann Fehler machen. Prüfe deine Ergebnisse sorgfältig. Verwende keine personenbezogenen Daten.&amp;quot;;&lt;br /&gt;
  display: block;&lt;br /&gt;
  text-align: center;&lt;br /&gt;
  color: #999;&lt;br /&gt;
  font-size: 14px;&lt;br /&gt;
  padding: 40px 16px;&lt;br /&gt;
}&lt;br /&gt;
.chat-msg {&lt;br /&gt;
  max-width: 85%;&lt;br /&gt;
  padding: 10px 14px;&lt;br /&gt;
  border-radius: 10px;&lt;br /&gt;
  font-size: 14.5px;&lt;br /&gt;
  line-height: 1.55;&lt;br /&gt;
  word-wrap: break-word;&lt;br /&gt;
}&lt;br /&gt;
.chat-msg-user {&lt;br /&gt;
  align-self: flex-end;&lt;br /&gt;
  background: #00308D;&lt;br /&gt;
  color: #fff;&lt;br /&gt;
  border-bottom-right-radius: 3px;&lt;br /&gt;
}&lt;br /&gt;
.chat-msg-assistant {&lt;br /&gt;
  align-self: flex-start;&lt;br /&gt;
  background: #f0f2f5;&lt;br /&gt;
  color: #212529;&lt;br /&gt;
  border-bottom-left-radius: 3px;&lt;br /&gt;
}&lt;br /&gt;
.chat-msg-assistant p {&lt;br /&gt;
  margin: 0 0 8px 0;&lt;br /&gt;
}&lt;br /&gt;
.chat-msg-assistant p:last-child {&lt;br /&gt;
  margin-bottom: 0;&lt;br /&gt;
}&lt;br /&gt;
@keyframes chatDots {&lt;br /&gt;
  0%, 80%, 100% { opacity: 0.3; }&lt;br /&gt;
  40% { opacity: 1; }&lt;br /&gt;
}&lt;br /&gt;
.chat-loading-dots span {&lt;br /&gt;
  display: inline-block;&lt;br /&gt;
  width: 7px;&lt;br /&gt;
  height: 7px;&lt;br /&gt;
  margin: 0 2px;&lt;br /&gt;
  background: #999;&lt;br /&gt;
  border-radius: 50%;&lt;br /&gt;
  animation: chatDots 1.2s ease-in-out infinite;&lt;br /&gt;
}&lt;br /&gt;
.chat-loading-dots span:nth-child(2) { animation-delay: 0.15s; }&lt;br /&gt;
.chat-loading-dots span:nth-child(3) { animation-delay: 0.3s; }&lt;br /&gt;
#chat-sources-panel {&lt;br /&gt;
  display: none;&lt;br /&gt;
}&lt;br /&gt;
#chat-sources-panel.visible {&lt;br /&gt;
  display: block;&lt;br /&gt;
  margin: 4px 0 8px 0;&lt;br /&gt;
}&lt;br /&gt;
.chat-sources-toggle {&lt;br /&gt;
  background: none;&lt;br /&gt;
  border: 1px solid #ddd;&lt;br /&gt;
  border-radius: 6px;&lt;br /&gt;
  padding: 6px 12px;&lt;br /&gt;
  font-size: 12px;&lt;br /&gt;
  color: #555;&lt;br /&gt;
  cursor: pointer;&lt;br /&gt;
  transition: background 0.15s;&lt;br /&gt;
}&lt;br /&gt;
.chat-sources-toggle:hover {&lt;br /&gt;
  background: #f5f5f5;&lt;br /&gt;
}&lt;br /&gt;
.chat-sources-list {&lt;br /&gt;
  display: none;&lt;br /&gt;
  margin-top: 8px;&lt;br /&gt;
}&lt;br /&gt;
.chat-sources-list.open {&lt;br /&gt;
  display: block;&lt;br /&gt;
}&lt;br /&gt;
.chat-source-item {&lt;br /&gt;
  padding: 10px 12px;&lt;br /&gt;
  margin-bottom: 6px;&lt;br /&gt;
  border: 1px solid #e0e0e0;&lt;br /&gt;
  border-radius: 6px;&lt;br /&gt;
  background: #fff;&lt;br /&gt;
  transition: border-color 0.15s;&lt;br /&gt;
}&lt;br /&gt;
.chat-source-item:hover {&lt;br /&gt;
  border-color: #b0b8c1;&lt;br /&gt;
}&lt;br /&gt;
.chat-source-item h5 {&lt;br /&gt;
  margin: 0 0 3px 0;&lt;br /&gt;
  font-size: 14px;&lt;br /&gt;
  font-weight: 600;&lt;br /&gt;
}&lt;br /&gt;
.chat-source-item h5 a {&lt;br /&gt;
  color: #00308D;&lt;br /&gt;
  text-decoration: none;&lt;br /&gt;
}&lt;br /&gt;
.chat-source-item h5 a:hover {&lt;br /&gt;
  text-decoration: underline;&lt;br /&gt;
}&lt;br /&gt;
.chat-source-item .chat-source-snippet {&lt;br /&gt;
  font-size: 12.5px;&lt;br /&gt;
  line-height: 1.45;&lt;br /&gt;
  color: #666;&lt;br /&gt;
  margin: 0;&lt;br /&gt;
}&lt;br /&gt;
.chat-source-item .chat-source-meta {&lt;br /&gt;
  font-size: 11px;&lt;br /&gt;
  color: #999;&lt;br /&gt;
  margin-top: 3px;&lt;br /&gt;
}&lt;br /&gt;
#chat-form {&lt;br /&gt;
  display: flex;&lt;br /&gt;
  margin-top: 8px;&lt;br /&gt;
}&lt;br /&gt;
#chat-input {&lt;br /&gt;
  flex: 1;&lt;br /&gt;
  padding: 10px 14px;&lt;br /&gt;
  font-size: 15px;&lt;br /&gt;
  border: 1px solid #ccc;&lt;br /&gt;
  border-right: none;&lt;br /&gt;
  border-radius: 4px 0 0 4px;&lt;br /&gt;
  outline: none;&lt;br /&gt;
  transition: border-color 0.2s;&lt;br /&gt;
  color: #212529;&lt;br /&gt;
  background: #fff;&lt;br /&gt;
}&lt;br /&gt;
#chat-input:focus {&lt;br /&gt;
  border-color: #4CAF50;&lt;br /&gt;
}&lt;br /&gt;
#chat-input:disabled {&lt;br /&gt;
  background: #f5f5f5;&lt;br /&gt;
  color: #999;&lt;br /&gt;
}&lt;br /&gt;
#chat-send {&lt;br /&gt;
  padding: 10px 20px;&lt;br /&gt;
  font-size: 15px;&lt;br /&gt;
  font-weight: 500;&lt;br /&gt;
  cursor: pointer;&lt;br /&gt;
  background: #4CAF50;&lt;br /&gt;
  color: #fff;&lt;br /&gt;
  border: none;&lt;br /&gt;
  border-radius: 0 4px 4px 0;&lt;br /&gt;
  transition: background 0.2s;&lt;br /&gt;
  white-space: nowrap;&lt;br /&gt;
}&lt;br /&gt;
#chat-send:hover {&lt;br /&gt;
  background: #43A047;&lt;br /&gt;
}&lt;br /&gt;
#chat-send:disabled {&lt;br /&gt;
  background: #a5d6a7;&lt;br /&gt;
  cursor: not-allowed;&lt;br /&gt;
}&lt;br /&gt;
#chat-footer {&lt;br /&gt;
  display: flex;&lt;br /&gt;
  align-items: center;&lt;br /&gt;
  justify-content: space-between;&lt;br /&gt;
  margin-top: 8px;&lt;br /&gt;
  min-height: 28px;&lt;br /&gt;
}&lt;br /&gt;
#chat-status {&lt;br /&gt;
  font-size: 12px;&lt;br /&gt;
  color: #888;&lt;br /&gt;
}&lt;br /&gt;
#chat-new {&lt;br /&gt;
  display: none;&lt;br /&gt;
  background: none;&lt;br /&gt;
  border: 1px solid #ccc;&lt;br /&gt;
  border-radius: 4px;&lt;br /&gt;
  padding: 4px 12px;&lt;br /&gt;
  font-size: 12px;&lt;br /&gt;
  color: #555;&lt;br /&gt;
  cursor: pointer;&lt;br /&gt;
  transition: background 0.15s;&lt;br /&gt;
}&lt;br /&gt;
#chat-new:hover {&lt;br /&gt;
  background: #f5f5f5;&lt;br /&gt;
}&lt;br /&gt;
#chat-new.visible {&lt;br /&gt;
  display: inline-block;&lt;br /&gt;
}&lt;br /&gt;
.chat-msg-error {&lt;br /&gt;
  align-self: center;&lt;br /&gt;
  background: #fef2f2;&lt;br /&gt;
  color: #b00;&lt;br /&gt;
  border: 1px solid #fca5a5;&lt;br /&gt;
  font-size: 13px;&lt;br /&gt;
  padding: 8px 14px;&lt;br /&gt;
  border-radius: 6px;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/style&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;script&amp;gt;&lt;br /&gt;
(function() {&lt;br /&gt;
  var form = document.getElementById(&#039;chat-form&#039;);&lt;br /&gt;
  var input = document.getElementById(&#039;chat-input&#039;);&lt;br /&gt;
  var sendBtn = document.getElementById(&#039;chat-send&#039;);&lt;br /&gt;
  var messagesEl = document.getElementById(&#039;chat-messages&#039;);&lt;br /&gt;
  var sourcesPanel = document.getElementById(&#039;chat-sources-panel&#039;);&lt;br /&gt;
  var statusEl = document.getElementById(&#039;chat-status&#039;);&lt;br /&gt;
  var newBtn = document.getElementById(&#039;chat-new&#039;);&lt;br /&gt;
  var apiHost = &#039;api.&#039; + location.hostname.split(&#039;.&#039;).slice(1).join(&#039;.&#039;);&lt;br /&gt;
&lt;br /&gt;
  var conversationId = null;&lt;br /&gt;
  var isLoading = false;&lt;br /&gt;
&lt;br /&gt;
  function escapeHtml(str) {&lt;br /&gt;
    var d = document.createElement(&#039;div&#039;);&lt;br /&gt;
    d.textContent = str;&lt;br /&gt;
    return d.innerHTML.replace(/&amp;quot;/g, &amp;quot;&amp;amp;quot;&amp;quot;).replace(/&#039;/g, &amp;quot;&amp;amp;#39;&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function truncate(str, len) {&lt;br /&gt;
    if (str.length &amp;lt;= len) return str;&lt;br /&gt;
    return str.substring(0, len).replace(/\s+\S*$/, &#039;&#039;) + &#039;\u2026&#039;;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function formatAnswer(text) {&lt;br /&gt;
    var html = escapeHtml(text);&lt;br /&gt;
    html = html.replace(/\*\*(.+?)\*\*/g, &#039;&amp;lt;strong&amp;gt;$1&amp;lt;/strong&amp;gt;&#039;);&lt;br /&gt;
    var paragraphs = html.split(/\n{2,}/);&lt;br /&gt;
    if (paragraphs.length &amp;gt; 1) {&lt;br /&gt;
      html = paragraphs.map(function(p) { return &#039;&amp;lt;p&amp;gt;&#039; + p.replace(/\n/g, &#039;&amp;lt;br&amp;gt;&#039;) + &#039;&amp;lt;/p&amp;gt;&#039;; }).join(&#039;&#039;);&lt;br /&gt;
    } else {&lt;br /&gt;
      html = html.replace(/\n/g, &#039;&amp;lt;br&amp;gt;&#039;);&lt;br /&gt;
    }&lt;br /&gt;
    return html;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function addUserMessage(text) {&lt;br /&gt;
    var div = document.createElement(&#039;div&#039;);&lt;br /&gt;
    div.className = &#039;chat-msg chat-msg-user&#039;;&lt;br /&gt;
    div.textContent = text;&lt;br /&gt;
    messagesEl.appendChild(div);&lt;br /&gt;
    scrollToBottom();&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function addAssistantMessage(text) {&lt;br /&gt;
    var div = document.createElement(&#039;div&#039;);&lt;br /&gt;
    div.className = &#039;chat-msg chat-msg-assistant&#039;;&lt;br /&gt;
    div.innerHTML = formatAnswer(text);&lt;br /&gt;
    messagesEl.appendChild(div);&lt;br /&gt;
    scrollToBottom();&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function addLoadingIndicator() {&lt;br /&gt;
    var div = document.createElement(&#039;div&#039;);&lt;br /&gt;
    div.className = &#039;chat-msg chat-msg-assistant chat-loading-dots&#039;;&lt;br /&gt;
    div.id = &#039;chat-loading&#039;;&lt;br /&gt;
    div.innerHTML = &#039;&amp;lt;span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt;&amp;lt;/span&amp;gt;&#039;;&lt;br /&gt;
    messagesEl.appendChild(div);&lt;br /&gt;
    scrollToBottom();&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function removeLoadingIndicator() {&lt;br /&gt;
    var el = document.getElementById(&#039;chat-loading&#039;);&lt;br /&gt;
    if (el) el.remove();&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function addError(msg) {&lt;br /&gt;
    var div = document.createElement(&#039;div&#039;);&lt;br /&gt;
    div.className = &#039;chat-msg chat-msg-error&#039;;&lt;br /&gt;
    div.textContent = msg;&lt;br /&gt;
    messagesEl.appendChild(div);&lt;br /&gt;
    scrollToBottom();&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function scrollToBottom() {&lt;br /&gt;
    messagesEl.scrollTop = messagesEl.scrollHeight;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function renderSources(sources) {&lt;br /&gt;
    if (!sources || sources.length === 0) {&lt;br /&gt;
      sourcesPanel.className = &#039;&#039;;&lt;br /&gt;
      sourcesPanel.innerHTML = &#039;&#039;;&lt;br /&gt;
      return;&lt;br /&gt;
    }&lt;br /&gt;
    sourcesPanel.className = &#039;visible&#039;;&lt;br /&gt;
    var listId = &#039;src-list-&#039; + Date.now();&lt;br /&gt;
    var html = &#039;&amp;lt;button class=&amp;quot;chat-sources-toggle&amp;quot; onclick=&amp;quot;var l=document.getElementById(\&#039;&#039; + listId + &#039;\&#039;);l.classList.toggle(\&#039;open\&#039;);this.textContent=l.classList.contains(\&#039;open\&#039;)?\&#039;▲ Quellen verbergen\&#039;:\&#039;▼ &#039; + sources.length + &#039; Quellen anzeigen\&#039;&amp;quot;&amp;gt;&#039;&lt;br /&gt;
      + &#039;▼ &#039; + sources.length + &#039; Quellen anzeigen&amp;lt;/button&amp;gt;&#039;;&lt;br /&gt;
    html += &#039;&amp;lt;div class=&amp;quot;chat-sources-list&amp;quot; id=&amp;quot;&#039; + listId + &#039;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
    sources.forEach(function(s) {&lt;br /&gt;
      var pct = Math.round((s.score || 0) * 100);&lt;br /&gt;
      var url = s.url || &#039;&#039;;&lt;br /&gt;
      try {&lt;br /&gt;
        var parsedSourceUrl = new URL(url, location.origin);&lt;br /&gt;
        if (parsedSourceUrl.protocol !== &#039;https:&#039; &amp;amp;&amp;amp; parsedSourceUrl.protocol !== &#039;http:&#039;) url = &#039;#&#039;;&lt;br /&gt;
      } catch (invalidSourceUrl) { url = &#039;#&#039;; }&lt;br /&gt;
      var title = &#039;&#039;;&lt;br /&gt;
      if (url) {&lt;br /&gt;
        var seg = url.split(&#039;/&#039;).pop();&lt;br /&gt;
        try { seg = decodeURIComponent(seg); } catch (e) {}&lt;br /&gt;
        title = seg.replace(/_/g, &#039; &#039;);&lt;br /&gt;
      }&lt;br /&gt;
      html += &#039;&amp;lt;div class=&amp;quot;chat-source-item&amp;quot;&amp;gt;&#039;&lt;br /&gt;
        + &#039;&amp;lt;h5&amp;gt;&amp;lt;a href=&amp;quot;&#039; + escapeHtml(url) + &#039;&amp;quot;&amp;gt;&#039; + escapeHtml(title) + &#039;&amp;lt;/a&amp;gt;&amp;lt;/h5&amp;gt;&#039;&lt;br /&gt;
        + &#039;&amp;lt;p class=&amp;quot;chat-source-snippet&amp;quot;&amp;gt;&#039; + escapeHtml(truncate(s.content || &#039;&#039;, 150)) + &#039;&amp;lt;/p&amp;gt;&#039;&lt;br /&gt;
        + &#039;&amp;lt;div class=&amp;quot;chat-source-meta&amp;quot;&amp;gt;Relevanz: &#039; + pct + &#039;% · &#039; + escapeHtml(s.source || &#039;&#039;) + &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
        + &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
    });&lt;br /&gt;
    html += &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
    sourcesPanel.innerHTML = html;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function setLoading(loading) {&lt;br /&gt;
    isLoading = loading;&lt;br /&gt;
    input.disabled = loading;&lt;br /&gt;
    sendBtn.disabled = loading;&lt;br /&gt;
    if (loading) {&lt;br /&gt;
      addLoadingIndicator();&lt;br /&gt;
    } else {&lt;br /&gt;
      removeLoadingIndicator();&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function updateStatus(remaining) {&lt;br /&gt;
    if (remaining &amp;gt; 0) {&lt;br /&gt;
      statusEl.textContent = remaining + &#039; R\u00fcckfrage&#039; + (remaining !== 1 ? &#039;n&#039; : &#039;&#039;) + &#039; verbleibend&#039;;&lt;br /&gt;
    } else if (remaining === 0) { if (conversationId) {&lt;br /&gt;
      statusEl.textContent = &#039;Keine R\u00fcckfragen mehr m\u00f6glich&#039;;&lt;br /&gt;
      input.disabled = true;&lt;br /&gt;
      sendBtn.disabled = true;&lt;br /&gt;
      input.placeholder = &#039;Starte eine neue Unterhaltung&#039;;&lt;br /&gt;
    } }&lt;br /&gt;
    newBtn.className = conversationId ? &#039;visible&#039; : &#039;&#039;;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function resetConversation() {&lt;br /&gt;
    conversationId = null;&lt;br /&gt;
    messagesEl.innerHTML = &#039;&#039;;&lt;br /&gt;
    sourcesPanel.className = &#039;&#039;;&lt;br /&gt;
    sourcesPanel.innerHTML = &#039;&#039;;&lt;br /&gt;
    statusEl.textContent = &#039;&#039;;&lt;br /&gt;
    newBtn.className = &#039;&#039;;&lt;br /&gt;
    input.disabled = false;&lt;br /&gt;
    sendBtn.disabled = false;&lt;br /&gt;
    input.placeholder = &#039;Stelle eine Frage \u00fcber M\u00fcnster \u2026&#039;;&lt;br /&gt;
    input.focus();&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  newBtn.addEventListener(&#039;click&#039;, resetConversation);&lt;br /&gt;
&lt;br /&gt;
  form.addEventListener(&#039;submit&#039;, function(e) {&lt;br /&gt;
    e.preventDefault();&lt;br /&gt;
    if (isLoading) return;&lt;br /&gt;
    var message = input.value.trim();&lt;br /&gt;
    if (!message) return;&lt;br /&gt;
&lt;br /&gt;
    input.value = &#039;&#039;;&lt;br /&gt;
    addUserMessage(message);&lt;br /&gt;
    setLoading(true);&lt;br /&gt;
&lt;br /&gt;
    var body = { message: message };&lt;br /&gt;
    if (conversationId) {&lt;br /&gt;
      body.conversation_id = conversationId;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    var url = location.protocol + &#039;//&#039; + apiHost + &#039;/chat&#039;;&lt;br /&gt;
&lt;br /&gt;
    fetch(url, {&lt;br /&gt;
      method: &#039;POST&#039;,&lt;br /&gt;
      headers: { &#039;Content-Type&#039;: &#039;application/json&#039; },&lt;br /&gt;
      body: JSON.stringify(body)&lt;br /&gt;
    })&lt;br /&gt;
      .then(function(res) {&lt;br /&gt;
        if (!res.ok) {&lt;br /&gt;
          return res.json().then(function(data) {&lt;br /&gt;
            throw new Error(data.detail || &#039;HTTP &#039; + res.status);&lt;br /&gt;
          });&lt;br /&gt;
        }&lt;br /&gt;
        return res.json();&lt;br /&gt;
      })&lt;br /&gt;
      .then(function(data) {&lt;br /&gt;
        setLoading(false);&lt;br /&gt;
        conversationId = data.conversation_id;&lt;br /&gt;
        addAssistantMessage(data.answer);&lt;br /&gt;
        renderSources(data.sources);&lt;br /&gt;
        updateStatus(data.remaining_followups);&lt;br /&gt;
        input.focus();&lt;br /&gt;
      })&lt;br /&gt;
      .catch(function(err) {&lt;br /&gt;
        setLoading(false);&lt;br /&gt;
        addError(&#039;Fehler: &#039; + err.message);&lt;br /&gt;
        input.focus();&lt;br /&gt;
      });&lt;br /&gt;
  });&lt;br /&gt;
})();&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;/includeonly&amp;gt;&lt;/div&gt;</summary>
		<author><name>Maintenance script</name></author>
	</entry>
</feed>