🎯 Complete dual integration architecture with JotForm and digital branding

- Add CyberSec Career Navigator with JotForm white-label integration
- Implement direct access agent system alongside webhook agents
- Add digital branding services page with SOSTAC+RACE methodology
- Create dual integration patterns: webhook vs direct access flows
- Clean up unused form API endpoints for streamlined architecture
- Add career navigator management command and templates
- Update marketplace with conditional logic for different agent types
- Fix UI consistency issues (remove category labels, fix animations)
- Update documentation to reflect new dual architecture

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Claude 2025-08-02 10:47:16 +05:30
parent d750857e4e
commit 3fac20fe28
12 changed files with 1592 additions and 30 deletions

View File

@ -4,13 +4,15 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
## Project Overview
Quantum Tasks AI is a Django-based AI agent marketplace platform. Users can purchase AI agent services through a web interface, with agent execution handled via N8N webhooks and payments processed through Stripe.
Quantum Tasks AI is a Django-based AI agent marketplace platform. Users can access AI agent services through a web interface, with execution handled via two distinct systems: N8N webhook integrations and direct form access integrations.
**Key Architecture:**
- **Django Framework**: Main web application using Django 5.2.4
- **Agent System**: Database-driven agents app with marketplace and N8N webhook execution
- **Agent System**: Database-driven agents app with dual integration systems:
- **Webhook Agents**: N8N integrations for complex processing
- **Direct Access Agents**: Form-based integrations (JotForm, etc.)
- **Authentication**: Custom user model with email verification
- **Payments**: Stripe integration with wallet system
- **Payments**: Stripe integration with wallet system (supports free agents)
- **Database**: SQLite for development, PostgreSQL for production (Railway)
- **Static Files**: WhiteNoise for production static file serving
@ -101,17 +103,27 @@ gunicorn netcop_hub.wsgi:application
### Agent System (agents app)
**Key Files:**
- `agents/models.py`: Agent, AgentCategory, AgentExecution models
- `agents/views.py`: REST API and web interface views
- `agents/templates/agents/`: Dynamic agent templates with form generation
- `agents/models.py`: Agent, AgentCategory, AgentExecution, ChatSession models
- `agents/views.py`: Dual integration systems and web interface views
- `agents/templates/agents/`: Dynamic agent templates and marketplace
- `agents/management/commands/`: Agent creation and management commands
- `templates/career_navigator.html`: Direct access form template
**Agent Flow:**
**Dual Integration Systems:**
**System 1: Webhook Agents (N8N Integration)**
1. User browses marketplace (`/agents/`)
2. Selects agent and fills dynamic form (`/agents/{slug}/`)
3. Form submission creates AgentExecution and calls N8N webhook
4. N8N processes request and returns response via webhook
5. Results displayed with file upload support and real-time wallet updates
2. Clicks "Try Now" → Agent detail page (`/agents/{slug}/`)
3. Fills dynamic form → Form submission calls `/agents/api/execute/`
4. N8N webhook processes request and returns response
5. Results displayed with file upload support
**System 2: Direct Access Agents (Form Integration)**
1. User browses marketplace (`/agents/`)
2. Clicks special "Try Now" button → Direct access (`/agents/{slug}/access/`)
3. Payment processed → Redirect to form page (`/agents/{slug}/`)
4. Form displays embedded interface (JotForm, etc.)
5. User interacts directly with external form system
### Database Models
**User Management:**
@ -136,9 +148,10 @@ gunicorn netcop_hub.wsgi:application
- `STRIPE_SECRET_KEY`, `STRIPE_WEBHOOK_SECRET`: Stripe API keys
- `DATABASE_URL`: PostgreSQL connection string (Railway)
**N8N Webhook URLs:**
Agent-specific webhook URLs are stored in the database with each agent. Current working agents (all tested and confirmed working):
**Current Agents:**
The platform supports both webhook-based agents (N8N integration) and direct access agents (embedded forms):
**Webhook Agents (N8N Integration):**
1. **Social Ads Generator** (social-ads-generator) - 6.00 AED
- Creates compelling social media advertisements
- Form fields: description, social_platform, include_emoji, language
@ -154,12 +167,27 @@ Agent-specific webhook URLs are stored in the database with each agent. Current
- Form fields: pdf_file (file upload with drag-and-drop), summary_type
- Webhook: N8N endpoint for PDF processing with multipart file support
4. **5 Whys Analyzer** (5-whys-analyzer) - 15.00 AED
- Interactive chat-based root cause analysis using 5 Whys methodology
- Chat interface with real-time N8N webhook integration
- Session timeout: 2 hours
**Direct Access Agents (Embedded Forms):**
5. **CyberSec Career Navigator** (cybersec-career-navigator) - 0.00 AED
- JotForm-based career guidance consultation
- Embedded white-label interface
- Session duration: 2 hours
- Direct access URL: `/agents/career-navigator/`
### URL Structure
```
/ # Homepage (core app)
/digital-branding/ # Digital branding services page
/auth/ # Authentication (login, register, etc.)
/agents/ # Agent marketplace (agents app)
/agents/{slug}/ # Individual agent pages
/agents/{slug}/ # Individual agent pages (webhook agents)
/agents/career-navigator/ # Career navigator form page
/agents/career-navigator/access/ # Career navigator payment processing
/wallet/ # Wallet management
/admin/ # Django admin
```
@ -271,17 +299,20 @@ class Command(BaseCommand):
## System Status
**Current Status: ✅ STABLE WORKING SYSTEM**
- All 3 agents confirmed working and tested
- Clean agents-only architecture (workflows app completely removed)
- Emergency recovery completed from optimization failures
- System restored to stable commit 657712f
- All 5 agents confirmed working and tested (4 webhook + 1 direct access)
- Dual integration architecture with clean separation
- Digital branding services integration complete
- Chat-based and form-based agent systems operational
- White-label integration patterns established
**Latest Changes:**
- Removed workflows app completely for simplified architecture
- Enhanced agent marketplace with modern responsive design
- Fixed all authentication-aware UI components
- Implemented file upload support for PDF Summarizer
- Real-time wallet balance updates after agent execution
- Implemented dual integration architecture (webhook + direct access)
- Added CyberSec Career Navigator with JotForm integration
- Enhanced agent marketplace with conditional button logic
- Added digital branding services page
- Cleaned up unused form API endpoints
- Implemented 2-hour session timeout system
- Fixed persistent success messages and UI consistency
**Future Development:**
- Optimization work available in feature/optimization-backup branch
@ -289,4 +320,4 @@ class Command(BaseCommand):
- Performance optimizations should be applied incrementally with testing
---
Last updated: Last updated: Last updated: Last updated: Last updated: 2025-08-01 09:22:55
Last updated: 2025-08-02 12:30:00

