KI Chat Bubble

This commit is contained in:
2026-03-25 15:20:00 +01:00
parent 64e1959a1b
commit b21ade22f3
13 changed files with 262 additions and 80 deletions

View File

@@ -0,0 +1,11 @@
{
"permissions": {
"allow": [
"Bash(for f:*)",
"Bash(do grep:*)",
"Bash(echo \"ALREADY: $f\")",
"Bash(echo \"NEEDS: $f\")",
"Bash(done)"
]
}
}

View File

@@ -1,6 +1,10 @@
# Security - Disable directory listing
Options -Indexes
# Flowise chat proxy — rewrites /api/v1/prediction/* to PHP proxy (hides real Flowise URL)
RewriteEngine On
RewriteRule ^api/v1/prediction/(.*)$ scripts/add/flowise-proxy.php [L,QSA,NC]
# Enable compression
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/plain

View File

@@ -208,8 +208,8 @@
</div>
</section>
<!-- KI Demo Widgets Section -->
<section class="ki-demo-section" id="demo-section">
<!-- KI Demo Widgets Section — hidden: chat replaced by Flowise bubble; telefon pending relocation -->
<section class="ki-demo-section" id="demo-section" style="display:none">
<div class="container">
<span class="section-label">LIVE DEMO</span>
<h2 class="demo-section-title">Testen Sie es selbst. Jetzt.</h2>
@@ -239,30 +239,6 @@
</div>
</div>
<!-- KI Chat Widget -->
<div class="demo-widget chat-demo">
<div class="demo-icon-circle chat-icon">
<img src="images/icons/chat.png" alt="Chat" style="width: 56px; height: 56px;">
</div>
<h3>KI-Chat</h3>
<p>Stellen Sie eine Frage die KI antwortet sofort und qualifiziert Ihr Anliegen.</p>
<div class="chat-preview">
<div class="chat-header">
<span class="online-dot"></span>
Profice KI · Online
</div>
<div class="chat-messages">
<div class="chat-bubble">
<span>Hallo! Ich bin der Profice KI-Assistent. Stellen Sie mir eine Frage ich zeige Ihnen, wie das System funktioniert.</span>
</div>
</div>
<div class="chat-input-area">
<input type="text" class="chat-input-field" placeholder="Ihre Nachricht...">
<button class="chat-send-btn">Senden</button>
</div>
<p style="font-size: 0.75rem; color: #999999; margin: 4px 8px 0; line-height: 1.3;">Dies ist ein KI-System. Bitte geben Sie keine sensiblen personenbezogenen Daten ein.</p>
</div>
</div>
</div>
</div>
</section>
@@ -373,48 +349,6 @@
</div>
</section>
<!-- Investition Section -->
<section class="pricing-section" id="pricing">
<div class="container">
<span class="section-label">INVESTITION</span>
<h2 class="pricing-headline">Klare Preise. Keine Überraschungen.</h2>
<div class="pricing-box">
<div class="pricing-cards">
<div class="pricing-card">
<div class="pricing-amount">
<span class="pricing-prefix">ab</span>
<span class="pricing-value">3.000 €</span>
</div>
<div class="pricing-label">Einmalig Setup</div>
<div class="pricing-detail">je nach Umfang & Integrationen</div>
</div>
<div class="pricing-card">
<div class="pricing-amount">
<span class="pricing-prefix">ab</span>
<span class="pricing-value">990 €</span>
<span class="pricing-suffix">/Monat</span>
</div>
<div class="pricing-label">Laufender Betrieb</div>
<div class="pricing-detail">inkl. Monitoring, Support & Optimierung</div>
</div>
</div>
<p class="pricing-note">Der genaue Preis hängt davon ab, welche Module Sie brauchen und welche Systeme angebunden werden. In einem 15-Minuten-Gespräch können wir das klären.</p>
<div class="pricing-cta">
<a href="sites/offers.html" class="pricing-btn">Unverbindlich anfragen</a>
</div>
<div class="pricing-benefits">
<span class="pricing-benefit">✓ Keine Mindestlaufzeit über 3 Monate</span>
<span class="pricing-benefit">✓ Danach monatlich kündbar</span>
<span class="pricing-benefit">✓ Keine versteckten Kosten</span>
</div>
</div>
</div>
</section>
<!-- 3 Schritte Section -->
<section class="process-section" id="process">
@@ -578,5 +512,20 @@
<script src="scripts/chat.js?v=20260320e" defer></script>
<script src="scripts/demo-chat.js?v=20260320e" defer></script>
<!-- KI Chat Bubble — remove this block (and ki-chat-bubble.js) to disable -->
<style>
flowise-chatbot::part(button) {
box-shadow: 0 4px 20px rgba(90, 82, 82, 0.3);
border-radius: 50%;
}
flowise-chatbot::part(chatwindow) {
border-radius: 16px;
overflow: hidden;
box-shadow: 0 8px 32px rgba(90, 82, 82, 0.2);
font-family: 'Montserrat', sans-serif;
}
</style>
<script type="module" src="scripts/ki-chat-bubble.js"></script>
</body>
</html>

