Commit Graph

27 Commits

Author SHA1 Message Date
ce56b2b936 fix(bricks): enable publicTemplates setting so /template/* URLs resolve
Bricks's frontend.php template_redirect() permanently redirects any
/template/* URL to the homepage (site_url(), 301) when :
  - is_singular(bricks_template)
  - !current_user_can_use_builder()
  - !isset(bricks_global_settings.publicTemplates)
  - !maintenance mode

This kicks in BEFORE the Bricks builder check can run, so clicking
"Edit with Bricks" on a template ends up redirected to home → admin
URL → Bricks's own builder.php sees current_post_type as empty (because
the post wasn't actually queried before the redirect) → final redirect
to wp-admin/edit.php?post_type=&bricks_notice=error_post_type with the
"Invalid post type" notice.

Setting bricks_global_settings.publicTemplates = '1' disables this
preemptive redirect. Templates stay excluded from search but their
permalinks resolve normally → builder can attach.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 07:54:09 +02:00
aad32fd0f1 fix(bricks): remove bricks_template from REST bridge entirely
Even adding only 'custom-fields' to bricks_template's supports turned out
to break the Bricks builder ("Invalid post type" on Edit with Bricks for
all templates including pre-existing Header / Footer).

bricks_template is now left exactly as Bricks registers it natively :
  supports : author, revisions, thumbnail, title
  show_in_rest : false

The MCP server route to bricks_template was experimental and we don't use
it actively — direct PHP scripts (av-fix-template-meta, av-generate-*,
av-add-submenus) handle template management. Templates are exposed only
to the Bricks builder, not external REST clients.

case_study + scenario CPTs keep REST exposure (used for content type
generators later).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 07:48:50 +02:00
86cd37ed80 fix(bricks): stop overriding bricks_template supports — only add custom-fields
The REST bridge was rewriting the `supports` array on bricks_template (and
case_study, scenario) by force-adding ['title','editor','author','custom-fields'].
For bricks_template specifically, Bricks's own registration sets supports =
['author','revisions','thumbnail','title'] — deliberately WITHOUT 'editor',
because the post type is meant to be edited only via the Bricks builder, not
the WP block editor.

Adding 'editor' confused Bricks's builder : it would refuse to open the
template with "Invalid post type" because the post type now claimed to support
two incompatible editors.

Fix : keep the original supports list untouched, only append 'custom-fields'
(which IS required for /wp/v2/<type>/<id> to expose the `meta` field). All
templates (Header #25, Footer #46, Single Post #154) should now open in the
Bricks builder again.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 07:39:44 +02:00
e52a1de268 fix(bricks): correct Single Post template conditions format
Bricks's templateConditions for single posts expects:
  main: 'postType', postType: ['post']      (array of post types)

NOT the singular/object variant I'd used:
  main: 'singular', object: 'post'

The wrong format triggered "Invalid post type" when opening the template
in the Bricks builder editor — Bricks's editor couldn't parse the
condition and refused to load the template.

Source : wp-content/themes/bricks/includes/admin.php line 1101 — the
switch case for 'postType' confirms the expected shape.

For 'any' (entire website, used by Header/Footer templates), no extra
keys are needed beyond main='any'. Section/single templates need this
postType array form.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 07:35:12 +02:00
918c000817 feat(insights): blog setup — hub page + Single Post template + 3 seed posts
Phase 12 (post-launch ready) — Insights blog scaffolding so the /insights/
menu link works and the user can start publishing.

Creates :
1. /insights/ hub page (#153) with hero + Bricks `posts` query-loop
   element + closer CTA. The posts element configured with :
   - query : post_type=post, posts_per_page=9, orderby=date DESC
   - layout=grid, columns=3, linkPost=true, imageDisable=true
   - fields : eyebrow "Insights", h3 post title, date, excerpt
   - _cssCustom for card styling (subtle bg, border, padding, flex column)
2. Single Post Bricks template (#154, template_type=single, conditions=
   singular post) : eyebrow + h1 {post_title} + date · author meta +
   featured image + post-content + closer CTA.
3. Three seed posts publication-ready :
   - the-10-to-15-gap (#155)
   - simulators-for-entertainment-vs-training (#156)
   - sovereign-by-default-gdpr-native (#157)
   Topics aligned with the brand : training gap reality, why
   entertainment-first simulators fail tactical training, GDPR-native
   sovereignty for security forces.

User adds more posts via WP Admin → Posts → Add New. The Bricks Single
template handles layout automatically (matches templateConditions).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 21:29:29 +02:00
1ddde1ffd5 feat(header): add About / Customers / Partners submenu under Why Asterion
Extends av-add-submenus.php to attach 3 editorial pages as children of
the 'Why Asterion' top-level menu item :
  Why Asterion
    ├ About
    ├ Customers
    └ Partners

Re-running ?av_add_submenus=1 is idempotent : Solutions / Industries /
Technology children stay as-is (matched by URL), only the new Why Asterion
children get inserted (menu items #150-152).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 21:19:03 +02:00
a795fb345f style(footer): align nav-menu links with column heading + restore tagline visibility
Adds wp_head CSS overrides to fix two issues :
1. Footer nav-menu links (under Solutions / Company / Legal columns) were
   indented ~40px due to the browser's default <ul> padding-left. Zero it
   out so links align with the gold eyebrow heading above them.
2. Brand tagline "Your Last Mistake Should Be in VR." was using
   var(--color-text-tertiary) which renders too dark on the navy footer.
   Force rgba(255,255,255,0.65) for visible muted-white.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 21:07:10 +02:00
094fdbea51 style(lists): replace '— ' dash prefix with vertical gold bar accent
The em-dash prefix on list items felt typographic but unbranded. Now each
list item gets a 3px-wide gold vertical bar on the left, evoking a tactical
breadcrumb. Implementation :
- Builders (av_build_list_section in _av-bricks-shared.php +
  av_build_form_two_col promise list in av-generate-forms.php) emit clean
  text without the '— ' prefix, and set _cssClasses = 'av-list-item'
- New mu-plugin av-list-bullet-style.php injects CSS via wp_head() :
  .av-list-item { position: relative; padding-left: 0.9rem; }
  .av-list-item::before { gold bar, 3px × 1.1em, aligned to first line }

Regen all sections (industries, solutions, technology, editorial, forms,
home) to switch existing pages to the new style.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 21:05:45 +02:00
1c297b336f style(footer): align + brand sub-title typography across columns
One-shot mu-plugin patches the Footer template (#46) :
- Column sub-titles (Solutions / Company / Legal / Contact) now use the
  eyebrow style : gold, uppercase, 0.75rem, 0.1em letter-spacing — matches
  the section-eyebrows used across content pages.
- Brand heading (ASTERION VR) downsized to 1.125rem so it stops dominating
  the row; tagline muted to text-tertiary 0.875rem.
- Columns wrapper set to align-items: flex-start with consistent 3rem gap
  → all sub-titles sit at the same vertical baseline.
- Each column container tightened to 0.5rem rowGap (less air between
  heading and links).

Patches both content_2 (JSON, source) and footer_2 (serialized, mirrored
by the REST bridge). Idempotent.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 21:02:10 +02:00
a5c15b4c7a feat(header): custom flag-based language switcher
Replaces WPML's default language selector with a compact branded dropdown :
current language flag + 2-letter code + chevron, with a CSS-only hover/focus
dropdown listing other available languages (flag + native name).

Implementation : remove_all_actions on wpml_add_language_selector + register
our own renderer. Bricks's wpml-language-switcher element (hdrlng) fires the
same action so no template edit needed.

Flags via emoji (🇬🇧 EN, 🇫🇷 FR) — no asset path concerns. Dropdown styled
to match the rest of the header (navy bg, gold-on-hover, subtle border +
shadow). Mobile : dropdown anchors left to stay in viewport.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 20:59:52 +02:00
b530b7a76f style(header): compact, branded dropdown for nav-menu submenus
CSS injected via wp_head() overrides Bricks default nav-menu sub-menu
spacing (which inherits a bloated line-height + item padding via the
parent menu's settings, not addressable through Bricks's nav-menu
controls alone). Tight padding (0.55rem 1.25rem), branded navy bg with
subtle gold hover, 16rem min-width, soft shadow.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 20:45:35 +02:00
7134b70db9 feat(header): add submenus for Solutions / Industries / Technology + style dropdown
One-shot mu-plugin (?av_add_submenus=1) :
1. Adds child menu items to the Header — Main WP menu (term_id 9) :
   - Solutions → MY PROSERVE, PROSERVE FLEX, PROSERVE ACADEMY, PROSERVE+
   - Industries → Police, Special Forces, Military, Firefighters
   - Technology → VR Hardware, Software & AI, Weapons & Tracking, Scenarios,
     Instructor Cockpit, After-Action Review
   Children are matched by URL → idempotent re-runs.
2. Updates the Bricks nav-menu element settings in template #25 with
   dropdown styling : navy background, gold-on-hover text, padding,
   subtle gold border, indicator arrow. Patches both content_2 (JSON)
   and header_2 (serialized) meta keys.

Bricks's nav-menu CSS automatically handles hover-to-show on .menu-item-has-children.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 20:20:54 +02:00
c4718658d4 fix(header): make Asterion logo link to home
One-shot mu-plugin patches the Bricks heading 'hdrlgo' in template #25 to
add link.type='external' + link.url='/'. Idempotent — re-runs are safe.
Patches both _bricks_page_content_2 (JSON, source) and _bricks_page_header_2
(serialized PHP, mirrored by the REST bridge), so the change takes effect
immediately without re-running av-fix-template-meta.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 20:18:37 +02:00
38c0c5031e feat(pages): generate Phases 8-11 — Technology + Editorial + Forms + Home
Brings the site to its full programmatic page count : 24 EN + 24 FR pages
(48 total), all wired into the WPML CTE workflow established in the previous
commit. Each phase reuses tools/_av-bricks-shared.php builders, adds its own
filter('av_fr_translation_dict') to extend the FR dictionary, and ships a
seed-FR mu-plugin for the initial WPML trid linking.

## Phase 8 — Technology (tools/av-generate-technology.php + seed)
Hub /technology/ + 6 pillar pages (vr-hardware, software-ai, weapons-tracking,
scenarios, instructor-cockpit, after-action-review). Hub uses a 6-card grid
(3+3 layout — added card_count=6 case in av_build_cards_section).
EN : 87-93. FR : 94-100.

## Phase 9 — Editorial (tools/av-generate-editorial.php + seed)
5 top-level pages : /why-asterion/, /about/, /customers/, /trust/, /partners/.
Required adding empty-parent-path support to av_upsert_detail_page() so pages
can be created at the site root (no hub). EN : 107-111. FR : 112-116.

## Phase 10 — Forms (tools/av-generate-forms.php + seed)
4 conversion pages : /request-demo/, /request-te-kit/, /request-quote/,
/contact/. Custom page builder (not the shared detail-page pattern) :
hero + 2-column section (Bricks `form` element on left, promise list on
right) + optional shortcuts row (Contact), eligibility list (T&E Kit), FAQ
accordion (Demo). Form actions=email, emailTo=hello@asterionvr.com.
Field labels, select options, FAQ Q&A all in the FR dict.
EN : 122-125. FR : 126-129.

## Phase 11 — Home page (tools/av-generate-home.php + seed)
Custom-written single page (no data file). Sections : hero + 3-pillar cards
(Operational reality / Modular / Sovereign) + 4 Industries cards + 4
Solutions cards + 4-stat numbers band + Why-Asterion teaser CTA + Customers
teaser CTA + custom navy closer. Set as WP static front via
update_option(show_on_front=page, page_on_front=ID).
EN : 134. FR : 135.

## tools/_av-bricks-shared.php
- av_upsert_detail_page() now accepts empty `$parent_path` → top-level page
- av_build_cards_section() handles card_count=6 → 3-per-row layout

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 19:58:48 +02:00
d2badf49d4 feat(bricks+wpml): full programmatic page generation + native WPML CTE integration
Sessions 3-4 deliverables. Establishes the Asterion content pipeline :
EN pages generated programmatically from content-source/*-data.php, FR
translations rebuilt natively by Bricks's WPML integration from EN structure
+ WPML strings (no direct FR _bricks_page_content_2 writes).

## tools/_av-bricks-shared.php (the library)
Shared helpers + element atoms (eyebrow/heading/text/button/text-link) +
section builders (hero/prose/list/cards/cta/upsell/closer) + page write
pipeline that handles : write EN content via $wpdb (bypass Bricks's filter),
force Bricks::Elements::load_elements() so controls are populated, fire
wpml_page_builder_register_strings, push dict FR into icl_string_translations
(skip user CTE edits, auto-prefix /fr on internal URLs), trigger Bricks
native FR rebuild via wpml_page_builder_string_translated, and ensure a CTE
job exists (icl_translate_job.editor='wpml' + revision=NULL + populate
icl_translate rows with base64+gzip-encoded EN/FR strings).

## tools/av-generate-{industries,solutions}.php
Thin wrappers : URL trigger (template_redirect, not init — Bricks elements
load on 'wp' hook), add_filter('av_fr_translation_dict', ...) to register
FR strings, content-type-specific hub builder. ~150 FR strings per type.

## tools/av-translate-{industries,solutions}-fr.php
One-shot seeds for the initial FR linked posts via WPML trid mapping.

## tools/av-wpml-* operational mu-plugins
- set-cte : switch doc_translation_method to ICL_TM_TMETHOD_EDITOR (=1)
- create-jobs : reset CTE jobs (status=10 + needs_update=1 + editor=wpml +
  revision=NULL). Integrated into pipeline via av_ensure_wpml_cte_job().
- fix-status / repair : align FR posts to correct trid + cleanup orphans.
- push-translations : push dict into icl_string_translations.
- plugins-check / debug / dump-strings / icl-dump / rescan : diagnostics.

## tools/av-fix-link-types.php
One-shot DB migration : convert legacy link.type='internal'+url to 'external'
across all _bricks_page_*_2 meta values (JSON and PHP-serialized). Bricks's
set_link_attributes() only renders href= for type='external' — older session-3
templates lost their href silently.

## Other tools/ mu-plugins
- av-bricks-rest-bridge : pivot — exposes Bricks CPTs over REST, dual-format
  read filter (JSON for MCP / array for renderer), auto-mirror content→header/
  footer for templates.
- av-apply-bricks-styles, av-cleanup-orphans, av-create-wp-menu, av-debug-meta,
  av-dump-bricks, av-fix-template-meta : misc operational scripts.

## Bricks Config/
JSON snapshots of bricks_theme_styles, bricks_color_palette,
bricks_global_settings for diffable inspection.

## .gitignore
Add .mcp.json — holds per-developer WP App Password for the Bricks MCP server.

## wp-content/themes/asterion-bricks/assets/css/utilities.css
Note that all responsive overrides are now emitted natively by the page
generator via Bricks per-breakpoint settings, no custom CSS needed.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 19:40:28 +02:00
af0ed66122 docs(tools): clarify that Bricks is a theme, not a plugin
The Bricks ZIP cannot be installed via WP admin → Plugins → Add New →
Upload (it returns "No valid plugins were found"). Update tools/README.md
to make the distinction explicit and provide both PowerShell and admin
paths for each install.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 14:41:43 +02:00
7765d0fab2 chore: add tools/fresh-setup-mu-plugin for clean LocalWP recreation
Helper for resetting the dev environment by deleting the LocalWP site and
creating a fresh one (cleaner than wiping pages/options/transients in place).

tools/fresh-setup-mu-plugin.php
  Drop into wp-content/mu-plugins/ of a brand-new LocalWP install named
  "Asterion 2026". On first hit it:
    - sets siteurl/home to http://localhost:10004 (override AV_TARGET_HOME
      if LocalWP allocates a different port)
    - sets pretty permalinks (/%postname%/)
    - timezone Europe/Paris
    - activates the Bricks parent + asterion-bricks child theme (assumes
      the Junction has been re-made and the Bricks ZIP unpacked)
    - activates WPML core
    - sets Bricks Builder Access postTypes to page/post/case_study/scenario
    - flushes rewrite rules
    - self-deletes

tools/README.md
  Step-by-step procedure for the LocalWP delete → recreate → junction →
  unpack ZIPs → drop mu-plugin → first-hit flow. Plus the manual follow-up
  for Bricks license, WPML wizard, Bricks Theme Styles.

This file path (tools/) is a deliberate sibling of content-source/ and
ThirdParty/, all of them used during setup or migration but never loaded
by the site at runtime.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 14:38:33 +02:00
fba223004f chore: phase 1 reset — minimalist child theme + content-source extraction
Resets the child theme to its Bricks-first minimalist form (per RESTART-PLAN.md
phases 1a-1d) and extracts the textual copy into a runtime-independent
/content-source/ directory.

Child theme files removed
- header.php, footer.php, page.php, index.php, front-page.php
- template-parts/{solution,industry,conversion-form}.php
- templates/page-*.php (10 Custom Page Templates)
- inc/render-blocks.php, render-blocks-native.php, render-bricks.php
- inc/shortcodes.php, i18n.php, form-handler.php, seo.php
- assets/css/components.css, assets/js/main.js

Reasoning: Bricks Templates (Header / Footer / Single — Page) and Bricks-edited
pages now drive every screen. Anything emitted from the child theme would
fight Bricks' own rendering and waste CSS specificity battles.

Child theme now contains only
- style.css, functions.php (simplified to ~60 lines), theme.json
- inc/cpt.php (case_study + scenario + industry taxonomy)
- assets/css/tokens.css (untouched — design system source of truth)
- assets/css/utilities.css (trimmed to skip-link + sr-only + focus-visible
  + reduced motion — everything else handled by Bricks)
- assets/fonts/Inter-Variable*.woff2 (RGPD self-hosted)
- README.md spelling out the Bricks-first contract

Content moved to /content-source/
- solutions-data.php, industries-data.php, technology-data.php,
  editorial-data.php, forms-data.php — git mv preserves history
- README.md explaining their dual role: copy reference while building
  in Bricks, and source for programmatic page generation when we
  replicate an archetype across its variants.

Root README.md updated with the new repo layout + a pointer to
RESTART-PLAN.md and the archive/session-2-php-templates branch.

Memory file project_asterion_status.md updated for next-session resume.

What's preserved as before
- /BRIEF-Claude-Code.md, both PDFs, all .txt extracts
- /MISSING-ASSETS.md
- /ThirdParty/ (Bricks + WPML ZIPs, gitignored)
- LocalWP site at localhost:10004, Bricks v2.3.4 + WPML 4.9.3 active
- WPML EN/FR with directory URL strategy
- All Git history, both main and archive/session-2-php-templates branches

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 14:36:19 +02:00
026be81373 chore: session 2 snapshot — archive before Bricks-first restart
Snapshots the project at the end of session 2, just before resetting to a
Bricks-first orthodox architecture. RESTART-PLAN.md at the root explains
why this approach is being abandoned and what the next session will look like.

Why we restart
- Three architectures got stacked: Custom PHP Templates → Gutenberg blocks
  in post_content → Bricks data in post meta. Each layer fights the next.
- Bricks Builder UI does not load because our header.php / footer.php /
  page.php emit chrome that conflicts with Bricks' own template-parts.
- CSS overrides multiplied (Gutenberg + Bricks variants) and still don't
  pixel-match the original PHP-rendered visual.
- 8+ one-shot mu-plugins live in LocalWP to patch over inconsistencies.

What survives the restart (preserved here on main)
- BRIEF, both PDFs, .txt extracts (sources of truth)
- assets/css/tokens.css (full design system, untouched)
- assets/fonts/Inter-Variable*.woff2 (RGPD self-hosted)
- inc/<section>-data.php files (text copy from PDF strategie, will become
  /content-source/ on next session for reuse as translation dictionary
  and as input to programmatic page generation)
- The Git repo, remote, branch main
- LocalWP site, Bricks v2.3.4, WPML 4.9.3 with active licenses
- WPML EN + FR setup with directory URL strategy

What gets wiped at the start of next session
- wp-content/themes/asterion-bricks/header.php / footer.php / page.php /
  index.php / front-page.php / template-parts/ / templates/
- inc/render-blocks.php, inc/render-blocks-native.php, inc/render-bricks.php
- inc/shortcodes.php, inc/i18n.php, inc/form-handler.php
- 35+ WP pages created over the session
- All one-shot mu-plugins in LocalWP/wp-content/mu-plugins/

Restart approach (detailed in RESTART-PLAN.md)
- Minimalist child theme: style.css, functions.php, theme.json, tokens.css,
  trimmed utilities.css, fonts, inc/cpt.php — that's it.
- No header.php / footer.php / page.php in child theme — Bricks Templates
  (Header / Footer / Single — Page) take over via Bricks' Conditions.
- User builds 5-7 archetype Bricks templates visually (~1-2h each) then
  programmatic generation fills the variants from inc/*-data.php sources.
- WPML duplication after EN is validated.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 14:30:51 +02:00
f18a57e83f feat(wpml): refactor to post_content + duplicate site in French via WPML
This commit makes the site editable from WP admin (Gutenberg or Bricks
"Edit with Bricks") and translatable via WPML Translation Editor by
shifting page rendering away from Custom Templates and into post_content.

Architecture change
-------------------
Before: Custom Templates assigned to each page (page-solution-detail.php
etc.) generated the page HTML at runtime by reading from inc/*-data.php
arrays. WPML had nothing to translate, Bricks Builder had nothing to
edit, the client could only modify content by editing PHP.

After:
- Pages now hold their full Gutenberg HTML inside post_content
- The default page.php template renders the_content() — no Custom
  Templates assigned anymore
- Bricks Builder picks up post_content and converts it to its element
  tree when "Edit with Bricks" is clicked
- WPML Translation Editor exposes every block for translation
- The client can edit pages directly in WP admin

What this commit ships
----------------------
- inc/render-blocks.php: data array → Gutenberg HTML payload generator
  with helpers per section type (prose / cards / list / cta) and per
  page archetype (solution / industry / technology / editorial / form
  / overview hub).
- inc/shortcodes.php: [av_form slug="request-demo"] for dynamic form
  blocks (forms can't live as static HTML — they need nonces and
  per-request state).
- inc/i18n.php: av_lang() / av_t() helpers for inline string translation
  in header.php and footer.php (covers ~80 UI strings); switches based
  on WPML's wpml_current_language filter.
- page.php: minimal default template — get_header() + the_content() +
  get_footer().
- header.php: real WPML language switcher driven by
  wpml_active_languages filter (replaces the placeholder EN · FR
  toggle); UI strings now route through av_t().
- footer.php: same UI string treatment.
- Custom Templates retained but no longer assigned (pages were stripped
  by the migration mu-plugin); they remain available if a page wants
  to opt back into the data-file pattern.

Operational migrations (one-shot mu-plugins, not versioned)
-----------------------------------------------------------
1. asterion-migrate-to-blocks.php walked all 26 PHP-templated pages,
   pre-rendered them via the new render-blocks helpers, wrote the
   result to post_content, and stripped _wp_page_template.
2. asterion-duplicate-fr.php cloned all 35 pages into French via WPML
   API, preserved parent/child hierarchy, linked translations through
   the trid table, marked them as duplicates pending refinement.
3. asterion-fix-fr-slugs.php aligned French slugs with English ones
   (WP's wp_unique_post_slug() had appended -2 suffixes; we bypass
   via $wpdb->update so /fr/solutions/ resolves correctly).

Verified
--------
- All 35 EN URLs return HTTP 200
- All 35 FR URLs return HTTP 200 under /fr/<slug>/
- Language switcher in header outputs correct hreflang links
- WPML emits hreflang en / fr / x-default in <head>
- Body class confirms wp-child-theme-asterion-bricks active
- Bricks frontend CSS still enqueued
- Inter Variable still preloaded

Next steps
----------
- French content is currently the duplicated EN copy. Translate via
  WP admin → WPML → Translation Editor (per-block UI), or edit pages
  directly in /fr/<slug>/ via Gutenberg / Bricks
- WPML String Translation can scan the theme to surface av_t() / __()
  strings for UI-level translation overrides

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 13:11:42 +02:00
70864129ed 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>
2026-05-09 12:41:36 +02:00
45b0b95232 feat(technology): build 7-page Technology section
Implements the Technology hub + 6 pillar detail pages, reusing the
data + partial pattern established for Solutions and Industries.

- inc/technology-data.php: 6 pillars keyed by slug, copy verbatim from
  PDF Strategie & Contenu D.12-D.17 (vr-hardware, software-ai,
  weapons-tracking, scenarios, instructor-cockpit, after-action-review).
- templates/page-technology-detail.php: Custom Template that reuses
  template-parts/industry-detail.php (same hero + sections + conversion
  banner schema works for both industries and technology).
- templates/page-technology-overview.php: hub /technology/ with 6 pillar
  cards (eyebrow numbered 01-06, gold accent).

7 pages seeded by one-shot mu-plugin (asterion-seed-technology.php in
LocalWP). All URLs verified HTTP 200:
  /technology/                      55 KB
  /technology/vr-hardware/          62 KB
  /technology/software-ai/          61 KB
  /technology/weapons-tracking/     57 KB
  /technology/scenarios/            60 KB
  /technology/instructor-cockpit/   59 KB
  /technology/after-action-review/  61 KB

Project tally now: 18 live pages (home + 5 solutions + 5 industries + 7 technology).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 12:31:17 +02:00
eb4a13ec0f feat(industries): build 5-page Industries section
Implements the Industries hub + 4 detail pages (Police, Special Forces,
Military, Firefighters) following the same data + partial + custom
template pattern as Solutions.

- inc/industries-data.php: 4 industries keyed by slug, copy verbatim
  from PDF Strategie & Contenu D.7-D.10.
- template-parts/industry-detail.php: hero + section iterator + shared
  conversion banner. Hero differs from Solution's: eyebrow + tagline-as-H1
  (no trademark concat), no upsell block.
- templates/page-industry-detail.php: Custom Template assigned to the
  4 child pages, looks up slug in industries-data.
- templates/page-industries-overview.php: Hub /industries/ with 4 cards.

5 pages seeded by one-shot mu-plugin (asterion-seed-industries.php in
LocalWP) and verified HTTP 200:
  /industries/                  55 KB
  /industries/police/           63 KB
  /industries/special-forces/   62 KB
  /industries/military/         60 KB
  /industries/firefighters/     60 KB

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 12:27:25 +02:00
8207c5f72b feat(solutions): build 5-page Solutions section
Implements the 5 Solutions pages (1 hub + 4 tier detail) with full EN copy
from PDF Strategie & Contenu D.2-D.6.

Architecture
- inc/solutions-data.php: single PHP array keyed by slug, holds the 4 tiers
  (my-proserve, proserve-flex, proserve-academy, customization). Each tier
  declares its hero, sections, and optional upsell. Section schema supports
  4 types: prose / cards / list / cta.
- template-parts/solution-detail.php: reusable partial that iterates the
  sections of a tier and renders each per its type. Alternates light/dark
  backgrounds for visual rhythm.
- templates/page-solution-detail.php: WP custom Page Template
  ("Template Name: Solution Detail"). Looks up the current page slug,
  pulls the matching tier from solutions-data.php, and hands off to the
  partial. Falls back gracefully if the slug is unknown.
- templates/page-solutions-overview.php: WP custom Page Template
  ("Template Name: Solutions Overview") for /solutions/. Renders the
  3-tier comparison table + PROSERVE+ teaser.

Pages were seeded into the DB by a one-shot mu-plugin
(wp-content/mu-plugins/asterion-seed-solutions.php in LocalWP) that
created the parent /solutions/ page and 4 children with the right
post_parent + _wp_page_template, then self-deleted.

Verified all 5 URLs return HTTP 200:
  /solutions/                  62 KB
  /solutions/my-proserve/      65 KB
  /solutions/proserve-flex/    65 KB
  /solutions/proserve-academy/ 63 KB
  /solutions/customization/    62 KB

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 12:22:34 +02:00
773f137eb7 feat(home): build complete homepage and global templates
Scaffolds all components needed for the home and ships a working
front-page implementation covering the 9-section wireframe.

Components (assets/css/components.css)
- 13 sections per Design Handoff section 3:
  buttons, links, forms, cards (5 variants), stat callouts, header,
  nav, mega menu, drawer, footer, hero, logo strip, eyebrow,
  section title/lead, conversion banner, scroll reveal.
- All token-driven, prefixed `av-`, BEM-light. Mobile-first with
  768/1024/1280 breakpoints. Respects prefers-reduced-motion.

Global templates
- header.php: sticky header (60px mobile / 72px desktop), 5-item
  nav, language switcher, primary CTA, mobile drawer with hamburger
  toggle. Skip link first focusable element.
- footer.php: 5-column dark footer (Solutions, Industries, Why
  Asterion, Why Asterion, Newsletter), bottom strip with legal
  links + social.
- index.php: archive/search/blog fallback rendering posts in
  card-blog layout.
- front-page.php: full home with 9 sections, EN copy lifted
  verbatim from PDF Strategie D.1:
    1. Hero "Your Last Mistake Should Be in VR." + 2 CTAs
    2. Trust bar (placeholder logos + 4 inline metrics)
    3. Solutions: MY / FLEX / ACADEMY (3 cards)
    4. Industries: Police / SF / Military / Firefighters (2x2)
    5. Feature heroes: UWeD, Instructor Cockpit, AAR (alternating)
    6. Featured case study with 3 stat callouts
    7. Testimonials (3 quote cards)
    8. Latest insights (queries `post`; placeholder when empty)
    9. Conversion banner (Demo / T&E / Quote)

Verified: HTTP 200 on http://localhost:10004/, 73 KB HTML, 418 ms.

Outstanding (deferred)
- Hero video master + photographs (see MISSING-ASSETS.md)
- Mega menu content (links currently flat to section index)
- Form posts (newsletter currently no-op POST)
- Bricks license activation (manual, requires user key)
- WPML setup wizard (manual, requires user key)
- Lighthouse + axe full audit (visual env required)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 12:08:43 +02:00
6f62082dc4 feat(child-theme): scaffold asterion-bricks v0.1.0
Initial child theme structure inheriting from Bricks parent. Token-driven,
RGPD-native, mobile-first foundation ready for component and template work.

What's in this commit
- style.css: WP theme metadata (Template: bricks, v0.1.0)
- functions.php: enqueue cascade tokens -> utilities -> components,
  defer-loaded main.js, font preload, theme support, image sizes
  (av-hero 2400x1350, av-card 800x600, av-thumb 400x300), Gutenberg
  default styles dequeued
- theme.json: Gutenberg color/typo palette mirroring tokens
- assets/css/tokens.css: full design system per Design Handoff section 2
  (brand colors, neutrals, semantics, type scale + line-heights, 8pt
  spacing, radii, shadows, z-index, motion, prefers-reduced-motion)
- assets/css/utilities.css: modern reset + .av-container, .av-skip-link,
  .av-sr-only, .av-stack, .av-section helpers, opinionated heading scale
- assets/css/components.css: index of planned components + buttons
  (5 variants x 4 sizes per Design Handoff section 3.1) and links
- assets/js/main.js: vanilla skeleton with header scroll, IntersectionObserver
  reveal, count-up, mobile drawer; respects prefers-reduced-motion
- inc/cpt.php: register_post_type case_study (slug /customers/) + scenario
  (slug /scenarios/) + shared 'industry' taxonomy
- inc/seo.php: Organization JSON-LD on home; placeholders for Product,
  Article, FAQPage, BreadcrumbList
- assets/fonts/: Inter Variable + Italic WOFF2 self-hosted (RGPD; no
  Google Fonts CDN). Inter Display @font-face commented — Inter 4+ uses
  opsz axis from the same file.

Out of scope (intentionally deferred)
- Component fills: cards, forms, navigation, alerts, modals, tabs (placeholders)
- Page templates: home and beyond
- Bricks JSON template exports
- Schema.org Product / Article / FAQPage / BreadcrumbList implementations

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 11:49:10 +02:00
f9192631ff chore: initial repo setup with project brief, design specs and base docs
- BRIEF-Claude-Code.md: Claude Code start brief (13 sections)
- 2 PDF deliverables: Strategie & Contenu (84p) + Design Handoff (31p)
- README.md: project overview, local setup, structure, conventions
- MISSING-ASSETS.md: live tracker for missing media (hero video, photos, logos)
- .gitignore: excludes ThirdParty/ (commercial plugin ZIPs), PDF text extracts, WP runtime

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 11:39:42 +02:00