View File

@ -0,0 +1,58 @@
from django.core.management.base import BaseCommand
from agents.models import AgentCategory, Agent
class Command(BaseCommand):
help = 'Create CyberSec Career Navigator agent with JotForm integration'
def handle(self, *args, **options):
# Create Career & Education category
career_category, created = AgentCategory.objects.get_or_create(
slug='career-education',
defaults={
'name': 'Career & Education',
'description': 'Professional career guidance and educational resources',
'icon': '🎓'
}
)
if created:
self.stdout.write(self.style.SUCCESS(f'Created category: {career_category.name}'))
else:
self.stdout.write(f'Category already exists: {career_category.name}')
# Create CyberSec Career Navigator agent
cybersec_agent, created = Agent.objects.get_or_create(
slug='cybersec-career-navigator',
defaults={
'name': 'CyberSec Career Navigator',
'short_description': 'Get personalized cybersecurity career guidance from AI expert Jessica',
'description': 'Navigate your cybersecurity career path with expert AI guidance. Whether you\'re starting out, changing careers, or advancing in cybersecurity, get personalized advice on certifications, job roles, skills development, and career progression. Jessica, your AI career consultant, provides tailored recommendations based on your experience level and goals.',
'category': career_category,
'price': 12.0,
'agent_type': 'form',
'form_schema': {
'fields': [] # Empty since we're using JotForm directly
},
'webhook_url': 'https://agent.jotform.com/019865a942ab7fa5b5b743a5fd2abe09e345'
}
)
if created:
self.stdout.write(self.style.SUCCESS(f'Created agent: {cybersec_agent.name}'))
self.stdout.write(f' 📝 Description: {cybersec_agent.short_description}')
self.stdout.write(f' 💰 Price: {cybersec_agent.price} AED')
self.stdout.write(f' 🔗 JotForm URL: {cybersec_agent.webhook_url}')
self.stdout.write(f' 📂 Category: {cybersec_agent.category.name}')
else:
self.stdout.write(f'Agent already exists: {cybersec_agent.name}')
self.stdout.write('')
self.stdout.write(self.style.SUCCESS('✅ CyberSec Career Navigator setup completed successfully'))
self.stdout.write('')
self.stdout.write('🚀 Next steps:')
self.stdout.write(' 1. Agent will appear in the Career & Education category')
self.stdout.write(' 2. Users will pay 12 AED and get direct access to JotForm interface')
self.stdout.write(' 3. Visit /agents/cybersec-career-navigator/ to test the interface')
self.stdout.write('')
self.stdout.write(f'Agent ID: {cybersec_agent.id}')
self.stdout.write(f'Agent Slug: {cybersec_agent.slug}')

View File

@ -6,6 +6,25 @@
{% block extra_css %}
<link rel="stylesheet" href="{% static 'css/agent-base.css' %}">
<link rel="stylesheet" href="{% static 'css/marketplace.css' %}">
<style>
/* Special styling for Career Navigator button */
.career-nav-btn {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important;
color: white !important;
border: none !important;
font-weight: 600 !important;
box-shadow: 0 4px 15px rgba(102, 126, 234, 0.3) !important;
transition: all 0.3s ease !important;
}
.career-nav-btn:hover {
transform: translateY(-2px) !important;
box-shadow: 0 6px 20px rgba(102, 126, 234, 0.4) !important;
color: white !important;
}
/* Career nav card styling removed pulse animation for consistency */
</style>
{% endblock %}
{% block content %}
@ -72,12 +91,23 @@
<p class="agent-description">{{ agent.short_description }}</p>
<div class="agent-footer">
{% if user.is_authenticated %}
<span class="agent-category">{{ agent.category.name }}</span>
<a href="{% url 'agents:detail' agent.slug %}" class="try-btn">Try Now →</a>
{% if agent.slug == 'cybersec-career-navigator' %}
<a href="{% url 'agents:career_navigator_access' %}" class="try-btn career-nav-btn">
🎓 Try Now →
</a>
{% else %}
<a href="{% url 'agents:detail' agent.slug %}" class="try-btn">Try Now →</a>
{% endif %}
{% else %}
<a href="{% url 'authentication:login' %}?next={% url 'agents:detail' agent.slug %}" class="try-btn login-required" style="width: 100%;">
🔐 Login to Try
</a>
{% if agent.slug == 'cybersec-career-navigator' %}
<a href="{% url 'authentication:login' %}?next={% url 'agents:career_navigator_access' %}" class="try-btn login-required" style="width: 100%;">
🔐 Login to Try
</a>
{% else %}
<a href="{% url 'authentication:login' %}?next={% url 'agents:detail' agent.slug %}" class="try-btn login-required" style="width: 100%;">
🔐 Login to Try
</a>
{% endif %}
{% endif %}
</div>
</div>

View File