View File

@@ -0,0 +1,68 @@
<?php
/**
* Flowise Chat Proxy — credentials hidden server-side
* Called via .htaccess rewrite: /api/v1/prediction/* → this file
*/
// SENSITIVE — never expose these in client-side JS
$FLOWISE_HOST = 'https://flowise.profice.de';
$FLOWISE_CHATFLOW = 'd63d3d02-b5fa-482c-9161-c21c615fb625';
// CORS — restrict to your domain in production
$allowedOrigins = [
'https://profice.de',
'https://www.profice.de',
'http://localhost',
'http://127.0.0.1',
'https://staging.profice.de'
];
$origin = $_SERVER['HTTP_ORIGIN'] ?? '';
header('Content-Type: application/json');
if (in_array($origin, $allowedOrigins)) {
header("Access-Control-Allow-Origin: $origin");
} else {
header('Access-Control-Allow-Origin: https://profice.de');
}
header('Access-Control-Allow-Methods: POST, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type, Authorization');
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
http_response_code(200);
exit();
}
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
http_response_code(405);
echo json_encode(['error' => 'Method not allowed']);
exit();
}
$input = file_get_contents('php://input');
$target = "$FLOWISE_HOST/api/v1/prediction/$FLOWISE_CHATFLOW";
$ch = curl_init($target);
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $input,
CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Accept: application/json'],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 60,
CURLOPT_CONNECTTIMEOUT => 10,
CURLOPT_SSL_VERIFYPEER => true,
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$error = curl_error($ch);
curl_close($ch);
if ($error) {
http_response_code(502);
echo json_encode(['error' => 'Proxy error', 'detail' => $error]);
exit();
}
http_response_code($httpCode);
echo $response;
?>

View File

@@ -0,0 +1,94 @@
// KI Chat Bubble — Flowise embed
// To remove: delete this file and the <script> tag in index.html that loads it.
import Chatbot from "https://cdn.jsdelivr.net/npm/flowise-embed/dist/web.js";
// On production the PHP proxy is used so credentials never appear in client JS.
// On localhost the embed talks directly to Flowise (dev only).
const isLocal = ['localhost', '127.0.0.1'].includes(window.location.hostname);
Chatbot.init({
chatflowid: isLocal ? "d63d3d02-b5fa-482c-9161-c21c615fb625" : "chat",
apiHost: isLocal ? "https://flowise.profice.de" : window.location.origin,
theme: {
button: {
backgroundColor: "#5a5252",
right: 24,
bottom: 24,
size: "medium",
iconColor: "#EBEBDE"
},
chatWindow: {
showTitle: true,
title: "Profice Assistent",
titleBackgroundColor: "#5a5252",
titleTextColor: "#EBEBDE",
welcomeMessage: "Hallo! Ich bin der KI-Assistent von Profice. Wie kann ich Ihnen helfen?\n\nIch berate Sie gerne zu unseren Lösungen für Automatisierung, KI-Systeme und digitale Prozesse.",
backgroundColor: "#ffffff",
fontSize: 15,
showAgentMessages: true,
poweredByTextColor: "#ffffff",
botMessage: {
backgroundColor: "#f5f4ef",
textColor: "#5a5252",
showAvatar: true,
avatarSrc: "/images/icons/KI.png"
},
userMessage: {
backgroundColor: "#5a5252",
textColor: "#EBEBDE",
showAvatar: false
},
textInput: {
placeholder: "Ihre Nachricht...",
backgroundColor: "#ffffff",
textColor: "#5a5252",
sendButtonColor: "#d4864a"
},
footer: {
textColor: "#ffffff",
text: " ",
company: " ",
companyLink: ""
}
}
}
});
// Inject orange border around just the header.
// ::part(header) is not exported by Flowise so we inject into the shadow root directly.
// The header is identified as the element that has the dark titleBackgroundColor AND
// contains the chat title — this avoids matching user message bubbles.
function injectHeaderStyle() {
const flowise = document.querySelector('flowise-chatbot');
if (!flowise?.shadowRoot) return false;
const shadow = flowise.shadowRoot;
if (shadow.querySelector('#profice-header-applied')) return true;
const all = [...shadow.querySelectorAll('*')];
const header = all.find(el => {
const bg = getComputedStyle(el).backgroundColor;
return bg === 'rgb(90, 82, 82)' && el.textContent.includes('Profice Assistent');
});
if (!header) return false;
header.style.border = '3px solid #d4864a';
header.style.boxSizing = 'border-box';
// No border-radius here — the parent chatwindow's overflow:hidden clips corners naturally
const marker = document.createElement('span');
marker.id = 'profice-header-applied';
marker.style.display = 'none';
shadow.appendChild(marker);
return true;
}
// Retry until shadow DOM is populated (widget loads async)
let attempts = 0;
const interval = setInterval(() => {
if (injectHeaderStyle() || ++attempts > 20) clearInterval(interval);
}, 300);

