mirror of
https://github.com/thecyberlearn/quantum-ai-v2.git
synced 2026-08-18 11:12:58 +00:00
- Extract 476 lines of inline CSS from pricing.html to external pricing.css file - Unify font stack across all pages to use 'Inter', Arial, sans-serif consistently - Fix font weight inconsistency between marketplace and pricing page navigation - Add clean active page indicator with thin blue underline for current page - Optimize CSS loading order: page-specific CSS first, header-component.css last - Remove font inheritance conflicts between agent-base.css and header component - Standardize Inter font loading in base.html for all pages (single source of truth) - Improve browser compatibility with font smoothing and rendering optimizations - Add comprehensive documentation in HEADER_OPTIMIZATION.md Key improvements: • Consistent navigation font weight across all pages (resolves bold font issue) • Better performance with external CSS files and browser caching • Clean component-based CSS architecture for maintainability • Subtle active state indicators without layout shifts • Unified theme system with CSS custom properties 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
346 lines
10 KiB
HTML
346 lines
10 KiB
HTML
{% extends 'base.html' %}
|
|
{% load static %}
|
|
|
|
{% block title %}Create Account{% endblock %}
|
|
|
|
{% block extra_css %}
|
|
<link rel="stylesheet" href="{% static 'css/agent-base.css' %}">
|
|
<style>
|
|
/* Override main-container for full-width sections */
|
|
.main-container {
|
|
max-width: none;
|
|
padding: 0;
|
|
}
|
|
|
|
/* Register page using agent-base.css */
|
|
.register-page {
|
|
background: var(--background);
|
|
min-height: calc(100vh - 84px);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
padding: var(--spacing-lg);
|
|
}
|
|
|
|
.register-container {
|
|
background: var(--surface);
|
|
border-radius: var(--radius-lg);
|
|
padding: 48px;
|
|
box-shadow: var(--shadow-lg);
|
|
width: 100%;
|
|
max-width: 520px;
|
|
border: 1px solid var(--outline);
|
|
}
|
|
|
|
.register-header {
|
|
text-align: center;
|
|
margin-bottom: 40px;
|
|
}
|
|
|
|
.register-title {
|
|
font-size: 28px;
|
|
font-weight: 700;
|
|
color: var(--on-surface);
|
|
margin: 0 0 var(--spacing-sm) 0;
|
|
}
|
|
|
|
.register-subtitle {
|
|
font-size: 16px;
|
|
color: var(--on-surface-variant);
|
|
margin: 0;
|
|
}
|
|
|
|
.form-row {
|
|
display: grid;
|
|
grid-template-columns: 1fr 1fr;
|
|
gap: var(--spacing-md);
|
|
margin-bottom: var(--spacing-lg);
|
|
}
|
|
|
|
.password-strength {
|
|
margin-top: var(--spacing-sm);
|
|
font-size: 12px;
|
|
color: var(--on-surface-variant);
|
|
}
|
|
|
|
.strength-indicator {
|
|
display: flex;
|
|
gap: var(--spacing-xs);
|
|
margin-top: var(--spacing-xs);
|
|
}
|
|
|
|
.strength-bar {
|
|
flex: 1;
|
|
height: 3px;
|
|
border-radius: 2px;
|
|
background: var(--outline);
|
|
transition: background-color var(--transition);
|
|
}
|
|
|
|
.strength-bar.weak { background-color: var(--on-surface-variant); }
|
|
.strength-bar.medium { background-color: var(--on-surface); }
|
|
.strength-bar.strong { background-color: var(--primary); }
|
|
|
|
.help-text {
|
|
font-size: 12px;
|
|
color: var(--on-surface-variant);
|
|
margin-top: var(--spacing-xs);
|
|
}
|
|
|
|
.register-btn {
|
|
width: 100%;
|
|
margin-bottom: 32px;
|
|
margin-top: 8px;
|
|
}
|
|
|
|
.messages {
|
|
margin-bottom: var(--spacing-lg);
|
|
}
|
|
|
|
.message {
|
|
padding: var(--spacing-md);
|
|
border-radius: var(--radius-sm);
|
|
margin-bottom: var(--spacing-sm);
|
|
font-size: 14px;
|
|
font-weight: 500;
|
|
border: 1px solid;
|
|
}
|
|
|
|
.message.success {
|
|
background: var(--surface-variant);
|
|
color: var(--on-surface);
|
|
border-color: var(--outline);
|
|
}
|
|
|
|
.message.error {
|
|
background: var(--surface-variant);
|
|
color: var(--on-surface);
|
|
border-color: var(--outline);
|
|
}
|
|
|
|
.register-auth-links {
|
|
text-align: center;
|
|
padding-top: 24px;
|
|
border-top: 1px solid var(--outline);
|
|
}
|
|
|
|
.register-auth-links p {
|
|
margin: var(--spacing-sm) 0;
|
|
color: var(--on-surface-variant);
|
|
font-size: 14px;
|
|
}
|
|
|
|
.register-auth-links a {
|
|
color: var(--primary);
|
|
text-decoration: none;
|
|
font-weight: 600;
|
|
transition: all var(--transition);
|
|
}
|
|
|
|
.register-auth-links a:hover {
|
|
text-decoration: underline;
|
|
}
|
|
|
|
/* Responsive */
|
|
@media (max-width: 640px) {
|
|
.form-row {
|
|
grid-template-columns: 1fr;
|
|
}
|
|
}
|
|
|
|
@media (max-width: 480px) {
|
|
.register-page {
|
|
padding: var(--spacing-md);
|
|
}
|
|
|
|
.register-container {
|
|
padding: 32px 24px;
|
|
}
|
|
|
|
.register-title {
|
|
font-size: 24px;
|
|
}
|
|
}
|
|
</style>
|
|
{% endblock %}
|
|
|
|
{% block content %}
|
|
<div class="register-page theme-professional">
|
|
<div class="register-container">
|
|
<div class="register-header">
|
|
<h1 class="register-title">Create Account</h1>
|
|
<p class="register-subtitle">Join our platform to get started</p>
|
|
</div>
|
|
|
|
{% if messages %}
|
|
<div class="messages">
|
|
{% for message in messages %}
|
|
<div class="message {{ message.tags }}">{{ message }}</div>
|
|
{% endfor %}
|
|
</div>
|
|
{% endif %}
|
|
|
|
<form method="post" class="register-form" id="registerForm">
|
|
{% csrf_token %}
|
|
|
|
<div class="form-row">
|
|
<div class="form-group">
|
|
<label for="username" class="form-label">Username</label>
|
|
<input
|
|
type="text"
|
|
id="username"
|
|
name="username"
|
|
class="form-input"
|
|
placeholder="Choose username"
|
|
required
|
|
autocomplete="username"
|
|
>
|
|
<div class="help-text">Your unique identifier</div>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="email" class="form-label">Email</label>
|
|
<input
|
|
type="email"
|
|
id="email"
|
|
name="email"
|
|
class="form-input"
|
|
placeholder="Enter your email"
|
|
required
|
|
autocomplete="email"
|
|
>
|
|
<div class="help-text">We'll use this for updates</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="password1" class="form-label">Password</label>
|
|
<input
|
|
type="password"
|
|
id="password1"
|
|
name="password1"
|
|
class="form-input"
|
|
placeholder="Create password"
|
|
required
|
|
autocomplete="new-password"
|
|
>
|
|
<div class="password-strength">
|
|
<div>Password strength:</div>
|
|
<div class="strength-indicator">
|
|
<div class="strength-bar" id="strength-1"></div>
|
|
<div class="strength-bar" id="strength-2"></div>
|
|
<div class="strength-bar" id="strength-3"></div>
|
|
<div class="strength-bar" id="strength-4"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="password2" class="form-label">Confirm Password</label>
|
|
<input
|
|
type="password"
|
|
id="password2"
|
|
name="password2"
|
|
class="form-input"
|
|
placeholder="Confirm password"
|
|
required
|
|
autocomplete="new-password"
|
|
>
|
|
<div class="help-text" id="password-match"></div>
|
|
</div>
|
|
|
|
<button type="submit" class="btn btn-primary register-btn" id="registerBtn">
|
|
Create Account
|
|
</button>
|
|
</form>
|
|
|
|
<div class="register-auth-links">
|
|
<p>Already have an account? <a href="{% url 'authentication:login' %}">Sign in</a></p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endblock %}
|
|
|
|
{% block extra_js %}
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
const usernameField = document.getElementById('username');
|
|
const password1Field = document.getElementById('password1');
|
|
const password2Field = document.getElementById('password2');
|
|
const registerForm = document.getElementById('registerForm');
|
|
const registerBtn = document.getElementById('registerBtn');
|
|
const passwordMatch = document.getElementById('password-match');
|
|
|
|
// Focus on username field
|
|
if (usernameField) {
|
|
usernameField.focus();
|
|
}
|
|
|
|
// Password strength checker
|
|
if (password1Field) {
|
|
password1Field.addEventListener('input', function() {
|
|
const password = this.value;
|
|
const strength = calculatePasswordStrength(password);
|
|
updateStrengthIndicator(strength);
|
|
});
|
|
}
|
|
|
|
// Password confirmation checker
|
|
if (password2Field) {
|
|
password2Field.addEventListener('input', function() {
|
|
const password1 = password1Field.value;
|
|
const password2 = this.value;
|
|
|
|
if (password2.length === 0) {
|
|
passwordMatch.textContent = '';
|
|
passwordMatch.style.color = '';
|
|
} else if (password1 === password2) {
|
|
passwordMatch.textContent = '✅ Passwords match';
|
|
passwordMatch.style.color = 'var(--primary)';
|
|
} else {
|
|
passwordMatch.textContent = '❌ Passwords do not match';
|
|
passwordMatch.style.color = 'var(--on-surface-variant)';
|
|
}
|
|
});
|
|
}
|
|
|
|
// Form submission
|
|
if (registerForm && registerBtn) {
|
|
registerForm.addEventListener('submit', function() {
|
|
registerBtn.innerHTML = 'Creating account...';
|
|
registerBtn.disabled = true;
|
|
});
|
|
}
|
|
|
|
function calculatePasswordStrength(password) {
|
|
let strength = 0;
|
|
|
|
if (password.length >= 8) strength++;
|
|
if (password.match(/[a-z]/)) strength++;
|
|
if (password.match(/[A-Z]/)) strength++;
|
|
if (password.match(/[0-9]/)) strength++;
|
|
if (password.match(/[^a-zA-Z0-9]/)) strength++;
|
|
|
|
return Math.min(strength, 4);
|
|
}
|
|
|
|
function updateStrengthIndicator(strength) {
|
|
const bars = document.querySelectorAll('.strength-bar');
|
|
|
|
bars.forEach((bar, index) => {
|
|
bar.className = 'strength-bar';
|
|
|
|
if (index < strength) {
|
|
if (strength <= 2) {
|
|
bar.classList.add('weak');
|
|
} else if (strength <= 3) {
|
|
bar.classList.add('medium');
|
|
} else {
|
|
bar.classList.add('strong');
|
|
}
|
|
}
|
|
});
|
|
}
|
|
});
|
|
</script>
|
|
{% endblock %} |