@ -7,6 +7,10 @@ urlpatterns = [
# Web interface
path('', views.agents_marketplace, name='marketplace'),
# Direct access routes
path('career-navigator/', views.career_navigator_view, name='career_navigator'),
path('career-navigator/access/', views.career_navigator_access, name='career_navigator_access'),
# API endpoints - specific URLs first to avoid slug conflicts
path('api/execute/', views.execute_agent, name='execute_agent'),
path('api/executions/', views.execution_list, name='execution_list'),

View File

@ -3,9 +3,10 @@ from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.pagination import PageNumberPagination
from django.shortcuts import get_object_or_404, render
from django.shortcuts import get_object_or_404, render, redirect
from django.utils import timezone
from django.contrib.auth.decorators import login_required
from django.contrib import messages
from django.db import models
from .models import Agent, AgentExecution, AgentCategory, ChatSession, ChatMessage
from .serializers import AgentSerializer, AgentExecutionSerializer
@ -184,6 +185,100 @@ def execute_agent(request):
'execution_id': str(execution.id)
}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
def career_navigator_access(request):
"""Handle Try Now button click - charge wallet and redirect to form"""
if not request.user.is_authenticated:
# Clear any existing messages to prevent confusion
storage = messages.get_messages(request)
storage.used = True
messages.error(request, 'Please login to access the Career Navigator.')
return redirect('authentication:login')
# Get the career navigator agent
try:
agent = Agent.objects.get(slug='cybersec-career-navigator', is_active=True)
except Agent.DoesNotExist:
messages.error(request, 'Career Navigator is currently unavailable.')
return redirect('agents:marketplace')
# Check if user has sufficient balance
if not request.user.has_sufficient_balance(agent.price):
messages.error(request, f'Insufficient balance! You need {agent.price} AED to access the Career Navigator.')
return redirect('wallet:wallet')
# Deduct fee from user wallet
success = request.user.deduct_balance(
agent.price,
f'{agent.name} - Direct Access',
agent.slug
)
if not success:
messages.error(request, 'Failed to process payment. Please try again.')
return redirect('agents:marketplace')
# Create execution record for tracking
execution = AgentExecution.objects.create(
agent=agent,
user=request.user,
input_data={'action': 'direct_access', 'source': 'try_now_button'},
fee_charged=agent.price,
status='completed',
output_data={
'type': 'direct_access',
'message': f'Direct access granted to {agent.name}',
'access_method': 'try_now_button'
},
completed_at=timezone.now()
)
# Success message and redirect to form
messages.success(request, f'✅ Payment processed! Welcome to your {agent.name} consultation.')
return redirect('agents:career_navigator')
def career_navigator_view(request):
"""Display the career navigator form page"""
if not request.user.is_authenticated:
# Clear any existing messages to prevent confusion
storage = messages.get_messages(request)
storage.used = True
messages.error(request, 'Please login to access the Career Navigator.')
return redirect('authentication:login')
# Get the career navigator agent
try:
agent = Agent.objects.get(slug='cybersec-career-navigator', is_active=True)
except Agent.DoesNotExist:
messages.error(request, 'Career Navigator is currently unavailable.')
return redirect('agents:marketplace')
# Check if user has a recent execution (within last 2 hours) or just redirect to payment
from django.utils import timezone
from datetime import timedelta
recent_execution = AgentExecution.objects.filter(
agent=agent,
user=request.user,
status='completed',
created_at__gte=timezone.now() - timedelta(hours=2)
).first()
if not recent_execution:
messages.info(request, 'Please click "Try Now" to access your Career Navigator consultation.')
return redirect('agents:marketplace')
context = {
'agent': agent,
'form_url': agent.webhook_url,
'user_balance': request.user.wallet_balance,
'execution': recent_execution
}
return render(request, 'career_navigator.html', context)
@api_view(['GET'])
@permission_classes([IsAuthenticated])
def execution_list(request):

View File

