initial commit

This commit is contained in:
mohamad
2026-06-21 17:54:19 +03:30
commit 20d6df3b27
191 changed files with 14362 additions and 0 deletions
+29
View File
@@ -0,0 +1,29 @@
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="{% block meta_description %}Tecvico — Innovation, Advancement, Competition{% endblock %}" />
<title>{% block title %}Tecvico{% endblock %} | Tecvico</title>
<link rel="icon" href="{% static 'images/tecvico/brand-logo.svg' %}" type="image/svg+xml" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Open+Sans:wght@400;600;700;800&family=Ubuntu:wght@400;500;700&display=swap" rel="stylesheet" />
<link rel="stylesheet" href="{% static 'css/main.css' %}" />
{% block extra_css %}{% endblock %}
</head>
<body>
{% include "partials/_navbar.html" %}
<main id="main-content">
{% block content %}{% endblock %}
</main>
{% include "partials/_footer.html" %}
<script src="{% static 'js/main.js' %}"></script>
{% block extra_js %}{% endblock %}
</body>
</html>
+8
View File
@@ -0,0 +1,8 @@
{% extends "base.html" %}
{% block title %}About{% endblock %}
{% block meta_description %}Learn about Tecvico — a dynamic team challenging business norms with innovative solutions.{% endblock %}
{% block content %}
{% include "partials/_page_sections.html" with sections=about_sections %}
{% endblock %}
+307
View File
@@ -0,0 +1,307 @@
{% extends "base.html" %}
{% load static %}
{% block title %}Contact{% endblock %}
{% block meta_description %}Contact Tecvico — support and general inquiries.{% endblock %}
{% block content %}
<section class="page-hero" aria-labelledby="contact-heading">
<div class="page-hero-blobs" aria-hidden="true">
<div class="blob blob--1"></div>
<div class="blob blob--2"></div>
</div>
<div class="container">
<div class="page-hero-content">
<div class="section-badge">Get in Touch</div>
<h1 class="page-hero-title" id="contact-heading">Contact Us</h1>
<p class="page-hero-subtitle">Have a question or want to reach the Tecvico team? Fill out the form or contact us directly below.</p>
</div>
</div>
</section>
{% include "partials/_page_videos.html" with videos=contact_videos %}
<section class="section" aria-labelledby="contact-form-heading">
<div class="container">
<div class="contact-layout{% if not site_contact.has_contact_sidebar %} contact-layout--full{% endif %}">
<div class="contact-form-wrap glass-card fade-in">
<h2 class="contact-form-title" id="contact-form-heading">Send a Message</h2>
<form id="contactForm" novalidate action="{% url 'pages:contact' %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
<div class="form-group">
<label for="id_name">Full Name <span class="required-star">*</span></label>
{{ form.name }}
<span class="form-field-error" data-field="name"></span>
</div>
<div class="form-group">
<label for="id_title">Subject / Title <span class="required-star">*</span></label>
{{ form.title }}
<span class="form-field-error" data-field="title"></span>
</div>
<div class="form-group">
<label for="id_description">Message <span class="required-star">*</span></label>
{{ form.description }}
<span class="form-field-error" data-field="description"></span>
</div>
<div class="form-group">
<label for="id_email">Email <span class="optional-label">(optional)</span></label>
{{ form.email }}
<span class="form-field-error" data-field="email"></span>
</div>
<div class="form-group">
<label for="id_attachments">Attachments <span class="optional-label">(optional)</span></label>
<input type="file" name="attachments" id="id_attachments" multiple
accept=".png,.jpg,.jpeg,.gif,.webp,.bmp,.zip,.log,.txt"
class="file-input" />
<p class="form-hint">Images, ZIP, or log/text files — up to 3 files, 10 MB each.</p>
<p class="form-file-list" id="attachmentFileList" aria-live="polite"></p>
<span class="form-field-error" data-field="attachments"></span>
</div>
<div class="form-group form-group--captcha">
<label for="id_captcha">
Verification: what is <strong id="captchaQuestion">{{ captcha_question }}</strong>?
<span class="required-star">*</span>
</label>
<input type="number" name="captcha_answer" id="id_captcha"
placeholder="Answer" min="0" max="18" required
class="captcha-input" />
<span class="form-field-error" data-field="captcha"></span>
</div>
<button type="submit" class="btn-primary btn-submit" id="submitBtn">
<span class="btn-label">Send Message</span>
<span class="btn-spinner" hidden aria-hidden="true">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M12 2v4M12 18v4M4.93 4.93l2.83 2.83M16.24 16.24l2.83 2.83M2 12h4M18 12h4M4.93 19.07l2.83-2.83M16.24 7.76l2.83-2.83"/>
</svg>
</span>
</button>
</form>
</div>
{% if site_contact.has_contact_sidebar %}
<aside class="contact-sidebar">
{% if site_contact.has_support_email %}
<div class="contact-card glass-card fade-in">
<div class="contact-icon" aria-hidden="true">
<svg width="28" height="28" viewBox="0 0 32 32" fill="none">
<path d="M5 8C5 6.895 5.895 6 7 6H25C26.105 6 27 6.895 27 8V22C27 23.105 26.105 24 25 24H7C5.895 24 5 23.105 5 22V8Z" stroke="currentColor" stroke-width="1.5"/>
<path d="M5 9L16 16L27 9" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
</svg>
</div>
<h3 class="contact-card-title">{{ site_contact.email_card_title_display }}</h3>
{% if site_contact.email_card_description %}
<p class="contact-card-desc">{{ site_contact.email_card_description }}</p>
{% endif %}
{% include "partials/_contact_email.html" with link_class="contact-email-link" %}
</div>
{% endif %}
{% if site_contact.has_discord %}
<div class="contact-card glass-card fade-in">
<div class="contact-icon" aria-hidden="true">
<svg width="28" height="28" viewBox="0 0 24 24" fill="currentColor">
<path d="M20.317 4.37a19.791 19.791 0 0 0-4.885-1.515.074.074 0 0 0-.079.037c-.21.375-.444.864-.608 1.25a18.27 18.27 0 0 0-5.487 0 12.64 12.64 0 0 0-.617-1.25.077.077 0 0 0-.079-.037A19.736 19.736 0 0 0 3.677 4.37a.07.07 0 0 0-.032.027C.533 9.046-.32 13.58.099 18.057.1 18.08.114 18.1.133 18.11a19.9 19.9 0 0 0 5.993 3.03.078.078 0 0 0 .084-.028c.462-.63.874-1.295 1.226-1.994a.076.076 0 0 0-.041-.106 13.107 13.107 0 0 1-1.872-.892.077.077 0 0 1-.008-.128 10.2 10.2 0 0 0 .372-.292.074.074 0 0 1 .077-.01c3.928 1.793 8.18 1.793 12.062 0a.074.074 0 0 1 .078.01c.12.098.246.198.373.292a.077.077 0 0 1-.006.127 12.299 12.299 0 0 1-1.873.892.077.077 0 0 0-.041.107c.36.698.772 1.362 1.225 1.993a.076.076 0 0 0 .084.028 19.839 19.839 0 0 0 6.002-3.03.077.077 0 0 0 .032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 0 0-.031-.03z"/>
</svg>
</div>
<h3 class="contact-card-title">{{ site_contact.discord_card_title_display }}</h3>
{% if site_contact.discord_card_description %}
<p class="contact-card-desc">{{ site_contact.discord_card_description }}</p>
{% endif %}
{% include "partials/_contact_discord.html" with button_class="btn-primary btn--sm" %}
</div>
{% endif %}
{% if site_contact.has_office_address %}
<div class="contact-card glass-card fade-in">
<div class="contact-icon" aria-hidden="true">
<svg width="28" height="28" viewBox="0 0 32 32" fill="none">
<path d="M16 3C11.029 3 7 7.029 7 12C7 19 16 29 16 29C16 29 25 19 25 12C25 7.029 20.971 3 16 3Z" stroke="currentColor" stroke-width="1.5"/>
<circle cx="16" cy="12" r="3" stroke="currentColor" stroke-width="1.5"/>
</svg>
</div>
<h3 class="contact-card-title">{{ site_contact.office_card_title_display }}</h3>
{% include "partials/_contact_office.html" with address_class="contact-address" %}
</div>
{% endif %}
</aside>
{% endif %}
</div>
</div>
</section>
<div id="noEmailModal" class="modal-overlay" role="dialog" aria-modal="true" aria-labelledby="noEmailTitle" hidden>
<div class="modal-box glass-card">
<div class="modal-icon-wrap">
<svg width="40" height="40" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
<path d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"/>
</svg>
</div>
<h3 class="modal-title" id="noEmailTitle">No reply address</h3>
<p class="modal-body">You haven't provided an email address. Without it, we won't be able to respond to your message. Would you like to add one, or send without a reply address?</p>
<div class="modal-actions">
<button class="btn-ghost" id="modalAddEmail">Add Email</button>
<button class="btn-primary" id="modalSendAnyway">Send Without Email</button>
</div>
</div>
</div>
<div id="successModal" class="modal-overlay" role="dialog" aria-modal="true" aria-labelledby="successTitle" hidden>
<div class="modal-box glass-card">
<div class="modal-icon-wrap modal-icon-wrap--success">
<svg width="40" height="40" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
<path d="M22 11.08V12a10 10 0 11-5.93-9.14"/><polyline points="22 4 12 14.01 9 11.01"/>
</svg>
</div>
<h3 class="modal-title" id="successTitle">Message Sent!</h3>
<p class="modal-body">Thank you for reaching out. We've received your message and will get back to you as soon as possible.</p>
<button class="btn-primary" id="successClose">Done</button>
</div>
</div>
<div id="errorModal" class="modal-overlay" role="dialog" aria-modal="true" aria-labelledby="errorTitle" hidden>
<div class="modal-box glass-card">
<div class="modal-icon-wrap modal-icon-wrap--error">
<svg width="40" height="40" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
<circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/>
</svg>
</div>
<h3 class="modal-title" id="errorTitle">Something Went Wrong</h3>
<p class="modal-body" id="errorModalMsg">Please check your answers and try again.</p>
<button class="btn-ghost" id="errorClose">Try Again</button>
</div>
</div>
{% endblock %}
{% block extra_js %}
<script>
(function () {
const form = document.getElementById('contactForm');
if (!form) return;
const emailField = form.querySelector('#id_email');
const fileInput = form.querySelector('#id_attachments');
const fileList = form.querySelector('#attachmentFileList');
const submitBtn = form.querySelector('#submitBtn');
const btnLabel = submitBtn.querySelector('.btn-label');
const btnSpinner = submitBtn.querySelector('.btn-spinner');
function showModal(id) {
const el = document.getElementById(id);
if (el) { el.hidden = false; el.focus(); }
}
function hideModal(id) {
const el = document.getElementById(id);
if (el) el.hidden = true;
}
function clearErrors() {
form.querySelectorAll('.form-field-error').forEach(el => { el.textContent = ''; });
form.querySelectorAll('.form-group').forEach(el => el.classList.remove('has-error'));
}
function showErrors(errors) {
clearErrors();
Object.entries(errors).forEach(([field, msgs]) => {
const span = form.querySelector(`[data-field="${field}"]`);
if (span) {
span.textContent = msgs[0] || '';
span.closest('.form-group')?.classList.add('has-error');
}
});
}
function setLoading(on) {
submitBtn.disabled = on;
btnLabel.hidden = on;
btnSpinner.hidden = !on;
}
async function submitForm() {
clearErrors();
setLoading(true);
const formData = new FormData(form);
try {
const res = await fetch(form.action || window.location.href, {
method: 'POST',
body: formData,
headers: { 'X-Requested-With': 'XMLHttpRequest' },
});
const data = await res.json();
if (data.success) {
form.reset();
if (fileList) fileList.textContent = '';
showModal('successModal');
} else {
if (data.errors) showErrors(data.errors);
if (data.errors?.captcha) {
document.getElementById('errorModalMsg').textContent = data.errors.captcha[0];
showModal('errorModal');
} else if (!res.ok) {
showModal('errorModal');
}
if (data.captcha_question) {
document.getElementById('captchaQuestion').textContent = data.captcha_question;
const captchaInput = form.querySelector('#id_captcha');
if (captchaInput) captchaInput.value = '';
}
}
} catch {
showModal('errorModal');
} finally {
setLoading(false);
}
}
fileInput?.addEventListener('change', () => {
if (!fileList) return;
const names = [...fileInput.files].map(file => file.name);
fileList.textContent = names.length ? names.join(', ') : '';
});
form.addEventListener('submit', e => {
e.preventDefault();
if (!emailField.value.trim()) {
showModal('noEmailModal');
} else {
submitForm();
}
});
document.getElementById('modalAddEmail')?.addEventListener('click', () => {
hideModal('noEmailModal');
emailField.focus();
});
document.getElementById('modalSendAnyway')?.addEventListener('click', () => {
hideModal('noEmailModal');
submitForm();
});
document.getElementById('successClose')?.addEventListener('click', () => hideModal('successModal'));
document.getElementById('errorClose')?.addEventListener('click', () => hideModal('errorModal'));
document.querySelectorAll('.modal-overlay').forEach(overlay => {
overlay.addEventListener('click', e => {
if (e.target === overlay) overlay.hidden = true;
});
});
document.addEventListener('keydown', e => {
if (e.key === 'Escape') {
document.querySelectorAll('.modal-overlay').forEach(m => { m.hidden = true; });
}
});
})();
</script>
{% endblock %}
+8
View File
@@ -0,0 +1,8 @@
{% extends "base.html" %}
{% block title %}{{ custom_page.title }}{% endblock %}
{% block meta_description %}{{ custom_page.meta_description|default:custom_page.title }}{% endblock %}
{% block content %}
{% include "partials/_page_sections.html" with sections=page_sections %}
{% endblock %}
+67
View File
@@ -0,0 +1,67 @@
{% extends "base.html" %}
{% load static %}
{% block title %}FAQ{% endblock %}
{% block meta_description %}Frequently asked questions about Tecvico products and services.{% endblock %}
{% block content %}
<section class="page-hero" aria-labelledby="faq-heading">
<div class="page-hero-blobs" aria-hidden="true">
<div class="blob blob--1"></div>
<div class="blob blob--2"></div>
</div>
<div class="container">
<div class="page-hero-content">
<div class="section-badge">Help</div>
<h1 class="page-hero-title" id="faq-heading">FAQ</h1>
<p class="page-hero-subtitle">Frequently Asked Questions</p>
</div>
</div>
</section>
{% include "partials/_page_videos.html" with videos=faq_videos %}
<section class="section" aria-labelledby="faq-list-heading">
<div class="container">
<h2 class="sr-only" id="faq-list-heading">FAQ List</h2>
{% if faq_entries %}
<div class="faq-list">
{% for entry in faq_entries %}
<div class="faq-item glass-card fade-in">
<button
class="faq-question"
aria-expanded="false"
aria-controls="faq-answer-{{ entry.pk }}"
id="faq-question-{{ entry.pk }}"
>
{{ entry.question }}
<svg class="faq-icon" width="20" height="20" viewBox="0 0 20 20" fill="none" aria-hidden="true">
<path d="M5 8L10 13L15 8" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</button>
<div
class="faq-answer"
id="faq-answer-{{ entry.pk }}"
role="region"
aria-labelledby="faq-question-{{ entry.pk }}"
hidden
>
<div class="rich-content">{{ entry.rendered_answer }}</div>
</div>
</div>
{% endfor %}
</div>
{% else %}
<p class="empty-state">No FAQ entries available yet.</p>
{% endif %}
<div class="faq-contact glass-card fade-in">
<h2>Still Have Questions?</h2>
<p>Can't find the answer you're looking for? Get in touch with our support team.</p>
<a href="{% url 'pages:contact' %}" class="btn-primary">Contact Support</a>
</div>
</div>
</section>
{% endblock %}
+42
View File
@@ -0,0 +1,42 @@
{% extends "base.html" %}
{% load static %}
{% block title %}Home{% endblock %}
{% block meta_description %}Tecvico — Innovation, Advancement, Competition. Advanced solutions for business development.{% endblock %}
{% block content %}
<section class="hero" aria-labelledby="hero-heading">
<div class="hero-blobs" aria-hidden="true">
<img src="{% static 'images/tecvico/hero-decoration.svg' %}" class="blob-img blob-img--hero-left" alt="" />
</div>
<div class="container hero-content">
<div class="hero-text">
{% if hero %}
{% if hero.badge %}<div class="hero-badge">{{ hero.badge }}</div>{% endif %}
{% if hero.title or hero.title_highlight %}
<h1 class="hero-title" id="hero-heading">
{% if hero.title %}{{ hero.title }}{% endif %}
{% if hero.title and hero.title_highlight %}<br />{% endif %}
{% if hero.title_highlight %}<span class="gradient-text">{{ hero.title_highlight }}</span>{% endif %}
</h1>
{% endif %}
{% if hero.subtitle %}<p class="hero-subtitle">{{ hero.subtitle }}</p>{% endif %}
{% if hero.description %}<p class="hero-description">{{ hero.description }}</p>{% endif %}
{% if hero.primary_cta_text or hero.secondary_cta_text %}
<div class="hero-actions">
{% if hero.primary_cta_text %}<a href="{{ hero.primary_cta_url }}" class="btn-primary">{{ hero.primary_cta_text }}</a>{% endif %}
{% if hero.secondary_cta_text %}<a href="{{ hero.secondary_cta_url }}" class="btn-ghost">{{ hero.secondary_cta_text }}</a>{% endif %}
</div>
{% endif %}
{% endif %}
</div>
<div class="hero-visual fade-in">
<img src="{% static 'images/tecvico/hero-image.svg' %}" alt="Tecvico showcase" loading="eager" />
</div>
</div>
</section>
{% include "partials/_page_sections.html" with sections=homepage_sections %}
{% endblock %}
+6
View File
@@ -0,0 +1,6 @@
{% load static %}
<img
src="{% static 'images/tecvico/brand-logo.svg' %}"
alt="Tecvico"
class="brand-icon"
/>
+8
View File
@@ -0,0 +1,8 @@
{% if site_contact.has_discord %}
<a href="{{ site_contact.discord_url }}" class="{{ button_class|default:'btn-ghost btn-sm' }}" target="_blank" rel="noopener noreferrer">
<svg width="18" height="18" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
<path d="M20.317 4.37a19.791 19.791 0 0 0-4.885-1.515.074.074 0 0 0-.079.037c-.21.375-.444.864-.608 1.25a18.27 18.27 0 0 0-5.487 0 12.64 12.64 0 0 0-.617-1.25.077.077 0 0 0-.079-.037A19.736 19.736 0 0 0 3.677 4.37a.07.07 0 0 0-.032.027C.533 9.046-.32 13.58.099 18.057.1 18.08.114 18.1.133 18.11a19.9 19.9 0 0 0 5.993 3.03.078.078 0 0 0 .084-.028c.462-.63.874-1.295 1.226-1.994a.076.076 0 0 0-.041-.106 13.107 13.107 0 0 1-1.872-.892.077.077 0 0 1-.008-.128 10.2 10.2 0 0 0 .372-.292.074.074 0 0 1 .077-.01c3.928 1.793 8.18 1.793 12.062 0a.074.074 0 0 1 .078.01c.12.098.246.198.373.292a.077.077 0 0 1-.006.127 12.299 12.299 0 0 1-1.873.892.077.077 0 0 0-.041.107c.36.698.772 1.362 1.225 1.993a.076.076 0 0 0 .084.028 19.839 19.839 0 0 0 6.002-3.03.077.077 0 0 0 .032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 0 0-.031-.03z"/>
</svg>
{{ site_contact.discord_label_display }}
</a>
{% endif %}
+3
View File
@@ -0,0 +1,3 @@
{% if site_contact.has_support_email %}
<a href="mailto:{{ site_contact.support_email }}" class="{{ link_class|default:'footer-email' }}">{{ site_contact.support_email }}</a>
{% endif %}
+7
View File
@@ -0,0 +1,7 @@
{% if site_contact.has_office_address %}
<address class="{{ address_class|default:'footer-address' }}">
{% for line in site_contact.office_address_lines %}
<p>{{ line }}</p>
{% endfor %}
</address>
{% endif %}
+51
View File
@@ -0,0 +1,51 @@
{% load static %}
<footer class="footer" role="contentinfo">
<div class="footer-main">
<div class="container footer-main-inner">
<div class="footer-brand">
<a href="{% url 'pages:home' %}" class="footer-logo" aria-label="Tecvico home">
<img src="{% static 'images/tecvico/brand-logo.svg' %}" alt="Tecvico" class="brand-icon" />
</a>
<p class="footer-tagline">
Join us in a world of<br />
innovation, advancement,<br />
and success. At Tecvico, our<br />
relentless commitment focuses on meeting evolving customer needs.
</p>
</div>
<div class="footer-social">
<h2 class="footer-social-title">Follow us</h2>
<ul class="footer-social-list" role="list">
<li>
<a href="https://www.facebook.com/tecvico/" target="_blank" rel="noopener noreferrer" aria-label="Facebook">
<img src="{% static 'images/tecvico/social/facebook.png' %}" alt="" />
</a>
</li>
<li>
<a href="https://ca.linkedin.com/company/tecvico" target="_blank" rel="noopener noreferrer" aria-label="LinkedIn">
<img src="{% static 'images/tecvico/social/linkedin.png' %}" alt="" />
</a>
</li>
<li>
<a href="https://twitter.com/tecvico" target="_blank" rel="noopener noreferrer" aria-label="Twitter">
<img src="{% static 'images/tecvico/social/twitter.png' %}" alt="" />
</a>
</li>
<li>
<a href="https://www.instagram.com/tecvico/" target="_blank" rel="noopener noreferrer" aria-label="Instagram">
<img src="{% static 'images/tecvico/social/instagram(1).png' %}" alt="" />
</a>
</li>
<li>
<a href="https://t.me/s/tecvico" target="_blank" rel="noopener noreferrer" aria-label="Telegram">
<img src="{% static 'images/tecvico/social/telegram.png' %}" alt="" />
</a>
</li>
</ul>
</div>
</div>
</div>
<div class="footer-bottom">
<p class="footer-copy">&copy; Copyright {% now "Y" %} TECVICO Group — All Rights Reserved.</p>
</div>
</footer>
@@ -0,0 +1,5 @@
{% if url %}
</a>
{% else %}
</div>
{% endif %}
@@ -0,0 +1,5 @@
{% if url %}
<a href="{{ url }}" class="{{ card_class }} glass-card fade-in section-item-link">
{% else %}
<div class="{{ card_class }} glass-card fade-in">
{% endif %}
+97
View File
@@ -0,0 +1,97 @@
{% load static %}
<nav class="navbar" id="navbar" role="navigation" aria-label="Main navigation">
<div class="navbar-container">
<a href="{% url 'pages:home' %}" class="navbar-brand" aria-label="Tecvico home">
{% include "partials/_brand_icon.html" with placement="navbar" %}
</a>
<button class="navbar-toggle" id="navbarToggle" aria-expanded="false" aria-controls="navbarMenu" aria-label="Toggle navigation">
<span class="toggle-bar"></span>
<span class="toggle-bar"></span>
<span class="toggle-bar"></span>
</button>
<div class="navbar-menu" id="navbarMenu">
<ul class="nav-list" role="list">
<li class="nav-item">
<a href="{% url 'pages:home' %}" class="nav-link {% if request.resolver_match.url_name == 'home' %}active{% endif %}">
Home
</a>
</li>
{% if nav_main_products %}
<li class="nav-item has-megamenu" id="productsNavItem">
<a href="{% url 'products:overview' %}" class="nav-link {% if 'products' in request.resolver_match.namespace %}active{% endif %}" aria-haspopup="true" aria-expanded="false" id="productsTrigger">
Products
<svg class="nav-arrow" width="12" height="12" viewBox="0 0 12 12" fill="none" aria-hidden="true">
<path d="M2 4L6 8L10 4" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</a>
<div class="megamenu" role="menu" aria-labelledby="productsTrigger">
<div class="megamenu-inner">
<div class="megamenu-products-scroll" tabindex="0" aria-label="Product list">
<ul class="megamenu-products" role="list">
{% for product in nav_main_products %}
<li class="megamenu-product-item{% if product.sub_products.all %} has-subproducts{% endif %}">
<a href="{{ product.get_absolute_url }}" class="megamenu-product-link" role="menuitem">
<span class="megamenu-product-name">
{{ product.name }}
{% if product.sub_products.all %}
<svg class="megamenu-sub-chevron" width="12" height="12" viewBox="0 0 12 12" fill="none" aria-hidden="true">
<path d="M2 4L6 8L10 4" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
{% endif %}
</span>
<span class="megamenu-product-desc">{{ product.short_description }}</span>
</a>
{% if product.sub_products.all %}
<ul class="megamenu-sublist" role="list" aria-label="{{ product.name }} modules">
{% for sub in product.sub_products.all %}
<li>
<a href="{{ sub.get_absolute_url }}" class="megamenu-sublink" role="menuitem">{{ sub.name }}</a>
</li>
{% endfor %}
</ul>
{% endif %}
</li>
{% endfor %}
</ul>
</div>
</div>
</div>
</li>
{% endif %}
<li class="nav-item">
<a href="{% url 'pages:about' %}" class="nav-link {% if request.resolver_match.url_name == 'about' %}active{% endif %}">
About
</a>
</li>
{% for page in nav_custom_pages %}
<li class="nav-item">
<a href="{% url 'pages:custom_page' slug=page.slug %}" class="nav-link {% if request.resolver_match.url_name == 'custom_page' and request.resolver_match.kwargs.slug == page.slug %}active{% endif %}">
{{ page.nav_label }}
</a>
</li>
{% endfor %}
<li class="nav-item">
<a href="{% url 'pages:faq' %}" class="nav-link {% if request.resolver_match.url_name == 'faq' %}active{% endif %}">
FAQ
</a>
</li>
<li class="nav-item">
<a href="{% url 'pages:contact' %}" class="nav-link nav-link--cta {% if request.resolver_match.url_name == 'contact' %}active{% endif %}">
Contact
</a>
</li>
</ul>
</div>
</div>
</nav>
+498
View File
@@ -0,0 +1,498 @@
{% load static %}
{% for section in sections %}
{% if section.section_type == "hero" %}
<section class="page-hero" aria-labelledby="page-hero-heading-{{ section.pk }}">
<div class="page-hero-blobs" aria-hidden="true">
<div class="blob blob--1"></div>
<div class="blob blob--2"></div>
<img src="{% static 'images/blob-blue-2.svg' %}" class="blob-img blob-img--page-hero" alt="" />
<img src="{% static 'images/abstract-shapes-2.svg' %}" class="blob-img blob-img--page-corner" alt="" />
</div>
<div class="container">
<div class="page-hero-content">
{% if section.badge %}<div class="section-badge">{{ section.badge }}</div>{% endif %}
{% if section.title %}<h1 class="page-hero-title" id="page-hero-heading-{{ section.pk }}">{{ section.title }}</h1>{% endif %}
{% if section.subtitle %}<p class="page-hero-subtitle">{{ section.subtitle }}</p>{% endif %}
{% if section.content %}<div class="rich-content page-hero-body" data-readmore="160">{{ section.rendered_content }}</div>{% endif %}
</div>
{% with items=section.items.all %}
{% if items %}
<div class="about-screenshots-grid about-hero-gallery">
{% for item in items %}
{% if item.image %}
{% if item.is_featured %}
{% include "partials/_linked_card_open.html" with url=item.url card_class="screenshot-item fade-in screenshot-item--featured" %}
{% else %}
{% include "partials/_linked_card_open.html" with url=item.url card_class="screenshot-item fade-in" %}
{% endif %}
<img src="{{ item.image.url }}" alt="{{ item.image_alt|default:item.title }}" loading="lazy" />
{% include "partials/_linked_card_close.html" with url=item.url %}
{% endif %}
{% endfor %}
</div>
{% endif %}
{% endwith %}
</div>
</section>
{% elif section.section_type == "intro" %}
<section class="section" aria-labelledby="intro-{{ section.pk }}-heading">
<div class="container">
<div class="about-intro glass-card fade-in">
<div class="about-intro-text">
{% if section.title %}<h2 id="intro-{{ section.pk }}-heading">{{ section.title }}</h2>{% endif %}
{% if section.content %}
<div class="rich-content" data-readmore="200">{{ section.rendered_content }}</div>
{% endif %}
</div>
</div>
{% with items=section.items.all %}
{% if items %}
<div class="standards-grid" style="margin-top: 1.5rem;">
{% for item in items %}
{% if item.is_featured and item.image %}
{% else %}
{% include "partials/_standard_item_card.html" with item=item %}
{% endif %}
{% endfor %}
</div>
{% include "partials/_section_featured_screenshots.html" with items=items %}
{% endif %}
{% endwith %}
</div>
</section>
{% elif section.section_type == "grid" %}
<section class="section" aria-labelledby="grid-{{ section.pk }}-heading">
<div class="container">
{% if section.badge or section.title %}
<div class="section-header">
{% if section.badge %}<div class="section-badge">{{ section.badge }}</div>{% endif %}
{% if section.title %}<h2 class="section-title" id="grid-{{ section.pk }}-heading">{{ section.title }}</h2>{% endif %}
</div>
{% endif %}
{% if section.content %}<div class="rich-content" data-readmore="200">{{ section.rendered_content }}</div>{% endif %}
{% with items=section.items.all %}
{% if items %}
<div class="standards-grid">
{% for item in items %}
{% if item.is_featured and item.image %}
{% else %}
{% include "partials/_standard_item_card.html" with item=item %}
{% endif %}
{% endfor %}
</div>
{% include "partials/_section_featured_screenshots.html" with items=items %}
{% endif %}
{% endwith %}
</div>
</section>
{% elif section.section_type == "history" %}
<section class="section" aria-labelledby="history-{{ section.pk }}-heading">
<div class="container">
<div class="history-block glass-card fade-in">
{% with links=section.items.all %}
<div class="history-content">
{% if section.badge %}<div class="section-badge">{{ section.badge }}</div>{% endif %}
{% if section.title %}<h2 id="history-{{ section.pk }}-heading">{{ section.title }}</h2>{% endif %}
{% if section.content %}<div class="rich-content" data-readmore="200">{{ section.rendered_content }}</div>{% endif %}
{% if links %}
<div class="history-links">
{% for link in links %}
{% if link.url %}
<a href="{{ link.url }}" class="btn-ghost" target="_blank" rel="noopener noreferrer">
{% if link.icon %}<span class="history-link-icon" aria-hidden="true">{{ link.icon }}</span>{% endif %}
{{ link.title }}
</a>
{% endif %}
{% endfor %}
</div>
{% endif %}
</div>
<div class="history-visual" aria-hidden="true">
<div class="history-blob history-blob--1"></div>
<div class="history-blob history-blob--2"></div>
{% for link in links %}
{% if link.image %}
<img src="{{ link.image.url }}" alt="{{ link.image_alt|default:link.title }}" class="history-visual-image" loading="lazy" />
{% endif %}
{% endfor %}
{% if section.subtitle %}<div class="history-year">{{ section.subtitle }}</div>{% endif %}
</div>
{% endwith %}
</div>
</div>
</section>
{% elif section.section_type == "custom" %}
<section class="section" aria-labelledby="custom-{{ section.pk }}-heading">
<div class="container">
{% if section.badge or section.title %}
<div class="section-header">
{% if section.badge %}<div class="section-badge">{{ section.badge }}</div>{% endif %}
{% if section.title %}<h2 class="section-title" id="custom-{{ section.pk }}-heading">{{ section.title }}</h2>{% endif %}
</div>
{% endif %}
{% if section.content %}
<div class="glass-card fade-in about-custom-card">
<div class="rich-content" data-readmore="200">{{ section.rendered_content }}</div>
</div>
{% endif %}
{% with items=section.items.all %}
{% if items %}
<div class="standards-grid" style="margin-top: 1.5rem;">
{% for item in items %}
{% if item.is_featured and item.image %}
{% else %}
{% include "partials/_standard_item_card.html" with item=item %}
{% endif %}
{% endfor %}
</div>
{% include "partials/_section_featured_screenshots.html" with items=items %}
{% endif %}
{% endwith %}
</div>
</section>
{% elif section.section_type == "features" %}
<section class="section features-section" aria-labelledby="features-heading-{{ section.pk }}">
<div class="container">
<div class="section-header">
{% if section.badge %}<div class="section-badge">{{ section.badge }}</div>{% endif %}
{% if section.title %}<h2 class="section-title" id="features-heading-{{ section.pk }}">{{ section.title }}</h2>{% endif %}
{% if section.description %}<p class="section-desc">{{ section.description }}</p>{% elif section.content %}<div class="rich-content section-desc">{{ section.rendered_content }}</div>{% endif %}
</div>
<div class="features-grid">
{% for item in section.items.all %}
{% include "partials/_linked_card_open.html" with url=item.url card_class="feature-card" %}
{% if item.icon %}<div class="feature-icon" aria-hidden="true">{{ item.icon }}</div>{% endif %}
<h3 class="feature-title">{{ item.title }}</h3>
<p class="feature-desc" data-readmore="88">{{ item.content }}</p>
{% include "partials/_linked_card_close.html" with url=item.url %}
{% endfor %}
</div>
</div>
</section>
{% elif section.section_type == "screenshots" %}
<section class="section screenshots-section" aria-labelledby="screenshots-heading-{{ section.pk }}">
<div class="container">
<div class="section-header">
{% if section.badge %}<div class="section-badge">{{ section.badge }}</div>{% endif %}
{% if section.title %}<h2 class="section-title" id="screenshots-heading-{{ section.pk }}">{{ section.title }}</h2>{% endif %}
{% if section.description %}<p class="section-desc">{{ section.description }}</p>{% elif section.content %}<div class="rich-content section-desc">{{ section.rendered_content }}</div>{% endif %}
</div>
<div class="screenshots-grid">
{% for item in section.items.all %}
{% if item.image %}
{% include "partials/_linked_card_open.html" with url=item.url card_class="screenshot-item" %}
<img src="{{ item.image.url }}" alt="{{ item.image_alt|default:item.title }}" loading="lazy" />
{% include "partials/_linked_card_close.html" with url=item.url %}
{% endif %}
{% endfor %}
</div>
</div>
</section>
{% elif section.section_type == "projects" %}
<section class="section projects-showcase-section" aria-labelledby="projects-showcase-heading-{{ section.pk }}" data-projects-section>
<div class="container">
<div class="section-header section-header--center">
{% if section.badge %}<div class="section-badge">{{ section.badge }}</div>{% endif %}
{% if section.title or section.title_highlight %}
<h2 class="section-title" id="projects-showcase-heading-{{ section.pk }}">
{% if section.title %}{{ section.title }}{% endif %}
{% if section.title_highlight %}<span class="gradient-text">{{ section.title_highlight }}</span>{% endif %}
</h2>
{% endif %}
{% if section.description %}<p class="section-desc">{{ section.description }}</p>{% endif %}
</div>
<div class="projects-filter" role="tablist" aria-label="Filter projects">
<button type="button" class="projects-filter-btn is-active" data-project-filter="all" role="tab" aria-selected="true">All</button>
<button type="button" class="projects-filter-btn" data-project-filter="new" role="tab" aria-selected="false">New</button>
<button type="button" class="projects-filter-btn" data-project-filter="ongoing" role="tab" aria-selected="false">Ongoing</button>
<button type="button" class="projects-filter-btn" data-project-filter="done" role="tab" aria-selected="false">Done</button>
</div>
<div class="projects-showcase-grid">
{% for item in section.items.all %}
{% if item.url %}
<a href="{{ item.url }}" class="project-card glass-card fade-in" data-project-status="{{ item.project_status|default:'all' }}"{% if item.url|slice:":4" == "http" %} target="_blank" rel="noopener noreferrer"{% endif %}>
{% else %}
<article class="project-card glass-card fade-in" data-project-status="{{ item.project_status|default:'all' }}">
{% endif %}
{% if item.image %}
<div class="project-card-image">
<img src="{{ item.image.url }}" alt="{{ item.image_alt|default:item.title }}" loading="lazy" />
</div>
{% endif %}
<div class="project-card-body">
{% if item.title %}<h3 class="project-card-title">{{ item.title }}</h3>{% endif %}
{% if item.content %}<p class="project-card-desc" data-readmore="120">{{ item.content }}</p>{% endif %}
{% if item.tag_list %}
<ul class="project-card-tags" role="list">
{% for tag in item.tag_list %}
<li>{{ tag }}</li>
{% endfor %}
</ul>
{% endif %}
</div>
{% if item.url %}
</a>
{% else %}
</article>
{% endif %}
{% endfor %}
</div>
</div>
</section>
{% elif section.section_type == "experience" %}
<section class="section experience-section" aria-labelledby="experience-heading-{{ section.pk }}">
<div class="container">
<div class="section-header section-header--center">
{% if section.badge %}<div class="section-badge">{{ section.badge }}</div>{% endif %}
{% if section.title or section.title_highlight %}
<h2 class="section-title" id="experience-heading-{{ section.pk }}">
{% if section.title %}<span class="gradient-text">{{ section.title }}</span>{% endif %}
{% if section.title_highlight %} {{ section.title_highlight }}{% endif %}
</h2>
{% endif %}
{% if section.description %}
<div class="experience-intro">{{ section.description|linebreaksbr }}</div>
{% endif %}
</div>
<div class="experience-grid">
{% for item in section.items.all %}
<article class="experience-card glass-card fade-in">
{% if item.image %}
<div class="experience-card-icon">
<img src="{{ item.image.url }}" alt="" aria-hidden="true" loading="lazy" />
</div>
{% elif item.icon %}
<div class="experience-card-icon experience-card-icon--text" aria-hidden="true">{{ item.icon }}</div>
{% endif %}
{% if item.title %}<h3 class="experience-card-title">{{ item.title }}</h3>{% endif %}
{% if item.content %}<p class="experience-card-desc">{{ item.content }}</p>{% endif %}
</article>
{% endfor %}
</div>
</div>
</section>
{% elif section.section_type == "products" %}
{% if homepage_products %}
<section class="section products-section" aria-labelledby="products-heading-{{ section.pk }}">
<div class="container">
<div class="section-header">
{% if section.badge %}<div class="section-badge">{{ section.badge }}</div>{% endif %}
{% if section.title %}<h2 class="section-title" id="products-heading-{{ section.pk }}">{{ section.title }}</h2>{% endif %}
{% if section.description %}<p class="section-desc">{{ section.description }}</p>{% elif section.content %}<div class="rich-content section-desc">{{ section.rendered_content }}</div>{% endif %}
</div>
<div class="products-grid">
{% for product in homepage_products %}
<a href="{{ product.get_absolute_url }}" class="product-card glass-card fade-in">
{% if product.image %}
<div class="product-card-image">
<img src="{{ product.image.url }}" alt="{{ product.name }}" loading="lazy" />
</div>
{% endif %}
<div class="product-card-body">
<h3 class="product-card-title">{{ product.name }}</h3>
<p class="product-card-desc" data-readmore="88">{{ product.short_description }}</p>
<span class="product-card-link">
Explore
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true">
<path d="M3 8H13M13 8L9 4M13 8L9 12" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</span>
</div>
</a>
{% endfor %}
</div>
</div>
</section>
{% endif %}
{% elif section.section_type == "about_strip" %}
<section class="section about-strip" aria-labelledby="about-strip-heading-{{ section.pk }}">
<div class="container">
<div class="about-strip-inner glass-card">
<div class="about-strip-content">
{% if section.badge %}<div class="section-badge">{{ section.badge }}</div>{% endif %}
{% if section.title %}<h2 class="section-title" id="about-strip-heading-{{ section.pk }}">{{ section.title }}</h2>{% endif %}
{% if section.description %}<p class="about-strip-text">{{ section.description }}</p>{% elif section.content %}<p class="about-strip-text">{{ section.rendered_content }}</p>{% endif %}
{% if section.link_text and section.link_url %}
<a href="{{ section.link_url }}" class="btn-primary">{{ section.link_text }}</a>
{% endif %}
</div>
<div class="about-strip-blobs" aria-hidden="true">
<div class="strip-blob strip-blob--1"></div>
<div class="strip-blob strip-blob--2"></div>
</div>
</div>
</div>
</section>
{% elif section.section_type == "products_catalog" %}
{% if homepage_products_catalog %}
<section class="section products-catalog-section" aria-labelledby="products-catalog-heading-{{ section.pk }}">
<div class="container">
<div class="section-header">
{% if section.badge %}<div class="section-badge">{{ section.badge }}</div>{% endif %}
{% if section.title %}<h2 class="section-title" id="products-catalog-heading-{{ section.pk }}">{{ section.title }}</h2>{% endif %}
{% if section.description %}<p class="section-desc">{{ section.description }}</p>{% elif section.content %}<div class="rich-content section-desc">{{ section.rendered_content }}</div>{% endif %}
</div>
<div class="products-overview-grid">
{% for product in homepage_products_catalog %}
<div class="product-overview-card glass-card fade-in">
{% if product.image %}
<div class="product-overview-image">
<img src="{{ product.image.url }}" alt="{{ product.name }}" loading="lazy" />
</div>
{% endif %}
<div class="product-overview-body">
<h3 class="product-overview-title">{{ product.name }}</h3>
<p class="product-overview-short">{{ product.short_description }}</p>
<p class="product-overview-desc" data-readmore="110">{{ product.description }}</p>
<a href="{{ product.get_absolute_url }}" class="btn-primary">Explore {{ product.name }}</a>
</div>
{% if product.sub_products.all %}
<div class="product-overview-subs">
<h4 class="product-overview-subs-title">Modules</h4>
<ul class="product-overview-subs-list" role="list">
{% for sub in product.sub_products.all %}
<li>
<a href="{{ sub.get_absolute_url }}" class="sub-link-chip">
{{ sub.name }}
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" aria-hidden="true">
<path d="M2.5 6H9.5M9.5 6L7 3.5M9.5 6L7 8.5" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</a>
</li>
{% endfor %}
</ul>
</div>
{% endif %}
</div>
{% endfor %}
</div>
</div>
</section>
{% endif %}
{% elif section.section_type == "problems" %}
<section class="section problems-section" aria-labelledby="problems-heading-{{ section.pk }}">
<div class="container">
<div class="section-header">
{% if section.badge %}<div class="section-badge">{{ section.badge }}</div>{% endif %}
{% if section.title %}<h2 class="section-title" id="problems-heading-{{ section.pk }}">{{ section.title }}</h2>{% endif %}
{% if section.description %}<p class="section-desc">{{ section.description }}</p>{% elif section.content %}<div class="rich-content section-desc">{{ section.rendered_content }}</div>{% endif %}
</div>
<div class="problems-grid">
{% for item in section.items.all %}
{% include "partials/_linked_card_open.html" with url=item.url card_class="problem-item" %}
{% if item.icon %}<div class="problem-number" aria-hidden="true">{{ item.icon }}</div>{% endif %}
<h3 class="problem-title">{{ item.title }}</h3>
<p class="problem-desc" data-readmore="88">{{ item.content }}</p>
{% include "partials/_linked_card_close.html" with url=item.url %}
{% endfor %}
</div>
</div>
</section>
{% elif section.section_type == "supporters" %}
<section class="section supporters-section" aria-labelledby="supporters-heading-{{ section.pk }}">
<div class="container">
<div class="section-header">
{% if section.badge %}<div class="section-badge">{{ section.badge }}</div>{% endif %}
{% if section.title %}<h2 class="section-title" id="supporters-heading-{{ section.pk }}">{{ section.title }}</h2>{% endif %}
{% if section.description %}<p class="section-desc">{{ section.description }}</p>{% elif section.content %}<div class="rich-content section-desc">{{ section.rendered_content }}</div>{% endif %}
</div>
<div class="supporters-grid">
{% for item in section.items.all %}
{% include "partials/_linked_card_open.html" with url=item.url card_class="supporter-card" %}
{% if item.image %}
<div class="supporter-logo">
<img src="{{ item.image.url }}" alt="{{ item.image_alt|default:item.title }} logo" loading="lazy" />
</div>
{% endif %}
<div class="supporter-body">
<h3 class="supporter-name">{{ item.title }}</h3>
{% if item.content %}<p class="supporter-desc">{{ item.content }}</p>{% endif %}
</div>
{% include "partials/_linked_card_close.html" with url=item.url %}
{% endfor %}
</div>
</div>
</section>
{% elif section.section_type == "faq" %}
<section class="section" aria-labelledby="faq-section-{{ section.pk }}-heading">
<div class="container">
{% if section.badge or section.title %}
<div class="section-header">
{% if section.badge %}<div class="section-badge">{{ section.badge }}</div>{% endif %}
{% if section.title %}<h2 class="section-title" id="faq-section-{{ section.pk }}-heading">{{ section.title }}</h2>{% endif %}
</div>
{% endif %}
{% with items=section.items.all %}
{% if items %}
<div class="faq-list">
{% for item in items %}
{% if item.url %}
{% include "partials/_linked_card_open.html" with url=item.url card_class="faq-item faq-item--link" %}
<div class="faq-question">
{{ item.title }}
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true">
<path d="M3 8H13M13 8L9 4M13 8L9 12" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</div>
{% if item.content %}<div class="rich-content faq-link-preview">{{ item.rendered_content }}</div>{% endif %}
{% include "partials/_linked_card_close.html" with url=item.url %}
{% else %}
<div class="faq-item glass-card fade-in">
<button
class="faq-question"
aria-expanded="false"
aria-controls="faq-answer-{{ section.pk }}-{{ item.pk }}"
id="faq-question-{{ section.pk }}-{{ item.pk }}"
>
{{ item.title }}
<svg class="faq-icon" width="20" height="20" viewBox="0 0 20 20" fill="none" aria-hidden="true">
<path d="M5 8L10 13L15 8" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</button>
<div
class="faq-answer"
id="faq-answer-{{ section.pk }}-{{ item.pk }}"
role="region"
aria-labelledby="faq-question-{{ section.pk }}-{{ item.pk }}"
hidden
>
<div class="rich-content">{{ item.rendered_content }}</div>
</div>
</div>
{% endif %}
{% endfor %}
</div>
{% endif %}
{% endwith %}
</div>
</section>
{% elif section.section_type == "video" %}
{% include "partials/_video_section.html" with section=section %}
{% endif %}
{% empty %}
<section class="section">
<div class="container">
<p style="color: var(--text-secondary); text-align: center; padding: 4rem 0;">
No content configured yet. Add sections in the admin panel.
</p>
</div>
</section>
{% endfor %}
+15
View File
@@ -0,0 +1,15 @@
{% if videos %}
<section class="section product-videos-section" aria-label="Product videos">
<div class="container">
<div class="product-videos-list">
{% for video in videos %}
{% if video.has_video %}
<div class="product-video-item">
{% include "partials/_video_block.html" with video=video compact_header=True %}
</div>
{% endif %}
{% endfor %}
</div>
</div>
</section>
{% endif %}
@@ -0,0 +1,9 @@
<div class="about-screenshots-grid about-section-screenshots">
{% for item in items %}
{% if item.is_featured and item.image %}
{% include "partials/_linked_card_open.html" with url=item.url card_class="screenshot-item fade-in screenshot-item--featured" %}
<img src="{{ item.image.url }}" alt="{{ item.image_alt|default:item.title }}" loading="lazy" />
{% include "partials/_linked_card_close.html" with url=item.url %}
{% endif %}
{% endfor %}
</div>
@@ -0,0 +1,20 @@
{% if item.image %}
{% include "partials/_linked_card_open.html" with url=item.url card_class="supporter-card" %}
<div class="supporter-logo">
<img src="{{ item.image.url }}" alt="{{ item.image_alt|default:item.title }} logo" loading="lazy" />
</div>
<div class="supporter-body">
{% if item.icon %}<div class="feature-icon feature-icon--inline" aria-hidden="true">{{ item.icon }}</div>{% endif %}
{% if item.badge %}<div class="standard-badge">{{ item.badge }}</div>{% endif %}
{% if item.title %}<h3 class="supporter-name">{{ item.title }}</h3>{% endif %}
{% if item.content %}<p class="supporter-desc" data-readmore="88">{{ item.content }}</p>{% endif %}
</div>
{% include "partials/_linked_card_close.html" with url=item.url %}
{% else %}
{% include "partials/_linked_card_open.html" with url=item.url card_class="feature-card" %}
{% if item.icon %}<div class="feature-icon" aria-hidden="true">{{ item.icon }}</div>{% endif %}
{% if item.badge %}<div class="standard-badge">{{ item.badge }}</div>{% endif %}
{% if item.title %}<h3 class="feature-title">{{ item.title }}</h3>{% endif %}
{% if item.content %}<p class="feature-desc" data-readmore="88">{{ item.content }}</p>{% endif %}
{% include "partials/_linked_card_close.html" with url=item.url %}
{% endif %}
+55
View File
@@ -0,0 +1,55 @@
{% if video.has_video %}
{% if video.video_styled_background %}
<div class="video-panel video-panel--styled fade-in">
<div class="video-panel-ambient" aria-hidden="true">
<div class="video-panel-blob video-panel-blob--1"></div>
<div class="video-panel-blob video-panel-blob--2"></div>
<div class="video-panel-blob video-panel-blob--3"></div>
</div>
<div class="video-panel-inner">
{% if video.badge or video.title %}
<div class="video-panel-header">
<div class="video-panel-heading">
{% if video.badge %}<div class="section-badge">{{ video.badge }}</div>{% endif %}
{% if video.title %}
<h2 class="video-panel-title" id="video-heading-{{ video.pk }}">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true">
<polygon points="5 3 19 12 5 21 5 3"/>
</svg>
{{ video.title }}
</h2>
{% else %}
<h2 class="sr-only" id="video-heading-{{ video.pk }}">Video</h2>
{% endif %}
</div>
</div>
{% else %}
<h2 class="sr-only" id="video-heading-{{ video.pk }}">Video</h2>
{% endif %}
{% if video.description %}
<div class="rich-content section-desc video-panel-desc">{{ video.rendered_description }}</div>
{% elif video.content %}
<div class="rich-content section-desc video-panel-desc">{{ video.rendered_content }}</div>
{% endif %}
{% include "partials/_video_player.html" with video=video %}
</div>
</div>
{% else %}
{% if video.badge or video.title %}
<div class="section-header{% if compact_header %} product-video-header{% endif %}">
{% if video.badge %}<div class="section-badge">{{ video.badge }}</div>{% endif %}
{% if video.title %}
<h2 class="section-title" id="video-heading-{{ video.pk }}">{{ video.title }}</h2>
{% else %}
<h2 class="sr-only" id="video-heading-{{ video.pk }}">Video</h2>
{% endif %}
</div>
{% endif %}
{% if video.description %}
<div class="rich-content section-desc">{{ video.rendered_description }}</div>
{% elif video.content %}
<div class="rich-content section-desc">{{ video.rendered_content }}</div>
{% endif %}
{% include "partials/_video_player.html" with video=video %}
{% endif %}
{% endif %}
+26
View File
@@ -0,0 +1,26 @@
{% if video.has_video %}
<div class="video-block {{ video.video_size_class }} {{ video.video_aspect_class }} fade-in">
<div class="video-block-inner glass-card">
{% if video.video_source == "upload" and video.video_file %}
<video
controls
playsinline
preload="metadata"
{% if video.video_poster %}poster="{{ video.video_poster.url }}"{% endif %}
title="{{ video.title|default:'Video' }}"
>
<source src="{{ video.video_file.url }}" />
</video>
{% elif video.youtube_embed_url %}
<iframe
src="{{ video.youtube_embed_url }}"
title="{{ video.title|default:'Video' }}"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
allowfullscreen
loading="lazy"
referrerpolicy="strict-origin-when-cross-origin"
></iframe>
{% endif %}
</div>
</div>
{% endif %}
+7
View File
@@ -0,0 +1,7 @@
{% if section.has_video %}
<section class="section video-section" aria-labelledby="video-heading-{{ section.pk }}">
<div class="container">
{% include "partials/_video_block.html" with video=section %}
</div>
</section>
{% endif %}
+69
View File
@@ -0,0 +1,69 @@
{% if articles %}
<section aria-label="Content sections">
<div class="articles-list">
{% for article in articles %}
<article class="article-card glass-card fade-in" aria-labelledby="article-{{ article.pk }}-title">
{% if article.badge %}<div class="article-card-header"><div class="section-badge article-badge">{{ article.badge }}</div></div>{% endif %}
<h3 class="article-title" id="article-{{ article.pk }}-title">{{ article.title }}</h3>
<div class="article-description rich-content" data-readmore="260">{{ article.rendered_description }}</div>
{% if article.sections.all %}
<div class="article-sections">
<dl class="article-sections-list">
{% for section in article.sections.all %}
<div class="article-section-item">
<dt class="section-key">{{ section.title }}</dt>
<dd class="section-value rich-content" data-readmore="160">{{ section.rendered_value }}</dd>
</div>
{% endfor %}
</dl>
</div>
{% endif %}
{% if article.citations.all %}
<div class="article-citations" id="article-{{ article.pk }}-citations">
<h4 class="article-citations-title">Citations</h4>
<ol class="article-citations-list">
{% for citation in article.citations.all %}
<li class="article-citation-item">
<span class="citation-text">{{ citation.text }}</span>
{% if citation.url %}
<span class="citation-actions">
<a href="{{ citation.url }}" class="citation-link" target="_blank" rel="noopener noreferrer" aria-label="Open citation source">
<svg width="13" height="13" viewBox="0 0 16 16" fill="none" aria-hidden="true">
<path d="M7 3H3a1 1 0 00-1 1v9a1 1 0 001 1h9a1 1 0 001-1V9M10 2h4m0 0v4m0-4L7 9" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</a>
<button type="button" class="citation-copy" data-citation-url="{{ citation.url }}" aria-label="Copy citation link">
<svg class="citation-copy-icon" width="15" height="15" viewBox="0 0 16 16" fill="none" aria-hidden="true">
<rect x="5" y="5" width="8" height="8" rx="1" stroke="currentColor" stroke-width="1.5"/>
<path d="M3 11V3a1 1 0 011-1h8" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
</svg>
<svg class="citation-copy-icon-done" width="13" height="13" viewBox="0 0 16 16" fill="none" aria-hidden="true">
<path d="M3.5 8.5L6.5 11.5L12.5 4.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
<span class="citation-copy-feedback" aria-live="polite" hidden>Copied!</span>
</button>
</span>
{% endif %}
</li>
{% endfor %}
</ol>
</div>
{% endif %}
{% if article.citation_count_display is not None or article.citation_count_label %}
{% if article.citations.exists %}
<a href="#article-{{ article.pk }}-citations" class="citation-count-badge" aria-label="{% if article.citation_count_display %}{{ article.citation_count_display }} {% endif %}{% if article.citation_count_label %}{{ article.citation_count_label }}{% endif %}">
{% if article.citation_count_display is not None %}<span class="citation-count-number">{{ article.citation_count_display }}</span>{% endif %}
{% if article.citation_count_label %}<span class="citation-count-label">{{ article.citation_count_label }}</span>{% endif %}
</a>
{% else %}
<div class="citation-count-badge" aria-label="{% if article.citation_count_display %}{{ article.citation_count_display }} {% endif %}{% if article.citation_count_label %}{{ article.citation_count_label }}{% endif %}">
{% if article.citation_count_display is not None %}<span class="citation-count-number">{{ article.citation_count_display }}</span>{% endif %}
{% if article.citation_count_label %}<span class="citation-count-label">{{ article.citation_count_label }}</span>{% endif %}
</div>
{% endif %}
{% endif %}
</article>
{% endfor %}
</div>
</section>
{% endif %}
@@ -0,0 +1,34 @@
{% load static %}
<div class="sub-downloads-channel{% if channel.is_previous %} sub-downloads-channel--prev{% endif %}">
{% include "products/_release_channel_badge.html" with version=channel.version %}
{% if channel.install_cells %}
<div class="sub-downloads-grid">
{% for cell in channel.install_cells %}
<div class="sub-dl-item">
<div class="sub-dl-icon-wrap">
{% if cell.icon %}
<img src="{% static cell.icon %}" alt="" width="32" height="32" class="platform-icon sub-dl-icon" aria-hidden="true" />
{% else %}
<span class="sub-dl-source-mark" aria-hidden="true">
<svg class="sub-dl-source-svg" width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.85" stroke-linecap="round">
<polyline points="16 18 22 12 16 6"/><polyline points="8 6 2 12 8 18"/>
</svg>
</span>
{% endif %}
</div>
<span class="sub-dl-platform">{{ cell.label }}</span>
<span class="download-version">{{ channel.version.version }}</span>
<a href="{{ cell.url }}" class="btn-primary btn--sm"{% if cell.external %} target="_blank" rel="noopener noreferrer"{% endif %}>{% if cell.label == "Source code" %}Source{% else %}Download{% endif %}</a>
</div>
{% endfor %}
</div>
{% endif %}
{% if channel.version.package_resource_url %}
<p class="sub-install-extra-resource">
<a href="{{ channel.version.package_resource_url }}" target="_blank" rel="noopener noreferrer">Package resource</a>
</p>
{% endif %}
{% if channel.version.release_notes %}
<p class="sub-release-notes">{{ channel.version.release_notes }}</p>
{% endif %}
</div>
@@ -0,0 +1,10 @@
{% if version.display_channel_label %}
<span class="release-channel-label release-channel-label--{{ version.display_channel_css_modifier }}">
{% if version.release_channel == "stable" %}
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true">
<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/>
</svg>
{% endif %}
{{ version.display_channel_label }}
</span>
{% endif %}
+69
View File
@@ -0,0 +1,69 @@
{% load static %}
{% if show_releases_section %}
{% if distribution_installable %}
<section class="sub-downloads fade-in" aria-labelledby="sub-dl-heading">
<div class="sub-downloads-header">
<h2 class="sub-downloads-title" id="sub-dl-heading">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true">
<path d="M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/>
</svg>
Downloads
</h2>
{% if downloads_section_link %}
<a href="{{ downloads_section_link.url }}" class="sub-downloads-corner-link link-arrow" target="_blank" rel="noopener noreferrer">{{ downloads_section_link.text }}</a>
{% endif %}
</div>
{% if featured_version %}
{% include "products/_installable_download_channel.html" with channel=featured_channel %}
{% endif %}
{% for channel in inline_download_channels %}
{% include "products/_installable_download_channel.html" %}
{% endfor %}
{% if show_older_versions_link %}
<p class="sub-older-versions-inner">
<a href="{{ versions_archive_url }}" class="link-arrow">Older releases</a>
</p>
{% endif %}
</section>
{% elif distribution_package %}
<section class="sub-downloads sub-downloads--package fade-in" aria-labelledby="sub-resources-heading">
<div class="sub-downloads-header">
<h2 class="sub-downloads-title" id="sub-resources-heading">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true">
<path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/>
<path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/>
</svg>
Resources
</h2>
{% if downloads_section_link %}
<a href="{{ downloads_section_link.url }}" class="sub-downloads-corner-link link-arrow" target="_blank" rel="noopener noreferrer">{{ downloads_section_link.text }}</a>
{% endif %}
</div>
<ul class="pkg-version-list" role="list">
{% for ver in package_versions %}
<li class="pkg-version-row">
<div class="pkg-version-meta">
<span class="download-version">{{ ver.version }}</span>
{% include "products/_release_channel_badge.html" with version=ver %}
</div>
<div class="pkg-version-actions">
{% if ver.package_resource_url %}
<a href="{{ ver.package_resource_url }}" class="btn-primary btn--sm" target="_blank" rel="noopener noreferrer">{{ package_resource_button_text }}</a>
{% endif %}
{% if ver.resolved_source_code_url %}
<a href="{{ ver.resolved_source_code_url }}" class="btn-ghost btn--sm"{% if ver.source_code_url %} target="_blank" rel="noopener noreferrer"{% endif %}>{{ package_source_button_text }}</a>
{% endif %}
</div>
{% if ver.release_notes %}
<p class="pkg-version-notes">{{ ver.release_notes }}</p>
{% endif %}
</li>
{% endfor %}
</ul>
</section>
{% endif %}
{% endif %}
@@ -0,0 +1,70 @@
{% load static %}
{% if not archive_versions %}
<p class="versions-empty glass-card">There are no archived releases{% if sub_product %} for this module{% else %} for this product{% endif %}.</p>
{% elif distribution_installable %}
<div class="versions-table-wrap glass-card fade-in">
<table class="versions-table">
<thead>
<tr>
<th scope="col">Version</th>
{% for fname, label, icon in archive_specs %}
<th scope="col">{{ label }}</th>
{% endfor %}
</tr>
</thead>
<tbody>
{% for row in archive_rows_installable %}
<tr>
<th scope="row">
<span class="versions-table-version">{{ row.version_obj.version }}</span>
{% include "products/_release_channel_badge.html" with version=row.version_obj %}
</th>
{% for cell in row.cells %}
<td>
{% if cell.url %}
{% if cell.icon %}
<a href="{{ cell.url }}" class="versions-table-link"{% if cell.external %} target="_blank" rel="noopener noreferrer"{% endif %}>
<img src="{% static cell.icon %}" alt="" width="22" height="22" class="versions-table-icon" aria-hidden="true" />
<span class="sr-only">{{ cell.label }}</span>
</a>
{% else %}
<a href="{{ cell.url }}" class="versions-table-text-link"{% if cell.external %} target="_blank" rel="noopener noreferrer"{% endif %}>Source</a>
{% endif %}
{% else %}
<span class="versions-na"></span>
{% endif %}
</td>
{% endfor %}
</tr>
{% if row.version_obj.release_notes %}
<tr class="versions-notes-row">
<td colspan="{{ archive_specs|length|add:1 }}">
<span class="versions-notes-label">Notes</span>
<p class="versions-notes-body">{{ row.version_obj.release_notes }}</p>
</td>
</tr>
{% endif %}
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<ul class="versions-package-list" role="list">
{% for ver in archive_versions %}
<li class="versions-package-card glass-card fade-in">
<div class="versions-package-head">
<div class="pkg-version-meta">
<span class="download-version">{{ ver.version }}</span>
{% include "products/_release_channel_badge.html" with version=ver %}
</div>
{% if ver.package_resource_url %}
<a href="{{ ver.package_resource_url }}" class="btn-ghost btn--sm" target="_blank" rel="noopener noreferrer">{{ package_resource_button_text }}</a>
{% endif %}
</div>
{% if ver.release_notes %}
<p class="versions-notes-body">{{ ver.release_notes }}</p>
{% endif %}
</li>
{% endfor %}
</ul>
{% endif %}
+105
View File
@@ -0,0 +1,105 @@
{% extends "base.html" %}
{% load static %}
{% block title %}{{ main_product.name }}{% endblock %}
{% block meta_description %}{{ main_product.short_description }}{% endblock %}
{% block content %}
<section class="page-hero" aria-labelledby="main-product-heading">
<div class="page-hero-blobs" aria-hidden="true">
<div class="blob blob--1"></div>
<div class="blob blob--2"></div>
<div class="blob blob--3"></div>
</div>
<div class="container">
<nav class="breadcrumb" aria-label="Breadcrumb">
<ol class="breadcrumb-list" role="list">
<li><a href="{% url 'pages:home' %}">Home</a></li>
<li aria-hidden="true" class="breadcrumb-sep"></li>
<li><a href="{% url 'products:overview' %}">Products</a></li>
<li aria-hidden="true" class="breadcrumb-sep"></li>
<li aria-current="page">{{ main_product.name }}</li>
</ol>
</nav>
<div class="page-hero-content">
<div class="section-badge">Product</div>
<h1 class="page-hero-title" id="main-product-heading">{{ main_product.name }}</h1>
<p class="page-hero-subtitle">{{ main_product.short_description }}</p>
</div>
</div>
</section>
<section class="section main-product-layout" aria-labelledby="product-desc-heading">
<div class="container">
<div class="main-product-main">
<div class="product-detail-intro glass-card fade-in">
<div class="product-detail-image">
{% if main_product.image %}
<img src="{{ main_product.image.url }}" alt="{{ main_product.name }}" loading="lazy" />
{% else %}
<img src="{% static 'images/logo.png' %}" alt="{{ main_product.name }} logo" loading="lazy" class="product-logo-img" />
{% endif %}
</div>
<div class="product-detail-text">
<h2 id="product-desc-heading">About {{ main_product.name }}</h2>
<div class="product-detail-desc rich-content" data-readmore="220">{{ main_product.rendered_description }}</div>
</div>
</div>
{% include "products/_releases_section.html" %}
</div>
</div>
</section>
{% include "partials/_page_videos.html" with videos=product_videos %}
{% if articles %}
<section class="section" aria-label="Product articles">
<div class="container">
{% include "products/_article_list.html" %}
</div>
</section>
{% endif %}
{% with subs=main_product.sub_products.all %}
{% if subs %}
<section class="section" aria-labelledby="subproducts-heading">
<div class="container">
<div class="section-header">
<div class="section-badge">Modules</div>
<h2 class="section-title" id="subproducts-heading">{{ main_product.name }} Modules</h2>
<p class="section-desc">
Explore the different modules and capabilities within {{ main_product.name }}.
</p>
</div>
<div class="subproducts-grid">
{% for sub in subs %}
{% if sub.is_active %}
<a href="{{ sub.get_absolute_url }}" class="subproduct-card glass-card fade-in">
{% if sub.image %}
<div class="subproduct-card-image">
<img src="{{ sub.image.url }}" alt="{{ sub.name }}" loading="lazy" />
</div>
{% endif %}
<div class="subproduct-card-body">
<h3 class="subproduct-card-title">{{ sub.name }}</h3>
<p class="subproduct-card-desc" data-readmore="88">{{ sub.short_description }}</p>
<span class="subproduct-card-link">
Learn More
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" aria-hidden="true">
<path d="M3 7H11M11 7L8 4M11 7L8 10" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</span>
</div>
</a>
{% endif %}
{% endfor %}
</div>
</div>
</section>
{% endif %}
{% endwith %}
{% endblock %}
+73
View File
@@ -0,0 +1,73 @@
{% extends "base.html" %}
{% load static %}
{% block title %}Products{% endblock %}
{% block meta_description %}Explore Tecvico's suite of products and solutions.{% endblock %}
{% block content %}
<section class="page-hero" aria-labelledby="products-overview-heading">
<div class="page-hero-blobs" aria-hidden="true">
<div class="blob blob--1"></div>
<div class="blob blob--2"></div>
</div>
<div class="container">
<div class="page-hero-content">
<div class="section-badge">Software Suite</div>
<h1 class="page-hero-title" id="products-overview-heading">Our Products</h1>
<p class="page-hero-subtitle">Advanced tools for medical imaging research and radiomics analysis.</p>
</div>
</div>
</section>
<section class="section" aria-labelledby="products-list-heading">
<div class="container">
<h2 class="sr-only" id="products-list-heading">Product List</h2>
{% if main_products %}
<div class="products-overview-grid">
{% for product in main_products %}
<div class="product-overview-card glass-card fade-in">
{% if product.image %}
<div class="product-overview-image">
<img src="{{ product.image.url }}" alt="{{ product.name }}" loading="lazy" />
</div>
{% endif %}
<div class="product-overview-body">
<h2 class="product-overview-title">{{ product.name }}</h2>
<p class="product-overview-short">{{ product.short_description }}</p>
<p class="product-overview-desc" data-readmore="110">{{ product.description }}</p>
<a href="{{ product.get_absolute_url }}" class="btn-primary">Explore {{ product.name }}</a>
</div>
{% with subs=product.sub_products.all %}
{% if subs %}
<div class="product-overview-subs">
<h3 class="product-overview-subs-title">Modules</h3>
<ul class="product-overview-subs-list" role="list">
{% for sub in subs %}
{% if sub.is_active %}
<li>
<a href="{{ sub.get_absolute_url }}" class="sub-link-chip">
{{ sub.name }}
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" aria-hidden="true">
<path d="M2.5 6H9.5M9.5 6L7 3.5M9.5 6L7 8.5" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</a>
</li>
{% endif %}
{% endfor %}
</ul>
</div>
{% endif %}
{% endwith %}
</div>
{% endfor %}
</div>
{% else %}
<div class="empty-state-block glass-card">
<p>No products available at this time. Check back soon.</p>
</div>
{% endif %}
</div>
</section>
{% endblock %}
+91
View File
@@ -0,0 +1,91 @@
{% extends "base.html" %}
{% load static %}
{% block title %}{{ sub_product.name }} — {{ main_product.name }}{% endblock %}
{% block meta_description %}{{ sub_product.short_description }}{% endblock %}
{% block content %}
<section class="page-hero" aria-labelledby="sub-product-heading">
<div class="page-hero-blobs" aria-hidden="true">
<div class="blob blob--1"></div>
<div class="blob blob--2"></div>
</div>
<div class="container">
<nav class="breadcrumb" aria-label="Breadcrumb">
<ol class="breadcrumb-list" role="list">
<li><a href="{% url 'pages:home' %}">Home</a></li>
<li aria-hidden="true" class="breadcrumb-sep"></li>
<li><a href="{% url 'products:overview' %}">Products</a></li>
<li aria-hidden="true" class="breadcrumb-sep"></li>
<li><a href="{{ main_product.get_absolute_url }}">{{ main_product.name }}</a></li>
<li aria-hidden="true" class="breadcrumb-sep"></li>
<li aria-current="page">{{ sub_product.name }}</li>
</ol>
</nav>
<div class="page-hero-content">
<div class="section-badge">{{ main_product.name }}</div>
<h1 class="page-hero-title" id="sub-product-heading">{{ sub_product.name }}</h1>
<p class="page-hero-subtitle">{{ sub_product.short_description }}</p>
</div>
</div>
</section>
<div class="section sub-product-layout">
<div class="container">
<div class="sub-product-grid">
<main class="sub-product-main">
{% if sub_product.image %}
<div class="sub-product-image glass-card fade-in">
<img src="{{ sub_product.image.url }}" alt="{{ sub_product.name }}" loading="lazy" />
</div>
{% endif %}
<div class="sub-product-desc glass-card fade-in">
<h2>About {{ sub_product.name }}</h2>
<div class="rich-content" data-readmore="220">{{ sub_product.rendered_description }}</div>
</div>
{% include "products/_releases_section.html" %}
{% include "partials/_page_videos.html" with videos=product_videos %}
{% include "products/_article_list.html" %}
</main>
<aside class="sub-product-sidebar" aria-label="Related modules">
<div class="sidebar-sticky">
<div class="sidebar-section glass-card">
<h3 class="sidebar-title">
<a href="{{ main_product.get_absolute_url }}">{{ main_product.name }}</a> Modules
</h3>
{% if siblings %}
<ul class="sidebar-list" role="list">
{% for sibling in siblings %}
<li>
<a href="{{ sibling.get_absolute_url }}" class="sidebar-link">
<span class="sidebar-dot" aria-hidden="true"></span>
{{ sibling.name }}
</a>
</li>
{% endfor %}
</ul>
{% else %}
<p class="sidebar-empty">No other modules in this product.</p>
{% endif %}
</div>
<a href="{{ main_product.get_absolute_url }}" class="btn-ghost sidebar-back-btn">
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true">
<path d="M10 3L5 8L10 13" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
Back to {{ main_product.name }}
</a>
</div>
</aside>
</div>
</div>
</div>
{% endblock %}
+43
View File
@@ -0,0 +1,43 @@
{% extends "base.html" %}
{% block title %}Older releases — {% if sub_product %}{{ sub_product.name }} — {% endif %}{{ main_product.name }}{% endblock %}
{% block meta_description %}Archived releases{% if sub_product %} for {{ sub_product.name }}{% else %} for {{ main_product.name }}{% endif %}.{% endblock %}
{% block content %}
<section class="page-hero" aria-labelledby="versions-heading">
<div class="page-hero-blobs" aria-hidden="true">
<div class="blob blob--1"></div>
<div class="blob blob--2"></div>
</div>
<div class="container">
<nav class="breadcrumb" aria-label="Breadcrumb">
<ol class="breadcrumb-list" role="list">
<li><a href="{% url 'pages:home' %}">Home</a></li>
<li aria-hidden="true" class="breadcrumb-sep"></li>
<li><a href="{% url 'products:overview' %}">Products</a></li>
<li aria-hidden="true" class="breadcrumb-sep"></li>
<li><a href="{{ main_product.get_absolute_url }}">{{ main_product.name }}</a></li>
{% if sub_product %}
<li aria-hidden="true" class="breadcrumb-sep"></li>
<li><a href="{{ sub_product.get_absolute_url }}">{{ sub_product.name }}</a></li>
{% endif %}
<li aria-hidden="true" class="breadcrumb-sep"></li>
<li aria-current="page">Older releases</li>
</ol>
</nav>
<div class="page-hero-content">
<div class="section-badge">{% if sub_product %}{{ sub_product.name }}{% else %}{{ main_product.name }}{% endif %}</div>
<h1 class="page-hero-title" id="versions-heading">Older releases</h1>
<p class="page-hero-subtitle">Archived versions of this {% if sub_product %}module{% else %}product{% endif %}.</p>
</div>
</div>
</section>
<section class="section versions-archive-section">
<div class="container">
{% include "products/_versions_archive_body.html" %}
</div>
</section>
{% endblock %}