feat(en-pages): build remaining 14 pages (Editorial / Forms / Hubs / Legal)

Brings the EN site to 34 live pages, completing the original sitemap
from PDF Strategie & Contenu Partie C.1.

Editorial section (5 pages, page-editorial-detail.php template)
- /why-asterion/, /about/, /customers/, /trust/, /partners/
- inc/editorial-data.php centralizes the copy from D.18-D.21, D.28
- Reuses the industry-detail partial (same section schema)

Conversion section (4 pages, page-conversion-form.php template)
- /request-demo/, /request-te-kit/, /request-quote/, /contact/
- inc/forms-data.php declares fields per page (text/email/select/textarea)
- template-parts/conversion-form.php renders two-column layout
  (form left, promise right), eligibility list (T&E), FAQ (Demo)
- inc/form-handler.php: nonce-protected POST handler with honeypot,
  per-field sanitizer, wp_mail to AV_LEADS_RECIPIENT (defaults to
  jerome.foucher@asterionvr.com, override via wp-config.php define),
  redirect-back-with-status pattern.

Insights & Resources (page-insights-hub.php, page-resources.php)
- /insights/ queries `post`, falls back to placeholder when empty
- /resources/ lists 4 resource groups (datasheets, whitepapers,
  videos, brochures) per D.23

Legal (page-legal.php template, parent + 4 children)
- /legal/, /legal/privacy/, /legal/terms/, /legal/cookies/, /legal/notice/
- Renders page content if filled, falls back to slug-driven section
  skeleton (per D.29) for counsel to draft against.

All 16 new URLs verified HTTP 200, sizes 49-66 KB each. Mu-plugin
asterion-seed-rest.php in LocalWP self-deleted after seeding.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-09 12:41:36 +02:00
parent 45b0b95232
commit 70864129ed
10 changed files with 1066 additions and 2 deletions

View File