@ -5,6 +5,7 @@ app_name = 'core'
urlpatterns = [
path('', views.homepage_view, name='homepage'),
path('digital-branding/', views.digital_branding_view, name='digital_branding'),
path('pricing/', views.pricing_view, name='pricing'),
path('contact/', views.contact_form_view, name='contact_form'),
path('health/', views.health_check_view, name='health_check'),

View File

@ -65,6 +65,27 @@ def pricing_view(request):
return render(request, 'core/pricing.html', {'sample_agents': []})
@ratelimit(key='ip', rate='60/m', method='GET', block=False)
def digital_branding_view(request):
"""Digital branding services page with rate limiting"""
# Check if rate limited
if getattr(request, 'limited', False):
logger.warning(f"Digital branding page rate limit exceeded for IP {request.META.get('REMOTE_ADDR')}")
messages.warning(request, 'Too many requests. Please wait a moment before refreshing.')
try:
context = {
'user_balance': request.user.wallet_balance if request.user.is_authenticated else 0,
}
return render(request, 'core/digital_branding.html', context)
except Exception as e:
logger.error(f"Digital branding view error: {e}")
messages.error(request, 'Unable to load digital branding page. Please try again.')
return render(request, 'core/digital_branding.html', {})
def validate_contact_input(name, email, message, company=""):
"""Validate and sanitize contact form input"""
errors = []

View File

@ -0,0 +1,652 @@
/* Digital Branding Services Page Styles */
/* Following homepage.css patterns and using unified color system from base.css */
/* Hero Section - matches homepage hero */
.digital-branding-hero {
position: relative;
background: var(--gradient-hero);
overflow: hidden;
min-height: 85vh;
display: flex;
align-items: center;
padding: clamp(40px, 10vw, 80px) clamp(16px, 4vw, 24px) clamp(60px, 15vw, 100px);
}
.hero-container {
max-width: 1280px;
margin: 0 auto;
text-align: center;
position: relative;
z-index: 10;
width: 100%;
}
.trust-badge {
display: inline-flex;
align-items: center;
gap: 0.5rem;
background: rgba(59, 130, 246, 0.08);
padding: 0.5rem 1.25rem;
border-radius: 50px;
margin-bottom: 2.5rem;
font-size: 0.875rem;
font-weight: 600;
color: var(--primary-blue);
border: 1px solid rgba(59, 130, 246, 0.15);
backdrop-filter: blur(10px);
}
.trust-badge-emoji {
font-size: 0.75rem;
}
.hero-title {
font-weight: 800;
margin-bottom: 2.5rem;
line-height: 1.1;
letter-spacing: -0.02em;
font-size: clamp(36px, 8vw, 110px);
margin-bottom: clamp(24px, 6vw, 40px);
}
.hero-title-gradient {
background: var(--gradient-primary);
background-size: 300% 300%;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.hero-title-normal {
color: var(--text-primary);
}
.hero-description {
color: var(--text-secondary);
margin-bottom: 3.5rem;
max-width: 720px;
margin-left: auto;
margin-right: auto;
line-height: 1.7;
font-weight: 400;
font-size: clamp(1.1rem, 3vw, 1.4rem);
margin-bottom: clamp(32px, 8vw, 56px);
padding: 0 clamp(8px, 2vw, 16px);
}
.hero-buttons {
display: flex;
justify-content: center;
flex-wrap: wrap;
margin-bottom: 5rem;
gap: clamp(12px, 3vw, 20px);
margin-bottom: clamp(40px, 10vw, 80px);
padding: 0 clamp(8px, 2vw, 16px);
}
.btn-primary {
background: var(--gradient-primary);
color: white;
border-radius: 1rem;
font-weight: bold;
border: none;
cursor: pointer;
box-shadow: 0 8px 24px rgba(59, 130, 246, 0.25), 0 4px 12px rgba(0, 0, 0, 0.05);
letter-spacing: 0.01em;
text-align: center;
text-decoration: none;
display: inline-block;
padding: clamp(14px, 4vw, 18px) clamp(24px, 6vw, 36px);
font-size: clamp(14px, 3.5vw, 18px);
min-height: 48px;
min-width: clamp(140px, 40vw, 180px);
transition: all 0.2s ease;
}
.btn-primary:hover {
transform: translateY(-2px);
box-shadow: 0 8px 20px rgba(59, 130, 246, 0.4);
filter: brightness(1.1);
}
.btn-primary:active {
transform: translateY(0);
box-shadow: 0 4px 12px rgba(59, 130, 246, 0.2);
}
.btn-secondary {
background: var(--background-card);
color: var(--primary-blue);
border-radius: 1rem;
font-weight: 600;
border: 2px solid var(--border-light);
text-decoration: none;
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.04), 0 4px 12px rgba(59, 130, 246, 0.08);
letter-spacing: 0.01em;
display: inline-block;
text-align: center;
padding: clamp(14px, 4vw, 18px) clamp(24px, 6vw, 36px);
font-size: clamp(14px, 3.5vw, 18px);
min-height: 48px;
min-width: clamp(140px, 40vw, 180px);
transition: all 0.2s ease;
}
.btn-secondary:hover {
transform: translateY(-2px);
box-shadow: 0 8px 20px rgba(59, 130, 246, 0.15);
border-color: var(--primary-blue);
background: rgba(59, 130, 246, 0.05);
}
.btn-secondary:active {
transform: translateY(0);
box-shadow: 0 4px 12px rgba(59, 130, 246, 0.12);
}
.trust-indicators {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(150px, 100%), 1fr));
gap: clamp(16px, 4vw, 48px);
max-width: 600px;
margin: 0 auto;
padding: 0 clamp(8px, 2vw, 16px);
}
.trust-card {
text-align: center;
background: rgba(255, 255, 255, 0.5);
border: 1px solid rgba(255, 255, 255, 0.8);
backdrop-filter: blur(10px);
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.03);
border-radius: 1rem;
padding: clamp(16px, 4vw, 24px) clamp(12px, 3vw, 16px);
}
.trust-number {
background: var(--text-gradient);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
font-weight: 800;
margin-bottom: 0.5rem;
font-size: clamp(1rem, 3vw, 1.2rem);
}
.trust-text {
color: var(--text-secondary);
font-weight: 500;
letter-spacing: 0.01em;
font-size: clamp(12px, 3vw, 15px);
}
/* Why Choose Us Section - matches company profile */
.why-choose-us {
position: relative;
background: var(--company-gradient);
overflow: hidden;
padding: clamp(60px, 15vw, 120px) clamp(16px, 4vw, 24px);
}
.section-container {
max-width: 1200px;
margin: 0 auto;
position: relative;
z-index: 10;
}
.section-header {
text-align: center;
margin-bottom: clamp(40px, 10vw, 80px);
}
.section-badge {
display: inline-flex;
align-items: center;
gap: 0.5rem;
background: rgba(30, 64, 175, 0.1);
padding: 0.5rem 1.25rem;
border-radius: 50px;
margin-bottom: 1.5rem;
border: 1px solid rgba(30, 64, 175, 0.2);
}
.section-badge-icon {
font-size: 1rem;
}
.section-badge-text {
font-size: 0.875rem;
font-weight: 600;
color: var(--primary-blue);
}
.section-title {
font-weight: 800;
color: var(--primary-blue);
margin-bottom: 1rem;
text-align: center;
font-size: clamp(2rem, 5vw, 3.5rem);
}
.section-subtitle {
font-size: 1.25rem;
color: var(--text-light);
max-width: 600px;
margin: 0 auto;
line-height: 1.6;
}
.why-choose-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr));
gap: clamp(24px, 6vw, 40px);
}
.choice-card {
background: white;
border-radius: clamp(16px, 4vw, 24px);
box-shadow: 0 8px 32px rgba(30, 64, 175, 0.08);
text-align: center;
padding: clamp(24px, 6vw, 40px);
transition: all 0.2s ease;
}
.choice-icon {
margin-bottom: 1.25rem;
font-size: clamp(2.5rem, 6vw, 3.5rem);
margin-bottom: clamp(16px, 4vw, 20px);
}
.choice-title {
font-weight: bold;
color: var(--primary-blue);
margin-bottom: 1rem;
font-size: clamp(1.2rem, 4vw, 1.5rem);
margin-bottom: clamp(12px, 3vw, 16px);
}
.choice-description {
color: var(--text-light);
line-height: 1.6;
font-size: clamp(14px, 3.5vw, 18px);
}
/* Our Process Section - matches services */
.our-process {
background: var(--services-gradient);
padding: clamp(60px, 15vw, 120px) clamp(16px, 4vw, 24px);
}
.process-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(280px, 100%), 1fr));
gap: clamp(20px, 5vw, 32px);
margin-bottom: clamp(40px, 10vw, 60px);
}
.process-step-card {
background: white;
border-radius: clamp(16px, 4vw, 20px);
box-shadow: 0 8px 32px rgba(30, 64, 175, 0.08);
padding: clamp(24px, 6vw, 32px);
display: flex;
align-items: flex-start;
gap: clamp(16px, 4vw, 20px);
transition: all 0.2s ease;
}
.step-number {
background: var(--gradient-primary);
color: white;
width: clamp(40px, 10vw, 50px);
height: clamp(40px, 10vw, 50px);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
font-size: clamp(16px, 4vw, 20px);
flex-shrink: 0;
}
.step-content {
flex: 1;
}
.step-title {
font-weight: bold;
color: var(--primary-blue);
margin-bottom: 0.75rem;
font-size: clamp(1.1rem, 3.5vw, 1.3rem);
}
.step-description {
color: var(--text-light);
line-height: 1.6;
font-size: clamp(14px, 3.5vw, 16px);
}
/* RACE Framework */
.race-framework {
background: white;
border-radius: clamp(16px, 4vw, 24px);
box-shadow: 0 12px 40px rgba(30, 64, 175, 0.08);
padding: clamp(24px, 6vw, 40px);
}
.race-title {
text-align: center;
font-weight: bold;
color: var(--primary-blue);
margin-bottom: clamp(20px, 5vw, 32px);
font-size: clamp(1.3rem, 4vw, 1.8rem);
}
.race-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(200px, 100%), 1fr));
gap: clamp(16px, 4vw, 24px);
}
.race-card {
text-align: center;
background: var(--background-light);
border-radius: clamp(12px, 3vw, 16px);
padding: clamp(16px, 4vw, 24px);
transition: all 0.2s ease;
}
.race-phase {
margin-bottom: 0.75rem;
}
.race-icon {
font-size: clamp(1.5rem, 4vw, 2rem);
margin-bottom: 0.5rem;
display: block;
}
.race-phase h4 {
font-weight: bold;
color: var(--primary-blue);
margin: 0;
font-size: clamp(1.1rem, 3.5vw, 1.3rem);
}
.race-focus {
font-weight: 600;
color: var(--text-primary);
margin-bottom: 0.5rem;
font-size: clamp(14px, 3.5vw, 16px);
}
.race-actions {
color: var(--text-light);
font-size: clamp(12px, 3vw, 14px);
line-height: 1.5;
}
/* Branding Services Section - matches services */
.branding-services {
background: var(--clients-gradient);
padding: clamp(60px, 15vw, 120px) clamp(16px, 4vw, 24px);
}
.services-title {
font-weight: bold;
text-align: center;
margin-bottom: 1rem;
color: var(--primary-blue);
font-size: clamp(1.8rem, 5vw, 2.5rem);
}
.services-subtitle {
text-align: center;
color: var(--text-light);
margin-bottom: 3rem;
font-size: clamp(16px, 4vw, 20px);
margin-bottom: clamp(24px, 6vw, 48px);
}
.branding-services-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr));
gap: clamp(20px, 5vw, 32px);
}
.service-card {
background: white;
border-radius: clamp(16px, 4vw, 20px);
box-shadow: 0 8px 32px rgba(30, 64, 175, 0.08);
text-align: center;
padding: clamp(24px, 6vw, 32px);
transition: all 0.2s ease;
}
.service-icon {
margin-bottom: 1.25rem;
font-size: clamp(2.5rem, 6vw, 3rem);
margin-bottom: clamp(16px, 4vw, 20px);
}
.service-title {
font-weight: bold;
color: var(--primary-blue);
margin-bottom: 1rem;
font-size: clamp(1.2rem, 4vw, 1.4rem);
margin-bottom: clamp(12px, 3vw, 16px);
}
.service-description {
color: var(--text-light);
line-height: 1.6;
font-size: clamp(14px, 3.5vw, 16px);
}
/* CTA Section - matches contact */
.branding-cta {
background: var(--contact-gradient);
padding: clamp(60px, 15vw, 120px) clamp(16px, 4vw, 24px);
}
.cta-container {
max-width: 1200px;
margin: 0 auto;
}
.cta-title {
font-weight: bold;
text-align: center;
color: var(--primary-blue);
font-size: clamp(1.8rem, 5vw, 2.5rem);
margin-bottom: clamp(24px, 6vw, 48px);
}
.cta-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(350px, 100%), 1fr));
gap: clamp(30px, 8vw, 60px);
align-items: start;
}
.cta-content {
background: white;
border-radius: clamp(16px, 4vw, 20px);
box-shadow: 0 8px 32px rgba(30, 64, 175, 0.08);
padding: clamp(24px, 6vw, 40px);
}
.cta-content-title {
font-weight: bold;
color: var(--primary-blue);
margin-bottom: 1rem;
font-size: clamp(1.3rem, 4vw, 1.6rem);
}
.cta-description {
color: var(--text-light);
line-height: 1.6;
margin-bottom: 1.5rem;
font-size: clamp(14px, 3.5vw, 18px);
}
.cta-features {
margin-bottom: 2rem;
}
.cta-feature {
display: flex;
align-items: center;
gap: 0.75rem;
margin-bottom: 0.75rem;
font-size: clamp(14px, 3.5vw, 16px);
}
.feature-icon {
color: var(--success-green);
font-weight: bold;
}
.cta-buttons {
display: flex;
flex-direction: column;
gap: clamp(12px, 3vw, 16px);
}
.cta-btn {
padding: clamp(14px, 4vw, 16px) clamp(20px, 5vw, 24px);
border-radius: clamp(8px, 2vw, 12px);
font-weight: 600;
text-decoration: none;
text-align: center;
font-size: clamp(14px, 3.5vw, 16px);
transition: all 0.2s ease;
min-height: 48px;
display: flex;
align-items: center;
justify-content: center;
}
.cta-btn.primary {
background: var(--gradient-primary);
color: white;
box-shadow: 0 4px 16px rgba(59, 130, 246, 0.25);
}
.cta-btn.primary:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(59, 130, 246, 0.35);
}
.cta-btn.secondary {
background: var(--background-card);
color: var(--primary-blue);
border: 2px solid var(--border-light);
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.05);
}
.cta-btn.secondary:hover {
transform: translateY(-2px);
border-color: var(--primary-blue);
background: rgba(59, 130, 246, 0.05);
box-shadow: 0 6px 20px rgba(59, 130, 246, 0.15);
}
.cta-info {
background: white;
border-radius: clamp(16px, 4vw, 20px);
box-shadow: 0 8px 32px rgba(30, 64, 175, 0.08);
padding: clamp(24px, 6vw, 40px);
}
.cta-info-title {
font-weight: bold;
color: var(--primary-blue);
margin-bottom: 1.5rem;
font-size: clamp(1.2rem, 4vw, 1.5rem);
margin-bottom: clamp(16px, 4vw, 24px);
}
.contact-item {
display: flex;
align-items: flex-start;
gap: clamp(12px, 3vw, 16px);
margin-bottom: clamp(20px, 5vw, 32px);
}
.contact-icon {
background: var(--primary-gradient);
border-radius: clamp(8px, 2vw, 12px);
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
width: clamp(40px, 10vw, 50px);
height: clamp(40px, 10vw, 50px);
font-size: clamp(16px, 4vw, 20px);
}
.contact-details h4 {
font-weight: 600;
color: var(--primary-blue);
margin-bottom: 0.5rem;
font-size: clamp(16px, 4vw, 19px);
}
.contact-details p {
color: var(--text-light);
line-height: 1.6;
font-size: clamp(14px, 3.5vw, 16px);
}
.contact-email {
color: var(--primary-blue);
text-decoration: none;
}
.contact-email:hover {
text-decoration: underline;
}
.commitment-statement {
background: var(--services-gradient);
border-left: 4px solid var(--primary-blue);
border-radius: clamp(12px, 3vw, 16px);
padding: clamp(16px, 4vw, 24px);
margin-top: clamp(20px, 5vw, 32px);
}
.commitment-text {
color: var(--primary-blue);
font-weight: 600;
text-align: center;
font-size: clamp(14px, 3.5vw, 18px);
line-height: 1.6;
}
/* Loading state for buttons */
.cta-btn.loading {
opacity: 0.7;
pointer-events: none;
}
/* Mobile responsive adjustments */
@media (max-width: 767px) {
.cta-buttons {
flex-direction: column;
}
.process-step-card {
flex-direction: column;
text-align: center;
}
.step-number {
margin: 0 auto 1rem auto;
}
.race-grid {
grid-template-columns: 1fr;
}
}