View File

@@ -342,6 +342,13 @@
<script src="../scripts/scroll-header.min.js?v=20260304" defer></script>
<script src="../scripts/console-image.js?v=20260304" defer></script>
<!-- KI Chat Bubble — remove this block (and ki-chat-bubble.js) to disable -->
<style>
flowise-chatbot::part(button) { box-shadow: 0 4px 20px rgba(90,82,82,0.3); border-radius: 50%; }
flowise-chatbot::part(chatwindow) { border-radius: 16px; overflow: hidden; box-shadow: 0 8px 32px rgba(90,82,82,0.2); font-family: 'Montserrat', sans-serif; }
</style>
<script type="module" src="../scripts/ki-chat-bubble.js"></script>
</body>
</html>

View File

@@ -318,5 +318,12 @@
<script src="../scripts/cursor.js?v=20260304" defer></script>
<script src="../scripts/scroll-header.min.js?v=20260304" defer></script>
<!-- KI Chat Bubble — remove this block (and ki-chat-bubble.js) to disable -->
<style>
flowise-chatbot::part(button) { box-shadow: 0 4px 20px rgba(90,82,82,0.3); border-radius: 50%; }
flowise-chatbot::part(chatwindow) { border-radius: 16px; overflow: hidden; box-shadow: 0 8px 32px rgba(90,82,82,0.2); font-family: 'Montserrat', sans-serif; }
</style>
<script type="module" src="../scripts/ki-chat-bubble.js"></script>
</body>
</html>

View File

