summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobby Zambito <contact@robbyzambito.me>2025-08-06 19:35:38 -0400
committerRobby Zambito <contact@robbyzambito.me>2025-08-06 19:38:52 -0400
commitd35903bf5b56cc40e3b61d34f57c192d6a8b3430 (patch)
tree93e234b499b497f070aab282aa4841b9588d44ee
parent60716f3ebb54f8a8f8426611c2727737678c66fb (diff)
Added contact page
Prompt: Create a contact page
-rw-r--r--static/about.html4
-rw-r--r--static/blog.html4
-rw-r--r--static/contact-script.js399
-rw-r--r--static/contact-styles.css773
-rw-r--r--static/contact.html368
-rw-r--r--static/index.html4
6 files changed, 1546 insertions, 6 deletions
diff --git a/static/about.html b/static/about.html
index 1b223c3..79a015d 100644
--- a/static/about.html
+++ b/static/about.html
@@ -15,7 +15,7 @@
<li><a href="/#features" class="nav-link">Features</a></li>
<li><a href="/#pricing" class="nav-link">Pricing</a></li>
<li><a href="about.html" class="nav-link active">About</a></li>
- <li><a href="#contact" class="nav-link">Contact</a></li>
+ <li><a href="/contact.html" class="nav-link">Contact</a></li>
</ul>
<div class="nav-actions">
<a href="login.html" class="btn btn-ghost">Sign In</a>
@@ -259,7 +259,7 @@
<h4>Support</h4>
<ul>
<li><a href="#help">Help Center</a></li>
- <li><a href="#contact">Contact</a></li>
+ <li><a href="/contact.html">Contact</a></li>
<li><a href="#status">Status</a></li>
<li><a href="#api">API Docs</a></li>
</ul>
diff --git a/static/blog.html b/static/blog.html
index e580cf7..d9dc7eb 100644
--- a/static/blog.html
+++ b/static/blog.html
@@ -15,7 +15,7 @@
<li><a href="/#features" class="nav-link">Features</a></li>
<li><a href="/#pricing" class="nav-link">Pricing</a></li>
<li><a href="about.html" class="nav-link">About</a></li>
- <li><a href="#contact" class="nav-link">Contact</a></li>
+ <li><a href="/contact.html" class="nav-link">Contact</a></li>
</ul>
<div class="nav-actions">
<a href="login.html" class="btn btn-ghost">Sign In</a>
@@ -325,7 +325,7 @@
<h4>Support</h4>
<ul>
<li><a href="#help">Help Center</a></li>
- <li><a href="#contact">Contact</a></li>
+ <li><a href="/contact.html">Contact</a></li>
<li><a href="#status">Status</a></li>
<li><a href="#api">API Docs</a></li>
</ul>
diff --git a/static/contact-script.js b/static/contact-script.js
new file mode 100644
index 0000000..d436dd5
--- /dev/null
+++ b/static/contact-script.js
@@ -0,0 +1,399 @@
+// DOM Elements
+const contactForm = document.getElementById('contactForm');
+const submitBtn = document.getElementById('submitBtn');
+const toast = document.getElementById('toast');
+const formSuccess = document.getElementById('formSuccess');
+const formError = document.getElementById('formError');
+const messageTextarea = document.getElementById('message');
+const charCount = document.getElementById('charCount');
+
+// Form validation
+const validateEmail = (email) => {
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
+ return emailRegex.test(email);
+};
+
+const validatePhone = (phone) => {
+ const phoneRegex = /^[\+]?[1-9][\d]{0,15}$/;
+ return phone === '' || phoneRegex.test(phone.replace(/[\s\-\(\)]/g, ''));
+};
+
+const showError = (fieldId, message) => {
+ const errorElement = document.getElementById(fieldId + 'Error');
+ const inputElement = document.getElementById(fieldId);
+
+ if (errorElement) {
+ errorElement.textContent = message;
+ }
+ if (inputElement) {
+ inputElement.classList.add('error');
+ }
+};
+
+const clearError = (fieldId) => {
+ const errorElement = document.getElementById(fieldId + 'Error');
+ const inputElement = document.getElementById(fieldId);
+
+ if (errorElement) {
+ errorElement.textContent = '';
+ }
+ if (inputElement) {
+ inputElement.classList.remove('error');
+ }
+};
+
+const clearAllErrors = () => {
+ const errorElements = document.querySelectorAll('.error-message');
+ const inputElements = document.querySelectorAll('.error');
+
+ errorElements.forEach(el => el.textContent = '');
+ inputElements.forEach(el => el.classList.remove('error'));
+};
+
+// Character counter for message textarea
+messageTextarea.addEventListener('input', () => {
+ const length = messageTextarea.value.length;
+ charCount.textContent = length;
+
+ if (length > 1000) {
+ charCount.style.color = 'var(--error)';
+ messageTextarea.style.borderColor = 'var(--error)';
+ } else {
+ charCount.style.color = 'var(--text-secondary)';
+ messageTextarea.style.borderColor = 'var(--border)';
+ }
+});
+
+// Real-time validation
+document.getElementById('email').addEventListener('blur', (e) => {
+ const email = e.target.value.trim();
+ if (email && !validateEmail(email)) {
+ showError('email', 'Please enter a valid email address');
+ } else {
+ clearError('email');
+ }
+});
+
+document.getElementById('phone').addEventListener('blur', (e) => {
+ const phone = e.target.value.trim();
+ if (phone && !validatePhone(phone)) {
+ showError('phone', 'Please enter a valid phone number');
+ } else {
+ clearError('phone');
+ }
+});
+
+// Clear errors on input
+['firstName', 'lastName', 'email', 'phone', 'subject', 'message'].forEach(fieldId => {
+ const element = document.getElementById(fieldId);
+ if (element) {
+ element.addEventListener('input', () => clearError(fieldId));
+ }
+});
+
+// Set loading state
+const setLoadingState = (loading) => {
+ if (loading) {
+ submitBtn.classList.add('loading');
+ submitBtn.disabled = true;
+ } else {
+ submitBtn.classList.remove('loading');
+ submitBtn.disabled = false;
+ }
+};
+
+// Show toast notification
+const showToast = (message, type = 'success') => {
+ const toastMessage = toast.querySelector('.toast-message');
+ const toastIcon = toast.querySelector('.toast-icon');
+
+ toastMessage.textContent = message;
+
+ if (type === 'success') {
+ toast.style.background = 'var(--success)';
+ toastIcon.textContent = '✓';
+ } else {
+ toast.style.background = 'var(--error)';
+ toastIcon.textContent = '✕';
+ }
+
+ toast.classList.add('show');
+
+ setTimeout(() => {
+ toast.classList.remove('show');
+ }, 4000);
+};
+
+// API Configuration
+const API_BASE_URL = 'https://api.taskflow.com/v1';
+const CONTACT_ENDPOINT = `${API_BASE_URL}/contact`;
+
+// Submit contact form
+const submitContactForm = async (formData) => {
+ try {
+ const response = await fetch(CONTACT_ENDPOINT, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ 'Accept': 'application/json',
+ },
+ body: JSON.stringify(formData)
+ });
+
+ const data = await response.json();
+
+ if (!response.ok) {
+ throw new Error(data.message || `HTTP error! status: ${response.status}`);
+ }
+
+ return data;
+ } catch (error) {
+ if (error.name === 'TypeError' && error.message.includes('fetch')) {
+ throw new Error('Network error. Please check your connection and try again.');
+ }
+ throw error;
+ }
+};
+
+// Form submission handler
+contactForm.addEventListener('submit', async (e) => {
+ e.preventDefault();
+
+ // Clear previous states
+ clearAllErrors();
+ formSuccess.classList.remove('show');
+ formError.classList.remove('show');
+
+ // Get form data
+ const formData = new FormData(contactForm);
+ const data = {
+ firstName: formData.get('firstName').trim(),
+ lastName: formData.get('lastName').trim(),
+ email: formData.get('email').trim(),
+ phone: formData.get('phone').trim(),
+ company: formData.get('company').trim(),
+ subject: formData.get('subject'),
+ priority: formData.get('priority'),
+ message: formData.get('message').trim(),
+ newsletter: formData.get('newsletter') === 'on',
+ privacy: formData.get('privacy') === 'on'
+ };
+
+ // Validate required fields
+ let hasErrors = false;
+
+ if (!data.firstName) {
+ showError('firstName', 'First name is required');
+ hasErrors = true;
+ }
+
+ if (!data.lastName) {
+ showError('lastName', 'Last name is required');
+ hasErrors = true;
+ }
+
+ if (!data.email) {
+ showError('email', 'Email address is required');
+ hasErrors = true;
+ } else if (!validateEmail(data.email)) {
+ showError('email', 'Please enter a valid email address');
+ hasErrors = true;
+ }
+
+ if (data.phone && !validatePhone(data.phone)) {
+ showError('phone', 'Please enter a valid phone number');
+ hasErrors = true;
+ }
+
+ if (!data.subject) {
+ showError('subject', 'Please select a subject');
+ hasErrors = true;
+ }
+
+ if (!data.message) {
+ showError('message', 'Message is required');
+ hasErrors = true;
+ } else if (data.message.length > 1000) {
+ showError('message', 'Message must be 1000 characters or less');
+ hasErrors = true;
+ }
+
+ if (!data.privacy) {
+ showError('privacy', 'You must agree to the Privacy Policy and Terms of Service');
+ hasErrors = true;
+ }
+
+ if (hasErrors) {
+ return;
+ }
+
+ // Set loading state
+ setLoadingState(true);
+
+ try {
+ // Submit form data
+ const response = await submitContactForm(data);
+
+ // Show success message
+ formSuccess.classList.add('show');
+ showToast('Message sent successfully! We\'ll get back to you soon.', 'success');
+
+ // Reset form
+ contactForm.reset();
+ charCount.textContent = '0';
+
+ // Scroll to success message
+ formSuccess.scrollIntoView({ behavior: 'smooth', block: 'center' });
+
+ } catch (error) {
+ console.error('Contact form error:', error);
+
+ // Show error message
+ const errorMessage = document.getElementById('errorMessage');
+ errorMessage.textContent = error.message || 'Something went wrong. Please try again.';
+ formError.classList.add('show');
+
+ showToast('Failed to send message. Please try again.', 'error');
+
+ // Scroll to error message
+ formError.scrollIntoView({ behavior: 'smooth', block: 'center' });
+
+ } finally {
+ setLoadingState(false);
+ }
+});
+
+// FAQ functionality
+document.querySelectorAll('.faq-question').forEach(question => {
+ question.addEventListener('click', () => {
+ const faqId = question.dataset.faq;
+ const answer = document.getElementById(`faq-${faqId}`);
+ const isActive = question.classList.contains('active');
+
+ // Close all other FAQs
+ document.querySelectorAll('.faq-question').forEach(q => {
+ q.classList.remove('active');
+ });
+ document.querySelectorAll('.faq-answer').forEach(a => {
+ a.classList.remove('active');
+ });
+
+ // Toggle current FAQ
+ if (!isActive) {
+ question.classList.add('active');
+ answer.classList.add('active');
+ }
+ });
+});
+
+// Contact option handlers
+document.getElementById('liveChatBtn').addEventListener('click', () => {
+ showToast('Opening live chat...', 'success');
+ // In a real app, this would open a chat widget
+ setTimeout(() => {
+ alert('Live chat would open here.\n\nThis would integrate with a service like Intercom, Zendesk Chat, or similar.');
+ }, 1000);
+});
+
+document.getElementById('scheduleDemoBtn').addEventListener('click', () => {
+ showToast('Opening demo scheduler...', 'success');
+ // In a real app, this would open a calendar booking widget
+ setTimeout(() => {
+ alert('Demo scheduler would open here.\n\nThis would integrate with Calendly, Acuity Scheduling, or similar.');
+ }, 1000);
+});
+
+// Social media link handlers
+document.querySelectorAll('.social-icon').forEach(icon => {
+ icon.addEventListener('click', (e) => {
+ e.preventDefault();
+ const platform = icon.getAttribute('aria-label');
+ showToast(`Opening ${platform}...`, 'success');
+ });
+});
+
+// Navbar background on scroll
+window.addEventListener('scroll', () => {
+ const navbar = document.querySelector('.navbar');
+ if (window.scrollY > 50) {
+ navbar.style.background = 'rgba(255, 255, 255, 0.98)';
+ } else {
+ navbar.style.background = 'rgba(255, 255, 255, 0.95)';
+ }
+});
+
+// Intersection Observer for animations
+const observerOptions = {
+ threshold: 0.1,
+ rootMargin: '0px 0px -50px 0px'
+};
+
+const observer = new IntersectionObserver((entries) => {
+ entries.forEach(entry => {
+ if (entry.isIntersecting) {
+ entry.target.style.opacity = '1';
+ entry.target.style.transform = 'translateY(0)';
+ }
+ });
+}, observerOptions);
+
+// Observe elements for animation
+document.querySelectorAll('.contact-card, .contact-detail, .faq-item').forEach(el => {
+ el.style.opacity = '0';
+ el.style.transform = 'translateY(30px)';
+ el.style.transition = 'opacity 0.6s ease, transform 0.6s ease';
+ observer.observe(el);
+});
+
+// Hero animation on load
+window.addEventListener('load', () => {
+ const heroTitle = document.querySelector('.hero-title');
+ const heroSubtitle = document.querySelector('.hero-subtitle');
+
+ [heroTitle, heroSubtitle].forEach((element, index) => {
+ if (element) {
+ element.style.opacity = '0';
+ element.style.transform = 'translateY(30px)';
+ element.style.transition = 'opacity 0.8s ease, transform 0.8s ease';
+
+ setTimeout(() => {
+ element.style.opacity = '1';
+ element.style.transform = 'translateY(0)';
+ }, 300 + (index * 200));
+ }
+ });
+});
+
+// Button click handlers
+document.querySelectorAll('.btn').forEach(btn => {
+ btn.addEventListener('click', (e) => {
+ const buttonText = btn.textContent.toLowerCase();
+
+ if (buttonText.includes('trial') || buttonText.includes('start')) {
+ if (!btn.closest('form')) { // Don't interfere with form submission
+ e.preventDefault();
+ showToast('Starting your free trial! Redirecting...', 'success');
+ setTimeout(() => {
+ window.location.href = 'signup.html';
+ }, 2000);
+ }
+ }
+ });
+});
+
+// Auto-resize textarea
+messageTextarea.addEventListener('input', function() {
+ this.style.height = 'auto';
+ this.style.height = Math.min(this.scrollHeight, 200) + 'px';
+});
+
+// Phone number formatting (optional enhancement)
+document.getElementById('phone').addEventListener('input', function(e) {
+ let value = e.target.value.replace(/\D/g, '');
+ if (value.length >= 6) {
+ value = value.replace(/(\d{3})(\d{3})(\d{4})/, '($1) $2-$3');
+ } else if (value.length >= 3) {
+ value = value.replace(/(\d{3})(\d{0,3})/, '($1) $2');
+ }
+ e.target.value = value;
+});
diff --git a/static/contact-styles.css b/static/contact-styles.css
new file mode 100644
index 0000000..612f14c
--- /dev/null
+++ b/static/contact-styles.css
@@ -0,0 +1,773 @@
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+:root {
+ --primary-color: #6366f1;
+ --primary-dark: #4f46e5;
+ --secondary-color: #f1f5f9;
+ --text-primary: #1e293b;
+ --text-secondary: #64748b;
+ --background: #ffffff;
+ --surface: #f8fafc;
+ --border: #e2e8f0;
+ --success: #10b981;
+ --warning: #f59e0b;
+ --error: #ef4444;
+ --shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
+ --shadow-lg: 0 20px 25px -5px rgba(0, 0, 0, 0.1);
+ --gradient: linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%);
+}
+
+body {
+ font-family: 'Inter', sans-serif;
+ line-height: 1.6;
+ color: var(--text-primary);
+ background: var(--background);
+}
+
+.container {
+ max-width: 1200px;
+ margin: 0 auto;
+ padding: 0 2rem;
+}
+
+/* Navigation */
+.navbar {
+ position: fixed;
+ top: 0;
+ width: 100%;
+ background: rgba(255, 255, 255, 0.95);
+ backdrop-filter: blur(10px);
+ z-index: 1000;
+ border-bottom: 1px solid var(--border);
+}
+
+.nav-container {
+ max-width: 1200px;
+ margin: 0 auto;
+ padding: 1rem 2rem;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+}
+
+.nav-logo {
+ font-size: 1.5rem;
+ font-weight: 700;
+ background: var(--gradient);
+ -webkit-background-clip: text;
+ -webkit-text-fill-color: transparent;
+ background-clip: text;
+ text-decoration: none;
+}
+
+.nav-menu {
+ display: flex;
+ list-style: none;
+ gap: 2rem;
+}
+
+.nav-link {
+ text-decoration: none;
+ color: var(--text-primary);
+ font-weight: 500;
+ transition: color 0.3s ease;
+}
+
+.nav-link:hover,
+.nav-link.active {
+ color: var(--primary-color);
+}
+
+.nav-actions {
+ display: flex;
+ align-items: center;
+ gap: 1rem;
+}
+
+/* Buttons */
+.btn {
+ padding: 0.75rem 1.5rem;
+ border: none;
+ border-radius: 0.5rem;
+ font-weight: 600;
+ cursor: pointer;
+ transition: all 0.3s ease;
+ text-decoration: none;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ gap: 0.5rem;
+ font-size: 0.875rem;
+ position: relative;
+}
+
+.btn-large {
+ padding: 1rem 2rem;
+ font-size: 1rem;
+}
+
+.btn-primary {
+ background: var(--gradient);
+ color: white;
+ box-shadow: var(--shadow);
+}
+
+.btn-primary:hover:not(:disabled) {
+ transform: translateY(-2px);
+ box-shadow: var(--shadow-lg);
+}
+
+.btn-primary:disabled {
+ opacity: 0.7;
+ cursor: not-allowed;
+ transform: none;
+}
+
+.btn-secondary {
+ background: white;
+ color: var(--text-primary);
+ border: 2px solid var(--border);
+}
+
+.btn-secondary:hover {
+ border-color: var(--primary-color);
+ color: var(--primary-color);
+}
+
+.btn-ghost {
+ background: transparent;
+ color: var(--text-primary);
+ border: none;
+}
+
+.btn-ghost:hover {
+ background: var(--surface);
+}
+
+.loading-spinner {
+ display: none;
+ width: 20px;
+ height: 20px;
+ border: 2px solid transparent;
+ border-top: 2px solid currentColor;
+ border-radius: 50%;
+ animation: spin 1s linear infinite;
+}
+
+.btn.loading .button-text {
+ opacity: 0;
+}
+
+.btn.loading .loading-spinner {
+ display: block;
+ position: absolute;
+}
+
+@keyframes spin {
+ 0% { transform: rotate(0deg); }
+ 100% { transform: rotate(360deg); }
+}
+
+/* Hero Section */
+.hero {
+ padding: 8rem 0 4rem;
+ background: linear-gradient(135deg, #f8fafc 0%, #e2e8f0 100%);
+ text-align: center;
+}
+
+.hero-title {
+ font-size: 3.5rem;
+ font-weight: 700;
+ line-height: 1.1;
+ margin-bottom: 1.5rem;
+}
+
+.gradient-text {
+ background: var(--gradient);
+ -webkit-background-clip: text;
+ -webkit-text-fill-color: transparent;
+ background-clip: text;
+}
+
+.hero-subtitle {
+ font-size: 1.25rem;
+ color: var(--text-secondary);
+ max-width: 600px;
+ margin: 0 auto;
+ line-height: 1.6;
+}
+
+/* Contact Options */
+.contact-options {
+ padding: 4rem 0;
+ background: var(--background);
+}
+
+.contact-grid {
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
+ gap: 2rem;
+}
+
+.contact-card {
+ background: white;
+ padding: 2rem;
+ border-radius: 1rem;
+ box-shadow: var(--shadow);
+ text-align: center;
+ transition: transform 0.3s ease;
+}
+
+.contact-card:hover {
+ transform: translateY(-5px);
+}
+
+.contact-icon {
+ font-size: 3rem;
+ margin-bottom: 1rem;
+}
+
+.contact-card h3 {
+ font-size: 1.25rem;
+ font-weight: 600;
+ margin-bottom: 1rem;
+}
+
+.contact-card p {
+ color: var(--text-secondary);
+ margin-bottom: 1.5rem;
+ line-height: 1.6;
+}
+
+/* Contact Form Section */
+.contact-form-section {
+ padding: 4rem 0;
+ background: var(--surface);
+}
+
+.contact-layout {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ gap: 4rem;
+ align-items: start;
+}
+
+.contact-info h2 {
+ font-size: 2rem;
+ font-weight: 700;
+ margin-bottom: 1rem;
+}
+
+.contact-info > p {
+ color: var(--text-secondary);
+ margin-bottom: 2rem;
+ font-size: 1.125rem;
+}
+
+.contact-details {
+ margin-bottom: 2rem;
+}
+
+.contact-detail {
+ display: flex;
+ align-items: flex-start;
+ gap: 1rem;
+ margin-bottom: 2rem;
+}
+
+.detail-icon {
+ font-size: 1.5rem;
+ margin-top: 0.25rem;
+}
+
+.detail-content h4 {
+ font-weight: 600;
+ margin-bottom: 0.5rem;
+}
+
+.detail-content p {
+ color: var(--text-secondary);
+ line-height: 1.6;
+}
+
+.social-links h4 {
+ font-weight: 600;
+ margin-bottom: 1rem;
+}
+
+.social-icons {
+ display: flex;
+ gap: 1rem;
+}
+
+.social-icon {
+ width: 48px;
+ height: 48px;
+ background: white;
+ border-radius: 50%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ color: var(--text-secondary);
+ text-decoration: none;
+ transition: all 0.3s ease;
+ box-shadow: var(--shadow);
+}
+
+.social-icon:hover {
+ color: var(--primary-color);
+ transform: translateY(-2px);
+ box-shadow: var(--shadow-lg);
+}
+
+/* Form Styles */
+.contact-form-container {
+ background: white;
+ padding: 2rem;
+ border-radius: 1rem;
+ box-shadow: var(--shadow);
+}
+
+.contact-form {
+ display: flex;
+ flex-direction: column;
+ gap: 1.5rem;
+}
+
+.form-row {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ gap: 1rem;
+}
+
+.form-group {
+ display: flex;
+ flex-direction: column;
+}
+
+.form-group label {
+ font-weight: 500;
+ margin-bottom: 0.5rem;
+ color: var(--text-primary);
+}
+
+.form-group input,
+.form-group select,
+.form-group textarea {
+ padding: 0.75rem 1rem;
+ border: 2px solid var(--border);
+ border-radius: 0.5rem;
+ font-size: 1rem;
+ transition: all 0.3s ease;
+ font-family: inherit;
+}
+
+.form-group input:focus,
+.form-group select:focus,
+.form-group textarea:focus {
+ outline: none;
+ border-color: var(--primary-color);
+ box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1);
+}
+
+.form-group input.error,
+.form-group select.error,
+.form-group textarea.error {
+ border-color: var(--error);
+}
+
+.form-group textarea {
+ resize: vertical;
+ min-height: 120px;
+}
+
+.character-count {
+ font-size: 0.875rem;
+ color: var(--text-secondary);
+ text-align: right;
+ margin-top: 0.25rem;
+}
+
+.error-message {
+ color: var(--error);
+ font-size: 0.875rem;
+ margin-top: 0.5rem;
+ min-height: 1.25rem;
+}
+
+/* Radio Group */
+.radio-group {
+ display: flex;
+ gap: 1.5rem;
+ flex-wrap: wrap;
+}
+
+.radio-label {
+ display: flex;
+ align-items: center;
+ cursor: pointer;
+ font-weight: 500;
+}
+
+.radio-label input[type="radio"] {
+ display: none;
+}
+
+.radio-custom {
+ width: 20px;
+ height: 20px;
+ border: 2px solid var(--border);
+ border-radius: 50%;
+ margin-right: 0.5rem;
+ position: relative;
+ transition: all 0.3s ease;
+}
+
+.radio-label input[type="radio"]:checked + .radio-custom {
+ border-color: var(--primary-color);
+}
+
+.radio-label input[type="radio"]:checked + .radio-custom::after {
+ content: '';
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ width: 8px;
+ height: 8px;
+ background: var(--primary-color);
+ border-radius: 50%;
+}
+
+/* Checkbox */
+.checkbox-container {
+ display: flex;
+ align-items: flex-start;
+ cursor: pointer;
+ font-size: 0.875rem;
+ color: var(--text-secondary);
+ line-height: 1.5;
+}
+
+.checkbox-container input {
+ display: none;
+}
+
+.checkmark {
+ width: 18px;
+ height: 18px;
+ border: 2px solid var(--border);
+ border-radius: 0.25rem;
+ margin-right: 0.75rem;
+ margin-top: 0.125rem;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ transition: all 0.3s ease;
+ flex-shrink: 0;
+}
+
+.checkbox-container input:checked + .checkmark {
+ background: var(--primary-color);
+ border-color: var(--primary-color);
+}
+
+.checkbox-container input:checked + .checkmark::after {
+ content: '✓';
+ color: white;
+ font-size: 0.75rem;
+ font-weight: bold;
+}
+
+.checkbox-container a {
+ color: var(--primary-color);
+ text-decoration: none;
+}
+
+.checkbox-container a:hover {
+ text-decoration: underline;
+}
+
+/* Form States */
+.form-success,
+.form-error {
+ display: none;
+ text-align: center;
+ padding: 2rem;
+ border-radius: 0.75rem;
+ margin-top: 1rem;
+}
+
+.form-success {
+ background: #f0fdf4;
+ border: 1px solid #bbf7d0;
+ color: #166534;
+}
+
+.form-error {
+ background: #fef2f2;
+ border: 1px solid #fecaca;
+ color: #dc2626;
+}
+
+.success-icon,
+.error-icon {
+ font-size: 3rem;
+ margin-bottom: 1rem;
+}
+
+.form-success h3,
+.form-error h3 {
+ font-size: 1.25rem;
+ font-weight: 600;
+ margin-bottom: 0.5rem;
+}
+
+.form-success.show,
+.form-error.show {
+ display: block;
+}
+
+/* FAQ Section */
+.faq-section {
+ padding: 4rem 0;
+ background: var(--background);
+}
+
+.section-header {
+ text-align: center;
+ margin-bottom: 3rem;
+}
+
+.section-title {
+ font-size: 2.5rem;
+ font-weight: 700;
+ margin-bottom: 1rem;
+}
+
+.section-subtitle {
+ font-size: 1.125rem;
+ color: var(--text-secondary);
+}
+
+.faq-grid {
+ max-width: 800px;
+ margin: 0 auto;
+}
+
+.faq-item {
+ border-bottom: 1px solid var(--border);
+}
+
+.faq-question {
+ width: 100%;
+ padding: 1.5rem 0;
+ background: none;
+ border: none;
+ text-align: left;
+ font-size: 1.125rem;
+ font-weight: 600;
+ color: var(--text-primary);
+ cursor: pointer;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ transition: color 0.3s ease;
+}
+
+.faq-question:hover {
+ color: var(--primary-color);
+}
+
+.faq-icon {
+ font-size: 1.5rem;
+ font-weight: 300;
+ transition: transform 0.3s ease;
+}
+
+.faq-question.active .faq-icon {
+ transform: rotate(45deg);
+}
+
+.faq-answer {
+ max-height: 0;
+ overflow: hidden;
+ transition: max-height 0.3s ease;
+}
+
+.faq-answer.active {
+ max-height: 200px;
+}
+
+.faq-answer p {
+ padding: 0 0 1.5rem 0;
+ color: var(--text-secondary);
+ line-height: 1.6;
+}
+
+/* Footer */
+.footer {
+ background: var(--text-primary);
+ color: white;
+ padding: 4rem 0 2rem;
+}
+
+.footer-content {
+ display: grid;
+ grid-template-columns: 2fr 1fr 1fr 1fr;
+ gap: 3rem;
+ margin-bottom: 3rem;
+}
+
+.footer-logo {
+ font-size: 1.5rem;
+ font-weight: 700;
+ margin-bottom: 1rem;
+}
+
+.footer-section h4 {
+ font-weight: 600;
+ margin-bottom: 1rem;
+}
+
+.footer-section ul {
+ list-style: none;
+}
+
+.footer-section ul li {
+ margin-bottom: 0.5rem;
+}
+
+.footer-section ul li a {
+ color: rgba(255, 255, 255, 0.8);
+ text-decoration: none;
+ transition: color 0.3s ease;
+}
+
+.footer-section ul li a:hover {
+ color: white;
+}
+
+.footer-bottom {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding-top: 2rem;
+ border-top: 1px solid rgba(255, 255, 255, 0.1);
+}
+
+.footer-links {
+ display: flex;
+ gap: 2rem;
+}
+
+.footer-links a {
+ color: rgba(255, 255, 255, 0.8);
+ text-decoration: none;
+ transition: color 0.3s ease;
+}
+
+.footer-links a:hover {
+ color: white;
+}
+
+/* Toast */
+.toast {
+ position: fixed;
+ top: 2rem;
+ right: 2rem;
+ background: var(--success);
+ color: white;
+ padding: 1rem 1.5rem;
+ border-radius: 0.5rem;
+ box-shadow: var(--shadow-lg);
+ transform: translateX(100%);
+ transition: transform 0.3s ease;
+ z-index: 1000;
+}
+
+.toast.show {
+ transform: translateX(0);
+}
+
+.toast-content {
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+}
+
+.toast-icon {
+ font-size: 1.25rem;
+}
+
+/* Responsive Design */
+@media (max-width: 768px) {
+ .nav-menu {
+ display: none;
+ }
+
+ .hero-title {
+ font-size: 2.5rem;
+ }
+
+ .contact-grid {
+ grid-template-columns: 1fr;
+ }
+
+ .contact-layout {
+ grid-template-columns: 1fr;
+ gap: 2rem;
+ }
+
+ .form-row {
+ grid-template-columns: 1fr;
+ }
+
+ .radio-group {
+ flex-direction: column;
+ gap: 1rem;
+ }
+
+ .footer-content {
+ grid-template-columns: 1fr;
+ text-align: center;
+ }
+
+ .footer-bottom {
+ flex-direction: column;
+ gap: 1rem;
+ text-align: center;
+ }
+}
+
+@media (max-width: 480px) {
+ .container {
+ padding: 0 1rem;
+ }
+
+ .hero {
+ padding: 6rem 0 3rem;
+ }
+
+ .hero-title {
+ font-size: 2rem;
+ }
+
+ .contact-form-container {
+ padding: 1.5rem;
+ }
+
+ .section-title {
+ font-size: 2rem;
+ }
+
+ .toast {
+ top: 1rem;
+ right: 1rem;
+ left: 1rem;
+ }
+}
diff --git a/static/contact.html b/static/contact.html
new file mode 100644
index 0000000..13f3828
--- /dev/null
+++ b/static/contact.html
@@ -0,0 +1,368 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <title>Contact Us - TaskFlow</title>
+ <link rel="stylesheet" href="contact-styles.css">
+ <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
+</head>
+<body>
+ <nav class="navbar">
+ <div class="nav-container">
+ <a href="/" class="nav-logo">TaskFlow</a>
+ <ul class="nav-menu">
+ <li><a href="/#features" class="nav-link">Features</a></li>
+ <li><a href="/#pricing" class="nav-link">Pricing</a></li>
+ <li><a href="about.html" class="nav-link">About</a></li>
+ <li><a href="contact.html" class="nav-link active">Contact</a></li>
+ </ul>
+ <div class="nav-actions">
+ <a href="login.html" class="btn btn-ghost">Sign In</a>
+ <button class="btn btn-primary">Start Free Trial</button>
+ </div>
+ </div>
+ </nav>
+
+ <main>
+ <section class="hero">
+ <div class="container">
+ <div class="hero-content">
+ <h1 class="hero-title">Get in <span class="gradient-text">Touch</span></h1>
+ <p class="hero-subtitle">
+ Have questions about TaskFlow? We're here to help. Reach out to our team
+ and we'll get back to you as soon as possible.
+ </p>
+ </div>
+ </div>
+ </section>
+
+ <section class="contact-options">
+ <div class="container">
+ <div class="contact-grid">
+ <div class="contact-card">
+ <div class="contact-icon">💬</div>
+ <h3>Live Chat</h3>
+ <p>Chat with our support team in real-time. Available 24/7 for urgent issues.</p>
+ <button class="btn btn-primary" id="liveChatBtn">Start Live Chat</button>
+ </div>
+ <div class="contact-card">
+ <div class="contact-icon">📧</div>
+ <h3>Email Support</h3>
+ <p>Send us an email and we'll respond within 24 hours during business days.</p>
+ <a href="mailto:support@taskflow.com" class="btn btn-secondary">Email Us</a>
+ </div>
+ <div class="contact-card">
+ <div class="contact-icon">📞</div>
+ <h3>Phone Support</h3>
+ <p>Call us directly for immediate assistance with your account or technical issues.</p>
+ <a href="tel:+1-555-123-4567" class="btn btn-secondary">Call Now</a>
+ </div>
+ <div class="contact-card">
+ <div class="contact-icon">📅</div>
+ <h3>Schedule a Demo</h3>
+ <p>Book a personalized demo to see how TaskFlow can transform your workflow.</p>
+ <button class="btn btn-primary" id="scheduleDemoBtn">Schedule Demo</button>
+ </div>
+ </div>
+ </div>
+ </section>
+
+ <section class="contact-form-section">
+ <div class="container">
+ <div class="contact-layout">
+ <div class="contact-info">
+ <h2>Send us a Message</h2>
+ <p>Fill out the form and our team will get back to you within 24 hours.</p>
+
+ <div class="contact-details">
+ <div class="contact-detail">
+ <div class="detail-icon">📍</div>
+ <div class="detail-content">
+ <h4>Office Address</h4>
+ <p>123 Innovation Drive<br>San Francisco, CA 94105<br>United States</p>
+ </div>
+ </div>
+ <div class="contact-detail">
+ <div class="detail-icon">⏰</div>
+ <div class="detail-content">
+ <h4>Business Hours</h4>
+ <p>Monday - Friday: 9:00 AM - 6:00 PM PST<br>Saturday - Sunday: 10:00 AM - 4:00 PM PST</p>
+ </div>
+ </div>
+ <div class="contact-detail">
+ <div class="detail-icon">🌍</div>
+ <div class="detail-content">
+ <h4>Global Support</h4>
+ <p>We provide support in multiple languages and time zones to serve our global customer base.</p>
+ </div>
+ </div>
+ </div>
+
+ <div class="social-links">
+ <h4>Follow Us</h4>
+ <div class="social-icons">
+ <a href="#" class="social-icon" aria-label="Twitter">
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor">
+ <path d="M23 3a10.9 10.9 0 0 1-3.14 1.53 4.48 4.48 0 0 0-7.86 3v1A10.66 10.66 0 0 1 3 4s-4 9 5 13a11.64 11.64 0 0 1-7 2c9 5 20 0 20-11.5a4.5 4.5 0 0 0-.08-.83A7.72 7.72 0 0 0 23 3z"/>
+ </svg>
+ </a>
+ <a href="#" class="social-icon" aria-label="LinkedIn">
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor">
+ <path d="M16 8a6 6 0 0 1 6 6v7h-4v-7a2 2 0 0 0-2-2 2 2 0 0 0-2 2v7h-4v-7a6 6 0 0 1 6-6z"/>
+ <rect x="2" y="9" width="4" height="12"/>
+ <circle cx="4" cy="4" r="2"/>
+ </svg>
+ </a>
+ <a href="#" class="social-icon" aria-label="GitHub">
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor">
+ <path d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22"/>
+ </svg>
+ </a>
+ </div>
+ </div>
+ </div>
+
+ <div class="contact-form-container">
+ <form class="contact-form" id="contactForm">
+ <div class="form-row">
+ <div class="form-group">
+ <label for="firstName">First Name *</label>
+ <input type="text" id="firstName" name="firstName" required>
+ <div class="error-message" id="firstNameError"></div>
+ </div>
+ <div class="form-group">
+ <label for="lastName">Last Name *</label>
+ <input type="text" id="lastName" name="lastName" required>
+ <div class="error-message" id="lastNameError"></div>
+ </div>
+ </div>
+
+ <div class="form-row">
+ <div class="form-group">
+ <label for="email">Email Address *</label>
+ <input type="email" id="email" name="email" required>
+ <div class="error-message" id="emailError"></div>
+ </div>
+ <div class="form-group">
+ <label for="phone">Phone Number</label>
+ <input type="tel" id="phone" name="phone">
+ <div class="error-message" id="phoneError"></div>
+ </div>
+ </div>
+
+ <div class="form-group">
+ <label for="company">Company Name</label>
+ <input type="text" id="company" name="company">
+ </div>
+
+ <div class="form-group">
+ <label for="subject">Subject *</label>
+ <select id="subject" name="subject" required>
+ <option value="">Select a subject</option>
+ <option value="general">General Inquiry</option>
+ <option value="support">Technical Support</option>
+ <option value="sales">Sales Question</option>
+ <option value="billing">Billing Issue</option>
+ <option value="feature">Feature Request</option>
+ <option value="partnership">Partnership Opportunity</option>
+ <option value="other">Other</option>
+ </select>
+ <div class="error-message" id="subjectError"></div>
+ </div>
+
+ <div class="form-group">
+ <label for="priority">Priority Level</label>
+ <div class="radio-group">
+ <label class="radio-label">
+ <input type="radio" name="priority" value="low" checked>
+ <span class="radio-custom"></span>
+ Low
+ </label>
+ <label class="radio-label">
+ <input type="radio" name="priority" value="medium">
+ <span class="radio-custom"></span>
+ Medium
+ </label>
+ <label class="radio-label">
+ <input type="radio" name="priority" value="high">
+ <span class="radio-custom"></span>
+ High
+ </label>
+ <label class="radio-label">
+ <input type="radio" name="priority" value="urgent">
+ <span class="radio-custom"></span>
+ Urgent
+ </label>
+ </div>
+ </div>
+
+ <div class="form-group">
+ <label for="message">Message *</label>
+ <textarea id="message" name="message" rows="6" required placeholder="Please provide details about your inquiry..."></textarea>
+ <div class="error-message" id="messageError"></div>
+ <div class="character-count">
+ <span id="charCount">0</span>/1000 characters
+ </div>
+ </div>
+
+ <div class="form-group">
+ <label class="checkbox-container">
+ <input type="checkbox" id="newsletter" name="newsletter">
+ <span class="checkmark"></span>
+ Subscribe to our newsletter for product updates and tips
+ </label>
+ </div>
+
+ <div class="form-group">
+ <label class="checkbox-container">
+ <input type="checkbox" id="privacy" name="privacy" required>
+ <span class="checkmark"></span>
+ I agree to the <a href="#privacy-policy" target="_blank">Privacy Policy</a> and <a href="#terms" target="_blank">Terms of Service</a> *
+ </label>
+ <div class="error-message" id="privacyError"></div>
+ </div>
+
+ <button type="submit" class="btn btn-primary btn-large" id="submitBtn">
+ <span class="button-text">Send Message</span>
+ <span class="loading-spinner" id="loadingSpinner"></span>
+ </button>
+
+ <div class="form-success" id="formSuccess">
+ <div class="success-icon">✓</div>
+ <h3>Message Sent Successfully!</h3>
+ <p>Thank you for contacting us. We'll get back to you within 24 hours.</p>
+ </div>
+
+ <div class="form-error" id="formError">
+ <div class="error-icon">✕</div>
+ <h3>Something went wrong</h3>
+ <p id="errorMessage">Please try again or contact us directly at support@taskflow.com</p>
+ </div>
+ </form>
+ </div>
+ </div>
+ </div>
+ </section>
+
+ <section class="faq-section">
+ <div class="container">
+ <div class="section-header">
+ <h2 class="section-title">Frequently Asked Questions</h2>
+ <p class="section-subtitle">Quick answers to common questions</p>
+ </div>
+ <div class="faq-grid">
+ <div class="faq-item">
+ <button class="faq-question" data-faq="1">
+ <span>How quickly can I get started with TaskFlow?</span>
+ <span class="faq-icon">+</span>
+ </button>
+ <div class="faq-answer" id="faq-1">
+ <p>You can get started with TaskFlow in minutes! Simply sign up for a free trial, and you'll have immediate access to all features. Our onboarding process guides you through setting up your first project.</p>
+ </div>
+ </div>
+ <div class="faq-item">
+ <button class="faq-question" data-faq="2">
+ <span>Do you offer customer support?</span>
+ <span class="faq-icon">+</span>
+ </button>
+ <div class="faq-answer" id="faq-2">
+ <p>Yes! We offer 24/7 live chat support, email support with 24-hour response time, and phone support during business hours. Enterprise customers also get dedicated account managers.</p>
+ </div>
+ </div>
+ <div class="faq-item">
+ <button class="faq-question" data-faq="3">
+ <span>Can I integrate TaskFlow with other tools?</span>
+ <span class="faq-icon">+</span>
+ </button>
+ <div class="faq-answer" id="faq-3">
+ <p>Absolutely! TaskFlow integrates with over 100 popular tools including Slack, Google Workspace, Microsoft Teams, GitHub, Jira, and many more. We also offer a robust API for custom integrations.</p>
+ </div>
+ </div>
+ <div class="faq-item">
+ <button class="faq-question" data-faq="4">
+ <span>Is my data secure with TaskFlow?</span>
+ <span class="faq-icon">+</span>
+ </button>
+ <div class="faq-answer" id="faq-4">
+ <p>Security is our top priority. We use bank-level encryption, SOC 2 compliance, regular security audits, and offer features like SSO and two-factor authentication. Your data is stored in secure, redundant data centers.</p>
+ </div>
+ </div>
+ <div class="faq-item">
+ <button class="faq-question" data-faq="5">
+ <span>What happens if I need to cancel my subscription?</span>
+ <span class="faq-icon">+</span>
+ </button>
+ <div class="faq-answer" id="faq-5">
+ <p>You can cancel your subscription at any time with no cancellation fees. You'll continue to have access until the end of your billing period, and you can export all your data before canceling.</p>
+ </div>
+ </div>
+ <div class="faq-item">
+ <button class="faq-question" data-faq="6">
+ <span>Do you offer training or onboarding assistance?</span>
+ <span class="faq-icon">+</span>
+ </button>
+ <div class="faq-answer" id="faq-6">
+ <p>Yes! We provide comprehensive onboarding resources including video tutorials, documentation, webinars, and personalized training sessions for Enterprise customers. Our success team is here to help you get the most out of TaskFlow.</p>
+ </div>
+ </div>
+ </div>
+ </div>
+ </section>
+ </main>
+
+ <footer class="footer">
+ <div class="container">
+ <div class="footer-content">
+ <div class="footer-section">
+ <div class="footer-logo">TaskFlow</div>
+ <p>Streamline your project management with the tools teams love to use.</p>
+ </div>
+ <div class="footer-section">
+ <h4>Product</h4>
+ <ul>
+ <li><a href="/#features">Features</a></li>
+ <li><a href="/#pricing">Pricing</a></li>
+ <li><a href="#integrations">Integrations</a></li>
+ <li><a href="#security">Security</a></li>
+ </ul>
+ </div>
+ <div class="footer-section">
+ <h4>Company</h4>
+ <ul>
+ <li><a href="about.html">About</a></li>
+ <li><a href="#careers">Careers</a></li>
+ <li><a href="blog.html">Blog</a></li>
+ <li><a href="#press">Press</a></li>
+ </ul>
+ </div>
+ <div class="footer-section">
+ <h4>Support</h4>
+ <ul>
+ <li><a href="#help">Help Center</a></li>
+ <li><a href="contact.html">Contact</a></li>
+ <li><a href="#status">Status</a></li>
+ <li><a href="#api">API Docs</a></li>
+ </ul>
+ </div>
+ </div>
+ <div class="footer-bottom">
+ <p>&copy; 2025 TaskFlow. All rights reserved.</p>
+ <div class="footer-links">
+ <a href="#privacy">Privacy Policy</a>
+ <a href="#terms">Terms of Service</a>
+ </div>
+ </div>
+ </div>
+ </footer>
+
+ <div class="toast" id="toast">
+ <div class="toast-content">
+ <span class="toast-icon">✓</span>
+ <span class="toast-message"></span>
+ </div>
+ </div>
+
+ <script src="contact-script.js"></script>
+</body>
+</html>
diff --git a/static/index.html b/static/index.html
index 9d8eca8..ef4d012 100644
--- a/static/index.html
+++ b/static/index.html
@@ -15,7 +15,7 @@
<li><a href="#features" class="nav-link">Features</a></li>
<li><a href="#pricing" class="nav-link">Pricing</a></li>
<li><a href="/about.html" class="nav-link">About</a></li>
- <li><a href="#contact" class="nav-link">Contact</a></li>
+ <li><a href="/contact.html" class="nav-link">Contact</a></li>
</ul>
<div class="nav-actions">
<a href="login.html" class="btn btn-ghost">Sign In</a>
@@ -296,7 +296,7 @@
<h4>Support</h4>
<ul>
<li><a href="#help">Help Center</a></li>
- <li><a href="#contact">Contact</a></li>
+ <li><a href="/contact.html">Contact</a></li>
<li><a href="#status">Status</a></li>
<li><a href="#api">API Docs</a></li>
</ul>