View File

@ -478,6 +478,109 @@ class AgentsCore extends WorkflowsCore {
return isValid;
}
/**
* Handle JotForm agent execution (CyberSec Career Navigator)
*/
async handleJotFormAgent() {
// Check authentication and balance
if (!this.constructor.checkAuthentication()) return;
if (!this.constructor.checkBalance(this.price)) return;
const submitBtn = document.getElementById('generateBtn');
if (submitBtn) {
submitBtn.disabled = true;
submitBtn.textContent = '⏳ Processing Payment...';
}
try {
// Create execution record and charge wallet via form API
const response = await fetch('/agents/api/form/access/', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': document.querySelector('[name=csrfmiddlewaretoken]').value
},
body: JSON.stringify({
agent_slug: this.agentSlug
})
});
if (response.ok) {
const result = await response.json();
// Update wallet balance
this.constructor.updateWalletBalance(result.new_balance);
// Show white-label interface
this.showWhiteLabelInterface(result.interface_url);
this.constructor.showToast('✅ Payment processed! Access granted to Quantum AI Career Navigator', 'success');
} else {
const error = await response.json();
throw new Error(error.error || 'Failed to process payment');
}
} catch (error) {
console.error('Form agent error:', error);
this.constructor.showToast(`${error.message}`, 'error');
this.resetSubmitButton();
}
}
/**
* Show white-label interface in results container
*/
showWhiteLabelInterface(interfaceUrl) {
const resultsContainer = document.getElementById('resultsContainer');
const resultsContent = document.getElementById('resultsContent');
if (resultsContainer && resultsContent) {
// Update header
const widgetTitle = resultsContainer.querySelector('.widget-title');
if (widgetTitle) {
widgetTitle.innerHTML = '<span class="widget-icon">🎓</span>Quantum AI Career Navigator';
}
// Create white-label interface
resultsContent.innerHTML = `
<div class="career-nav-container" style="text-align: center; margin-bottom: 20px;">
<h3 style="color: #0369a1; margin-bottom: 10px;">🎓 Quantum AI Career Navigator</h3>
<p style="color: #6b7280; margin-bottom: 20px;">Meet Jessica, your personal AI cybersecurity career advisor. Share your goals and get expert guidance tailored to your journey.</p>
</div>
<div class="career-interface-container" style="width: 100%; min-height: 600px; border-radius: 12px; overflow: hidden; box-shadow: 0 4px 20px rgba(0,0,0,0.1);">
<iframe
src="${interfaceUrl}"
style="width: 100%; min-height: 600px; border: none; background: white;"
frameborder="0"
scrolling="auto"
title="Quantum AI Career Navigator - Your Personal Career Advisor">
</iframe>
</div>
<div class="career-footer" style="margin-top: 20px; padding: 15px; background: #f8fafc; border-radius: 8px; text-align: center;">
<p style="color: #6b7280; font-size: 14px; margin: 0;">
💡 <strong>Pro Tip:</strong> Be specific about your experience level and career goals for the most personalized advice from your AI advisor!
</p>
</div>
`;
// Hide action buttons since this is an interactive interface
const actionButtons = resultsContainer.querySelector('.results-actions');
if (actionButtons) {
actionButtons.style.display = 'none';
}
// Show results container
resultsContainer.style.display = 'block';
// Scroll to results
resultsContainer.scrollIntoView({ behavior: 'smooth', block: 'start' });
// Reset submit button
this.resetSubmitButton();
}
}
/**
* Reset submit button to original state
*/