@@ -156,42 +156,42 @@
<div class="feature-grid">
<div class="feature-card">
<div class="feature-icon-wrap teal">
<svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="#4a4645" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><rect x="4" y="14" width="4" height="6" rx="1"/><rect x="10" y="9" width="4" height="11" rx="1"/><rect x="16" y="4" width="4" height="16" rx="1"/></svg>
<svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="#4a4645" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><rect x="4" y="14" width="4" height="6" rx="1"/><rect x="10" y="9" width="4" height="11" rx="1"/><rect x="16" y="4" width="4" height="16" rx="1"/></svg>
</div>
<h3>Profitabilität pro Produkt</h3>
<p>Jedes Produkt wird individuell bewertet — basierend auf echtem Gewinn.</p>
</div>
<div class="feature-card">
<div class="feature-icon-wrap orange">
<svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="#4a4645" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg>
<svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="#4a4645" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg>
</div>
<h3>Intelligente Segmentierung</h3>
<p>Automatische Einteilung in profitable, neue und unprofitable Gruppen.</p>
</div>
<div class="feature-card">
<div class="feature-icon-wrap green">
<svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="#4a4645" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="2 12 6 12 8 5 11 19 14 9 16 14 18 12 22 12"/></svg>
<svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="#4a4645" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="2 12 6 12 8 5 11 19 14 9 16 14 18 12 22 12"/></svg>
</div>
<h3>Live-Daten</h3>
<p>Performance-Daten werden automatisch abgerufen — immer aktuell.</p>
</div>
<div class="feature-card">
<div class="feature-icon-wrap teal">
<svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="#4a4645" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="18" height="18" rx="3"/><polyline points="7 13 10.5 16.5 17 9"/></svg>
<svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="#4a4645" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="18" height="18" rx="3"/><polyline points="7 13 10.5 16.5 17 9"/></svg>
</div>
<h3>Feed-Qualität gesichert</h3>
<p>Fehlerhafte Produktdaten werden automatisch korrigiert.</p>
</div>
<div class="feature-card">
<div class="feature-icon-wrap orange">
<svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="#4a4645" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg>
<svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="#4a4645" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg>
</div>
<h3>Voll automatisiert</h3>
<p>Läuft eigenständig — mit Benachrichtigungen bei Bedarf.</p>
</div>
<div class="feature-card">
<div class="feature-icon-wrap green">
<svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="#4a4645" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="17 8 12 3 7 8"/><line x1="12" y1="3" x2="12" y2="15"/></svg>
<svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="#4a4645" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="17 8 12 3 7 8"/><line x1="12" y1="3" x2="12" y2="15"/></svg>
</div>
<h3>Direkt einsatzbereit</h3>
<p>Sofort kompatibel mit Google Merchant Center.</p>
@@ -269,7 +269,7 @@
<div class="segment-cards">
<div class="seg-card core">
<div class="seg-icon">
<svg width="26" height="26" viewBox="0 0 24 24" fill="none" stroke="#4a4645" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="23 6 13.5 15.5 8.5 10.5 1 18"/><polyline points="17 6 23 6 23 12"/></svg>
<svg width="26" height="26" viewBox="0 0 24 24" fill="none" stroke="#4a4645" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="23 6 13.5 15.5 8.5 10.5 1 18"/><polyline points="17 6 23 6 23 12"/></svg>
</div>
<div class="seg-text">
<h3>Core — Gewinnbringer</h3>
@@ -278,7 +278,7 @@
</div>
<div class="seg-card longtail">
<div class="seg-icon">
<svg width="26" height="26" viewBox="0 0 24 24" fill="none" stroke="#4a4645" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>
<svg width="26" height="26" viewBox="0 0 24 24" fill="none" stroke="#4a4645" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>
</div>
<div class="seg-text">
<h3>Feeder — Neue Chancen</h3>
@@ -287,7 +287,7 @@
</div>
<div class="seg-card feeder">
<div class="seg-icon">
<svg width="26" height="26" viewBox="0 0 24 24" fill="none" stroke="#4a4645" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="15" y1="9" x2="9" y2="15"/><line x1="9" y1="9" x2="15" y2="15"/></svg>
<svg width="26" height="26" viewBox="0 0 24 24" fill="none" stroke="#4a4645" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="15" y1="9" x2="9" y2="15"/><line x1="9" y1="9" x2="15" y2="15"/></svg>
</div>
<div class="seg-text">
<h3>Longtail — Budgetfresser</h3>
@@ -306,7 +306,7 @@
<div class="pipeline">
<div class="pipeline-step">
<div class="pipe-icon">
<svg width="26" height="26" viewBox="0 0 24 24" fill="none" stroke="#4a4645" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"/><polyline points="3.27 6.96 12 12.01 20.73 6.96"/><line x1="12" y1="22.08" x2="12" y2="12"/></svg>
<svg width="26" height="26" viewBox="0 0 24 24" fill="none" stroke="#4a4645" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"/><polyline points="3.27 6.96 12 12.01 20.73 6.96"/><line x1="12" y1="22.08" x2="12" y2="12"/></svg>
</div>
<h3>Daten verbinden</h3>
<p>Shop-Feed, Einkaufspreise und Google-Ads-Daten</p>
@@ -316,7 +316,7 @@
</div>
<div class="pipeline-step">
<div class="pipe-icon">
<svg width="26" height="26" viewBox="0 0 24 24" fill="none" stroke="#4a4645" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="16 18 22 12 16 6"/><polyline points="8 6 2 12 8 18"/></svg>
<svg width="26" height="26" viewBox="0 0 24 24" fill="none" stroke="#4a4645" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="16 18 22 12 16 6"/><polyline points="8 6 2 12 8 18"/></svg>
</div>
<h3>Gewinn berechnen</h3>
<p>POAS-Wert pro Produkt ermitteln</p>
@@ -326,7 +326,7 @@
</div>
<div class="pipeline-step">
<div class="pipe-icon">
<svg width="26" height="26" viewBox="0 0 24 24" fill="none" stroke="#4a4645" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/><polyline points="22 4 12 14.01 9 11.01"/></svg>
<svg width="26" height="26" viewBox="0 0 24 24" fill="none" stroke="#4a4645" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/><polyline points="22 4 12 14.01 9 11.01"/></svg>
</div>
<h3>Feed optimieren</h3>
<p>Optimierter Feed für Google Merchant Center</p>
@@ -473,5 +473,12 @@
<script src="../scripts/scroll-header.min.js?v=20260304" defer></script>
<script src="../scripts/feed-calculator.js?v=20260320" defer></script>
<!-- KI Chat Bubble — remove this block (and ki-chat-bubble.js) to disable -->
<style>
flowise-chatbot::part(button) { box-shadow: 0 4px 20px rgba(90,82,82,0.3); border-radius: 50%; }
flowise-chatbot::part(chatwindow) { border-radius: 16px; overflow: hidden; box-shadow: 0 8px 32px rgba(90,82,82,0.2); font-family: 'Montserrat', sans-serif; }
</style>
<script type="module" src="../scripts/ki-chat-bubble.js"></script>
</body>
</html>

