chatbot / templates /base.html
Moderator404's picture
Upload 39 files
41bd0b8 verified
Raw
History Blame Contribute Delete
104 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>{% block title %}Too Many Cables - Premium Cables & Accessories{% endblock %}</title>
<!-- <link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}"> -->
<link rel="icon" type="image/x-icon" href="{{ url_for('static', filename='favicon.ico') }}">
<meta name="description" content="{% block description %}Too Many Cables - Your trusted source for premium USB-C, HDMI, charging cables and tech accessories. Fast shipping, lifetime warranty.{% endblock %}">
<!-- Ultra-Modern Professional Design -->
<style>
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html, body {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important;
min-height: 100vh !important;
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif !important;
line-height: 1.6 !important;
color: #333 !important;
}
/* Premium Navigation Header */
.navbar {
background: linear-gradient(135deg, rgba(255, 255, 255, 0.98), rgba(255, 255, 255, 0.95)) !important;
backdrop-filter: blur(25px) !important;
-webkit-backdrop-filter: blur(25px) !important;
box-shadow: 0 12px 40px rgba(0, 0, 0, 0.12), 0 4px 16px rgba(102, 126, 234, 0.08) !important;
border-bottom: 1px solid rgba(255, 255, 255, 0.3) !important;
padding: 1.5rem 0 !important;
position: sticky !important;
top: 0 !important;
z-index: 1000 !important;
}
.nav-container {
max-width: 1400px !important;
margin: 0 auto !important;
padding: 0 2.5rem !important;
display: flex !important;
justify-content: space-between !important;
align-items: center !important;
}
.nav-brand {
display: flex !important;
align-items: center !important;
}
.brand-logo {
display: flex !important;
align-items: center !important;
text-decoration: none !important;
color: #1a202c !important;
font-size: 2rem !important;
font-weight: 800 !important;
letter-spacing: -0.03em !important;
transition: all 0.3s ease !important;
}
.brand-logo:hover {
transform: scale(1.02) !important;
color: #667eea !important;
}
.logo-icon {
font-size: 2.5rem !important;
margin-right: 0.75rem !important;
filter: drop-shadow(0 4px 8px rgba(0,0,0,0.15)) !important;
transition: all 0.3s ease !important;
}
.brand-logo:hover .logo-icon {
transform: rotate(5deg) !important;
}
.brand-text {
background: linear-gradient(135deg, #1a202c 0%, #667eea 100%) !important;
-webkit-background-clip: text !important;
-webkit-text-fill-color: transparent !important;
background-clip: text !important;
}
/* Navigation Menu */
.nav-menu {
display: flex !important;
list-style: none !important;
gap: 0.25rem !important;
align-items: center !important;
}
.nav-link {
text-decoration: none !important;
color: #2d3748 !important;
font-weight: 600 !important;
padding: 0.85rem 1.5rem !important;
border-radius: 14px !important;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important;
font-size: 1rem !important;
position: relative !important;
overflow: hidden !important;
}
.nav-link::before {
content: '' !important;
position: absolute !important;
top: 0 !important;
left: -100% !important;
width: 100% !important;
height: 100% !important;
background: linear-gradient(135deg, rgba(102, 126, 234, 0.15), rgba(118, 75, 162, 0.15)) !important;
transition: left 0.3s ease !important;
z-index: -1 !important;
}
.nav-link:hover {
background: linear-gradient(135deg, rgba(102, 126, 234, 0.12), rgba(118, 75, 162, 0.08)) !important;
color: #667eea !important;
transform: translateY(-2px) !important;
box-shadow: 0 8px 24px rgba(102, 126, 234, 0.15) !important;
}
.nav-link:hover::before {
left: 0 !important;
}
.nav-link.active {
background: linear-gradient(135deg, rgba(102, 126, 234, 0.15), rgba(118, 75, 162, 0.1)) !important;
color: #667eea !important;
}
/* Special styling for Live Chat button */
.chat-link {
background: linear-gradient(135deg, #667eea, #764ba2) !important;
color: white !important;
font-weight: 700 !important;
box-shadow: 0 6px 20px rgba(102, 126, 234, 0.3) !important;
}
.chat-link:hover {
background: linear-gradient(135deg, #5a6fd8, #6a42a0) !important;
transform: translateY(-3px) !important;
box-shadow: 0 10px 30px rgba(102, 126, 234, 0.4) !important;
}
.chat-icon {
margin-right: 0.5rem !important;
}
/* User Menu and Buttons */
.nav-user {
display: flex !important;
align-items: center !important;
gap: 1rem !important;
}
.user-menu {
display: flex !important;
align-items: center !important;
gap: 1rem !important;
}
.user-greeting {
color: #2d3748 !important;
font-weight: 500 !important;
font-size: 0.95rem !important;
background: linear-gradient(135deg, rgba(102, 126, 234, 0.1), rgba(118, 75, 162, 0.1)) !important;
padding: 0.5rem 1rem !important;
border-radius: 8px !important;
backdrop-filter: blur(5px) !important;
border: 1px solid rgba(102, 126, 234, 0.15) !important;
}
.btn {
display: inline-flex !important;
align-items: center !important;
justify-content: center !important;
padding: 0.7rem 1.5rem !important;
border-radius: 12px !important;
font-weight: 600 !important;
font-size: 0.95rem !important;
text-decoration: none !important;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important;
border: none !important;
cursor: pointer !important;
}
.btn-outline {
background: transparent !important;
color: #2d3748 !important;
border: 2px solid rgba(45, 55, 72, 0.2) !important;
}
.btn-outline:hover {
background: linear-gradient(135deg, rgba(102, 126, 234, 0.1), rgba(118, 75, 162, 0.1)) !important;
border-color: #667eea !important;
color: #667eea !important;
transform: translateY(-2px) !important;
box-shadow: 0 6px 20px rgba(102, 126, 234, 0.2) !important;
}
/* Primary Button Style for User Actions */
.nav-user .btn-outline {
background: linear-gradient(135deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0.05)) !important;
backdrop-filter: blur(10px) !important;
border: 2px solid rgba(255, 255, 255, 0.3) !important;
color: #2d3748 !important;
font-weight: 600 !important;
text-shadow: 0 1px 2px rgba(255, 255, 255, 0.5) !important;
}
.nav-user .btn-outline:hover {
background: linear-gradient(135deg, #667eea, #764ba2) !important;
color: white !important;
border-color: transparent !important;
box-shadow: 0 8px 25px rgba(102, 126, 234, 0.3) !important;
text-shadow: none !important;
}
/* Mobile Navigation Toggle */
.nav-toggle {
display: none !important;
flex-direction: column !important;
cursor: pointer !important;
padding: 0.5rem !important;
}
.nav-toggle .bar {
width: 25px !important;
height: 3px !important;
background: #2d3748 !important;
margin: 3px 0 !important;
transition: 0.3s !important;
}
@media (max-width: 768px) {
.nav-toggle {
display: flex !important;
}
.nav-menu {
position: fixed !important;
left: -100% !important;
top: 70px !important;
flex-direction: column !important;
background: rgba(255, 255, 255, 0.95) !important;
backdrop-filter: blur(20px) !important;
width: 100% !important;
text-align: center !important;
transition: 0.3s !important;
box-shadow: 0 10px 27px rgba(0, 0, 0, 0.05) !important;
padding: 2rem 0 !important;
}
.nav-menu.active {
left: 0 !important;
}
.nav-menu .nav-link {
padding: 1rem !important;
display: block !important;
margin: 0.5rem 0 !important;
}
.nav-user {
position: absolute !important;
right: 70px !important;
top: 50% !important;
transform: translateY(-50%) !important;
}
}
/* Mobile responsiveness */
@media (max-width: 768px) {
.nav-container {
padding: 0 1.5rem !important;
}
.brand-logo {
font-size: 1.5rem !important;
}
.logo-icon {
font-size: 2rem !important;
}
.nav-links {
gap: 0 !important;
}
.nav-links a {
padding: 0.6rem 1rem !important;
font-size: 0.9rem !important;
}
}
/* Hero Section - Premium Design */
.hero, .hero-section {
background: linear-gradient(135deg, rgba(255, 255, 255, 0.18), rgba(255, 255, 255, 0.08)) !important;
backdrop-filter: blur(25px) !important;
-webkit-backdrop-filter: blur(25px) !important;
border-radius: 32px !important;
border: 1px solid rgba(255, 255, 255, 0.25) !important;
padding: 5rem 4rem !important;
margin: 4rem 3rem 5rem 3rem !important;
max-width: calc(100% - 6rem) !important;
color: white !important;
text-align: center !important;
box-shadow: 0 32px 96px rgba(0, 0, 0, 0.2), 0 16px 48px rgba(102, 126, 234, 0.15), inset 0 1px 0 rgba(255, 255, 255, 0.3) !important;
position: relative !important;
overflow: hidden !important;
}
.hero-section::before {
content: '' !important;
position: absolute !important;
top: 0 !important;
left: 0 !important;
right: 0 !important;
bottom: 0 !important;
background: radial-gradient(circle at 30% 20%, rgba(255,255,255,0.15) 0%, transparent 70%),
linear-gradient(135deg, rgba(255,255,255,0.08) 0%, transparent 50%, rgba(255,255,255,0.05) 100%) !important;
pointer-events: none !important;
}
.hero-section::after {
content: '' !important;
position: absolute !important;
top: -50% !important;
left: -50% !important;
width: 200% !important;
height: 200% !important;
background: conic-gradient(from 0deg, transparent, rgba(255,255,255,0.03), transparent 60deg) !important;
animation: rotate 20s linear infinite !important;
pointer-events: none !important;
}
@keyframes rotate {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.hero h1, .hero-section h1, .hero-title {
font-size: 4rem !important;
font-weight: 800 !important;
margin-bottom: 2rem !important;
text-shadow: 0 8px 16px rgba(0,0,0,0.3) !important;
letter-spacing: -0.05em !important;
line-height: 1.05 !important;
position: relative !important;
z-index: 2 !important;
background: linear-gradient(135deg, #ffffff 0%, #f0f8ff 100%) !important;
-webkit-background-clip: text !important;
-webkit-text-fill-color: transparent !important;
background-clip: text !important;
}
.hero p, .hero-section p, .hero-subtitle {
font-size: 1.4rem !important;
margin-bottom: 3rem !important;
opacity: 0.95 !important;
font-weight: 400 !important;
max-width: 800px !important;
margin-left: auto !important;
margin-right: auto !important;
position: relative !important;
z-index: 2 !important;
line-height: 1.7 !important;
color: white !important;
}
.hero-buttons, .hero-actions {
display: flex !important;
gap: 1.5rem !important;
justify-content: center !important;
flex-wrap: wrap !important;
position: relative !important;
z-index: 2 !important;
}
/* Hero container styling */
.hero-container {
max-width: 1400px !important;
margin: 0 auto !important;
padding: 2rem !important;
text-align: center !important;
}
/* Section Headers */
.section-header {
text-align: center !important;
margin: 6rem 0 4rem 0 !important;
}
.section-header h2 {
font-size: 3.2rem !important;
font-weight: 700 !important;
margin-bottom: 1.5rem !important;
background: linear-gradient(135deg, #ffffff 0%, #e6f3ff 100%) !important;
-webkit-background-clip: text !important;
-webkit-text-fill-color: transparent !important;
background-clip: text !important;
text-shadow: none !important;
letter-spacing: -0.03em !important;
}
.section-header p {
font-size: 1.2rem !important;
color: rgba(255, 255, 255, 0.8) !important;
max-width: 600px !important;
margin: 0 auto !important;
}
/* Feature Cards - Ultra Premium */
.features-grid {
display: grid !important;
grid-template-columns: repeat(auto-fit, minmax(350px, 1fr)) !important;
gap: 2.5rem !important;
margin: 4rem 0 6rem 0 !important;
}
.feature-card {
background: linear-gradient(145deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0.05)) !important;
backdrop-filter: blur(25px) !important;
-webkit-backdrop-filter: blur(25px) !important;
border-radius: 24px !important;
border: 1px solid rgba(255, 255, 255, 0.2) !important;
padding: 3rem 2.5rem !important;
color: white !important;
text-align: center !important;
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.12), inset 0 1px 0 rgba(255, 255, 255, 0.2) !important;
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1) !important;
position: relative !important;
overflow: hidden !important;
}
.feature-card::before {
content: '' !important;
position: absolute !important;
top: 0 !important;
left: 0 !important;
right: 0 !important;
bottom: 0 !important;
background: radial-gradient(circle at 50% 0%, rgba(255,255,255,0.12) 0%, transparent 70%) !important;
opacity: 0 !important;
transition: opacity 0.4s ease !important;
pointer-events: none !important;
}
.feature-card:hover {
transform: translateY(-12px) scale(1.02) !important;
box-shadow: 0 32px 80px rgba(0, 0, 0, 0.18), 0 16px 48px rgba(102, 126, 234, 0.25), inset 0 1px 0 rgba(255, 255, 255, 0.3) !important;
}
.feature-card:hover::before {
opacity: 1 !important;
}
.feature-icon {
font-size: 3rem !important;
margin-bottom: 1.5rem !important;
display: block !important;
filter: drop-shadow(0 4px 8px rgba(0,0,0,0.2)) !important;
}
.feature-card h3 {
font-size: 1.6rem !important;
font-weight: 700 !important;
margin-bottom: 1.5rem !important;
color: #fff !important;
position: relative !important;
z-index: 1 !important;
letter-spacing: -0.025em !important;
}
.feature-card p {
font-size: 1.1rem !important;
opacity: 0.9 !important;
line-height: 1.7 !important;
position: relative !important;
z-index: 1 !important;
}
/* Support CTA Section */
.support-cta {
background: linear-gradient(135deg, rgba(255, 255, 255, 0.12), rgba(255, 255, 255, 0.04)) !important;
backdrop-filter: blur(25px) !important;
-webkit-backdrop-filter: blur(25px) !important;
border-radius: 32px !important;
border: 1px solid rgba(255, 255, 255, 0.2) !important;
margin: 4rem 3rem 5rem 3rem !important;
max-width: calc(100% - 6rem) !important;
padding: 4rem !important;
text-align: center !important;
box-shadow: 0 32px 96px rgba(0, 0, 0, 0.15), 0 16px 48px rgba(102, 126, 234, 0.1) !important;
}
.cta-content h2 {
color: white !important;
font-size: 2.5rem !important;
font-weight: 700 !important;
margin-bottom: 1.5rem !important;
text-shadow: 0 2px 4px rgba(0,0,0,0.2) !important;
}
.cta-content p {
color: rgba(255, 255, 255, 0.9) !important;
font-size: 1.2rem !important;
line-height: 1.6 !important;
margin-bottom: 3rem !important;
max-width: 600px !important;
margin-left: auto !important;
margin-right: auto !important;
}
.cta-actions {
display: flex !important;
gap: 1.5rem !important;
justify-content: center !important;
margin-bottom: 4rem !important;
flex-wrap: wrap !important;
}
.cta-features {
display: flex !important;
justify-content: center !important;
align-items: center !important;
gap: 3rem !important;
flex-wrap: wrap !important;
margin-top: 3rem !important;
}
.cta-feature {
display: flex !important;
flex-direction: column !important;
align-items: center !important;
gap: 1rem !important;
text-align: center !important;
min-width: 150px !important;
}
.cta-feature .feature-icon {
font-size: 2.5rem !important;
margin-bottom: 0.5rem !important;
filter: drop-shadow(0 4px 8px rgba(0,0,0,0.2)) !important;
display: block !important;
}
.cta-feature span:last-child {
color: white !important;
font-weight: 600 !important;
font-size: 1rem !important;
text-shadow: 0 1px 2px rgba(0,0,0,0.2) !important;
}
/* Customer Reviews Section */
.reviews {
padding: 5rem 0 !important;
margin: 2rem 0 !important;
}
.reviews .container {
max-width: 1400px !important;
margin: 0 auto !important;
padding: 0 3rem !important;
}
.reviews .section-title {
color: white !important;
font-size: 2.5rem !important;
font-weight: 700 !important;
text-align: center !important;
margin-bottom: 4rem !important;
text-shadow: 0 2px 4px rgba(0,0,0,0.2) !important;
}
.reviews-grid {
display: grid !important;
grid-template-columns: repeat(auto-fit, minmax(350px, 1fr)) !important;
gap: 2.5rem !important;
margin-bottom: 3rem !important;
}
.review-card {
background: linear-gradient(145deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0.05)) !important;
backdrop-filter: blur(25px) !important;
-webkit-backdrop-filter: blur(25px) !important;
border-radius: 24px !important;
border: 1px solid rgba(255, 255, 255, 0.2) !important;
padding: 2.5rem !important;
color: white !important;
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.12), inset 0 1px 0 rgba(255, 255, 255, 0.2) !important;
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1) !important;
position: relative !important;
overflow: hidden !important;
}
.review-card::before {
content: '' !important;
position: absolute !important;
top: 0 !important;
left: 0 !important;
right: 0 !important;
bottom: 0 !important;
background: radial-gradient(circle at 50% 0%, rgba(255,255,255,0.08) 0%, transparent 70%) !important;
opacity: 0 !important;
transition: opacity 0.4s ease !important;
pointer-events: none !important;
}
.review-card:hover {
transform: translateY(-8px) scale(1.01) !important;
box-shadow: 0 32px 80px rgba(0, 0, 0, 0.18), 0 16px 48px rgba(102, 126, 234, 0.15), inset 0 1px 0 rgba(255, 255, 255, 0.3) !important;
}
.review-card:hover::before {
opacity: 1 !important;
}
.review-rating {
font-size: 1.5rem !important;
margin-bottom: 1.5rem !important;
filter: drop-shadow(0 2px 4px rgba(0,0,0,0.2)) !important;
}
.review-text {
font-size: 1.1rem !important;
line-height: 1.7 !important;
margin-bottom: 2rem !important;
color: rgba(255, 255, 255, 0.95) !important;
font-style: italic !important;
position: relative !important;
z-index: 1 !important;
}
.review-text::before {
content: '"' !important;
font-size: 3rem !important;
color: rgba(102, 126, 234, 0.3) !important;
position: absolute !important;
top: -1rem !important;
left: -0.5rem !important;
font-family: serif !important;
line-height: 1 !important;
}
.review-author {
font-weight: 600 !important;
color: rgba(255, 255, 255, 0.8) !important;
font-size: 0.95rem !important;
position: relative !important;
z-index: 1 !important;
}
/* Simple Footer */
.footer {
background: linear-gradient(135deg, rgba(255, 255, 255, 0.12), rgba(255, 255, 255, 0.04)) !important;
backdrop-filter: blur(25px) !important;
-webkit-backdrop-filter: blur(25px) !important;
border-radius: 32px 32px 0 0 !important;
border: 1px solid rgba(255, 255, 255, 0.2) !important;
border-bottom: none !important;
margin: 4rem 3rem 0 3rem !important;
max-width: calc(100% - 6rem) !important;
box-shadow: 0 -16px 48px rgba(0, 0, 0, 0.15), 0 -8px 24px rgba(102, 126, 234, 0.1) !important;
color: white !important;
padding: 4rem 0 6rem 0 !important; /* extra bottom padding to make room for footer-bottom */
position: relative !important; /* make footer-bottom position relative to footer */
}
.footer-container {
max-width: 1400px !important;
margin: 0 auto !important;
padding: 0 3rem !important;
text-align: center !important;
}
.footer-simple h3 {
color: white !important;
font-size: 2rem !important;
font-weight: 700 !important;
margin-bottom: 1rem !important;
text-shadow: 0 2px 4px rgba(0,0,0,0.2) !important;
}
.footer-simple p {
color: rgba(255, 255, 255, 0.8) !important;
line-height: 1.6 !important;
margin: 0 !important;
font-size: 1.1rem !important;
max-width: 500px !important;
margin: 0 auto !important;
}
.footer-bottom {
position: absolute !important;
left: 0 !important;
right: 0 !important;
bottom: 0 !important;
background: rgba(0, 0, 0, 0.06) !important; /* subtle divider look */
border-top: 1px solid rgba(255, 255, 255, 0.06) !important;
padding: 1rem 0 !important;
}
.footer-bottom p {
color: rgba(255, 255, 255, 0.75) !important;
margin: 0 !important;
font-size: 0.9rem !important;
text-align: center !important;
}
/* Premium Buttons */
.btn {
display: inline-flex !important;
align-items: center !important;
justify-content: center !important;
padding: 1rem 2rem !important;
border-radius: 16px !important;
text-decoration: none !important;
font-weight: 600 !important;
font-size: 1rem !important;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important;
position: relative !important;
overflow: hidden !important;
border: none !important;
cursor: pointer !important;
background: linear-gradient(135deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0.05)) !important;
backdrop-filter: blur(10px) !important;
color: white !important;
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1) !important;
}
.btn-primary {
background: linear-gradient(135deg, #667eea, #764ba2) !important;
color: white !important;
box-shadow: 0 6px 20px rgba(102, 126, 234, 0.3) !important;
}
.btn-primary:hover {
background: linear-gradient(135deg, #5a6fd8, #6a42a0) !important;
transform: translateY(-3px) !important;
box-shadow: 0 10px 30px rgba(102, 126, 234, 0.4) !important;
}
.btn-outline {
background: transparent !important;
border: 2px solid rgba(255, 255, 255, 0.3) !important;
color: white !important;
}
.btn-outline:hover {
background: linear-gradient(135deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0.05)) !important;
border-color: rgba(255, 255, 255, 0.5) !important;
}
.btn::before {
content: '' !important;
position: absolute !important;
top: 0 !important;
left: -100% !important;
width: 100% !important;
height: 100% !important;
background: linear-gradient(90deg, transparent, rgba(255,255,255,0.2), transparent) !important;
transition: left 0.5s !important;
}
.btn:hover:not(.btn-primary):not(.btn-outline) {
background: linear-gradient(135deg, rgba(255, 255, 255, 0.25), rgba(255, 255, 255, 0.15)) !important;
transform: translateY(-2px) !important;
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.2) !important;
}
.btn:hover::before {
left: 100% !important;
}
/* Container Improvements */
.container {
max-width: 1400px !important;
margin: 0 auto !important;
padding: 2rem !important;
}
/* Products Section */
.popular-products {
padding: 5rem 0 !important;
margin: 2rem 0 !important;
}
.popular-products .container {
max-width: 1400px !important;
margin: 0 auto !important;
padding: 0 3rem !important;
}
.popular-products .section-title {
color: white !important;
font-size: 2.5rem !important;
font-weight: 700 !important;
text-align: center !important;
margin-bottom: 4rem !important;
text-shadow: 0 2px 4px rgba(0,0,0,0.2) !important;
}
.products-grid {
display: grid !important;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)) !important;
gap: 2.5rem !important;
margin-bottom: 4rem !important;
}
.product-card {
background: linear-gradient(145deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0.05)) !important;
backdrop-filter: blur(25px) !important;
-webkit-backdrop-filter: blur(25px) !important;
border-radius: 24px !important;
border: 1px solid rgba(255, 255, 255, 0.2) !important;
padding: 2.5rem !important;
color: white !important;
text-align: center !important;
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.12), inset 0 1px 0 rgba(255, 255, 255, 0.2) !important;
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1) !important;
position: relative !important;
overflow: hidden !important;
}
.product-card::before {
content: '' !important;
position: absolute !important;
top: 0 !important;
left: 0 !important;
right: 0 !important;
bottom: 0 !important;
background: radial-gradient(circle at 50% 0%, rgba(255,255,255,0.08) 0%, transparent 70%) !important;
opacity: 0 !important;
transition: opacity 0.4s ease !important;
pointer-events: none !important;
}
.product-card:hover {
transform: translateY(-12px) scale(1.02) !important;
box-shadow: 0 32px 80px rgba(0, 0, 0, 0.18), 0 16px 48px rgba(102, 126, 234, 0.15), inset 0 1px 0 rgba(255, 255, 255, 0.3) !important;
}
.product-card:hover::before {
opacity: 1 !important;
}
.product-image {
font-size: 4rem !important;
margin-bottom: 1.5rem !important;
filter: drop-shadow(0 4px 8px rgba(0,0,0,0.2)) !important;
height: 80px !important;
display: flex !important;
align-items: center !important;
justify-content: center !important;
}
.product-card h3 {
font-size: 1.4rem !important;
font-weight: 700 !important;
margin-bottom: 1rem !important;
color: #fff !important;
position: relative !important;
z-index: 1 !important;
letter-spacing: -0.025em !important;
}
.product-description {
font-size: 0.95rem !important;
opacity: 0.9 !important;
line-height: 1.6 !important;
margin-bottom: 1.5rem !important;
position: relative !important;
z-index: 1 !important;
color: rgba(255, 255, 255, 0.8) !important;
}
.product-price {
font-size: 1.8rem !important;
font-weight: 700 !important;
color: #000000 !important;
margin-bottom: 1rem !important;
text-shadow: 0 1px 2px rgba(255, 255, 255, 0.8) !important;
position: relative !important;
z-index: 1 !important;
}
.product-rating {
font-size: 0.9rem !important;
margin-bottom: 2rem !important;
color: rgba(255, 255, 255, 0.8) !important;
position: relative !important;
z-index: 1 !important;
}
.product-card .btn {
width: 100% !important;
margin-top: auto !important;
position: relative !important;
z-index: 1 !important;
}
.section-cta {
text-align: center !important;
margin-top: 3rem !important;
}
/* Page Header with Glassmorphism */
.page-header {
padding: 6rem 0 4rem 0 !important;
margin-bottom: 3rem !important;
}
.header-container {
max-width: 1400px !important;
margin: 0 auto !important;
padding: 0 3rem !important;
}
.header-card {
background: linear-gradient(135deg, rgba(255, 255, 255, 0.18), rgba(255, 255, 255, 0.08)) !important;
backdrop-filter: blur(25px) !important;
-webkit-backdrop-filter: blur(25px) !important;
border-radius: 32px !important;
border: 1px solid rgba(255, 255, 255, 0.25) !important;
padding: 4rem 3rem !important;
margin: 0 3rem !important;
max-width: calc(100% - 6rem) !important;
color: white !important;
text-align: center !important;
box-shadow: 0 32px 96px rgba(0, 0, 0, 0.2), 0 16px 48px rgba(102, 126, 234, 0.15), inset 0 1px 0 rgba(255, 255, 255, 0.3) !important;
position: relative !important;
overflow: hidden !important;
}
.header-card::before {
content: '' !important;
position: absolute !important;
top: 0 !important;
left: 0 !important;
right: 0 !important;
bottom: 0 !important;
background: radial-gradient(circle at 50% 0%, rgba(255,255,255,0.12) 0%, transparent 70%) !important;
opacity: 0.5 !important;
pointer-events: none !important;
}
.header-card h1 {
font-size: 3rem !important;
font-weight: 700 !important;
margin-bottom: 1.5rem !important;
color: white !important;
text-shadow: 0 4px 8px rgba(0,0,0,0.3) !important;
position: relative !important;
z-index: 1 !important;
letter-spacing: -0.025em !important;
}
.header-card p {
font-size: 1.3rem !important;
line-height: 1.6 !important;
color: rgba(255, 255, 255, 0.9) !important;
margin: 0 !important;
max-width: 600px !important;
margin: 0 auto !important;
position: relative !important;
z-index: 1 !important;
}
/* Typography Improvements */
h1, h2, h3, h4, h5, h6 {
font-weight: 600 !important;
letter-spacing: -0.025em !important;
}
h2 {
color: white !important;
font-size: 2.5rem !important;
margin-bottom: 2rem !important;
text-align: center !important;
text-shadow: 0 2px 4px rgba(0,0,0,0.2) !important;
}
/* Responsive Design */
@media (max-width: 768px) {
.hero, .hero-section {
margin: 3rem 1.5rem 4rem 1.5rem !important;
max-width: calc(100% - 3rem) !important;
padding: 3rem 2rem !important;
border-radius: 24px !important;
}
.hero-section h1 {
font-size: 2.5rem !important;
}
.nav-container {
padding: 0 1rem !important;
}
.container {
padding: 1rem !important;
}
}
@media (max-width: 480px) {
.hero, .hero-section {
margin: 2rem 1rem 3rem 1rem !important;
max-width: calc(100% - 2rem) !important;
padding: 2.5rem 1.5rem !important;
border-radius: 20px !important;
}
}
/* Support CTA Responsive Design */
@media (max-width: 768px) {
.support-cta {
margin: 3rem 1.5rem 4rem 1.5rem !important;
max-width: calc(100% - 3rem) !important;
padding: 3rem 2rem !important;
border-radius: 24px !important;
}
.cta-content h2 {
font-size: 2rem !important;
}
.cta-features {
gap: 2rem !important;
}
.cta-actions {
flex-direction: column !important;
align-items: center !important;
}
}
@media (max-width: 480px) {
.support-cta {
margin: 2rem 1rem 3rem 1rem !important;
max-width: calc(100% - 2rem) !important;
padding: 2.5rem 1.5rem !important;
border-radius: 20px !important;
}
.cta-content h2 {
font-size: 1.8rem !important;
}
.cta-features {
flex-direction: column !important;
gap: 1.5rem !important;
}
}
/* Reviews Responsive Design */
@media (max-width: 768px) {
.reviews .container {
padding: 0 1.5rem !important;
}
.reviews .section-title {
font-size: 2rem !important;
margin-bottom: 3rem !important;
}
.reviews-grid {
grid-template-columns: 1fr !important;
gap: 2rem !important;
}
.review-card {
padding: 2rem !important;
border-radius: 20px !important;
}
.review-text {
font-size: 1rem !important;
}
}
@media (max-width: 480px) {
.reviews .container {
padding: 0 1rem !important;
}
.reviews .section-title {
font-size: 1.8rem !important;
}
.review-card {
padding: 1.5rem !important;
border-radius: 16px !important;
}
.review-text::before {
font-size: 2.5rem !important;
top: -0.8rem !important;
left: -0.3rem !important;
}
}
/* Footer Responsive Design */
@media (max-width: 768px) {
.footer {
margin: 3rem 1.5rem 0 1.5rem !important;
max-width: calc(100% - 3rem) !important;
border-radius: 24px 24px 0 0 !important;
padding: 3rem 0 3.5rem 0 !important; /* room for bottom bar */
position: relative !important;
}
.footer-container {
padding: 0 2rem !important;
}
.footer-simple h3 {
font-size: 1.7rem !important;
}
.footer-simple p {
font-size: 1rem !important;
}
.footer-bottom {
position: absolute !important;
left: 0 !important;
right: 0 !important;
bottom: 0 !important;
padding: 1rem 0 !important;
background: rgba(0,0,0,0.06) !important;
}
}
@media (max-width: 480px) {
.footer {
margin: 2rem 1rem 0 1rem !important;
max-width: calc(100% - 2rem) !important;
border-radius: 20px 20px 0 0 !important;
padding: 2.5rem 0 3rem 0 !important;
position: relative !important;
}
.footer-container {
padding: 0 1.5rem !important;
}
.footer-simple h3 {
font-size: 1.5rem !important;
}
.footer-simple p {
font-size: 0.95rem !important;
}
.footer-bottom {
position: absolute !important;
left: 0 !important;
right: 0 !important;
bottom: 0 !important;
padding: 1rem 0 !important;
background: rgba(0,0,0,0.06) !important;
}
.footer-bottom p {
font-size: 0.85rem !important;
}
}
/* Product Cards Responsive Design */
@media (max-width: 768px) {
.popular-products .container {
padding: 0 1.5rem !important;
}
.popular-products .section-title {
font-size: 2rem !important;
margin-bottom: 3rem !important;
}
.products-grid {
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)) !important;
gap: 2rem !important;
}
.product-card {
padding: 2rem !important;
border-radius: 20px !important;
}
.product-image {
font-size: 3rem !important;
height: 60px !important;
}
.product-card h3 {
font-size: 1.2rem !important;
}
.product-price {
font-size: 1.5rem !important;
}
}
@media (max-width: 480px) {
.popular-products .container {
padding: 0 1rem !important;
}
.popular-products .section-title {
font-size: 1.8rem !important;
}
.products-grid {
grid-template-columns: 1fr !important;
gap: 1.5rem !important;
}
.product-card {
padding: 1.5rem !important;
border-radius: 16px !important;
}
.product-image {
font-size: 2.5rem !important;
height: 50px !important;
}
}
/* Page Header Responsive Design */
@media (max-width: 768px) {
.page-header {
padding: 4rem 0 3rem 0 !important;
}
.header-container {
padding: 0 1.5rem !important;
}
.header-card {
margin: 0 1.5rem !important;
max-width: calc(100% - 3rem) !important;
padding: 3rem 2rem !important;
border-radius: 24px !important;
}
.header-card h1 {
font-size: 2.2rem !important;
}
.header-card p {
font-size: 1.1rem !important;
}
}
@media (max-width: 480px) {
.page-header {
padding: 3rem 0 2rem 0 !important;
}
.header-container {
padding: 0 1rem !important;
}
.header-card {
margin: 0 1rem !important;
max-width: calc(100% - 2rem) !important;
padding: 2.5rem 1.5rem !important;
border-radius: 20px !important;
}
.header-card h1 {
font-size: 1.9rem !important;
}
.header-card p {
font-size: 1rem !important;
}
}
/* Product Support CTA Section */
.product-support-cta {
padding: 4rem 0 !important;
margin: 3rem 0 !important;
}
.product-support-cta .container {
max-width: 1400px !important;
margin: 0 auto !important;
padding: 0 3rem !important;
}
.product-support-cta .cta-content {
text-align: center !important;
max-width: 800px !important;
margin: 0 auto !important;
}
.product-support-cta h2 {
color: white !important;
font-size: 2.2rem !important;
font-weight: 700 !important;
margin-bottom: 1.5rem !important;
text-shadow: 0 2px 4px rgba(0,0,0,0.2) !important;
}
.product-support-cta p {
color: rgba(255, 255, 255, 0.9) !important;
font-size: 1.1rem !important;
line-height: 1.6 !important;
margin-bottom: 2.5rem !important;
}
.product-support-cta .btn {
margin: 0 auto !important;
}
/* Product Support CTA Responsive */
@media (max-width: 768px) {
.product-support-cta .container {
padding: 0 1.5rem !important;
}
.product-support-cta h2 {
font-size: 1.8rem !important;
}
.product-support-cta p {
font-size: 1rem !important;
}
}
@media (max-width: 480px) {
.product-support-cta .container {
padding: 0 1rem !important;
}
.product-support-cta h2 {
font-size: 1.6rem !important;
}
}
/* Chat Page Styles */
.status-indicator {
display: flex;
align-items: center;
gap: 8px;
margin-top: 1rem;
}
.status-dot {
width: 12px;
height: 12px;
border-radius: 50%;
background: #10b981;
box-shadow: 0 0 10px rgba(16, 185, 129, 0.5);
animation: pulse 2s infinite;
}
@keyframes pulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.5; }
}
.chat-section {
padding: 4rem 0;
}
.chat-container {
max-width: 800px;
margin: 0 auto;
}
.chat-messages {
height: 500px;
overflow-y: auto;
padding: 2rem;
margin-bottom: 0;
border: 1px solid rgba(255, 255, 255, 0.2);
border-bottom: none;
border-radius: 20px 20px 0 0;
background: rgba(255, 255, 255, 0.95);
backdrop-filter: blur(10px);
}
.welcome-message {
display: flex;
gap: 1rem;
align-items: flex-start;
padding: 1.5rem;
background: rgba(102, 126, 234, 0.1);
border-radius: 15px;
border: 1px solid rgba(102, 126, 234, 0.2);
}
.agent-avatar {
font-size: 2rem;
flex-shrink: 0;
}
.message-content h4 {
margin: 0 0 0.5rem 0;
color: #2d3748;
font-weight: 600;
}
.message-content p {
margin: 0;
color: #4a5568;
line-height: 1.5;
}
.user-message {
display: flex;
justify-content: flex-end;
margin-bottom: 1rem;
}
.user-message .message-bubble {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
padding: 1rem 1.5rem;
border-radius: 20px 20px 5px 20px;
max-width: 70%;
word-wrap: break-word;
}
.ai-message {
display: flex;
gap: 1rem;
margin-bottom: 1rem;
}
.ai-message .message-bubble {
background: #f7fafc;
color: #2d3748;
padding: 1rem 1.5rem;
border-radius: 20px 20px 20px 5px;
max-width: 70%;
word-wrap: break-word;
border: 1px solid #e2e8f0;
}
.typing-indicator {
display: flex;
align-items: center;
gap: 0.5rem;
color: #718096;
font-size: 0.9rem;
margin-bottom: 1rem;
}
.typing-dots {
display: flex;
gap: 3px;
}
.typing-dots span {
width: 6px;
height: 6px;
border-radius: 50%;
background: #718096;
animation: typing 1.4s infinite ease-in-out;
}
.typing-dots span:nth-child(1) { animation-delay: -0.32s; }
.typing-dots span:nth-child(2) { animation-delay: -0.16s; }
@keyframes typing {
0%, 80%, 100% { transform: scale(0.8); opacity: 0.5; }
40% { transform: scale(1); opacity: 1; }
}
.chat-input-form {
position: relative;
}
.input-group {
display: flex;
align-items: end;
gap: 1rem;
padding: 1.5rem;
background: rgba(255, 255, 255, 0.95);
border-radius: 0 0 20px 20px;
border: 1px solid rgba(255, 255, 255, 0.2);
border-top: 1px solid #e2e8f0;
backdrop-filter: blur(10px);
}
.input-group textarea {
flex: 1;
background: transparent;
border: none;
color: #2d3748;
font-size: 1rem;
line-height: 1.5;
resize: none;
outline: none;
min-height: 20px;
max-height: 120px;
}
.input-group textarea::placeholder {
color: #a0aec0;
}
.send-button {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border: none;
border-radius: 50%;
width: 44px;
height: 44px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
transition: all 0.3s ease;
flex-shrink: 0;
}
.send-button:hover:not(:disabled) {
transform: scale(1.05);
box-shadow: 0 8px 25px rgba(102, 126, 234, 0.4);
}
.send-button:disabled {
opacity: 0.5;
cursor: not-allowed;
}
.send-icon {
color: white;
font-size: 1.2rem;
transform: rotate(-45deg);
}
/* Chat Responsive Design */
@media (max-width: 768px) {
.chat-messages {
height: 400px;
padding: 1rem;
}
.welcome-message {
flex-direction: column;
text-align: center;
}
.user-message .message-bubble,
.ai-message .message-bubble {
max-width: 85%;
}
.input-group {
padding: 1rem;
}
}
/* Floating Chat Widget Styles */
.floating-chat-widget {
position: fixed;
bottom: 20px;
right: 20px;
z-index: 1000;
font-family: 'Inter', sans-serif;
}
.chat-toggle-btn {
position: relative;
width: 60px;
height: 60px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
box-shadow: 0 8px 25px rgba(102, 126, 234, 0.4);
transition: all 0.3s ease;
border: 3px solid rgba(255, 255, 255, 0.2);
}
.chat-toggle-btn:hover {
transform: scale(1.05);
box-shadow: 0 12px 30px rgba(102, 126, 234, 0.6);
}
.chat-toggle-btn .chat-icon {
font-size: 1.5rem;
color: white;
}
.notification-dot {
position: absolute;
top: -2px;
right: -2px;
width: 12px;
height: 12px;
background: #ef4444;
border-radius: 50%;
border: 2px solid white;
animation: pulse 2s infinite;
}
.chat-window {
position: absolute;
bottom: 80px;
right: 0;
width: 380px;
height: 500px;
background: rgba(255, 255, 255, 0.95);
backdrop-filter: blur(20px);
border-radius: 20px;
border: 1px solid rgba(255, 255, 255, 0.2);
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.1);
display: flex;
flex-direction: column;
overflow: hidden;
animation: slideUp 0.3s ease;
}
@keyframes slideUp {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.chat-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 1rem 1.5rem;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border-radius: 20px 20px 0 0;
}
.chat-header-info {
display: flex;
align-items: center;
gap: 0.75rem;
}
.agent-avatar-small {
font-size: 1.2rem;
}
.agent-info h4 {
margin: 0;
font-size: 1rem;
font-weight: 600;
}
.status-text {
font-size: 0.8rem;
opacity: 0.9;
}
.chat-controls {
display: flex;
gap: 0.5rem;
}
.control-btn {
background: rgba(255, 255, 255, 0.2);
border: none;
color: white;
width: 24px;
height: 24px;
border-radius: 50%;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
font-size: 1rem;
transition: background 0.2s ease;
}
.control-btn:hover {
background: rgba(255, 255, 255, 0.3);
}
.control-btn#close-chat {
background: rgba(255, 193, 193, 0.3);
color: #fff;
}
.control-btn#close-chat:hover {
background: rgba(255, 193, 193, 0.6);
color: #fff;
}
.floating-chat-messages {
flex: 1;
overflow-y: auto;
padding: 1rem;
}
.welcome-message-floating {
display: flex;
gap: 0.75rem;
align-items: flex-start;
padding: 1rem;
background: rgba(102, 126, 234, 0.1);
border-radius: 12px;
border: 1px solid rgba(102, 126, 234, 0.2);
margin-bottom: 1rem;
}
.welcome-message-floating .agent-avatar {
font-size: 1.5rem;
flex-shrink: 0;
}
.welcome-message-floating .message-content h4 {
margin: 0 0 0.5rem 0;
color: #2d3748;
font-weight: 600;
font-size: 0.9rem;
}
.welcome-message-floating .message-content p {
margin: 0;
color: #4a5568;
line-height: 1.4;
font-size: 0.85rem;
}
.floating-user-message {
display: flex;
justify-content: flex-end;
margin-bottom: 1rem;
}
.floating-user-message .message-bubble {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
padding: 0.75rem 1rem;
border-radius: 15px 15px 4px 15px;
max-width: 80%;
word-wrap: break-word;
font-size: 0.9rem;
}
.floating-ai-message {
display: flex;
gap: 0.75rem;
margin-bottom: 1rem;
}
.floating-ai-message .message-bubble {
background: #f7fafc;
color: #2d3748;
padding: 0.75rem 1rem;
border-radius: 15px 15px 15px 4px;
max-width: 80%;
word-wrap: break-word;
border: 1px solid #e2e8f0;
font-size: 0.9rem;
}
.floating-ai-message .agent-avatar {
font-size: 1.2rem;
flex-shrink: 0;
}
/* Enhancement Status Indicators */
.enhancement-status {
margin-top: 0.5rem;
padding: 0.25rem 0.5rem;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
font-size: 0.7rem;
border-radius: 12px;
display: inline-flex;
align-items: center;
gap: 0.3rem;
opacity: 0.9;
}
.rag-indicator, .ticket-indicator {
font-size: 0.8rem;
}
.response-time {
margin-top: 0.3rem;
color: #a0aec0;
font-size: 0.6rem;
text-align: right;
}
.floating-typing-indicator {
display: flex;
align-items: center;
gap: 0.5rem;
color: #718096;
font-size: 0.8rem;
padding: 0 1rem 0.5rem 1rem;
}
.floating-chat-input-form {
border-top: 1px solid #e2e8f0;
}
.floating-input-group {
display: flex;
align-items: end;
gap: 0.5rem;
padding: 1rem;
background: rgba(255, 255, 255, 0.95);
flex-wrap: wrap;
}
.floating-input-group textarea {
flex: 1;
background: transparent;
border: 1px solid #e2e8f0;
border-radius: 12px;
padding: 0.75rem;
color: #2d3748;
font-size: 0.9rem;
line-height: 1.4;
resize: none;
outline: none;
min-height: 20px;
max-height: 80px;
font-family: 'Inter', sans-serif;
}
.floating-input-group textarea::placeholder {
color: #a0aec0;
}
.floating-input-group textarea:focus {
border-color: #667eea;
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
}
.floating-send-button {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border: none;
border-radius: 50%;
width: 36px;
height: 36px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
transition: all 0.3s ease;
flex-shrink: 0;
}
.floating-send-button:hover:not(:disabled) {
transform: scale(1.05);
box-shadow: 0 6px 20px rgba(102, 126, 234, 0.4);
}
.floating-send-button:disabled {
opacity: 0.5;
cursor: not-allowed;
}
.floating-send-button .send-icon {
color: white;
font-size: 1rem;
transform: rotate(-45deg);
}
/* Floating Chat Responsive Design */
@media (max-width: 480px) {
.floating-chat-widget {
bottom: 15px;
right: 15px;
}
.chat-window {
width: calc(100vw - 30px);
height: 70vh;
bottom: 80px;
right: -15px;
}
.chat-toggle-btn {
width: 50px;
height: 50px;
}
.chat-toggle-btn .chat-icon {
font-size: 1.2rem;
}
.floating-user-message .message-bubble,
.floating-ai-message .message-bubble {
max-width: 90%;
}
.floating-input-group {
padding: 0.75rem;
gap: 0.4rem;
}
}
</style>
<!-- Global modal readability overrides -->
<style>
/* Make modals readable by default */
.modal-content {
background: rgba(255,255,255,0.98) !important;
color: #1a202c !important;
}
.modal-content * {
color: #1a202c !important;
}
.modal .close-modal {
color: #1a202c !important;
}
</style>
{% block extra_head %}{% endblock %}
</head>
<body>
<!-- Navigation Header -->
<nav class="navbar">
<div class="nav-container">
<div class="nav-brand">
<a href="{{ url_for('homepage') }}" class="brand-logo">
<span class="logo-icon">🔌</span>
<span class="brand-text">Too Many Cables</span>
</a>
</div>
<div class="nav-menu" id="nav-menu">
<a href="{{ url_for('homepage') }}" class="nav-link {% if request.endpoint == 'homepage' %}active{% endif %}">Home</a>
<a href="{{ url_for('products') }}" class="nav-link {% if request.endpoint == 'products' %}active{% endif %}">Products</a>
<a href="{{ url_for('tickets') }}" class="nav-link {% if request.endpoint == 'tickets' %}active{% endif %}" id="tickets-link" style="display: none;">
My Tickets
</a>
<a href="#" id="nav-chat-trigger" class="nav-link chat-link">
<span class="chat-icon">💬</span> Live Chat
</a>
</div>
<div class="nav-user">
<div id="user-menu" class="user-menu">
<span id="user-greeting" class="user-greeting" style="display: none;">
Hello, <span id="user-name"></span>
</span>
<button id="auth-btn" class="btn btn-outline">Login</button>
</div>
</div>
<div class="nav-toggle" id="nav-toggle">
<span class="bar"></span>
<span class="bar"></span>
<span class="bar"></span>
</div>
</div>
</nav>
<!-- Main Content -->
<main class="main-content">
{% block content %}{% endblock %}
</main>
<!-- Footer -->
<footer class="footer">
<div class="footer-container">
<div class="footer-simple">
<h3>Too Many Cables</h3>
<p>Your trusted source for premium cables and accessories since 2018.</p>
</div>
</div>
<div class="footer-bottom">
<div class="footer-container">
<p>&copy; 2025 Too Many Cables. All rights reserved.</p>
</div>
</div>
</footer>
<!-- Modal CSS -->
<style>
.modal {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
z-index: 10000;
}
.modal-content {
background: white;
border-radius: 10px;
padding: 20px;
max-width: 400px;
width: 90%;
max-height: 90vh;
overflow-y: auto;
}
.modal-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
border-bottom: 1px solid #eee;
padding-bottom: 10px;
}
.close-modal {
font-size: 24px;
cursor: pointer;
color: #999;
}
.close-modal:hover {
color: #333;
}
.form-group {
margin-bottom: 15px;
}
.form-group label {
display: block;
margin-bottom: 5px;
font-weight: bold;
}
.form-group input {
width: 100%;
padding: 10px;
border: 1px solid #ddd;
border-radius: 5px;
font-size: 14px;
}
.form-actions {
display: flex;
gap: 10px;
justify-content: space-between;
margin-top: 20px;
}
.btn {
padding: 10px 20px;
border: none;
border-radius: 5px;
cursor: pointer;
font-size: 14px;
text-decoration: none;
display: inline-block;
text-align: center;
}
.btn-primary {
background: #007bff;
color: white;
}
.btn-primary:hover {
background: #0056b3;
}
.btn-outline {
background: transparent;
color: #007bff;
border: 1px solid #007bff;
}
.btn-outline:hover {
background: #007bff;
color: white;
}
.btn-link {
background: transparent;
color: #007bff;
text-decoration: underline;
}
.btn-link:hover {
color: #0056b3;
}
</style>
<!-- Login Modal -->
<div id="login-modal" class="modal" style="display: none;">
<div class="modal-content">
<div class="modal-header">
<h3>Customer Login</h3>
<span class="close-modal" id="close-login-modal">&times;</span>
</div>
<div class="modal-body">
<form id="login-form">
<div class="form-group">
<label for="login-email">Email:</label>
<input type="email" id="login-email" name="email" required>
</div>
<div class="form-group">
<label for="login-password">Password:</label>
<input type="password" id="login-password" name="password" required>
</div>
<div class="form-actions">
<button type="submit" class="btn btn-primary">Login</button>
<button type="button" id="show-register" class="btn btn-link">Create Account</button>
</div>
</form>
</div>
</div>
</div>
<script>
// Ensure any modal we open uses readable colors — defensive inline styles
function ensureModalReadability(modalEl) {
if (!modalEl) return;
const content = modalEl.querySelector('.modal-content');
if (content) {
content.style.backgroundColor = 'rgba(255,255,255,0.98)';
content.style.color = '#1a202c';
// also ensure close buttons are visible
const close = content.querySelector('.close-modal');
if (close) close.style.color = '#1a202c';
// force all text descendants to inherit the color
const descendants = content.querySelectorAll('*');
descendants.forEach(el => el.style.color = '#1a202c');
}
}
// Hook into modal opens across the site
document.addEventListener('click', function(e) {
// If something opens a modal by toggling style.display = 'flex' or similar, detect the modal ancestor
const modal = e.target.closest('.modal');
if (modal && (modal.style.display === 'flex' || getComputedStyle(modal).display === 'flex')) {
ensureModalReadability(modal);
}
});
// Also observe DOM for modals being shown programmatically
const observer = new MutationObserver((mutations) => {
for (const m of mutations) {
if (m.type === 'attributes' && m.target && m.target.classList && m.target.classList.contains('modal')) {
if (getComputedStyle(m.target).display === 'flex') ensureModalReadability(m.target);
}
}
});
// Start observing any modals present now
document.querySelectorAll('.modal').forEach(modal => observer.observe(modal, { attributes: true }));
</script>
<!-- Register Modal -->
<div id="register-modal" class="modal" style="display: none;">
<div class="modal-content">
<div class="modal-header">
<h3>Create Account</h3>
<span class="close-modal" id="close-register-modal">&times;</span>
</div>
<div class="modal-body">
<form id="register-form">
<div class="form-group">
<label for="register-email">Email:</label>
<input type="email" id="register-email" name="email" required>
</div>
<div class="form-group">
<label for="register-first-name">First Name:</label>
<input type="text" id="register-first-name" name="first_name" required>
</div>
<div class="form-group">
<label for="register-last-name">Last Name:</label>
<input type="text" id="register-last-name" name="last_name" required>
</div>
<div class="form-group">
<label for="register-password">Password:</label>
<input type="password" id="register-password" name="password" required>
</div>
<div class="form-group">
<label for="register-phone">Phone (optional):</label>
<input type="tel" id="register-phone" name="phone">
</div>
<div class="form-group">
<label for="register-company">Company (optional):</label>
<input type="text" id="register-company" name="company">
</div>
<div class="form-actions">
<button type="submit" class="btn btn-primary">Create Account</button>
<button type="button" id="show-login" class="btn btn-link">Already have account? Login</button>
</div>
</form>
</div>
</div>
</div>
<!-- Floating Chat Widget -->
<div id="floating-chat-widget" class="floating-chat-widget">
<!-- Chat Toggle Button -->
<div id="chat-toggle-btn" class="chat-toggle-btn">
<span class="chat-icon">💬</span>
<span class="notification-dot" id="notification-dot" style="display: none;"></span>
</div>
<!-- Chat Window -->
<div id="chat-window" class="chat-window" style="display: none;">
<div class="chat-header">
<div class="chat-header-info">
<div class="agent-avatar-small">🤖</div>
<div class="agent-info">
<h4>TMCBot</h4>
<span class="status-text">Online</span>
</div>
</div>
<div class="chat-controls">
<button id="minimize-chat" class="control-btn" title="Minimize"></button>
<button id="close-chat" class="control-btn" title="End Conversation & Close">×</button>
</div>
</div>
<div id="floating-chat-messages" class="floating-chat-messages">
<div class="welcome-message-floating">
<div class="agent-avatar">🤖</div>
<div class="message-content">
<h4>Hi! I'm TMCBot</h4>
<p>I'm here to help you find the perfect cables and accessories. Ask me about products, compatibility, or any technical questions!</p>
</div>
</div>
</div>
<div class="floating-typing-indicator" id="floating-typing-indicator" style="display: none;">
<div class="typing-dots">
<span></span>
<span></span>
<span></span>
</div>
<span>TMCBot is typing...</span>
</div>
<form id="floating-chat-form" class="floating-chat-input-form" onsubmit="event.preventDefault(); return false;" novalidate>
<div class="floating-input-group">
<textarea
id="floating-message-input"
placeholder="Type your message here..."
rows="1"
maxlength="1000"
></textarea>
<button type="submit" id="floating-send-button" class="floating-send-button" disabled>
<span class="send-icon"></span>
</button>
</div>
</form>
</div>
</div>
<script src="{{ url_for('static', filename='script.js') }}"></script>
<!-- Login Modal JavaScript -->
<script>
document.addEventListener('DOMContentLoaded', function() {
// Authentication elements
const authBtn = document.getElementById('auth-btn');
const loginModal = document.getElementById('login-modal');
const closeLoginModal = document.getElementById('close-login-modal');
const loginForm = document.getElementById('login-form');
const registerModal = document.getElementById('register-modal');
const closeRegisterModal = document.getElementById('close-register-modal');
const registerForm = document.getElementById('register-form');
const showRegisterBtn = document.getElementById('show-register');
const showLoginBtn = document.getElementById('show-login');
let currentUser = null;
// Immediately set logged-out state on page load
updateUserInterface(null);
// Handle auth button click (login or logout)
if (authBtn) {
authBtn.addEventListener('click', function(e) {
e.preventDefault();
if (currentUser) {
// User is logged in, so logout
handleLogout();
} else {
// User is logged out, so show login modal
if (loginModal) {
loginModal.style.display = 'flex';
}
}
});
}
// Close modals
if (closeLoginModal) {
closeLoginModal.addEventListener('click', function() {
loginModal.style.display = 'none';
});
}
if (closeRegisterModal) {
closeRegisterModal.addEventListener('click', function() {
registerModal.style.display = 'none';
});
}
// Switch between login and register
if (showRegisterBtn) {
showRegisterBtn.addEventListener('click', function() {
loginModal.style.display = 'none';
registerModal.style.display = 'flex';
});
}
if (showLoginBtn) {
showLoginBtn.addEventListener('click', function() {
registerModal.style.display = 'none';
loginModal.style.display = 'flex';
});
}
// Close modals when clicking outside
window.addEventListener('click', function(event) {
if (event.target === loginModal) {
loginModal.style.display = 'none';
}
if (event.target === registerModal) {
registerModal.style.display = 'none';
}
});
// Handle login form submission
if (loginForm) {
loginForm.addEventListener('submit', function(e) {
e.preventDefault();
const email = document.getElementById('login-email').value;
const password = document.getElementById('login-password').value;
fetch('/api/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ email, password })
})
.then(response => response.json())
.then(data => {
if (data.success) {
// Login successful
loginModal.style.display = 'none';
updateUserInterface(data.user);
showNotification('Login successful!', 'success');
// Reload page to update all user-specific content
setTimeout(() => {
window.location.reload();
}, 1000);
} else {
showNotification('Login failed: ' + data.error, 'error');
}
})
.catch(error => {
console.error('Login error:', error);
showNotification('Login failed. Please try again.', 'error');
});
});
}
// Handle register form submission
if (registerForm) {
registerForm.addEventListener('submit', function(e) {
e.preventDefault();
const formData = new FormData(registerForm);
const registerData = Object.fromEntries(formData);
fetch('/api/register', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(registerData)
})
.then(response => response.json())
.then(data => {
if (data.success) {
registerModal.style.display = 'none';
showNotification('Registration successful! Please check your email to verify your account.', 'success');
// Switch to login modal
setTimeout(() => {
loginModal.style.display = 'flex';
}, 2000);
} else {
showNotification('Registration failed: ' + data.error, 'error');
}
})
.catch(error => {
console.error('Registration error:', error);
showNotification('Registration failed. Please try again.', 'error');
});
});
}
// Handle logout
function handleLogout() {
fetch('/api/logout', {
method: 'POST'
})
.then(response => response.json())
.then(data => {
if (data.success) {
updateUserInterface(null);
showNotification('Logged out successfully!', 'success');
// Reload page to clear user-specific content
setTimeout(() => {
window.location.reload();
}, 1000);
}
})
.catch(error => {
console.error('Logout error:', error);
});
}
// Update user interface based on login status
function updateUserInterface(user) {
const userGreeting = document.getElementById('user-greeting');
const userName = document.getElementById('user-name');
const ticketsLink = document.getElementById('tickets-link');
console.log('updateUserInterface called with user:', user);
console.log('authBtn found:', !!authBtn);
currentUser = user;
if (user) {
// User is logged in
console.log('Setting logged in state');
if (authBtn) {
authBtn.textContent = 'Logout';
authBtn.title = 'Click to logout';
}
if (userGreeting) {
userGreeting.style.display = 'inline-block';
if (userName) userName.textContent = user.name;
}
if (ticketsLink) ticketsLink.style.display = 'inline-block';
} else {
// User is logged out
console.log('Setting logged out state');
if (authBtn) {
authBtn.textContent = 'Login';
authBtn.title = 'Click to login';
}
if (userGreeting) userGreeting.style.display = 'none';
if (ticketsLink) ticketsLink.style.display = 'none';
}
}
// Show notification
function showNotification(message, type) {
// Create notification element
const notification = document.createElement('div');
notification.className = `notification ${type}`;
notification.innerHTML = `
<div class="notification-content">
<span>${message}</span>
<button class="notification-close">&times;</button>
</div>
`;
// Add styles if not already present
if (!document.getElementById('notification-styles')) {
const style = document.createElement('style');
style.id = 'notification-styles';
style.textContent = `
.notification {
position: fixed;
top: 20px;
right: 20px;
background: white;
padding: 1rem 1.5rem;
border-radius: 8px;
box-shadow: 0 4px 20px rgba(0,0,0,0.15);
z-index: 10000;
transition: all 0.3s ease;
}
.notification.success {
border-left: 4px solid #10b981;
}
.notification.error {
border-left: 4px solid #ef4444;
}
.notification-content {
display: flex;
align-items: center;
gap: 1rem;
}
.notification-close {
background: none;
border: none;
font-size: 1.2rem;
cursor: pointer;
opacity: 0.7;
}
.notification-close:hover {
opacity: 1;
}
`;
document.head.appendChild(style);
}
document.body.appendChild(notification);
// Close notification
const closeBtn = notification.querySelector('.notification-close');
closeBtn.addEventListener('click', () => {
notification.remove();
});
// Auto-close after 5 seconds
setTimeout(() => {
if (notification.parentNode) {
notification.remove();
}
}, 5000);
}
// Check current user status on page load
fetch('/api/user')
.then(response => response.json())
.then(data => {
if (data.success && data.user) {
updateUserInterface(data.user);
} else {
updateUserInterface(null);
}
})
.catch(error => {
console.log('No user logged in');
updateUserInterface(null);
});
});
</script>
<!-- Floating Chat Widget JavaScript -->
<script>
document.addEventListener('DOMContentLoaded', function() {
const chatToggleBtn = document.getElementById('chat-toggle-btn');
const chatWindow = document.getElementById('chat-window');
const minimizeBtn = document.getElementById('minimize-chat');
const closeBtn = document.getElementById('close-chat');
const navChatTrigger = document.getElementById('nav-chat-trigger');
const floatingChatForm = document.getElementById('floating-chat-form');
const floatingMessageInput = document.getElementById('floating-message-input');
const floatingSendButton = document.getElementById('floating-send-button');
const floatingChatMessages = document.getElementById('floating-chat-messages');
const floatingTypingIndicator = document.getElementById('floating-typing-indicator');
let isChatOpen = localStorage.getItem('floating_chat_open') === 'true';
let messageHistory = JSON.parse(localStorage.getItem('floating_chat_history') || '[]');
// Initialize chat state on page load
function initializeChatState() {
if (isChatOpen) {
chatWindow.style.display = 'flex';
floatingMessageInput.focus();
} else {
chatWindow.style.display = 'none';
}
// Restore chat history
restoreChatHistory();
}
// Toggle chat window
function toggleChat() {
if (isChatOpen) {
chatWindow.style.display = 'none';
isChatOpen = false;
localStorage.setItem('floating_chat_open', 'false');
} else {
chatWindow.style.display = 'flex';
isChatOpen = true;
localStorage.setItem('floating_chat_open', 'true');
floatingMessageInput.focus();
}
}
// Event listeners
chatToggleBtn.addEventListener('click', toggleChat);
navChatTrigger.addEventListener('click', function(e) {
e.preventDefault();
if (!isChatOpen) {
toggleChat();
}
});
// Handle all chat trigger buttons
document.addEventListener('click', function(e) {
if (e.target.classList.contains('chat-trigger-btn') || e.target.closest('.chat-trigger-btn')) {
e.preventDefault();
if (!isChatOpen) {
toggleChat();
}
}
});
minimizeBtn.addEventListener('click', function() {
chatWindow.style.display = 'none';
isChatOpen = false;
localStorage.setItem('floating_chat_open', 'false');
});
closeBtn.addEventListener('click', function() {
smartCloseChat();
});
// Smart close: End conversation and minimize
async function smartCloseChat() {
const conversationId = localStorage.getItem('floating_chat_conversation_id');
const hasMessages = messageHistory.length > 0;
// Immediately close the chat for responsive UI
chatWindow.style.display = 'none';
isChatOpen = false;
localStorage.setItem('floating_chat_open', 'false');
// Clear chat history immediately
clearChatHistory();
// End conversation in the background (non-blocking)
if (conversationId && hasMessages) {
// Don't await - let it run in background
fetch('/api/conversation/end', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
conversation_id: conversationId
})
}).then(response => {
if (response.ok) {
return response.json();
}
}).then(result => {
if (result) {
console.log('Conversation ended:', result.message || 'Successfully ended conversation');
}
}).catch(error => {
console.error('Error ending conversation:', error);
});
}
}
// Auto-resize textarea
floatingMessageInput.addEventListener('input', function() {
this.style.height = 'auto';
this.style.height = Math.min(this.scrollHeight, 80) + 'px';
// Enable/disable send button
floatingSendButton.disabled = this.value.trim().length === 0;
});
// Handle message sending
floatingChatForm.addEventListener('submit', function(e) {
console.log('=== FORM SUBMIT EVENT TRIGGERED ===');
e.preventDefault();
const message = floatingMessageInput.value.trim();
console.log('Message value:', message);
if (!message) {
console.log('Message empty, returning');
return;
}
// Add user message to chat
addMessage(message, 'user');
floatingMessageInput.value = '';
floatingMessageInput.style.height = 'auto';
floatingSendButton.disabled = true;
// Show typing indicator
floatingTypingIndicator.style.display = 'flex';
// Log the request for debugging
console.log('Sending message to /api/chat');
console.log('Current location:', window.location.href);
console.log('Will fetch from:', window.location.origin + '/api/chat');
// Send message to backend
const apiUrl = window.location.origin + '/api/chat';
console.log('Starting fetch to:', apiUrl);
fetch(apiUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
message: message,
conversation_id: localStorage.getItem('floating_chat_conversation_id')
})
})
.then(response => {
console.log('Response received, status:', response.status);
console.log('Response ok:', response.ok);
// Parse JSON regardless of status
return response.json().then(data => ({ data, status: response.status, ok: response.ok }));
})
.then(({ data, status, ok }) => {
console.log('JSON parsed, data:', data);
// Hide typing indicator
floatingTypingIndicator.style.display = 'none';
// Check if request was successful
if (!ok) {
const errorMsg = data.error || `Server error: ${status}`;
addMessage('Error: ' + errorMsg, 'ai');
return;
}
// Store conversation ID for future messages
if (data.conversation_id) {
localStorage.setItem('floating_chat_conversation_id', data.conversation_id);
}
// Add AI response to chat with RAG and tickets info
if (data.success && data.response) {
addMessage(data.response, 'ai', false, {
rag_used: data.rag_used,
rag_context_length: data.rag_context_length,
tickets_used: data.tickets_used,
tickets_count: data.tickets_count,
response_time_ms: data.response_time_ms
});
} else if (data.error) {
addMessage('Sorry, there was an error: ' + data.error, 'ai');
} else {
// Handle case where success is false but no error message
addMessage('Sorry, an unexpected error occurred. Please try again.', 'ai');
}
})
.catch(error => {
console.error('Error:', error);
console.error('Error type:', error.name);
console.error('Error message:', error.message);
console.error('Full error:', JSON.stringify(error, Object.getOwnPropertyNames(error)));
floatingTypingIndicator.style.display = 'none';
// Display the actual error message
const errorMsg = error.message || 'Sorry, there was an error processing your message. Please try again.';
addMessage('Error: ' + errorMsg, 'ai');
});
});
// Add message to chat
function addMessage(message, sender, skipHistory = false, metadata = {}) {
const messageElement = document.createElement('div');
if (sender === 'user') {
messageElement.className = 'floating-user-message';
messageElement.innerHTML = `
<div class="message-bubble">${escapeHtml(message)}</div>
`;
} else {
messageElement.className = 'floating-ai-message';
// Build enhancement status indicators
let enhancementStatus = '';
const statusItems = [];
if (metadata.rag_used) {
statusItems.push(`<span class="rag-indicator">📚</span> Knowledge Enhanced`);
}
if (metadata.tickets_used) {
statusItems.push(`<span class="ticket-indicator">🎫</span> Tickets Accessed`);
}
if (statusItems.length > 0) {
const title = [];
if (metadata.rag_used) title.push(`Knowledge enhanced (${metadata.rag_context_length} chars)`);
if (metadata.tickets_used) title.push(`Tickets accessed (${metadata.tickets_count} tickets)`);
enhancementStatus = `<div class="enhancement-status" title="${title.join(', ')}">
${statusItems.join(' • ')}
</div>`;
}
// Build response time info
let responseTime = '';
if (metadata.response_time_ms) {
responseTime = `<div class="response-time">${metadata.response_time_ms}ms</div>`;
}
messageElement.innerHTML = `
<div class="agent-avatar">🤖</div>
<div class="message-bubble">
${escapeHtml(message)}
${enhancementStatus}
${responseTime}
</div>
`;
}
floatingChatMessages.appendChild(messageElement);
floatingChatMessages.scrollTop = floatingChatMessages.scrollHeight;
// Store in message history and localStorage (unless restoring from history)
if (!skipHistory) {
const messageData = { message, sender, timestamp: new Date().toISOString() };
messageHistory.push(messageData);
localStorage.setItem('floating_chat_history', JSON.stringify(messageHistory));
}
}
// Restore chat history from localStorage
function restoreChatHistory() {
// Clear current messages except welcome message
const welcomeMessage = floatingChatMessages.querySelector('.welcome-message-floating');
floatingChatMessages.innerHTML = '';
if (welcomeMessage) {
floatingChatMessages.appendChild(welcomeMessage);
}
// Add stored messages
messageHistory.forEach(msgData => {
addMessage(msgData.message, msgData.sender, true);
});
}
// Clear chat history
function clearChatHistory() {
messageHistory = [];
localStorage.removeItem('floating_chat_history');
localStorage.removeItem('floating_chat_conversation_id');
// Reset UI to welcome message only
const welcomeMessage = floatingChatMessages.querySelector('.welcome-message-floating');
floatingChatMessages.innerHTML = '';
if (welcomeMessage) {
floatingChatMessages.appendChild(welcomeMessage);
}
}
// Escape HTML function
function escapeHtml(text) {
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}
// Enter key to send message (with Shift+Enter for new line)
floatingMessageInput.addEventListener('keypress', function(e) {
if (e.key === 'Enter' && !e.shiftKey) {
e.preventDefault();
floatingChatForm.dispatchEvent(new Event('submit'));
}
});
// Initialize chat state when page loads
initializeChatState();
// Close chat when clicking outside (optional)
document.addEventListener('click', function(e) {
if (isChatOpen && !document.getElementById('floating-chat-widget').contains(e.target)) {
// Uncomment the next line if you want clicking outside to close the chat
// toggleChat();
}
});
});
</script>
{% block extra_scripts %}{% endblock %}
</body>
</html>