View File

@ -30,6 +30,7 @@
</a>
<nav class="header-nav" id="header-nav">
<a href="{% url 'core:homepage' %}" class="nav-link {% if request.resolver_match.url_name == 'homepage' %}active{% endif %}">Home</a>
<a href="{% url 'core:digital_branding' %}" class="nav-link {% if request.resolver_match.url_name == 'digital_branding' %}active{% endif %}">Digital Branding</a>
<a href="{% url 'agents:marketplace' %}" class="nav-link {% if request.resolver_match.url_name == 'marketplace' %}active{% endif %}">AI Marketplace</a>
<a href="{% url 'core:pricing' %}" class="nav-link {% if request.resolver_match.url_name == 'pricing' %}active{% endif %}">Pricing</a>
</nav>

View File

@ -0,0 +1,43 @@
{% extends 'base.html' %}
{% load static %}
{% block title %}Career Navigator - Quantum Tasks AI{% endblock %}
{% block extra_css %}
<style>
/* Override main-container for full-width iframe */
.main-container {
max-width: none;
padding: 0;
height: calc(100vh - 80px); /* Account for header height */
}
.iframe-container {
width: 100%;
height: 100%;
}
.iframe-container iframe {
width: 100%;
height: 100%;
border: none;
display: block;
}
/* Hide footer for this page */
.footer {
display: none !important;
}
</style>
{% endblock %}
{% block content %}
<div class="iframe-container">
<iframe
src="{{ form_url }}"
frameborder="0"
scrolling="auto"
title="Career Navigator">
</iframe>
</div>
{% endblock %}

View File

