<style>

  #fritz-widget-container {

    position: fixed;

    bottom: 20px;

    right: 20px;

    z-index: 999999;

    font-family: ‘Lato’, Arial, sans-serif;

  }

 

  #fritz-toggle-btn {

    width: 64px;

    height: 64px;

    border-radius: 50%;

    background: #ff0000;

    border: none;

    box-shadow: 0 4px 12px rgba(0,0,0,0.25);

    cursor: pointer;

    display: flex;

    align-items: center;

    justify-content: center;

    padding: 0;

    transition: transform 0.2s ease;

  }

  #fritz-toggle-btn:hover { transform: scale(1.06); }

  #fritz-toggle-btn img {

    width: 44px;

    height: 44px;

    border-radius: 50%;

  }

 

  #fritz-chat-window {

    display: none;

    flex-direction: column;

    position: absolute;

    bottom: 80px;

    right: 0;

    width: 360px;

    max-width: 90vw;

    height: 520px;

    max-height: 75vh;

    background: #ffffff;

    border-radius: 12px;

    box-shadow: 0 8px 30px rgba(0,0,0,0.25);

    overflow: hidden;

  }

  #fritz-chat-window.open { display: flex; }

 

  #fritz-header {

    background: #ff0000;

    color: #ffffff;

    padding: 14px 16px;

    display: flex;

    align-items: center;

    gap: 10px;

  }

  #fritz-header img {

    width: 36px;

    height: 36px;

    border-radius: 50%;

    background: #ffffff;

  }

  #fritz-header-text { flex: 1; }

  #fritz-header-name { font-weight: 700; font-size: 15px; line-height: 1.2; }

  #fritz-header-sub { font-size: 11px; opacity: 0.9; }

  #fritz-close-btn {

    background: none;

    border: none;

    color: #ffffff;

    font-size: 20px;

    cursor: pointer;

    line-height: 1;

    padding: 4px;

  }

 

  #fritz-messages {

    flex: 1;

    overflow-y: auto;

    padding: 14px;

    background: #f7f7f7;

    display: flex;

    flex-direction: column;

    gap: 10px;

  }

 

  .fritz-msg {

    max-width: 80%;

    padding: 9px 13px;

    border-radius: 14px;

    font-size: 14px;

    line-height: 1.4;

    word-wrap: break-word;

  }

  .fritz-msg.bot {

    background: #ffffff;

    color: #565656;

    align-self: flex-start;

    border: 1px solid #e2e2e2;

    border-bottom-left-radius: 4px;

  }

  .fritz-msg.user {

    background: #ff0000;

    color: #ffffff;

    align-self: flex-end;

    border-bottom-right-radius: 4px;

  }

  .fritz-msg.typing {

    background: #ffffff;

    color: #999999;

    border: 1px solid #e2e2e2;

    align-self: flex-start;

    font-style: italic;

    border-bottom-left-radius: 4px;

  }

 

  #fritz-privacy-note {

    font-size: 11px;

    color: #888888;

    padding: 6px 14px;

    background: #f7f7f7;

    border-top: 1px solid #ececec;

  }

  #fritz-privacy-note a { color: #565656; }

 

  #fritz-input-row {

    display: flex;

    border-top: 1px solid #e2e2e2;

    padding: 10px;

    gap: 8px;

    background: #ffffff;

  }

  #fritz-input {

    flex: 1;

    border: 1px solid #cccccc;

    border-radius: 20px;

    padding: 9px 14px;

    font-size: 14px;

    outline: none;

    font-family: ‘Lato’, Arial, sans-serif;

  }

  #fritz-input:focus { border-color: #ff0000; }

  #fritz-send-btn {

    background: #ff0000;

    color: #ffffff;

    border: none;

    border-radius: 50%;

    width: 38px;

    height: 38px;

    cursor: pointer;

    font-size: 16px;

    flex-shrink: 0;

  }

  #fritz-send-btn:disabled { background: #cccccc; cursor: default; }

 

  @media (max-width: 480px) {

    #fritz-chat-window { width: 92vw; right: -4px; }

  }

</style>

 

<div id=”fritz-widget-container”>

  <div id=”fritz-chat-window”>

    <div id=”fritz-header”>

      <img src=”https://www.steinlen.de/fritz-data/Steinlen_Fritz_512x512.png” alt=”Fritz”>

      <div id=”fritz-header-text”>

        <div id=”fritz-header-name”>Fritz</div>

        <div id=”fritz-header-sub”>Digitaler Praktikant · Steinlen</div>

      </div>

      <button id=”fritz-close-btn” aria-label=”Schliessen”>&times;</button>

    </div>

    <div id=”fritz-messages”></div>

    <div id=”fritz-privacy-note”>

      Bitte keine personenbezogenen Daten eingeben. <a href=”https://steinlen.de/datenschutz/” target=”_blank” rel=”noopener”>Datenschutzhinweis</a>

    </div>

    <div id=”fritz-input-row”>

      <input type=”text” id=”fritz-input” placeholder=”Frag Fritz etwas…” autocomplete=”off”>

      <button id=”fritz-send-btn” aria-label=”Senden”>&#10148;</button>

    </div>

  </div>

 

  <button id=”fritz-toggle-btn” aria-label=”Chat mit Fritz öffnen”>

    <img src=”https://www.steinlen.de/fritz-data/Steinlen_Fritz_512x512.png” alt=”Fritz”>

  </button>

</div>

 

<script>