View File

@@ -270,5 +270,12 @@
<script src="../scripts/cursor.js?v=20260304" defer></script>
<script src="../scripts/scroll-header.min.js?v=20260304" defer></script>
<!-- KI Chat Bubble — remove this block (and ki-chat-bubble.js) to disable -->
<style>
flowise-chatbot::part(button) { box-shadow: 0 4px 20px rgba(90,82,82,0.3); border-radius: 50%; }
flowise-chatbot::part(chatwindow) { border-radius: 16px; overflow: hidden; box-shadow: 0 8px 32px rgba(90,82,82,0.2); font-family: 'Montserrat', sans-serif; }
</style>
<script type="module" src="../scripts/ki-chat-bubble.js"></script>
</body>
</html>

View File

@@ -354,6 +354,13 @@
<script src="../scripts/scroll-header.min.js?v=20260304" defer></script>
<script src="../scripts/console-image.js?v=20260304" defer></script>
<!-- KI Chat Bubble — remove this block (and ki-chat-bubble.js) to disable -->
<style>
flowise-chatbot::part(button) { box-shadow: 0 4px 20px rgba(90,82,82,0.3); border-radius: 50%; }
flowise-chatbot::part(chatwindow) { border-radius: 16px; overflow: hidden; box-shadow: 0 8px 32px rgba(90,82,82,0.2); font-family: 'Montserrat', sans-serif; }
</style>
<script type="module" src="../scripts/ki-chat-bubble.js"></script>
</body>
</html>

View File

@@ -248,6 +248,13 @@
<script src="../scripts/scroll-header.min.js?v=20260304" defer></script>
<script src="../scripts/console-image.js?v=20260304" defer></script>
<!-- KI Chat Bubble — remove this block (and ki-chat-bubble.js) to disable -->
<style>
flowise-chatbot::part(button) { box-shadow: 0 4px 20px rgba(90,82,82,0.3); border-radius: 50%; }
flowise-chatbot::part(chatwindow) { border-radius: 16px; overflow: hidden; box-shadow: 0 8px 32px rgba(90,82,82,0.2); font-family: 'Montserrat', sans-serif; }
</style>
<script type="module" src="../scripts/ki-chat-bubble.js"></script>
</body>
</html>

View File

@@ -437,5 +437,12 @@
<script src="../scripts/scroll-header.min.js?v=20260304" defer></script>
<script src="../scripts/console-image.js?v=20260304" defer></script>
<!-- KI Chat Bubble — remove this block (and ki-chat-bubble.js) to disable -->
<style>
flowise-chatbot::part(button) { box-shadow: 0 4px 20px rgba(90,82,82,0.3); border-radius: 50%; }
flowise-chatbot::part(chatwindow) { border-radius: 16px; overflow: hidden; box-shadow: 0 8px 32px rgba(90,82,82,0.2); font-family: 'Montserrat', sans-serif; }
</style>
<script type="module" src="../scripts/ki-chat-bubble.js"></script>
</body>
</html>

View File

@@ -328,6 +328,13 @@
<script src="../scripts/scroll-header.min.js?v=20260304" defer></script>
<script src="../scripts/console-image.js?v=20260304" defer></script>
<!-- KI Chat Bubble — remove this block (and ki-chat-bubble.js) to disable -->
<style>
flowise-chatbot::part(button) { box-shadow: 0 4px 20px rgba(90,82,82,0.3); border-radius: 50%; }
flowise-chatbot::part(chatwindow) { border-radius: 16px; overflow: hidden; box-shadow: 0 8px 32px rgba(90,82,82,0.2); font-family: 'Montserrat', sans-serif; }
</style>
<script type="module" src="../scripts/ki-chat-bubble.js"></script>
</body>
</html>