@ -0,0 +1,523 @@
{% extends 'base.html' %}
{% load static %}
{% block title %}Digital Branding Services - Quantum Tasks AI{% endblock %}
{% block extra_css %}
<link rel="stylesheet" href="{% static 'css/digital-branding.css' %}">
{% endblock %}
{% block content %}
<style>
/* Override main-container for full-width sections */
.main-container {
max-width: none;
padding: 0;
}
</style>
<!-- Hero Section -->
<section id="digital-branding-hero" class="digital-branding-hero">
<div class="hero-container">
<!-- Trust Badge -->
<div class="trust-badge">
<span class="trust-badge-emoji"></span>
<span>Trusted Digital Brand Partner</span>
</div>
<h1 class="hero-title">
<span class="hero-title-gradient">
Digital Branding
</span>
<br />
<span class="hero-title-normal">
Services
</span>
</h1>
<p class="hero-description">
Elevate Your Brand in the AI-Driven Era. Unlock unparalleled digital visibility, recognition, and growth with Quantum Task AI's expert digital branding solutions.
</p>
<!-- CTA Buttons -->
<div class="hero-buttons">
{% if user.is_authenticated %}
<a href="https://form.jotform.com/252121444918050" target="_blank" class="btn-primary">
Start Discovery
</a>
<a href="#our-process" class="btn-secondary">
View Process
</a>
{% else %}
<a href="https://form.jotform.com/252121444918050" target="_blank" class="btn-primary">
Get Started
</a>
<a href="#our-process" class="btn-secondary">
Learn More
</a>
{% endif %}
</div>
<!-- Trust Indicators -->
<div class="trust-indicators">
<div class="trust-card">
<div class="trust-number">
AI-Powered
</div>
<div class="trust-text">
Strategies
</div>
</div>
<div class="trust-card">
<div class="trust-number">
End-to-End
</div>
<div class="trust-text">
Digital Presence
</div>
</div>
<div class="trust-card">
<div class="trust-number">
Custom
</div>
<div class="trust-text">
Tailored Approach
</div>
</div>
</div>
</div>
</section>
<!-- Why Choose Us Section -->
<section id="why-choose-us" class="why-choose-us">
<div class="section-container">
<!-- Section Header -->
<div class="section-header">
<div class="section-badge">
<span class="section-badge-icon">🎯</span>
<span class="section-badge-text">Why Choose Us</span>
</div>
<h2 class="section-title">
AI-Powered Digital Excellence
</h2>
<p class="section-subtitle">
Transform your brand with cutting-edge AI strategies and comprehensive digital solutions
</p>
</div>
<div class="why-choose-grid">
<div class="choice-card">
<div class="choice-icon">🤖</div>
<h3 class="choice-title">AI-Powered Strategies</h3>
<p class="choice-description">
Harness cutting-edge AI to analyze your digital landscape, audience trends, and competitor benchmarks, ensuring your brand stands out in the AI-driven era.
</p>
</div>
<div class="choice-card">
<div class="choice-icon">🌐</div>
<h3 class="choice-title">End-to-End Digital Presence</h3>
<p class="choice-description">
From LLM, SEO and social activation to influencer partnerships and review management - we handle every aspect of your digital brand presence.
</p>
</div>
<div class="choice-card">
<div class="choice-icon"></div>
<h3 class="choice-title">Custom-Tailored Approach</h3>
<p class="choice-description">
Our process adapts to your unique vision, market challenges, and growth ambitions, delivering personalized strategies that drive real results.
</p>
</div>
</div>
</div>
</section>
<!-- Our Process Section -->
<section id="our-process" class="our-process">
<div class="section-container">
<div class="section-header">
<div class="section-badge">
<span class="section-badge-icon">📋</span>
<span class="section-badge-text">Our Process</span>
</div>
<h2 class="section-title">
The SOSTAC+RACE Method
</h2>
<p class="section-subtitle">
A unified, data-driven planning system that combines proven strategy with powerful digital execution
</p>
</div>
<div class="process-grid">
<div class="process-step-card">
<div class="step-number">1</div>
<div class="step-content">
<h3 class="step-title">Situation Analysis</h3>
<p class="step-description">
Understand your brand's current status, digital footprint, and competitor landscape to establish a baseline for growth.
</p>
</div>
</div>
<div class="process-step-card">
<div class="step-number">2</div>
<div class="step-content">
<h3 class="step-title">Objectives</h3>
<p class="step-description">
Set SMART goals to grow brand awareness, engagement, leads, and loyalty with measurable targets and timelines.
</p>
</div>
</div>
<div class="process-step-card">
<div class="step-number">3</div>
<div class="step-content">
<h3 class="step-title">Strategy</h3>
<p class="step-description">
Map your customer journey, segment audiences, define your value proposition, and select optimal channels for maximum impact.
</p>
</div>
</div>
<div class="process-step-card">
<div class="step-number">4</div>
<div class="step-content">
<h3 class="step-title">Tactics (RACE Framework)</h3>
<p class="step-description">
Execute with Reach (visibility), Act (engagement), Convert (sales), and Engage (loyalty) strategies across all channels.
</p>
</div>
</div>
<div class="process-step-card">
<div class="step-number">5</div>
<div class="step-content">
<h3 class="step-title">Action</h3>
<p class="step-description">
Assign tasks, manage timelines, and ensure streamlined brand asset creation across all digital channels and platforms.
</p>
</div>
</div>
<div class="process-step-card">
<div class="step-number">6</div>
<div class="step-content">
<h3 class="step-title">Control</h3>
<p class="step-description">
Monitor analytics, measure KPIs, and refine strategy through continuous feedback loops for ongoing optimization.
</p>
</div>
</div>
</div>
<!-- RACE Framework Details -->
<div class="race-framework">
<h3 class="race-title">RACE Framework Breakdown</h3>
<div class="race-grid">
<div class="race-card">
<div class="race-phase">
<span class="race-icon">📢</span>
<h4>Reach</h4>
</div>
<div class="race-focus">Maximize visibility</div>
<div class="race-actions">LLM & SEO, paid ads, influencer partnerships, digital PR</div>
</div>
<div class="race-card">
<div class="race-phase">
<span class="race-icon">💬</span>
<h4>Act</h4>
</div>
<div class="race-focus">Drive engagement</div>
<div class="race-actions">Content marketing, landing pages, audience interaction</div>
</div>
<div class="race-card">
<div class="race-phase">
<span class="race-icon">🎯</span>
<h4>Convert</h4>
</div>
<div class="race-focus">Increase conversions</div>
<div class="race-actions">Optimized CTAs, retargeting, AI-powered lead nurture</div>
</div>
<div class="race-card">
<div class="race-phase">
<span class="race-icon">❤️</span>
<h4>Engage</h4>
</div>
<div class="race-focus">Cultivate loyalty & advocacy</div>
<div class="race-actions">Email/CRM, community management, advocacy campaigns</div>
</div>
</div>
</div>
</div>
</section>
<!-- Services Section -->
<section id="services" class="branding-services">
<div class="section-container">
<h2 class="services-title">
What We Offer
</h2>
<p class="services-subtitle">
Comprehensive digital branding solutions tailored to your business needs
</p>
<div class="branding-services-grid">
<div class="service-card">
<div class="service-icon">🎨</div>
<h3 class="service-title">Brand Discovery & Identity Design</h3>
<p class="service-description">
Complete brand audit, identity creation, and visual design systems that reflect your unique value proposition and market position.
</p>
</div>
<div class="service-card">
<div class="service-icon">📱</div>
<h3 class="service-title">Digital Platform Prioritization & Setup</h3>
<p class="service-description">
Strategic platform selection and optimization across social media, websites, and digital touchpoints for maximum brand impact.
</p>
</div>
<div class="service-card">
<div class="service-icon">🔍</div>
<h3 class="service-title">LLMO, SEO, Paid Media & Social Activation</h3>
<p class="service-description">
Advanced Large Language Model Optimization, search engine optimization, targeted advertising, and social media strategy execution.
</p>
</div>
<div class="service-card">
<div class="service-icon">📢</div>
<h3 class="service-title">Influencer & PR Campaigns</h3>
<p class="service-description">
Strategic influencer partnerships, public relations campaigns, and media outreach to amplify your brand's reach and credibility.
</p>
</div>
<div class="service-card">
<div class="service-icon">🎯</div>
<h3 class="service-title">Consistent Visual & Messaging Systems</h3>
<p class="service-description">
Unified brand guidelines, messaging frameworks, and visual standards that ensure consistency across all digital touchpoints.
</p>
</div>
<div class="service-card">
<div class="service-icon">📊</div>
<h3 class="service-title">Comprehensive Tracking & Analytics</h3>
<p class="service-description">
Advanced analytics setup, performance monitoring, and data-driven insights to measure and optimize your brand's digital performance.
</p>
</div>
</div>
</div>
</section>
<!-- CTA Section -->
<section id="discovery-form" class="branding-cta">
<div class="cta-container">
<h2 class="cta-title">
Start Your Digital Branding Journey
</h2>
<div class="cta-grid">
<!-- CTA Content -->
<div class="cta-content">
<h3 class="cta-content-title">Ready to transform your digital brand?</h3>
<p class="cta-description">
Fill out our Digital Branding Discovery Questionnaire and we'll review your goals and craft a personalized proposal within 24 hours.
</p>
<!-- Features List -->
<div class="cta-features">
<div class="cta-feature">
<span class="feature-icon"></span>
<span>Free brand assessment and consultation</span>
</div>
<div class="cta-feature">
<span class="feature-icon"></span>
<span>Customized digital strategy roadmap</span>
</div>
<div class="cta-feature">
<span class="feature-icon"></span>
<span>24-hour response with detailed proposal</span>
</div>
</div>
<!-- CTA Buttons -->
<div class="cta-buttons">
<!-- <a href="https://form.jotform.com/252121444918050" target="_blank" class="cta-btn primary">
🚀 Get Discovery Questionnaire
</a> -->
<a href="https://form.jotform.com/252121444918050" target="_blank" class="cta-btn secondary">
💬 Contact Us Directly
</a>
</div>
</div>
<!-- Contact Information -->
<div class="cta-info">
<h3 class="cta-info-title">Get in Touch</h3>
<!-- Contact Item -->
<div class="contact-item">
<div class="contact-icon">
✉️
</div>
<div class="contact-details">
<h4>Email Address</h4>
<p>
<a href="mailto:abhay@quantumtaskai.com" class="contact-email">
abhay@quantumtaskai.com
</a>
</p>
</div>
</div>
<!-- Commitment Statement -->
<div class="commitment-statement">
<p class="commitment-text">
Transforming Brands for the Digital Future with AI-powered solutions and expert cybersecurity strategies.
</p>
</div>
</div>
</div>
</div>
</section>
{% endblock %}
{% block extra_js %}
<script>
class DigitalBrandingManager {
constructor() {
this.processCards = document.querySelectorAll('.process-step-card');
this.raceCards = document.querySelectorAll('.race-card');
this.serviceCards = document.querySelectorAll('.service-card');
this.ctaButtons = document.querySelectorAll('.cta-btn');
this.init();
}
init() {
this.setupCardInteractions();
this.setupButtonHovers();
this.addScrollAnimations();
this.setupSmoothScrolling();
}
setupCardInteractions() {
// Process step cards
this.processCards.forEach(card => {
card.addEventListener('mouseenter', () => {
this.highlightCard(card);
});
card.addEventListener('mouseleave', () => {
this.removeHighlight(card);
});
});
// RACE framework cards
this.raceCards.forEach(card => {
card.addEventListener('mouseenter', () => {
this.highlightCard(card);
});
card.addEventListener('mouseleave', () => {
this.removeHighlight(card);
});
});
// Service cards
this.serviceCards.forEach(card => {
card.addEventListener('mouseenter', () => {
this.highlightCard(card);
});
card.addEventListener('mouseleave', () => {
this.removeHighlight(card);
});
});
}
highlightCard(card) {
card.style.transform = 'translateY(-4px)';
card.style.boxShadow = '0 20px 40px rgba(30, 64, 175, 0.15)';
}
removeHighlight(card) {
card.style.transform = 'translateY(0)';
card.style.boxShadow = '';
}
setupButtonHovers() {
this.ctaButtons.forEach(button => {
button.addEventListener('mouseenter', () => {
button.style.transform = 'translateY(-2px)';
});
button.addEventListener('mouseleave', () => {
button.style.transform = '';
});
button.addEventListener('click', () => {
if (!button.classList.contains('loading')) {
button.classList.add('loading');
const originalText = button.textContent;
button.textContent = '⏳ Loading...';
setTimeout(() => {
if (button.classList.contains('loading')) {
button.classList.remove('loading');
button.textContent = originalText;
}
}, 2000);
}
});
});
}
addScrollAnimations() {
if ('IntersectionObserver' in window) {
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 cards for scroll animations
[...this.processCards, ...this.raceCards, ...this.serviceCards].forEach((card, index) => {
card.style.opacity = '0';
card.style.transform = 'translateY(20px)';
card.style.transition = `opacity 0.6s ease ${index * 0.1}s, transform 0.6s ease ${index * 0.1}s`;
observer.observe(card);
});
// Observe sections
document.querySelectorAll('.section-header, .cta-content').forEach(section => {
section.style.opacity = '0';
section.style.transform = 'translateY(20px)';
section.style.transition = 'opacity 0.6s ease, transform 0.6s ease';
observer.observe(section);
});
}
}
setupSmoothScrolling() {
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener('click', function (e) {
e.preventDefault();
const target = document.querySelector(this.getAttribute('href'));
if (target) {
target.scrollIntoView({
behavior: 'smooth',
block: 'start'
});
}
});
});
}
}
// Initialize when DOM is loaded
document.addEventListener('DOMContentLoaded', function() {
new DigitalBrandingManager();
});
</script>
{% endblock %}