(function () {

  // ============================================================

  // SEITEN-BESCHRAENKUNG — Widget erscheint NUR auf dieser Seite

  // ============================================================

  const ALLOWED_PATH = ‘/konfigurator/’;

  if (window.location.pathname.indexOf(ALLOWED_PATH) === -1) {

    return; // Auf allen anderen Seiten: Widget gar nicht erst aufbauen

  }

 

  // ============================================================

  // KONFIGURATION — diese 3 Werte vor dem Einsatz pruefen!

  // ============================================================

  const WEBHOOK_URL = ‘http://10.56.4.56:5678/webhook/fritz-chat’; // TODO: interne IP pruefen/anpassen

  const AUTH_TOKEN   = ‘C?=hK~8Jj!Z6:Ry=’;                          // muss mit n8n-Node uebereinstimmen

  const AUTO_POPUP_DELAY_MS = 4000; // Chat-Fenster nach 4s automatisch oeffnen (einmalig pro Sitzung)

  // ============================================================

 

  const container   = document.getElementById(‘fritz-widget-container’);

  const toggleBtn   = document.getElementById(‘fritz-toggle-btn’);

  const closeBtn    = document.getElementById(‘fritz-close-btn’);

  const chatWindow  = document.getElementById(‘fritz-chat-window’);

  const messagesEl  = document.getElementById(‘fritz-messages’);

  const inputEl     = document.getElementById(‘fritz-input’);

  const sendBtn     = document.getElementById(‘fritz-send-btn’);

 

  // Einfache Session-ID pro Browser-Tab (kein Tracking, nur fuer Konversationskontext)

  let sessionId = sessionStorage.getItem(‘fritz_session_id’);

  if (!sessionId) {

    sessionId = ‘web-‘ + Date.now() + ‘-‘ + Math.random().toString(36).slice(2, 9);

    sessionStorage.setItem(‘fritz_session_id’, sessionId);

  }

 

  function detectLanguage() {

    const htmlLang = (document.documentElement.lang || ”).toLowerCase();

    return htmlLang.startsWith(‘en’) ? ‘en’ : ‘de’;

  }

 

  function addMessage(text, role) {

    const div = document.createElement(‘div’);

    div.className = ‘fritz-msg ‘ + role;

    div.textContent = text;

    messagesEl.appendChild(div);

    messagesEl.scrollTop = messagesEl.scrollHeight;

    return div;

  }

 

  function openChat() {

    chatWindow.classList.add(‘open’);

    if (messagesEl.children.length === 0) {

      const greeting = detectLanguage() === ‘en’

        ? “Hi, I’m Fritz! I’m still learning, but happy to help with questions about Steinlen. What can I do for you?”

        : ‘Hallo, ich bin Fritz! Ich lerne noch, helfe aber gerne bei Fragen rund um Steinlen. Was kann ich für dich tun?’;

      addMessage(greeting, ‘bot’);

    }

    inputEl.focus();

  }

 

  function closeChat() {

    chatWindow.classList.remove(‘open’);

  }

 

  toggleBtn.addEventListener(‘click’, function () {

    if (chatWindow.classList.contains(‘open’)) closeChat();

    else openChat();

  });

  closeBtn.addEventListener(‘click’, closeChat);

 

  async function sendMessage() {

    const text = inputEl.value.trim();

    if (!text) return;

 

    addMessage(text, ‘user’);

    inputEl.value = ”;

    sendBtn.disabled = true;

 

    const typingEl = addMessage(

      detectLanguage() === ‘en’ ? ‘Fritz is thinking…’ : ‘Fritz überlegt…’,

      ‘typing’

    );

 

    try {

      const response = await fetch(WEBHOOK_URL, {

        method: ‘POST’,

        headers: { ‘Content-Type’: ‘application/json’ },

        body: JSON.stringify({

          sessionId: sessionId,

          message: text,

          language: detectLanguage(),

          token: AUTH_TOKEN

        })

      });

 

      const data = await response.json();

      typingEl.remove();

 

      if (data && data.ok !== false && data.reply) {

        addMessage(data.reply, ‘bot’);

      } else {

        const errText = (data && data.reply)

          ? data.reply

          : (detectLanguage() === ‘en’

              ? ‘Sorry, something went wrong. Please contact us directly.’

              : ‘Entschuldigung, da ist etwas schiefgelaufen. Bitte kontaktiere uns direkt.’);

        addMessage(errText, ‘bot’);

      }

    } catch (err) {

      typingEl.remove();

      addMessage(

        detectLanguage() === ‘en’

          ? “Sorry, I can’t be reached right now. Please contact us directly.”

          : ‘Entschuldigung, ich bin gerade nicht erreichbar. Bitte kontaktiere uns direkt.’,

        ‘bot’

      );

    } finally {

      sendBtn.disabled = false;

      inputEl.focus();

    }

  }

 

  sendBtn.addEventListener(‘click’, sendMessage);

  inputEl.addEventListener(‘keydown’, function (e) {

    if (e.key === ‘Enter’) sendMessage();

  });

 

  // Automatisches Aufpoppen (einmal pro Browser-Sitzung)

  if (!sessionStorage.getItem(‘fritz_auto_popup_shown’)) {

    setTimeout(function () {

      if (!chatWindow.classList.contains(‘open’)) {

        openChat();

        sessionStorage.setItem(‘fritz_auto_popup_shown’, ‘1’);

      }

    }, AUTO_POPUP_DELAY_MS);

  }

})();

</script>