@@ -101,6 +101,7 @@ add_action('wp_head', function () {
$av_includes = [ $av_includes = [
'inc/cpt.php', // Custom post types: case_study, scenario. 'inc/cpt.php', // Custom post types: case_study, scenario.
'inc/seo.php', // Schema.org JSON-LD overrides. 'inc/seo.php', // Schema.org JSON-LD overrides.
'inc/form-handler.php', // Conversion form POST handler.
]; ];
foreach ($av_includes as $av_include) { foreach ($av_includes as $av_include) {

View File

@@ -0,0 +1,246 @@
<?php
/**
* Asterion Bricks — Editorial pages data
*
* Data for editorial pages (Why Asterion, About, Customers hub, Trust, Partners).
* Copy from PDF Strategie & Contenu D.18-D.21, D.28.
*
* Same schema as industries-data.php (eyebrow / title / tagline / hero_lead /
* ctas / sections), consumed by template-parts/industry-detail.php.
*
* @package AsterionBricks
*/
defined('ABSPATH') || exit;
return [
/* Why Asterion — D.18 ============================================= */
'why-asterion' => [
'eyebrow' => 'Why Asterion',
'title' => 'Why Asterion',
'tagline' => 'A platform built around the operator. Not the other way around.',
'meta_title' => 'Why Asterion VR — French-Engineered, Sovereign, Modular',
'meta_description' => '10 years of XR R&D for security forces. Made in France. Modular from solo to academy. Fully offline. GDPR-native.',
'hero_lead' => 'Asterion VR was founded in 2016 to solve one specific problem: security forces need more repetition than the ranges, ammunition budgets, and exercise calendars allow. Ten years later, the platform we built does exactly that — at every scale, in every environment, for every role.',
'ctas' => [
['label' => 'Read our customer stories', 'href' => '/customers/', 'variant' => 'primary'],
['label' => 'Meet the team', 'href' => '/about/', 'variant' => 'secondary'],
],
'sections' => [
[
'type' => 'cards',
'eyebrow' => 'What makes us different',
'title' => 'Six commitments engineered into the platform.',
'items' => [
['title' => 'French-engineered, EU-sovereign', 'body' => 'Designed and produced in France. Software developed in our French studio. Operates fully offline. No data leaves your network. No foreign cloud dependency. No ITAR exposure. GDPR-native by default.'],
['title' => 'Modular from day one', 'body' => 'MY PROSERVE, FLEX, ACADEMY — same software, same scenarios, same instructor tools, three deployment formats. Start solo. Add operators. Scale to a full academy. Your investment never resets.'],
['title' => 'Real-recoil weapon integration', 'body' => 'Train with the weapon you carry. Our Universal Weapon Digitizer attaches to gas-blowback replicas, CO2 replicas, or real service weapons firing blanks. Recoil is real. Tracking survives recoil. Muscle memory transfers.'],
['title' => 'Behavior, not scripts', 'body' => 'AI civilians and adversaries with vision, hearing, and configurable personality. Same starting conditions, different outcomes. Trainees train against decisions, not pattern recognition.'],
['title' => 'Instructor-first, not trainee-first', 'body' => 'Most VR products are built for the headset wearer. We built ours for the instructor — because the instructor is the one who turns immersion into learning.'],
['title' => 'AAR redefined', 'body' => 'Frame-level replay. Per-trainee statistics. Unit-level dashboards. Comparable across time. Exportable to your reporting systems. Every drill ends measurable.'],
],
],
[
'type' => 'prose',
'eyebrow' => 'Where we come from',
'title' => 'The thread of Ariadne.',
'body' => "Asterion is the original Greek name of the Minotaur — the creature that lived at the heart of Daedalus's labyrinth. He was confronted by Theseus, who survived by training, intelligence, and the thread of Ariadne. The name we carry is a reminder: in the labyrinth of contemporary security operations, training is the thread that brings operators home.",
],
[
'type' => 'list',
'eyebrow' => 'The numbers',
'title' => 'Asterion VR in figures.',
'items' => [
'Founded in 2016 — 10 years of XR R&D dedicated exclusively to security forces',
'11 validated training environments · 50+ scenarios · 4 software updates per year',
'Operators from police, gendarmerie, special forces, and military across Europe',
'Designed, engineered, and supported from France',
],
],
],
],
/* About — D.19 ==================================================== */
'about' => [
'eyebrow' => 'About',
'title' => 'About',
'tagline' => 'Built in France, for forces that train where it counts.',
'meta_title' => 'About Asterion VR — Our Story, Our Team, Our Mission',
'meta_description' => 'From a 2016 conviction to a deployed XR training platform. Meet the team behind PROSERVE.',
'hero_lead' => 'Asterion VR was founded in 2016 by Jérôme Foucher and a small team convinced of one thing: that the gap between regulation and reality in security forces training would not close on its own.',
'ctas' => [
['label' => 'Read our customer stories', 'href' => '/customers/', 'variant' => 'primary'],
],
'sections' => [
[
'type' => 'prose',
'eyebrow' => 'The conviction',
'title' => 'In 2016, we looked at the numbers.',
'body' => 'French police regulation required 90 cartridges per officer per year. The actual median was between 10 and 15. Tactical errors under stress increased by 40% compared to baseline conditions. 42% of intervention errors were linked to insufficient realistic preparation. The infrastructure to fix this — saturated ranges, expensive live exercises, finite instructor time — was not going to expand. Something had to change in the methodology. VR was the obvious answer. But the VR available in 2016 was built for entertainment. The recoil was fake. The civilians were on rails. The instructor saw what the trainee saw. The data was nowhere. We started over.',
],
[
'type' => 'prose',
'eyebrow' => 'Ten years of one focus',
'title' => 'Security forces. Nothing else.',
'body' => 'Asterion has never built a single product for entertainment, education, or industry. Our entire roadmap, from day one, has been the training of security forces. Every iteration of our weapon tracker, every line of code in our AI engine, every environment in our scenario library was specified by serving or former operators.',
],
[
'type' => 'prose',
'eyebrow' => 'The team',
'title' => 'Engineers, operators, designers.',
'body' => '[Section to populate with team photos and bios — Founder, Head of Engineering, Head of Product, Head of Operations, Head of Studio. Each entry: photo, name, role, 2-line bio. Recommendation: include a serving-or-former-operator advisor in the team page to reinforce the "built with operators" narrative.]',
],
[
'type' => 'prose',
'eyebrow' => 'Asterion in your network',
'title' => 'Members and partners.',
'body' => 'We are members of the French defense innovation cluster, the French Tech ecosystem, and active partners with HTC VIVE Business and Unreal Engine programmes for defense and public sector applications. We work with a network of distributors and integrators across Europe, the Middle East, and Asia.',
],
],
],
/* Customers hub — D.20 ============================================ */
'customers' => [
'eyebrow' => 'Customers & Case Studies',
'title' => 'Customers',
'tagline' => 'Real deployments. Measured results.',
'meta_title' => 'Customer Stories — How Security Forces Train with PROSERVE',
'meta_description' => 'Real deployments. Measured results. From regional police to special forces, see how PROSERVE changes training.',
'hero_lead' => 'PROSERVE is in active service with police, gendarmerie, and tactical units across Europe. Some are public references. Some operate under nondisclosure agreements. The case studies below show — under their own names, with their own metrics, in their own words — how they train with us.',
'ctas' => [
['label' => 'Become the next case study', 'href' => '/contact/', 'variant' => 'primary'],
],
'sections' => [
[
'type' => 'cards',
'eyebrow' => 'Featured case studies',
'title' => 'Sample deployments — to be detailed in /customers/[slug]/.',
'items' => [
['title' => 'National police academy, France', 'body' => 'Continuous marksmanship training across 12 stations. 1500 officers trained in the first 18 months. Per-officer median annual cartridge count rose from 14 to 117 (live + simulated). Tactical-error rate on benchmark drill dropped 35%.'],
['title' => 'Regional gendarmerie tactical unit', 'body' => 'PROSERVE FLEX deployed for forward training during multi-week field rotations. Hostage-rescue drill repetition multiplied by 8 over 6 months. Reaction time under contact improved 22% on benchmark drill.'],
['title' => 'Municipal police, large city', 'body' => 'MY PROSERVE rolled out to 24 stations. Self-reported training confidence improved 41%. Continuous-training compliance rose from 38% to 92% within 12 months.'],
['title' => 'Firefighter regional training centre', 'body' => 'PROSERVE ACADEMY-FLEX hybrid for hazmat and confined-space rescue. Annual exercise volume tripled. Recruit retention improved due to better preparation for live exercise.'],
],
],
[
'type' => 'prose',
'eyebrow' => 'Reference partners',
'title' => 'If your unit is interested in becoming a public reference.',
'body' => 'We work with reference partners on a long-term basis. In exchange for the right to publish your story (with the level of detail you authorize), we offer extended support, priority on custom scenarios, and active involvement in our product roadmap. Reach out to discuss.',
],
],
],
/* Trust & Compliance — D.21 ======================================= */
'trust' => [
'eyebrow' => 'Trust & Compliance',
'title' => 'Trust & Compliance',
'tagline' => 'Trust by engineering, not by claim.',
'meta_title' => 'Trust & Compliance — GDPR, Sovereignty, Security | Asterion VR',
'meta_description' => 'Made in France. GDPR-native. Operates fully offline. No cloud, no foreign jurisdiction. Your training data never leaves your network.',
'hero_lead' => 'Asterion VR is engineered for the trust requirements of public security forces. Sovereignty, data protection, and operational autonomy are designed into the platform — not bolted on for compliance.',
'ctas' => [
['label' => 'Request a Trust Pack', 'href' => '/contact/', 'variant' => 'primary'],
],
'sections' => [
[
'type' => 'list',
'eyebrow' => 'Sovereignty',
'title' => 'Designed European, supported European.',
'items' => [
'Designed and produced in France',
'Software written, compiled, and supported in France',
'Hardware sourcing favors European and trusted-allied suppliers',
'No US Cloud Act exposure (no US-controlled cloud services)',
'No ITAR exposure on the standard PROSERVE configuration',
'Custom development under sovereign-clearable conditions on request',
],
],
[
'type' => 'list',
'eyebrow' => 'Data protection',
'title' => 'Your data never leaves your network.',
'items' => [
"All training data, AAR videos, and operator profiles stored locally on the customer's network",
"No telemetry leaves the customer's network",
'GDPR-compliant by design — operator data minimization, purpose limitation, retention controls',
'Data export and deletion controls in operator dashboard',
'Compatible with customer-controlled identity providers (Active Directory, LDAP, SAML on request)',
],
],
[
'type' => 'list',
'eyebrow' => 'Operational autonomy',
'title' => 'Train without an internet connection.',
'items' => [
'Fully offline operation — no internet connection required during training',
'Software updates delivered via offline installers when required',
'Field-replaceable hardware — common spare parts can be sourced and shipped within standard SLAs',
'Remote technical support available, on customer-controlled connectivity',
],
],
[
'type' => 'list',
'eyebrow' => 'Cyber posture',
'title' => 'Hardened for institutional environments.',
'items' => [
'WPA3 wireless security on the included Wi-Fi 6E router',
'Local-only authentication by default',
"Hardening guidelines and IT integration documentation provided to customer's IT teams",
'Regular security review with customer-side IT on request',
],
],
[
'type' => 'list',
'eyebrow' => 'Warranty & support',
'title' => 'Perpetual licenses. Predictable support.',
'items' => [
'Perpetual licenses for all software including PROSERVE',
'1 year warranty (extendable to 3 years)',
'1 year of software updates and new scenario integration',
'1 year of remote technical support',
'Extended support contracts available',
],
],
],
],
/* Partners — D.28 ================================================= */
'partners' => [
'eyebrow' => 'Partners',
'title' => 'Partners',
'tagline' => 'Distribute PROSERVE in your region.',
'meta_title' => 'Become a Partner — Distributors & Integrators | Asterion VR',
'meta_description' => 'Join our partner network. Distribute PROSERVE in your region. Strong margins, dedicated technical support, ready-to-use sales kit.',
'hero_lead' => 'Asterion partners with established defense, security, and integrator companies across Europe, the Middle East, Asia, and Latin America. Our partner network combines local presence with our French engineering and studio. We are looking for new partners in selected regions.',
'ctas' => [
['label' => 'Become a partner — apply', 'href' => '/contact/', 'variant' => 'primary'],
],
'sections' => [
[
'type' => 'list',
'eyebrow' => 'Why partner with Asterion',
'title' => 'A complete commercial framework.',
'items' => [
'Strong commercial margins on hardware and software',
'Dedicated technical support and pre-sales engineering',
'Ready-to-use sales kit (pitch decks, brochures, video assets, demo content)',
'Co-marketing opportunities and joint presence at sector events',
'Training programme for your sales and technical teams',
'Exclusive territory rights on qualifying volumes',
],
],
[
'type' => 'list',
'eyebrow' => 'What we look for',
'title' => 'Selection criteria.',
'items' => [
'Established commercial presence in defense, public security, or fire & rescue procurement',
'Technical capability to support the platform first-line',
'Local language and cultural fit with the target customer base',
'Clean compliance posture and willingness to operate under our distribution code',
],
],
],
],
];

View File

@@ -0,0 +1,108 @@
<?php
/**
* Asterion Bricks — Conversion form handler
*
* Receives POSTs from /request-demo/, /request-te-kit/, /request-quote/,
* /contact/. Validates the WordPress nonce, screens the honeypot, sanitizes
* the payload, and emails the lead to the configured recipient.
*
* Hook : admin_post_av_form_submit (logged-out users use admin_post_nopriv).
*
* Lead destination defaults to AV_LEADS_RECIPIENT (override in wp-config.php),
* falling back to the WP admin email.
*
* @package AsterionBricks
*/
defined('ABSPATH') || exit;
if (! defined('AV_LEADS_RECIPIENT')) {
define('AV_LEADS_RECIPIENT', 'jerome.foucher@asterionvr.com');
}
function av_handle_form_submit() {
// 1. Nonce
if (! isset($_POST['av_nonce']) || ! wp_verify_nonce(wp_unslash($_POST['av_nonce']), 'av_form_submit')) {
wp_safe_redirect(home_url('/?av_status=error'));
exit;
}
// 2. Honeypot — bots fill anything
if (! empty($_POST['av_hp'])) {
// Pretend success so bots don't retry.
$redirect = isset($_POST['redirect_to']) ? esc_url_raw(wp_unslash($_POST['redirect_to'])) : home_url('/');
wp_safe_redirect(add_query_arg('av_status', 'success', $redirect));
exit;
}
// 3. Form data
$slug = isset($_POST['form_slug']) ? sanitize_key(wp_unslash($_POST['form_slug'])) : '';
$forms_data = include AV_THEME_DIR . '/inc/forms-data.php';
if (! isset($forms_data[$slug])) {
wp_safe_redirect(home_url('/?av_status=error'));
exit;
}
$form = $forms_data[$slug];
// 4. Sanitize fields
$payload = [];
foreach ($form['fields'] as $field) {
$name = $field['name'];
if (! isset($_POST[$name])) {
$payload[$name] = '';
continue;
}
$raw = wp_unslash($_POST[$name]);
if ($field['type'] === 'email') {
$payload[$name] = sanitize_email($raw);
} elseif ($field['type'] === 'textarea') {
$payload[$name] = sanitize_textarea_field($raw);
} else {
$payload[$name] = sanitize_text_field($raw);
}
}
// 5. Required-field validation
foreach ($form['fields'] as $field) {
if (! empty($field['required']) && empty($payload[$field['name']])) {
$redirect = isset($_POST['redirect_to']) ? esc_url_raw(wp_unslash($_POST['redirect_to'])) : home_url('/');
wp_safe_redirect(add_query_arg('av_status', 'error', $redirect));
exit;
}
}
// 6. Compose mail
$subject_prefix = '[Asterion VR · ' . $form['title'] . ']';
$subject = $subject_prefix . ' ' . ($payload['organization'] ?? $payload['full_name'] ?? '(unidentified lead)');
$body = "New lead from " . get_bloginfo('name') . " — form: " . $form['title'] . "\n";
$body .= "URL : " . (isset($_POST['redirect_to']) ? esc_url_raw(wp_unslash($_POST['redirect_to'])) : home_url('/')) . "\n";
$body .= str_repeat('-', 60) . "\n";
foreach ($form['fields'] as $field) {
$value = $payload[$field['name']] ?? '';
if ($value === '') continue;
$body .= str_pad($field['label'], 28) . ': ' . $value . "\n";
}
$body .= str_repeat('-', 60) . "\n";
$body .= "Submitted : " . current_time('mysql') . "\n";
$body .= "IP : " . (isset($_SERVER['REMOTE_ADDR']) ? sanitize_text_field($_SERVER['REMOTE_ADDR']) : '?') . "\n";
$body .= "User Agent: " . (isset($_SERVER['HTTP_USER_AGENT']) ? sanitize_text_field(wp_unslash($_SERVER['HTTP_USER_AGENT'])) : '?') . "\n";
$headers = ['Content-Type: text/plain; charset=UTF-8'];
if (! empty($payload['email'])) {
$headers[] = 'Reply-To: ' . $payload['email'];
}
$recipient = apply_filters('av_form_recipient', AV_LEADS_RECIPIENT, $slug, $payload);
$sent = wp_mail($recipient, $subject, $body, $headers);
// 7. Redirect
$redirect = isset($_POST['redirect_to']) ? esc_url_raw(wp_unslash($_POST['redirect_to'])) : home_url('/');
$status = $sent ? 'success' : 'error';
wp_safe_redirect(add_query_arg('av_status', $status, $redirect));
exit;
}
add_action('admin_post_av_form_submit', 'av_handle_form_submit');
add_action('admin_post_nopriv_av_form_submit', 'av_handle_form_submit');

View File

@@ -0,0 +1,167 @@
<?php
/**
* Asterion Bricks — Conversion forms data
*
* Data for the 4 conversion pages: Request a Demo, T&E Kit, Quote, Contact.
* Copy from PDF Strategie & Contenu D.24-D.27.
*
* Each entry: hero, promise list (right column), form fields, FAQ, reassurance.
*
* @package AsterionBricks
*/
defined('ABSPATH') || exit;
return [
/* Request a Demo — D.24 =========================================== */
'request-demo' => [
'eyebrow' => 'Request a Demo',
'title' => 'Request a Demo',
'tagline' => 'See PROSERVE in action.',
'meta_title' => 'Request a Demo — See PROSERVE in Action | Asterion VR',
'meta_description' => 'Schedule a 30-minute tailored demo with our team. We respond within 48 hours.',
'hero_lead' => 'A live demo, calibrated to your role and your unit. We respond within 48 hours.',
'promise_title' => 'What you receive',
'promise_items' => [
'A 30-minute video call with a member of our team — typically Jérôme, our founder, or a senior product manager.',
'A live walkthrough of the configuration most relevant to your needs (MY / FLEX / ACADEMY).',
'A scenario demonstration matched to your segment (police, special forces, military, fire).',
'Honest answers to your technical and procurement questions.',
'A follow-up email summarizing the discussion, with the right resources for your evaluation.',
],
'fields' => [
['name' => 'full_name', 'label' => 'Full name', 'type' => 'text', 'required' => true],
['name' => 'organization', 'label' => 'Organization', 'type' => 'text', 'required' => true],
['name' => 'job_title', 'label' => 'Job title / role', 'type' => 'text', 'required' => true],
['name' => 'country', 'label' => 'Country', 'type' => 'text', 'required' => true],
['name' => 'email', 'label' => 'Email', 'type' => 'email', 'required' => true],
['name' => 'segment', 'label' => 'Segment', 'type' => 'select', 'required' => true,
'options' => ['', 'Police', 'Special Forces', 'Military', 'Firefighters', 'Other']],
['name' => 'trainees', 'label' => 'Estimated number of trainees in your unit', 'type' => 'text', 'required' => false],
['name' => 'timeframe', 'label' => 'Preferred timeframe', 'type' => 'select', 'required' => false,
'options' => ['', 'This week', 'Next week', 'Next month', 'No rush']],
['name' => 'message', 'label' => 'Message — anything specific you want us to demonstrate', 'type' => 'textarea', 'required' => false],
],
'reassurance' => 'We respond within 48 hours. We never share your information. No newsletter sign-up unless you ask.',
'submit_label' => 'Schedule the demo',
'faq' => [
['q' => 'Will there be a sales pitch?', 'a' => "No. The first call is technical and pedagogical. We assume you'll evaluate three or four solutions before deciding — we want to give you the information you need to compare honestly."],
['q' => 'Can I bring colleagues?', 'a' => 'Of course. The more roles in the room (training officer, IT, finance, command), the more useful the call.'],
['q' => 'In what language?', 'a' => 'EN, FR. Other languages on a per-request basis.'],
],
],
/* Request a T&E Kit — D.25 ======================================== */
'request-te-kit' => [
'eyebrow' => 'Request a T&E Kit',
'title' => 'Request a T&E Kit',
'tagline' => 'Try PROSERVE in your own facility, with your own people.',
'meta_title' => 'Request a T&E Kit — Try PROSERVE on Site | Asterion VR',
'meta_description' => 'Get a PROSERVE case on loan at your facility for 5 to 10 days. Limited availability — qualifying applications only.',
'hero_lead' => "A demo only goes so far. The Test & Evaluation Kit programme lends a fully configured PROSERVE case to qualifying organizations for 5 to 10 days, on site, with our team's support.",
'promise_title' => 'What you receive',
'promise_items' => [
'A complete PROSERVE FLEX or MY PROSERVE configuration delivered to your facility.',
'On-site setup and instructor onboarding by our team (1-2 days).',
'Remote technical support throughout the loan period.',
'Up to 10 days of unrestricted use by your operators and instructors.',
'A debrief session at the end to capture observations and answer technical questions.',
],
'fields' => [
['name' => 'full_name', 'label' => 'Full name', 'type' => 'text', 'required' => true],
['name' => 'organization', 'label' => 'Organization', 'type' => 'text', 'required' => true],
['name' => 'job_title', 'label' => 'Job title', 'type' => 'text', 'required' => true],
['name' => 'email', 'label' => 'Email', 'type' => 'email', 'required' => true],
['name' => 'country', 'label' => 'Country', 'type' => 'text', 'required' => true],
['name' => 'address', 'label' => 'Address of evaluation facility', 'type' => 'text', 'required' => true],
['name' => 'segment', 'label' => 'Segment', 'type' => 'select','required' => true,
'options' => ['', 'Police', 'Special Forces', 'Military', 'Firefighters', 'Other']],
['name' => 'trainees', 'label' => 'Number of trainees who would participate in evaluation', 'type' => 'text', 'required' => false],
['name' => 'timeline', 'label' => 'Procurement timeline', 'type' => 'select','required' => true,
'options' => ['', '3 months', '6 months', '12 months', '18+ months']],
['name' => 'budget', 'label' => 'Indicative budget range', 'type' => 'text', 'required' => true],
['name' => 'authorization', 'label' => 'Authorization status', 'type' => 'select','required' => false,
'options' => ['', 'Cleared', 'Pending', 'Non-applicable']],
['name' => 'message', 'label' => 'Message', 'type' => 'textarea', 'required' => false],
],
'reassurance' => 'Limited slots per quarter. We respond within 5 working days with a yes-or-no on the loan, and a proposed schedule if eligible.',
'submit_label' => 'Apply for a T&E Kit',
'eligibility' => [
'title' => 'Eligibility',
'lead' => 'The T&E Kit programme is reserved for organizations with a clear procurement intent and the capacity to run meaningful evaluation drills. We accept applications from:',
'items' => [
'National and regional police, gendarmerie, and security forces',
'Special forces and tactical units',
'Military training centres',
'Firefighter and emergency services training schools',
'Approved distributors and integrators bidding on identified projects',
],
],
],
/* Request a Quote — D.26 ========================================== */
'request-quote' => [
'eyebrow' => 'Request a Quote',
'title' => 'Request a Quote',
'tagline' => 'From specification to deployment plan.',
'meta_title' => 'Request a Quote — PROSERVE Pricing & Deployment Plan',
'meta_description' => 'Get a detailed quote and deployment plan within 5 working days. Volume pricing for regional rollouts.',
'hero_lead' => 'Tell us what you need. We send back a detailed quote — including hardware, software, options, training, support, and deployment plan — within 5 working days.',
'promise_title' => 'What you receive',
'promise_items' => [
'A detailed quote (PDF, suitable for procurement records)',
'A deployment plan with milestones and timing',
'A 30-minute call with our commercial team to walk through the quote',
'References for an introduction call with comparable customers (subject to NDA)',
],
'fields' => [
['name' => 'full_name', 'label' => 'Full name', 'type' => 'text', 'required' => true],
['name' => 'organization', 'label' => 'Organization', 'type' => 'text', 'required' => true],
['name' => 'job_title', 'label' => 'Job title', 'type' => 'text', 'required' => true],
['name' => 'email', 'label' => 'Email', 'type' => 'email', 'required' => true],
['name' => 'country', 'label' => 'Country', 'type' => 'text', 'required' => true],
['name' => 'procurement', 'label' => 'Procurement vehicle', 'type' => 'select', 'required' => false,
'options' => ['', 'Direct purchase', 'Open tender', 'Framework contract', 'Other']],
['name' => 'configuration', 'label' => 'Configuration desired', 'type' => 'text', 'required' => false],
['name' => 'units', 'label' => 'Number of units / packs / seats', 'type' => 'text', 'required' => false],
['name' => 'options', 'label' => 'Options', 'type' => 'text', 'required' => false],
['name' => 'deployment', 'label' => 'Deployment location and timeline', 'type' => 'text', 'required' => false],
['name' => 'constraints', 'label' => 'Administrative constraints (open tender deadline, cybersecurity review process, etc.)', 'type' => 'textarea', 'required' => false],
['name' => 'message', 'label' => 'Message', 'type' => 'textarea', 'required' => false],
],
'reassurance' => 'We respond within 5 working days. Detailed quote suitable for procurement records.',
'submit_label' => 'Request the quote',
],
/* Contact — D.27 ================================================== */
'contact' => [
'eyebrow' => 'Contact',
'title' => 'Contact',
'tagline' => 'How can we help?',
'meta_title' => 'Contact — Asterion VR',
'meta_description' => 'General inquiries, partnerships, press. Three response paths.',
'hero_lead' => "If you know what you're looking for, the three CTAs below take you directly there. For everything else, the form at the bottom reaches our office.",
'promise_title' => 'Other inquiries',
'promise_items' => [
'Press & media — press@asterionvr.com (response within 24 hours)',
'Partnerships & distributors — partners@asterionvr.com',
'Careers — careers@asterionvr.com',
'General — hello@asterionvr.com',
'Office — Asterion VR · 9 rue de la Marebaudière · 35760 Montgermont · France · +33 6 86 94 33 51',
],
'fields' => [
['name' => 'full_name', 'label' => 'Full name', 'type' => 'text', 'required' => true],
['name' => 'organization', 'label' => 'Organization', 'type' => 'text', 'required' => false],
['name' => 'email', 'label' => 'Email', 'type' => 'email', 'required' => true],
['name' => 'subject', 'label' => 'Subject', 'type' => 'text', 'required' => true],
['name' => 'message', 'label' => 'Message', 'type' => 'textarea', 'required' => true],
],
'reassurance' => 'We respond within 48 hours on weekdays.',
'submit_label' => 'Send the message',
'shortcuts' => [
['label' => 'Request a Demo (response within 48 hours)', 'href' => '/request-demo/', 'variant' => 'primary'],
['label' => 'Request a T&E Kit (response within 5 working days)', 'href' => '/request-te-kit/', 'variant' => 'secondary'],
['label' => 'Request a Quote (response within 5 working days)', 'href' => '/request-quote/', 'variant' => 'secondary'],
],
],
];

View File

@@ -0,0 +1,208 @@
<?php
/**
* Asterion Bricks — Conversion form partial
*
* Renders one conversion page (Demo / T&E / Quote / Contact). Two-column
* hero (form left, promise right) + optional eligibility list + FAQ.
*
* Data passed via `set_query_var('av_form', $form_data)`.
*
* Form posts to admin-post.php with action=av_form_submit; the handler in
* inc/form-handler.php validates the nonce, sanitizes, and emails the lead
* to jerome.foucher@asterionvr.com.
*
* @package AsterionBricks
*/
defined('ABSPATH') || exit;
$form = get_query_var('av_form');
if (! is_array($form)) {
return;
}
$home_url = home_url('/');
$slug = get_post_field('post_name', get_queried_object_id());
// Surface success/error from query string (set by the handler on redirect).
$av_status = isset($_GET['av_status']) ? sanitize_key($_GET['av_status']) : '';
?>
<!-- HERO -->
<section class="av-hero" aria-labelledby="form-headline">
<div class="av-hero__media" aria-hidden="true">
<div style="width:100%;height:100%;background:
radial-gradient(ellipse at 50% 30%, rgba(201,164,90,0.12), transparent 60%),
linear-gradient(135deg, #081427 0%, #0B1F3A 50%, #13294B 100%);"></div>
</div>
<div class="av-container">
<div class="av-hero__inner">
<p class="av-hero__eyebrow"><?php echo esc_html($form['eyebrow']); ?></p>
<h1 id="form-headline" class="av-hero__headline" style="font-size:clamp(2.25rem,5vw,var(--text-display-lg));line-height:var(--leading-display-lg);"><?php echo esc_html($form['tagline']); ?></h1>
<p class="av-hero__sub"><?php echo esc_html($form['hero_lead']); ?></p>
<?php if (! empty($form['shortcuts'])) : ?>
<div class="av-hero__ctas">
<?php foreach ($form['shortcuts'] as $sc) :
$variant = ($sc['variant'] === 'primary') ? 'av-btn--primary' : 'av-btn--on-dark av-btn--secondary';
?>
<a href="<?php echo esc_url($home_url . ltrim($sc['href'], '/')); ?>" class="av-btn <?php echo esc_attr($variant); ?> av-btn--md">
<?php echo esc_html($sc['label']); ?>
</a>
<?php endforeach; ?>
</div>
<?php endif; ?>
</div>
</div>
</section>
<!-- TWO-COLUMN: form (left) + promise (right) -->
<section class="av-section" aria-labelledby="form-title">
<div class="av-container">
<?php if ($av_status === 'success') : ?>
<div role="status" aria-live="polite" style="padding:var(--space-6);background:rgba(31,139,76,0.08);border-left:3px solid var(--color-success);border-radius:var(--radius-sm);margin-bottom:var(--space-8);">
<strong><?php esc_html_e('Thank you — your request was sent.', 'asterion-bricks'); ?></strong><br>
<?php esc_html_e('We will reply within the timeframe stated above. Check your inbox (and spam) for confirmation.', 'asterion-bricks'); ?>
</div>
<?php elseif ($av_status === 'error') : ?>
<div role="alert" style="padding:var(--space-6);background:rgba(200,16,46,0.06);border-left:3px solid var(--color-error);border-radius:var(--radius-sm);margin-bottom:var(--space-8);">
<strong><?php esc_html_e('Something went wrong.', 'asterion-bricks'); ?></strong>
<?php esc_html_e(' Please try again, or email us directly at hello@asterionvr.com.', 'asterion-bricks'); ?>
</div>
<?php endif; ?>
<div style="display:grid;grid-template-columns:1fr;gap:var(--space-12);" class="av-form-grid">
<!-- FORM -->
<div>
<h2 id="form-title" class="av-section__title" style="font-size:var(--text-h2);"><?php esc_html_e('Tell us about your unit.', 'asterion-bricks'); ?></h2>
<p class="av-section__lead" style="margin-bottom:var(--space-6);"><?php echo esc_html($form['reassurance']); ?></p>
<form method="post" action="<?php echo esc_url(admin_url('admin-post.php')); ?>" class="av-form">
<?php wp_nonce_field('av_form_submit', 'av_nonce'); ?>
<input type="hidden" name="action" value="av_form_submit">
<input type="hidden" name="form_slug" value="<?php echo esc_attr($slug); ?>">
<input type="hidden" name="redirect_to" value="<?php echo esc_attr(get_permalink()); ?>">
<input type="text" name="av_hp" value="" tabindex="-1" autocomplete="off" style="position:absolute;left:-9999px;" aria-hidden="true">
<div class="av-stack av-stack--lg">
<?php foreach ($form['fields'] as $field) :
$field_id = 'av-' . esc_attr($field['name']);
$required = ! empty($field['required']);
?>
<div>
<label for="<?php echo esc_attr($field_id); ?>" class="av-label">
<?php echo esc_html($field['label']); ?>
<?php if ($required) : ?><span class="av-label__required" aria-hidden="true">*</span><?php endif; ?>
</label>
<?php if ($field['type'] === 'textarea') : ?>
<textarea
id="<?php echo esc_attr($field_id); ?>"
name="<?php echo esc_attr($field['name']); ?>"
class="av-textarea"
rows="5"
<?php echo $required ? 'required aria-required="true"' : ''; ?>></textarea>
<?php elseif ($field['type'] === 'select') : ?>
<select
id="<?php echo esc_attr($field_id); ?>"
name="<?php echo esc_attr($field['name']); ?>"
class="av-select"
<?php echo $required ? 'required aria-required="true"' : ''; ?>>
<?php foreach ($field['options'] as $opt) : ?>
<option value="<?php echo esc_attr($opt); ?>"<?php echo $opt === '' ? ' disabled selected' : ''; ?>>
<?php echo $opt === '' ? esc_html__('— select —', 'asterion-bricks') : esc_html($opt); ?>
</option>
<?php endforeach; ?>
</select>
<?php else : ?>
<input
type="<?php echo esc_attr($field['type']); ?>"
id="<?php echo esc_attr($field_id); ?>"
name="<?php echo esc_attr($field['name']); ?>"
class="av-input"
<?php echo $required ? 'required aria-required="true"' : ''; ?>
autocomplete="<?php echo $field['type'] === 'email' ? 'email' : 'on'; ?>">
<?php endif; ?>
</div>
<?php endforeach; ?>
<button type="submit" class="av-btn av-btn--primary av-btn--lg" style="width:auto;align-self:flex-start;">
<?php echo esc_html($form['submit_label'] ?? __('Send', 'asterion-bricks')); ?>
</button>
</div>
</form>
</div>
<!-- PROMISE -->
<aside style="background:var(--color-bg-subtle);padding:var(--space-8);border-radius:var(--radius-md);align-self:start;">
<h2 style="font-family:var(--font-display);font-size:var(--text-h3);font-weight:var(--font-weight-semibold);margin-bottom:var(--space-4);">
<?php echo esc_html($form['promise_title']); ?>
</h2>
<ul style="list-style:none;padding:0;margin:0;display:flex;flex-direction:column;gap:var(--space-3);font-size:var(--text-body-md);line-height:var(--leading-body-md);color:var(--color-text-secondary);">
<?php foreach ($form['promise_items'] as $item) : ?>
<li style="padding-left:var(--space-6);position:relative;">
<span aria-hidden="true" style="position:absolute;left:0;top:0.55em;width:8px;height:8px;background:var(--color-brand-gold);border-radius:50%;"></span>
<?php echo esc_html($item); ?>
</li>
<?php endforeach; ?>
</ul>
</aside>
</div>
<style>
@media (min-width: 1024px) {
.av-form-grid { grid-template-columns: 1.4fr 1fr !important; }
}
</style>
</div>
</section>
<!-- ELIGIBILITY (T&E only) -->
<?php if (! empty($form['eligibility'])) : ?>
<section class="av-section av-section--dark" data-av-reveal>
<div class="av-container">
<div class="av-section__head">
<span class="av-eyebrow av-eyebrow--gold"><?php esc_html_e('Eligibility', 'asterion-bricks'); ?></span>
<h2 class="av-section__title"><?php echo esc_html($form['eligibility']['title']); ?></h2>
<p class="av-section__lead"><?php echo esc_html($form['eligibility']['lead']); ?></p>
</div>
<ul style="list-style:none;padding:0;margin:0;display:flex;flex-direction:column;gap:var(--space-3);max-width:72ch;color:var(--color-text-on-dark-muted);">
<?php foreach ($form['eligibility']['items'] as $item) : ?>
<li style="padding-left:var(--space-6);position:relative;">
<span aria-hidden="true" style="position:absolute;left:0;top:0.6em;width:8px;height:8px;background:var(--color-brand-gold);border-radius:50%;"></span>
<?php echo esc_html($item); ?>
</li>
<?php endforeach; ?>
</ul>
</div>
</section>
<?php endif; ?>
<!-- FAQ (Demo only) -->
<?php if (! empty($form['faq'])) : ?>
<section class="av-section" data-av-reveal>
<div class="av-container av-container--narrow">
<div class="av-section__head">
<span class="av-eyebrow"><?php esc_html_e('Frequently asked', 'asterion-bricks'); ?></span>
<h2 class="av-section__title"><?php esc_html_e('Quick answers.', 'asterion-bricks'); ?></h2>
</div>
<div class="av-stack av-stack--lg">
<?php foreach ($form['faq'] as $i => $qa) : ?>
<details style="border-bottom:1px solid var(--color-border-subtle);padding-block:var(--space-4);">
<summary style="font-family:var(--font-display);font-size:var(--text-h4);font-weight:var(--font-weight-semibold);cursor:pointer;list-style:none;display:flex;justify-content:space-between;align-items:center;">
<?php echo esc_html($qa['q']); ?>
<span aria-hidden="true">+</span>
</summary>
<p style="margin-top:var(--space-3);color:var(--color-text-secondary);font-size:var(--text-body-md);line-height:var(--leading-body-md);">
<?php echo esc_html($qa['a']); ?>
</p>
</details>
<?php endforeach; ?>
</div>
</div>
</section>
<?php endif; ?>

View File

@@ -0,0 +1,27 @@
<?php
/**
* Template Name: Conversion Form
*
* Custom page template for /request-demo/, /request-te-kit/, /request-quote/, /contact/.
*
* @package AsterionBricks
*/
defined('ABSPATH') || exit;
$slug = get_post_field('post_name', get_queried_object_id());
$data = include AV_THEME_DIR . '/inc/forms-data.php';
if (! isset($data[$slug])) {
get_header();
echo '<section class="av-section"><div class="av-container">';
echo '<h1>' . esc_html(get_the_title()) . '</h1>';
echo '<p>' . esc_html__('Form data not found for slug:', 'asterion-bricks') . ' ' . esc_html($slug) . '</p>';
echo '</div></section>';
get_footer();
return;
}
get_header();
set_query_var('av_form', $data[$slug]);
get_template_part('template-parts/conversion-form');
get_footer();

View File

@@ -0,0 +1,28 @@
<?php
/**
* Template Name: Editorial Detail
*
* Custom page template for editorial pages (Why Asterion, About, Customers
* hub, Trust, Partners). Reuses the industry-detail partial.
*
* @package AsterionBricks
*/
defined('ABSPATH') || exit;
$slug = get_post_field('post_name', get_queried_object_id());
$data = include AV_THEME_DIR . '/inc/editorial-data.php';
if (! isset($data[$slug])) {
get_header();
echo '<section class="av-section"><div class="av-container">';
echo '<h1>' . esc_html(get_the_title()) . '</h1>';
echo '<p>' . esc_html__('Editorial data not found for slug:', 'asterion-bricks') . ' ' . esc_html($slug) . '</p>';
echo '</div></section>';
get_footer();
return;
}
get_header();
set_query_var('av_industry', $data[$slug]);
get_template_part('template-parts/industry-detail');
get_footer();

View File

@@ -0,0 +1,87 @@
<?php
/**
* Template Name: Insights Hub
*
* /insights/ — blog hub. Lists native `post` items as blog cards.
*
* @package AsterionBricks
*/
defined('ABSPATH') || exit;
get_header();
$home_url = home_url('/');
?>
<section class="av-hero" aria-labelledby="insights-headline">
<div class="av-hero__media" aria-hidden="true">
<div style="width:100%;height:100%;background:
radial-gradient(ellipse at 60% 40%, rgba(201,164,90,0.12), transparent 60%),
linear-gradient(135deg, #081427 0%, #0B1F3A 70%, #13294B 100%);"></div>
</div>
<div class="av-container">
<div class="av-hero__inner">
<p class="av-hero__eyebrow"><?php esc_html_e('Insights', 'asterion-bricks'); ?></p>
<h1 id="insights-headline" class="av-hero__headline">Notes from the front of immersive training.</h1>
<p class="av-hero__sub">
Doctrine. Training science. Instructor stories. AAR data. Comparisons of VR vs live training. Found something useful? It probably came from a customer conversation. We publish what we learn.
</p>
</div>
</div>
</section>
<section class="av-section" data-av-reveal>
<div class="av-container">
<?php
// Categories filter chips (placeholders — wired to native `category` taxonomy if used).
$categories = ['Doctrine', 'Technology', 'Case Studies', 'Industry News', "Founder's Notes"];
?>
<div style="display:flex;flex-wrap:wrap;gap:var(--space-3);margin-bottom:var(--space-10);">
<?php foreach ($categories as $cat) : ?>
<span class="av-btn av-btn--ghost av-btn--sm" style="border:1px solid var(--color-border-default);"><?php echo esc_html($cat); ?></span>
<?php endforeach; ?>
</div>
<?php $posts = get_posts(['numberposts' => 12, 'post_status' => 'publish']); ?>
<?php if (! empty($posts)) : ?>
<div class="av-grid-3">
<?php foreach ($posts as $post) : setup_postdata($post); ?>
<article class="av-card av-card--blog">
<a href="<?php the_permalink(); ?>" class="av-card__media" aria-hidden="true" tabindex="-1" style="background:linear-gradient(135deg,#CCD3DC,#E5E9EE);"></a>
<div class="av-card__body">
<span class="av-card__eyebrow"><?php echo esc_html(get_the_date('M j, Y')); ?></span>
<h2 class="av-card__title"><a href="<?php the_permalink(); ?>" style="color:inherit;text-decoration:none;"><?php the_title(); ?></a></h2>
<p class="av-card__excerpt"><?php echo esc_html(wp_trim_words(get_the_excerpt(), 22)); ?></p>
<div class="av-card__cta"><a href="<?php the_permalink(); ?>" class="av-link av-link--with-arrow"><?php esc_html_e('Read more', 'asterion-bricks'); ?></a></div>
</div>
</article>
<?php endforeach; wp_reset_postdata(); ?>
</div>
<?php else : ?>
<p style="color:var(--color-text-muted);max-width:64ch;">
<?php esc_html_e('Editorial blog launches with the site go-live. The 12-month content calendar is in the Strategy & Content brief, section B.4. New articles will appear here as soon as they ship.', 'asterion-bricks'); ?>
</p>
<?php endif; ?>
</div>
</section>
<section class="av-section av-section--dark" data-av-reveal>
<div class="av-container">
<div style="display:grid;grid-template-columns:1fr;gap:var(--space-8);align-items:center;" class="av-newsletter-row">
<div>
<span class="av-eyebrow av-eyebrow--gold"><?php esc_html_e('Newsletter', 'asterion-bricks'); ?></span>
<h2 style="font-family:var(--font-display);font-size:var(--text-h1);line-height:var(--leading-h1);color:var(--color-text-on-dark);margin:var(--space-3) 0;">Subscribe — one article per month.</h2>
<p style="color:var(--color-text-on-dark-muted);max-width:60ch;">
Insights from the front of immersive training. One email per month. No spam. Unsubscribe in one click.
</p>
</div>
<form method="post" action="#" style="display:flex;gap:var(--space-3);flex-wrap:wrap;align-items:flex-start;" aria-label="<?php esc_attr_e('Newsletter signup', 'asterion-bricks'); ?>">
<label for="av-insights-newsletter" class="av-sr-only"><?php esc_html_e('Your email', 'asterion-bricks'); ?></label>
<input type="email" id="av-insights-newsletter" name="email" class="av-input" placeholder="<?php esc_attr_e('your@email.com', 'asterion-bricks'); ?>" required style="flex:1;min-width:200px;">
<button type="submit" class="av-btn av-btn--primary av-btn--md"><?php esc_html_e('Subscribe', 'asterion-bricks'); ?></button>
</form>
</div>
<style>@media (min-width: 768px) { .av-newsletter-row { grid-template-columns: 2fr 1.5fr !important; } }</style>
</div>
</section>
<?php get_footer(); ?>

View File

@@ -0,0 +1,92 @@
<?php
/**
* Template Name: Legal
*
* /legal/privacy/, /legal/terms/, /legal/cookies/, /legal/notice/.
* Renders the WP page content (filled in by counsel) inside the standard
* narrow container with a clean editorial hero.
*
* @package AsterionBricks
*/
defined('ABSPATH') || exit;
get_header();
?>
<section class="av-section">
<div class="av-container av-container--narrow">
<header class="av-section__head">
<span class="av-eyebrow"><?php esc_html_e('Legal', 'asterion-bricks'); ?></span>
<h1 class="av-section__title"><?php the_title(); ?></h1>
<p class="av-section__lead">
<?php esc_html_e('Last updated:', 'asterion-bricks'); ?>
<?php echo esc_html(get_the_modified_date()); ?>
</p>
</header>
<div class="av-prose" style="font-size:var(--text-body-md);line-height:var(--leading-body-md);color:var(--color-text-secondary);">
<?php
if (have_posts()) :
while (have_posts()) : the_post();
the_content();
endwhile;
endif;
// Default skeleton when the page content is empty — populated by counsel later.
$content = get_post_field('post_content', get_queried_object_id());
if (trim($content) === '') :
?>
<p style="padding:var(--space-6);background:var(--color-bg-subtle);border-left:3px solid var(--color-warning);border-radius:var(--radius-sm);">
<strong><?php esc_html_e('Placeholder.', 'asterion-bricks'); ?></strong>
<?php esc_html_e('This page is to be drafted with legal counsel. The structure below outlines the sections expected.', 'asterion-bricks'); ?>
</p>
<?php
// Slug-driven placeholder sections.
$slug = get_post_field('post_name', get_queried_object_id());
$skeletons = [
'privacy' => [
'Data controller (Asterion VR), contact, DPO if relevant',
'Data collected (form submissions, cookie identifiers, IP, etc.)',
'Purpose of processing (sales follow-up, newsletter, analytics)',
'Legal basis (consent, contract, legitimate interest)',
'Retention periods',
'Data sharing (subcontractors, hosts)',
'Data subject rights (access, rectification, deletion, portability, objection)',
'Complaint procedure (CNIL link)',
],
'terms' => [
'Site usage conditions',
'Intellectual property',
'Liability limitations',
'Applicable law and jurisdiction',
],
'cookies' => [
'List of cookies (functional, analytics, marketing)',
'Cookie purpose, retention, third parties',
'Consent management procedure',
],
'notice' => [
'Asterion VR — RCS 821 520 970 Rennes — NAF 6201Z — SIRET 821 520 970 00012',
'Adresse, téléphone, e-mail, directeur de la publication',
'Hébergeur',
],
];
if (isset($skeletons[$slug])) :
?>
<h2 style="font-family:var(--font-display);font-size:var(--text-h3);margin-top:var(--space-10);margin-bottom:var(--space-4);"><?php esc_html_e('Sections to include', 'asterion-bricks'); ?></h2>
<ul style="display:flex;flex-direction:column;gap:var(--space-2);padding-left:var(--space-6);">
<?php foreach ($skeletons[$slug] as $line) : ?>
<li style="list-style:disc;"><?php echo esc_html($line); ?></li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
<?php endif; ?>
</div>
</div>
</section>
<?php get_footer(); ?>

View File

@@ -0,0 +1,100 @@
<?php
/**
* Template Name: Resources
*
* /resources/ — datasheets, whitepapers, videos, brochures.
*
* @package AsterionBricks
*/
defined('ABSPATH') || exit;
get_header();
$home_url = home_url('/');
$groups = [
[
'eyebrow' => 'Datasheets',
'title' => 'Technical specifications.',
'items' => [
['title' => 'PROSERVE — full datasheet', 'note' => 'Hardware specifications, software capabilities, scenarios. Gated, light form.'],
['title' => 'MY PROSERVE — quick datasheet', 'note' => '4-page summary.'],
['title' => 'PROSERVE FLEX — quick datasheet', 'note' => '4-page summary.'],
['title' => 'PROSERVE ACADEMY — quick datasheet', 'note' => '4-page summary.'],
['title' => 'PROSERVE+ — customization brochure', 'note' => 'Hardware add-ons, custom scenarios, process.'],
],
],
[
'eyebrow' => 'Whitepapers',
'title' => 'Long-form analyses.',
'items' => [
['title' => 'VR vs Live Fire: the 2026 cost-benefit comparison', 'note' => 'Quantified comparison across cost, fidelity, scalability, environmental.'],
['title' => "The Instructor's Guide to VR Training Programs", 'note' => "Methodology, drill design, AAR debriefing, assessment frameworks."],
['title' => 'Use of Force Training: how immersive simulation reduces tactical errors', 'note' => 'Reviews academic literature and Asterion deployment data.'],
['title' => 'Sovereignty in security simulation: why your training data must never leave your network', 'note' => 'For procurement and IT teams.'],
],
],
[
'eyebrow' => 'Videos',
'title' => 'Show, not tell.',
'items' => [
['title' => 'PROSERVE — 90-second product film', 'note' => 'Cinematic overview.'],
['title' => 'Instructor Cockpit walkthrough (3 minutes)', 'note' => 'Inside the instructor PC.'],
['title' => 'AAR replay — annotated example (4 minutes)', 'note' => 'A drill replayed with overlays.'],
['title' => 'MY PROSERVE — unboxing & first deployment (6 min)', 'note' => 'From mini-case to first scenario in real time.'],
['title' => 'Customer story — [name redacted unit] (8 min)', 'note' => 'Operational deployment, instructor interview, AAR excerpts.'],
],
],
[
'eyebrow' => 'Brochures',
'title' => 'For procurement and end-user briefs.',
'items' => [
['title' => 'PROSERVE general brochure', 'note' => '8 pages, EN/FR.'],
['title' => 'Industry-specific brochures', 'note' => 'Police, Special Forces, Military, Firefighters — one PDF each.'],
],
],
];
?>
<section class="av-hero" aria-labelledby="resources-headline">
<div class="av-hero__media" aria-hidden="true">
<div style="width:100%;height:100%;background:linear-gradient(135deg, #081427 0%, #0B1F3A 50%, #13294B 100%);"></div>
</div>
<div class="av-container">
<div class="av-hero__inner">
<p class="av-hero__eyebrow"><?php esc_html_e('Resources', 'asterion-bricks'); ?></p>
<h1 id="resources-headline" class="av-hero__headline">Everything to evaluate, justify, and procure.</h1>
<p class="av-hero__sub">
Whether you are building an internal pitch, drafting a procurement specification, or briefing your team — these resources are designed to help.
</p>
</div>
</div>
</section>
<?php foreach ($groups as $idx => $group) :
$is_dark = ($idx % 2 === 1);
$section_class = 'av-section' . ($is_dark ? ' av-section--dark' : '');
?>
<section class="<?php echo esc_attr($section_class); ?>" data-av-reveal>
<div class="av-container">
<div class="av-section__head">
<span class="av-eyebrow<?php echo $is_dark ? ' av-eyebrow--gold' : ''; ?>"><?php echo esc_html($group['eyebrow']); ?></span>
<h2 class="av-section__title"><?php echo esc_html($group['title']); ?></h2>
</div>
<div class="av-grid-3">
<?php foreach ($group['items'] as $item) : ?>
<article class="av-card<?php echo $is_dark ? ' is-on-dark' : ''; ?>">
<div class="av-card__body">
<h3 class="av-card__title" style="font-size:var(--text-h4);"><?php echo esc_html($item['title']); ?></h3>
<p class="av-card__excerpt"><?php echo esc_html($item['note']); ?></p>
<div class="av-card__cta">
<a href="<?php echo esc_url($home_url . 'contact/'); ?>" class="av-link<?php echo $is_dark ? ' av-link--on-dark' : ''; ?> av-link--with-arrow"><?php esc_html_e('Request access', 'asterion-bricks'); ?></a>
</div>
</div>
</article>
<?php endforeach; ?>
</div>
</div>
</section>
<?php endforeach; ?>
<?php get_footer(); ?>