Files
weval-l99/wevia-site-builder.php.bak-post-unmerge
opus-wire 7f67eb6bdf auto-push
2026-04-18 14:33:55 +02:00

1347 lines
100 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
// wevia-site-builder.php v2.0 — 2026-04-18 — Phase B1 doctrine 108 §9 (light default + toggle)
// Génère pages produit WEVAL en thème clair par défaut avec toggle jour/nuit
declare(strict_types=1);
const FORBIDDEN_TERMS = [
'Abbott', 'AbbVie', 'Johnson & Johnson', 'Johnson and Johnson',
'Servier', 'Rim Pharma', 'IQVIA', "L'Oréal", 'LVMH', 'Nestlé',
'Chanel', 'Carrefour', 'Intermarché', 'Michelin', 'Valeo', 'Safran',
'Vinci', 'Bombardier', 'Faiveley', 'RATP', 'Geodis', 'Deloitte', 'PwC',
'CGI', 'Sage', 'Markem', 'Givaudan', 'Lesaffre', 'Nocibe', 'Fnac',
'Pixmania', 'Shell', 'Total', 'Daher', 'Telenor', 'SNTL', 'Saham Bank',
'OCP Group', 'Reunicaa',
'SAP Gold', 'Gold Partner',
'Paperclip', 'DeerFlow', 'MiroFish', 'OSS Discovery', 'Cowork',
'131K+', '131000', '131 000', 'Tunisie · Maroc · Algérie',
'TN/MA/DZ', 'TN · MA · DZ',
];
const PRODUCTS = [
'arsenal' => [
'name' => 'Arsenal',
'tagline' => 'Framework ERP Intelligence - Fill-Gap, IA, Reporting',
'suite' => 'WEVAL ERP Intelligence',
'accent' => 'gold',
'badge' => 'FLAGSHIP - Framework ERP en production',
'h1_a' => 'Votre ERP fait 80%.',
'h1_b' => 'Arsenal fait les <em>20% manquants</em>.',
'desc' => "Framework ERP Intelligence propriétaire WEVAL. 150+ écrans modulaires, Brain Engine IA embarqué, reporting temps réel, orchestration des gaps. Se branche sur n'importe quel ERP (SAP, Oracle, Odoo, Salesforce, custom) pour combler les manques fonctionnels sans remplacer l'existant. Déploiement incrémental, ROI mesuré à chaque écran activé.",
'stats' => [['150+', 'Écrans modulaires'], ['Cross-ERP', 'SAP, Oracle, Odoo...'], ['Brain Engine', '646 configs IA'], ['Déploiement', 'Incrémental']],
'features' => [
['Écrans modulaires', "Catalogue de 150+ écrans métiers prêts à activer : finance, RH, achats, production, supply, qualité, reporting exécutif."],
['Cross-ERP natif', "Connecteurs SAP (RFC, oData), Oracle, Odoo, Salesforce, APIs REST. Même framework, multi-backends simultanés."],
['Brain Engine IA', "646 configurations IA pré-packagées par secteur et taille. Apprentissage continu sur vos données métier."],
['Reporting temps réel', "Dashboards live, alertes intelligentes, exports multi-formats, intégration Power BI/Tableau/Qlik."],
['Déploiement progressif', "Activation écran par écran, ROI mesuré à chaque étape, pas de big-bang, pas de rupture de service."],
['Gouvernance unifiée', "SSO, RBAC granulaire, audit trail complet, conformité RGPD et AI Act, traçabilité métier native."],
],
],
'wevanalytics' => [
'name' => 'WEVANALYTICS',
'tagline' => 'Analytics cross-ERP - Du datalake à la décision',
'suite' => 'WEVAL ERP Intelligence',
'accent' => 'gold',
'badge' => 'Analytics Intelligence - Production',
'h1_a' => 'Tous vos systèmes parlent',
'h1_b' => 'un <em>même langage analytique</em>.',
'desc' => "Plateforme analytics cross-ERP et cross-datasources. Unifie vos données issues de SAP, Oracle, Odoo, CRM, datalake, fichiers plats dans un même modèle sémantique. Dashboards self-service, alertes intelligentes, requêtes en langage naturel, prédictions embarquées. Remplace ou complète Power BI, Tableau, Qlik.",
'stats' => [['Cross-ERP', 'Multi-sources unifiées'], ['NL queries', 'Langage naturel'], ['Alertes IA', 'Prédictives'], ['Temps réel', 'Streaming']],
'features' => [
['Modèle sémantique unifié', "Mappings métiers pré-construits pour SAP, Oracle, Odoo, Salesforce. Une seule définition du CA, du stock, du coût par entité."],
['NL Queries', "Posez vos questions en français ou anglais, obtenez graphiques et tables. Pas besoin de SQL, plus d'intermédiaires techniques."],
['Alertes prédictives IA', "Détection d'anomalies temps réel, prévision de ruptures stock, scoring risque client, alerting proactif au bon niveau."],
['Dashboards self-service', "Glisser-déposer, templates métier, personnalisation par rôle, export PDF/PNG/Excel automatisé."],
['Temps réel & streaming', "Synchronisation CDC depuis ERP, événements Kafka, mise à jour sub-seconde des visualisations critiques."],
['Intégration BI', "Export vers Power BI, Tableau, Qlik en parallèle. Pas de remplacement forcé, enrichissement de l'existant."],
],
],
'agents-gaps' => [
'name' => 'Agents Gaps',
'tagline' => 'Agents IA spécialisés par lacune ERP',
'suite' => 'WEVAL ERP Intelligence',
'accent' => 'gold',
'badge' => 'IA Agents - Gap Closing',
'h1_a' => 'Un agent IA,',
'h1_b' => '<em>par gap business</em>.',
'desc' => "Catalogue d'agents IA spécialisés, chacun conçu pour combler une lacune ERP connue. Rapprochement bancaire intelligent, matching fournisseurs-factures, scoring crédit clients, prévision de demande, optimisation stock multi-sites, gestion des exceptions supply chain, réconciliation intercos, audit automatisé. Déploiement par agent, ROI à 3 mois.",
'stats' => [['30+', "Agents catalogue"], ['Cross-ERP', 'API-first'], ['Déploiement', '2 à 6 semaines / agent'], ['ROI', '3 mois moyen']],
'features' => [
['Rapprochement bancaire', "Agent de matching relevés bancaires vs écritures ERP. Règles apprises, taux auto-rapprochement >95% après 30 jours."],
['Matching fournisseurs-factures', "Agent 3-way matching (PO-BL-facture). Tolérances adaptatives, gestion écarts, workflow de validation intelligent."],
['Scoring crédit clients', "Agent temps réel qui score la solvabilité clients, combine data interne + externe, propose limites et conditions."],
['Prévision demande', "Agent forecasting multi-modèle (ARIMA, Prophet, LSTM ensembles), détection saisonnalités, ajustement promotions."],
['Optimisation stock', "Agent multi-sites qui arbitre réassort, transferts, safety stocks selon SLA et contraintes logistiques."],
['Exceptions supply chain', "Agent de gestion proactive des retards livraison, détection de risques, propositions d'alternatives fournisseurs."],
['Réconciliation intercos', "Agent intercompagnies : détection d'écarts, rapprochement automatique, préparation clôture multi-entités."],
['Audit continu', "Agent audit automatisé sur contrôles clés (ségrégation tâches, accès sensibles, dépassements seuils, dormance comptes)."],
['Extensible via API', "Chaque agent = une API. Intégration webhook, planification cron, orchestration via WEVIA Master possible."],
],
],
'wevia-em' => [
'name' => 'WEVIA EM',
'tagline' => "Enterprise Model - L'IA souveraine qui orchestre la valeur de bout en bout",
'suite' => 'WEVIA Enterprise',
'accent' => 'purple',
'badge' => 'FLAGSHIP - Enterprise Model - En production',
'h1_a' => "L'IA souveraine qui",
'h1_b' => "<em>orchestre la valeur</em> de bout en bout.",
'desc' => "Plateforme d'orchestration multi-agents IA qui couvre l'intégralité de votre value chain et de vos process métier. Finance, RH, Marketing, Commerce, Supply Chain, Achats, Production, SI, QA et Cyber — un seul Brain Center, piloté par votre comex. Lean Six Sigma et BPMN intégrés, méthodologie DMAIC, déploiement on-premise. Vos données restent chez vous.",
'stats' => [['9', 'Metiers orchestres'], ['-40%', 'Delais de pilotage'], ['ROI', '4 mois moyen'], ['6sigma', 'DMAIC zero regression']],
'features' => [
['Finance', "P and L, previsions, facturation et audit automatises. Cloture mensuelle accélérée, consolidation multi-entites, alertes derives en temps reel."],
['RH and Talents', "Sourcing, onboarding, formation et gestion des talents. Agents de matching, parcours d'integration, developpement des competences automatises."],
['Marketing', "Ciblage, creation de contenu, campagnes et analytics en continu. Optimisation budget, A/B testing industriel, attribution multi-touch."],
['Commerce', "Qualification de leads, redaction de proposals, CRM et closing. Agents commerciaux specialises par secteur, scoring IA, handover fluide."],
['Supply Chain', "Collecte, enrichissement, routage et livraison. Previsions demande, optimisation stock, suivi transport, alertes rupture."],
['Achats', "RFP, evaluation fournisseurs, negociation et contrats. Sourcing automatise, scoring risque, benchmarks marche continus."],
['Production', "Qualite, assemblage, tests et expedition. Controle qualité vision IA, maintenance predictive, optimisation OEE."],
['SI and Infrastructure', "Monitoring, déploiement, scaling et sécurité. Observability IA, auto-remediation, rightsizing cloud, DevOps augmente."],
['QA and Cybersecurity', "Tests automatises, audits, patching et conformité. SAST/DAST IA, threat intelligence, compliance continue RGPD et AI Act."],
],
],
'wevia-master' => [
'name' => 'WEVIA Master',
'tagline' => 'IA autonome propriétaire — orchestration multi-agents',
'suite' => 'WEVIA Enterprise',
'accent' => 'teal',
'badge' => 'IA Souveraine · En production',
'h1_a' => "L'agent qui <em>exécute</em>.", 'h1_b' => 'Pas juste répond.',
'desc' => 'Agent IA autonome propriétaire. Ne se contente pas de conseiller : scanne votre infrastructure, exécute des décisions contrôlées, apprend en continu sur votre domaine métier. Cascade multi-modèles intelligente pour combiner performance, coût maîtrisé et souveraineté des données.',
'stats' => [['Multi-model', 'Cascade intelligente'], ['Sovereign', 'EU certified'], ['<200ms', 'Latence médiane'], ['6σ', 'Qualité L99']],
'features' => [
['Orchestration multi-agents', 'Décompose les demandes complexes en sous-tâches distribuées sur agents spécialisés.'],
['Exécution contrôlée', 'Actions réelles avec journalisation, audit trail complet et gouvernance fine.'],
['Raisonnement métier', 'Fine-tuning possible sur votre domaine pour précision supérieure aux modèles génériques.'],
['Intégration système', 'API REST, webhooks, SSE streaming, hooks dans CRM, ERP, Slack, email, outils internes.'],
['Cascade souveraine', 'Combine plusieurs providers IA avec fallback intelligent, optimisation coût-qualité dynamique.'],
['Monitoring natif', 'Dashboard temps réel, métriques Six Sigma, alerting proactif sur dérive de qualité.'],
],
],
'wevia-inference' => [
'name' => 'WEVIA Inference',
'tagline' => 'GPU dédié souverain · multi-modèles',
'suite' => 'WEVIA Enterprise',
'accent' => 'teal',
'badge' => 'Infrastructure IA · Haute disponibilité',
'h1_a' => 'Inférence IA <em>sans compromis</em>',
'h1_b' => 'sur vos données.',
'desc' => "Plateforme d'inférence IA sur GPU dédiés, hébergée en souveraineté européenne. Déploiement multi-modèles (LLMs, vision, embeddings), API compatible OpenAI, zéro exfiltration, SLA 100%.",
'stats' => [['GPU dédié', 'A100 · H100'], ['EU Sovereign', 'Certifié'], ['API compatible', 'OpenAI spec'], ['100%', 'SLA garanti']],
'features' => [
['GPUs dédiés premium', 'A100 et H100 allouées exclusivement à vos workloads, aucun partage multi-tenant.'],
['Multi-modèles unifié', "LLMs, vision, audio, embeddings — une seule API pour tous les cas d'usage."],
["API drop-in OpenAI", "Migration depuis OpenAI en changeant uniquement l'URL endpoint, aucun refactor code."],
['Souveraineté stricte', 'Données et modèles hébergés en Europe, conformité RGPD, AI Act et HDS.'],
['Scaling automatique', 'Autoscaling horizontal basé sur la charge, facturation au token consommé.'],
['Fine-tuning intégré', 'Entraînement domaine métier sur vos données, versioning et rollback des modèles.'],
],
],
'projectflow' => [
'name' => 'ProjectFlow',
'tagline' => 'Orchestration projets &amp; agents IA',
'suite' => 'WEVIA Enterprise',
'accent' => 'teal',
'badge' => 'Project Intelligence · Live',
'h1_a' => 'Vos projets,',
'h1_b' => '<em>orchestrés par IA.</em>',
'desc' => "Plateforme de gestion de projets augmentée par agents IA. Planification, suivi d'objectifs, orchestration d'équipes hybrides humains-agents, reporting temps réel sur avancement et bloquants.",
'stats' => [['Agents IA', 'Spécialisés par rôle'], ['SSE', 'Streaming temps réel'], ['Kanban', '+ Agents'], ['RACI', 'Auto-généré']],
'features' => [
['Équipes hybrides', 'Humains et agents IA travaillent sur les mêmes tâches, coordination fluide.'],
['Goals &amp; OKRs', "Objectifs mesurables, suivi d'avancement, alertes dérive, boucles de rétroaction."],
['Dashboard temps réel', "Vue directeur de l'avancement global, des risques, des décisions en attente."],
['Auto-RACI', 'Matrice responsabilités générée automatiquement depuis la structure du projet.'],
['Intégration native', "Connecteurs Jira, GitHub, Slack, Gmail, Teams — pas de silo d'information."],
['Audit trail', 'Traçabilité complète des décisions, idéal pour environnements réglementés.'],
],
],
'researchflow' => [
'name' => 'ResearchFlow',
'tagline' => 'Recherche multi-agents approfondie',
'suite' => 'WEVIA Enterprise',
'accent' => 'teal',
'badge' => 'Research Intelligence · Live',
'h1_a' => 'La recherche approfondie,',
'h1_b' => '<em>automatisée.</em>',
'desc' => 'Moteur de recherche multi-agents. Décompose une question complexe en sous-requêtes, explore sources publiques et internes, synthétise un rapport structuré avec citations vérifiables.',
'stats' => [['Multi-agents', 'Spécialisés'], ['Sources', 'Web + interne'], ['Citations', 'Vérifiables'], ['Markdown', 'Structuré']],
'features' => [
['Décomposition automatique', "Une question complexe devient un arbre de sous-questions explorées en parallèle."],
['Sources internes &amp; web', 'Combine votre base documentaire privée avec les sources publiques crédibles.'],
['Citations vérifiables', "Chaque affirmation liée à sa source, lien direct, extraction du passage original."],
['Rapport Markdown', "Livrable structuré prêt à l'emploi : exec summary, détails, annexes, bibliographie."],
['Vérification croisée', 'Triangulation automatique des informations entre sources pour fiabilité.'],
['Export multi-format', 'PDF, Word, Notion, Confluence — intégration dans vos flux existants.'],
],
],
'boardflow' => [
'name' => 'BoardFlow',
'tagline' => 'Whiteboard collaboratif intelligent',
'suite' => 'WEVIA Enterprise',
'accent' => 'teal',
'badge' => 'Collaboration · Live',
'h1_a' => 'Le whiteboard',
'h1_b' => '<em>qui pense avec vous.</em>',
'desc' => "Tableau collaboratif visuel augmenté par IA. Brainstorming, architecture, mind-mapping, process design. L'IA suggère, structure, reformule, détecte les angles morts en temps réel.",
'stats' => [['Temps réel', 'Multi-user'], ['IA intégrée', 'Contextuelle'], ['Templates', 'Design thinking'], ['Export', 'Multi-format']],
'features' => [
['Canvas infini', 'Espace visuel illimité pour sketches, diagrammes, notes, connexions, structures.'],
['Co-création IA', "L'agent propose, restructure, consolide, détecte les incohérences en temps réel."],
['Templates métier', 'Bibliothèque de patterns : design thinking, BPMN, architecture, product canvas.'],
['Présence multi-user', 'Curseurs temps réel, voix-vidéo embarquée, mode focus ou revue synchrone.'],
['Versioning', 'Historique complet des évolutions, fork et merge de branches créatives.'],
['Intégration outils', 'Import depuis Figma, Lucidchart, Visio ; export multi-format.'],
],
],
'stackscan' => [
'name' => 'StackScan',
'tagline' => 'Audit &amp; inventaire OSS entreprise',
'suite' => 'WEVIA Enterprise',
'accent' => 'teal',
'badge' => 'Open Source Discovery · Live',
'h1_a' => 'Votre stack open source,',
'h1_b' => '<em>en pleine lumière.</em>',
'desc' => 'Scanner et cartographe de votre écosystème open source. Détecte dépendances, licences, vulnérabilités, versions obsolètes. Recommandations de remédiation priorisées par impact et effort.',
'stats' => [['Licences', 'SPDX complet'], ['CVE', 'Temps réel'], ['SBOM', 'CycloneDX'], ['Priorisation', 'Impact × effort']],
'features' => [
['SBOM automatique', 'Génération Software Bill of Materials au format CycloneDX ou SPDX, exports continus.'],
['Licences &amp; conformité', "Détection de toutes licences, alertes sur incompatibilités et contraintes juridiques."],
['CVE temps réel', 'Scanning continu des vulnérabilités, alertes proactives, corrélation avec contexte.'],
['Priorisation intelligente', "Impact business × effort de remédiation = file d'attente d'actions claire."],
['Intégration CI/CD', 'Hooks GitHub Actions, GitLab CI, Jenkins — bloque les déploiements non conformes.'],
['Dashboard exécutif', 'Vue directeur du risque OSS, tendances, score santé de chaque composant métier.'],
],
],
'wevia-desk' => [
'name' => 'WEVIA Desk',
'tagline' => 'Automatisation bureautique par IA',
'suite' => 'WEVIA Enterprise',
'accent' => 'teal',
'badge' => 'Desktop Automation · Live',
'h1_a' => "L'agent qui pilote", 'h1_b' => '<em>votre poste de travail.</em>',
'desc' => "Agent IA desktop. Automatise tâches répétitives : tri d'emails, extraction de données, remplissage de formulaires, génération de livrables. Contrôle des applications natives via API ou vision.",
'stats' => [['Native apps', 'Contrôle direct'], ['Vision IA', 'OCR + reconnaissance'], ['Workflows', 'Low-code'], ['Audit', 'Log complet']],
'features' => [
['Contrôle natif', "Pilote Excel, Word, Outlook, navigateur, applications métier via API ou automation visuelle."],
['Vision IA intégrée', 'OCR et reconnaissance visuelle pour interagir avec interfaces legacy sans API.'],
['Workflows low-code', "Éditeur visuel pour orchestrer des séquences complexes sans savoir coder."],
['Déclencheurs contextuels', 'Actions lancées sur email reçu, fichier déposé, heure, événement calendrier.'],
['Mode supervisé', "Validation humaine requise pour actions sensibles, audit trail exhaustif."],
['Déploiement groupé', 'Rollout sur parc de postes avec gouvernance centrale, policies par rôle.'],
],
],
'wevia-life' => [
'name' => 'WEVIA Life',
'tagline' => 'Classification IA des emails professionnels',
'suite' => 'WEVIA Enterprise',
'accent' => 'teal',
'badge' => 'Email Intelligence - En production',
'h1_a' => 'Vos emails,',
'h1_b' => '<em>classifies et actionnables.</em>',
'desc' => "Agent IA qui analyse vos emails professionnels en continu. Classification multi-axes : opportunités business, risques, actions requises. Chat RAG sur l'historique, extraction automatique de décisions, deadlines, engagements. Intégration IMAP multi-comptes, aucune donnée exposée à l'extérieur.",
'stats' => [['Multi-compte', 'IMAP natif'], ['Classification', 'Opportunite / Risque / Action'], ['RAG chat', 'Historique complet'], ['Souverain', 'Hosting EU']],
'features' => [
['Classification multi-axes', "Chaque email score sur 3 dimensions : opportunité commerciale, risque business, action requise. Priorisation automatique."],
['Extraction de décisions', 'Détection des engagements pris, deadlines mentionnées, livrables attendus — consolidés dans un journal actionnable.'],
['Chat RAG emails', 'Posez des questions en langage naturel sur votre historique email. Retrouvez contexte, pièces jointes, fils de discussion.'],
['IMAP multi-comptes', 'Connexion native IMAP, support multi-boîtes, synchronisation continue. OAuth2 et app-passwords supportés.'],
['Attachments intelligents', 'OCR et parsing de pièces jointes (PDF, Word, Excel) — contenu indexé et recherchable.'],
['Alerts et digests', 'Notifications ciblées sur opportunités et risques critiques. Digest quotidien synthétique pour le comex.'],
],
],
'wevia-white-label' => [
'name' => 'WEVIA White-Label',
'tagline' => 'Deployer WEVIA sous votre marque',
'suite' => 'WEVIA Enterprise',
'accent' => 'teal',
'badge' => 'Multi-tenant White-Label - Enterprise',
'h1_a' => 'Votre IA souveraine,',
'h1_b' => '<em>votre marque.</em>',
'desc' => "Déployez la stack WEVIA sous votre propre branding. Thème custom, domaine dédié, kit de marque intégré, isolation tenant stricte. Idéal pour intégrateurs, éditeurs logiciels, cabinets de conseil qui veulent revendre WEVIA à leurs clients. Gouvernance centralisée, billing unifié.",
'stats' => [['Branding', 'Thème + domaine + logo'], ['Multi-tenant', 'Isolation stricte'], ['Billing', 'Unifie ou per-tenant'], ['Gouvernance', 'Centralisee']],
'features' => [
['Theming complet', 'Couleurs, typographie, logo, favicon, images marketing personnalisables sans code.'],
['Domaine dedie', 'Chaque déploiement sur votre sous-domaine ou domaine client, SSL automatique, CDN intégré.'],
['Isolation tenant', 'Données, modèles fine-tunés, historique conversations strictement séparés entre tenants.'],
['Kit de marque', 'Emails transactionnels, PDF générés, dashboards exportés adoptent automatiquement votre charte.'],
['Billing flexible', 'Facturation unifiée pour vous ou refacturation au tenant final via API de gestion.'],
['Support partenaire', 'SLA dédié, documentation blanche, onboarding partenaires, programme revenue-share.'],
],
],
'consulting-pro' => [
'name' => 'Consulting Pro',
'tagline' => 'Conseil senior à la demande — interventions cadrées ROI',
'suite' => 'WEVAL Advisory',
'accent' => 'purple',
'badge' => 'Conseil Senior — Engagement ROI',
'h1_a' => "Un directeur d'expérience",
'h1_b' => 'à votre <em>table de direction.</em>',
'desc' => "Interventions de conseil senior à la demande. Directeurs techniques, architectes IA, DSI transformés. Missions cadrées sur KPIs contractuels, engagement au ROI, livrables mesurables. Idéal pour dé-risquer une transformation, arbitrer une stack technique, ou cadrer un programme stratégique. Facturation au forfait mission ou au jour-homme.",
'stats' => [['10+', 'Années expérience minimum'], ['ROI', 'Contractuel'], ['KPIs', 'Mesurables'], ['Europe', '+ MENA']],
'features' => [
['Diagnostic flash', 'Audit express 2 à 5 jours pour cartographier enjeux, risques et opportunités. Livrable directeur exécutif actionnable.'],
['Sparring strategique', 'Conseiller senior disponible en continu pour arbitrer décisions critiques : stack IA, governance data, transformation ERP.'],
['Architecture &amp; design', "Revue d'architectures techniques, recommandations d'évolution, validation choix stratégiques par des experts cloud et IA."],
['Program management', "Direction de programme par un PMP senior. Coordination multi-équipes, gestion des risques, reporting executive COMEX."],
['Due diligence', "Due diligence technique sur acquisitions ou investissements tech. Audit code, infrastructure, équipe, dette technique, scalability."],
['Fractional leadership', 'CTO, CIO, CDO à temps partagé pour PME et scale-ups. 2 à 4 jours par semaine, engagement 6 à 12 mois minimum.'],
],
],
'reachhcp' => [
'name' => 'ReachHCP',
'tagline' => 'Base HCP mondiale · consent-based',
'suite' => 'WEVAL Pharma Cloud',
'accent' => 'coral',
'badge' => 'Healthcare Intelligence · Live',
'h1_a' => 'Les professionnels de santé,',
'h1_b' => '<em>atteints dans les règles.</em>',
'desc' => "Base de données de professionnels de santé vérifiés, consent-based, couverture mondiale. Segmentation fine par spécialité, zone, typologie d'exercice. Conformité RGPD, HDS, exports auditables.",
'stats' => [['Mondial', 'Multi-continents'], ['Consent', 'Opt-in vérifié'], ['RGPD', '+ HDS'], ['Update', 'Continu']],
'features' => [
['Couverture mondiale', "Europe, Amériques, MENA, Asie — spécialistes hospitaliers et libéraux, tous secteurs."],
['Consent-based strict', 'Opt-in vérifié source, traçabilité complète, retrait à tout moment, conformité maximale.'],
['Segmentation fine', "Spécialité, sous-spécialité, zone géographique, typologie d'exercice, affiliation."],
['Enrichissement continu', 'Mises à jour en continu, détection automatique des changements, déduplication ML.'],
['Exports auditables', "Logs complets de chaque extraction, justification du consent, preuves horodatées."],
['API temps réel', 'REST et GraphQL pour intégration CRM, automation marketing, analytics.'],
],
],
'campaign-studio' => [
'name' => 'Campaign Studio',
'tagline' => 'Création &amp; orchestration campagnes pharma',
'suite' => 'WEVAL Pharma Cloud',
'accent' => 'coral',
'badge' => 'Pharma Campaigns · Live',
'h1_a' => 'La campagne omnicanale,',
'h1_b' => '<em>compliant by design.</em>',
'desc' => "Studio de création et orchestration de campagnes pharma. Assets conformes (validation médicale embarquée), multicanal (email, print, meetings, digital), tracking conforme, reporting exécutif.",
'stats' => [['Multicanal', 'Email · Print · Live'], ['Validation', 'Médicale auto'], ['Compliance', 'Track complet'], ['ROI', 'Vue exec']],
'features' => [
['Studio de création', "Éditeur visuel avec bibliothèque d'assets, templates validés, versioning complet."],
['Validation médicale', 'Workflow de relecture obligatoire, audit trail, signature électronique des MRL.'],
['Orchestration multicanal', 'Une séquence = email + courrier + meeting + push — cadencement intelligent.'],
['Tracking compliant', "Attribution fine conforme RGPD, pas de cookies tiers, pixels propriétaires."],
['Dashboard ROI', "Vue exécutive par campagne, par produit, par territoire, par spécialité."],
['A/B testing rigoureux', "Plans d'expérience statistiquement signifiants, significance testing intégré."],
],
],
'consent-manager' => [
'name' => 'Consent Manager',
'tagline' => 'Gestion du consentement B2B healthcare',
'suite' => 'WEVAL Pharma Cloud',
'accent' => 'coral',
'badge' => 'B2B Consent · Live',
'h1_a' => 'Le consentement professionnel,',
'h1_b' => '<em>géré comme un asset.</em>',
'desc' => "Plateforme de gestion du consentement B2B pour les interactions avec professionnels de santé. Collecte, stockage horodaté, retrait, audit, preuve légale. Conformité RGPD, LPD, LGPD, CCPA.",
'stats' => [['Multi-juridictions', 'RGPD · LPD · LGPD'], ['Preuve', 'Horodatée'], ['Retrait', 'Un clic'], ['Audit', 'Exports complets']],
'features' => [
['Collecte multi-canal', "Formulaires web, mobile, print avec QR, signature électronique, validation téléphonique."],
['Stockage horodaté', "Chaque consent ou refus daté, sourcé, signé — preuve juridique opposable."],
['Retrait en un clic', "Liens de désinscription dans chaque communication, propagation immédiate aux systèmes."],
['Audit trail complet', "Qui, quoi, quand, depuis où — exports complets à la demande d'un régulateur."],
['Conformité multi-juridictions', 'RGPD européen, LPD suisse, LGPD brésilien, CCPA californien, mises à jour continues.'],
['API temps réel', 'Hooks vers CRM, marketing automation, data warehouse — synchro sub-seconde.'],
],
],
];
const SUITES = [
'WEVIA Enterprise' => [
'slug' => 'wevia-enterprise',
'desc' => "L'écosystème d'IA souveraine propriétaire WEVAL. Agent autonome, inférence GPU dédiée, orchestration multi-agents, whiteboard collaboratif, audit de stack, automatisation desktop — une stack complète, interopérable, souveraine.",
'siblings' => ['WEVIA EM', 'WEVIA Master', 'WEVIA Inference', 'WEVIA Life', 'WEVIA White-Label', 'ProjectFlow', 'ResearchFlow', 'BoardFlow', 'Blade AI', 'StackScan', 'WEVIA Desk'],
],
'WEVAL Pharma Cloud' => [
'slug' => 'pharma-cloud',
'desc' => "Suite dédiée aux sciences de la vie et à l'industrie pharmaceutique. Base HCP mondiale consent-based, CRM pharma, studio de campagnes compliant, gestion du consentement, dashboard exécutif.",
'siblings' => ['ReachHCP', 'ReachHCP API', 'Healthcare CRM', 'Campaign Studio', 'HCP Dashboard', 'Consent Manager'],
],
];
// Light + Dark accent palettes (per suite)
const ACCENTS = [
'teal' => ['light' => '#0d9488', 'dark' => '#00c9a7', 'soft_l' => 'rgba(13,148,136,.08)', 'soft_d' => 'rgba(0,201,167,.12)'],
'purple' => ['light' => '#6f5cff', 'dark' => '#7c5cfc', 'soft_l' => 'rgba(111,92,255,.08)', 'soft_d' => 'rgba(124,92,252,.12)'],
'gold' => ['light' => '#b88a2e', 'dark' => '#f0c674', 'soft_l' => 'rgba(184,138,46,.08)', 'soft_d' => 'rgba(240,198,116,.12)'],
'coral' => ['light' => '#dc3e3e', 'dark' => '#ff6b6b', 'soft_l' => 'rgba(220,62,62,.08)', 'soft_d' => 'rgba(255,107,107,.12)'],
];
function get_template(): string {
return <<<'HTML'
<!DOCTYPE html>
<html lang="fr" data-theme="light"><head>
<link rel="icon" href="/favicon.ico" type="image/x-icon">
<link rel="apple-touch-icon" href="/apple-touch-icon.png">
<meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>{{NAME}} — {{TAGLINE}} | WEVAL Consulting</title>
<meta name="description" content="{{NAME}} — {{DESC_SHORT}} Part of {{SUITE}} suite.">
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=Space+Mono:wght@400;700&display=swap" rel="stylesheet">
<script>(function(){var t=localStorage.getItem('weval-theme')||'light';document.documentElement.setAttribute('data-theme',t);})();</script>
<style>
:root{--bg:#ffffff;--bg-alt:#fafbfc;--surface:#ffffff;--text:#1a1f3a;--text-soft:#5a6480;--text-dim:#8893a8;--border:rgba(26,31,58,.08);--border-mid:rgba(26,31,58,.14);--shadow:0 1px 3px rgba(26,31,58,.04),0 8px 24px rgba(26,31,58,.04);--shadow-hover:0 2px 6px rgba(26,31,58,.06),0 16px 40px rgba(26,31,58,.08);--a:{{A_LIGHT}};--a-soft:{{A_SOFT_L}};--btn-p:#5b4cdb;--btn-p-h:#4a3dc4}
html[data-theme="dark"]{--bg:#05080f;--bg-alt:#080c18;--surface:#0c1222;--text:#edf2f7;--text-soft:#a8b4c8;--text-dim:#7a8ba5;--border:rgba(255,255,255,.06);--border-mid:rgba(255,255,255,.12);--shadow:0 1px 3px rgba(0,0,0,.3),0 8px 24px rgba(0,0,0,.3);--shadow-hover:0 2px 6px rgba(0,0,0,.4),0 16px 40px rgba(0,0,0,.4);--a:{{A_DARK}};--a-soft:{{A_SOFT_D}};--btn-p:#7c5cfc;--btn-p-h:#9277ff}
*{margin:0;padding:0;box-sizing:border-box}
html{scroll-behavior:smooth}
body{font-family:'Inter',sans-serif;background:var(--bg);color:var(--text);-webkit-font-smoothing:antialiased;transition:background .3s,color .3s}
body::before{content:'';position:fixed;inset:0;background-image:radial-gradient(circle at 20% 10%,var(--a-soft) 0%,transparent 40%),radial-gradient(circle at 80% 60%,var(--a-soft) 0%,transparent 45%);pointer-events:none;opacity:.6;z-index:-1;transition:opacity .3s}
nav{position:fixed;top:0;width:100%;padding:1rem 4%;display:flex;justify-content:space-between;align-items:center;z-index:100;backdrop-filter:blur(20px);background:color-mix(in srgb,var(--bg) 85%,transparent);border-bottom:1px solid var(--border)}
.logo{font-weight:800;font-size:1.35rem;letter-spacing:-.035em;display:flex;align-items:center;gap:.5rem;color:var(--text);text-decoration:none}
.logo-dot{width:10px;height:10px;border-radius:50%;background:var(--a);box-shadow:0 0 18px var(--a-soft)}
.nav-r{display:flex;gap:1.6rem;align-items:center}
.nav-r a{color:var(--text-soft);text-decoration:none;font-size:.86rem;font-weight:500;transition:color .25s}
.nav-r a:hover{color:var(--a)}
.btn-n,a.btn-n{background:var(--btn-p) !important;color:#ffffff !important;padding:.6rem 1.3rem;border-radius:8px;font-weight:600;font-size:.84rem;text-decoration:none !important;transition:all .2s;border:none;cursor:pointer;display:inline-block}
.btn-n:hover,a.btn-n:hover{background:var(--btn-p-h) !important;color:#ffffff !important;transform:translateY(-1px)}
.theme-toggle{width:38px;height:38px;border-radius:50%;background:var(--bg-alt);border:1px solid var(--border);display:inline-flex;align-items:center;justify-content:center;cursor:pointer;transition:all .2s;color:var(--text-soft)}
.theme-toggle:hover{border-color:var(--a);color:var(--a);transform:translateY(-1px)}
.theme-toggle svg{width:18px;height:18px}
html[data-theme="light"] .icon-moon{display:none}
html[data-theme="dark"] .icon-sun{display:none}
.hero{min-height:92vh;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;padding:9rem 4% 5rem;position:relative;overflow:hidden}
.badge{display:inline-flex;align-items:center;gap:.5rem;background:var(--a-soft);border:1px solid var(--a-soft);border-radius:100px;padding:.42rem 1.05rem;font-size:.72rem;font-weight:700;color:var(--a);margin-bottom:2rem;font-family:'Space Mono',monospace;letter-spacing:.05em}
.badge::before{content:'';width:6px;height:6px;background:var(--a);border-radius:50%;animation:pulse 2s infinite}
@keyframes pulse{0%,100%{opacity:1}50%{opacity:.35}}
h1{font-size:clamp(2.4rem,5vw,4.1rem);font-weight:800;line-height:1.04;letter-spacing:-.04em;max-width:900px;margin-bottom:1.5rem;color:var(--text)}
h1 em{font-style:normal;color:var(--a)}
.sub{font-size:clamp(1rem,1.2vw,1.1rem);color:var(--text-soft);max-width:700px;line-height:1.65;margin-bottom:2.5rem;font-weight:400}
.btns{display:flex;gap:1rem;flex-wrap:wrap;justify-content:center}
.btn-p{background:var(--btn-p);color:#fff;padding:.95rem 2rem;border-radius:10px;font-weight:600;font-size:.9rem;text-decoration:none;transition:all .25s;display:inline-flex;align-items:center;gap:.4rem;box-shadow:0 4px 12px color-mix(in srgb,var(--btn-p) 25%,transparent)}
.btn-p:hover{background:var(--btn-p-h);transform:translateY(-2px);box-shadow:0 8px 24px color-mix(in srgb,var(--btn-p) 30%,transparent)}
.btn-o{background:transparent;color:var(--text);padding:.95rem 2rem;border-radius:10px;font-weight:500;font-size:.9rem;text-decoration:none;border:1px solid var(--border-mid);transition:all .25s;display:inline-flex;align-items:center;gap:.4rem}
.btn-o:hover{border-color:var(--a);color:var(--a);background:var(--a-soft)}
.suite-chip{display:inline-flex;align-items:center;gap:.5rem;margin-top:1.5rem;padding:.38rem .95rem;background:var(--bg-alt);border:1px solid var(--border);border-radius:100px;font-size:.74rem;color:var(--text-soft);font-family:'Space Mono',monospace;font-weight:600;letter-spacing:.04em;text-decoration:none;transition:all .2s}
.suite-chip:hover{color:var(--a);border-color:var(--a)}
.sec{padding:5.5rem 4%;max-width:1180px;margin:0 auto}
.sec.alt{background:var(--bg-alt);max-width:none;padding-left:max(4%,calc((100% - 1180px) / 2));padding-right:max(4%,calc((100% - 1180px) / 2))}
.stag{font-family:'Space Mono',monospace;font-size:.72rem;font-weight:700;text-transform:uppercase;letter-spacing:.22em;color:var(--a);margin-bottom:1rem;display:inline-block}
h2{font-size:clamp(1.8rem,2.8vw,2.4rem);font-weight:800;letter-spacing:-.032em;line-height:1.1;margin-bottom:.9rem;max-width:700px;color:var(--text)}
h2 em{font-style:normal;color:var(--a)}
.sd{color:var(--text-soft);font-size:1rem;line-height:1.65;max-width:600px;margin-bottom:3rem;font-weight:400}
.stats{display:grid;grid-template-columns:repeat(4,1fr);gap:0;background:var(--surface);border:1px solid var(--border);border-radius:14px;overflow:hidden;margin:2rem 0 3rem;box-shadow:var(--shadow)}
.stat{padding:1.6rem 1rem;text-align:center;border-right:1px solid var(--border)}
.stat:last-child{border-right:none}
.stat-n{font-family:'Space Mono',monospace;font-size:1.35rem;font-weight:700;color:var(--a);line-height:1}
.stat-l{font-size:.72rem;color:var(--text-soft);margin-top:.5rem;text-transform:uppercase;letter-spacing:.1em;font-weight:500}
.g3{display:grid;grid-template-columns:repeat(3,1fr);gap:1rem;margin-top:1.5rem}
.fcd{background:var(--surface);border:1px solid var(--border);border-radius:14px;padding:1.7rem;transition:all .3s;position:relative;overflow:hidden;box-shadow:var(--shadow)}
.fcd::before{content:'';position:absolute;top:0;left:0;width:3px;height:100%;background:var(--a);opacity:0;transition:opacity .3s}
.fcd:hover{border-color:var(--a);transform:translateY(-3px);box-shadow:var(--shadow-hover)}
.fcd:hover::before{opacity:1}
.fcd h3{font-size:1.02rem;font-weight:700;margin-bottom:.55rem;letter-spacing:-.01em;color:var(--text)}
.fcd p{font-size:.87rem;color:var(--text-soft);line-height:1.6}
.suite-box{background:var(--surface);border:1px solid var(--border);border-radius:18px;padding:2.2rem;display:grid;grid-template-columns:1.2fr .8fr;gap:2.2rem;align-items:center;margin-top:2rem;box-shadow:var(--shadow)}
.suite-box-l h3{font-size:1.35rem;font-weight:700;margin-bottom:.7rem;letter-spacing:-.02em;color:var(--text)}
.suite-box-l p{color:var(--text-soft);font-size:.94rem;line-height:1.6;margin-bottom:1.2rem}
.suite-box-r{display:flex;flex-wrap:wrap;gap:.4rem}
.apptag{background:var(--bg-alt);border:1px solid var(--border);border-radius:6px;padding:.32rem .7rem;font-size:.72rem;color:var(--text);font-family:'Space Mono',monospace;font-weight:500}
.apptag.self{background:var(--a-soft);color:var(--a);border-color:var(--a)}
.cta{text-align:center;padding:4.5rem 2rem;margin:3rem 4% 2rem;background:var(--bg-alt);border:1px solid var(--border);border-radius:22px;position:relative;overflow:hidden;max-width:1100px;margin-left:auto;margin-right:auto}
.cta h2{margin:0 auto .9rem}
.cta p{color:var(--text-soft);max-width:560px;margin:0 auto 2rem}
footer{padding:2.5rem 4% 1.5rem;max-width:1180px;margin:2rem auto 0;border-top:1px solid var(--border)}
.foot-t{display:flex;justify-content:space-between;align-items:center;margin-bottom:1rem;flex-wrap:wrap;gap:1rem}
.foot-t .logo{font-size:1.1rem}
.foot-links{display:flex;gap:1.5rem;font-size:.85rem}
.foot-links a{color:var(--text-soft);text-decoration:none;transition:color .2s}
.foot-links a:hover{color:var(--a)}
.foot-b{font-size:.74rem;color:var(--text-dim);font-family:'Space Mono',monospace;letter-spacing:.04em}
@media(max-width:900px){h1{font-size:2.2rem}.stats{grid-template-columns:1fr 1fr}.stat:nth-child(odd){border-right:1px solid var(--border)}.stat:nth-child(even){border-right:none}.stat{border-bottom:1px solid var(--border)}.g3{grid-template-columns:1fr}.suite-box{grid-template-columns:1fr;padding:1.6rem}.nav-r a:not(.btn-n):not(.theme-toggle){display:none}}
@media all{.in-iframe nav{display:none!important}.in-iframe .hero{padding-top:3rem!important;min-height:auto!important}.in-iframe footer{display:none!important}.in-iframe .cta{display:none!important}}
</style>
<script>if(window!==window.top)document.documentElement.classList.add('in-iframe');</script>
<link rel="canonical" href="https://weval-consulting.com/products/{{SLUG}}.html">
<meta property="og:title" content="{{NAME}} — {{TAGLINE}}">
<meta property="og:description" content="{{NAME}} — {{DESC_SHORT}}">
<meta property="og:url" content="https://weval-consulting.com/products/{{SLUG}}.html">
<meta property="og:type" content="website">
<meta property="og:site_name" content="WEVAL Consulting">
<meta property="og:image" content="https://weval-consulting.com/assets/logo-weval-png-DChrMGao.png">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="{{NAME}} — {{TAGLINE}}">
<meta name="twitter:description" content="{{NAME}} — {{DESC_SHORT}}">
</head><body>
<nav>
<a class="logo" href="/"><span class="logo-dot"></span>{{NAME}}<span style="color:var(--a)">.</span></a>
<div class="nav-r">
<a href="/">Accueil</a>
<a href="/products/">Produits</a>
<a href="/marketplace">Marketplace</a>
<button class="theme-toggle" onclick="(function(){var c=document.documentElement.getAttribute('data-theme')==='dark'?'light':'dark';document.documentElement.setAttribute('data-theme',c);localStorage.setItem('weval-theme',c);})()" aria-label="Basculer thème jour/nuit">
<svg class="icon-sun" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4"/><path d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M6.34 17.66l-1.41 1.41M19.07 4.93l-1.41 1.41"/></svg>
<svg class="icon-moon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/></svg>
</button>
<a href="#cta" class="btn-n">Demander une démo →</a>
</div>
</nav>
<section class="hero">
<div class="badge">{{BADGE}}</div>
<h1>{{H1_A}}<br>{{H1_B}}</h1>
<p class="sub">{{DESC}}</p>
<div class="btns">
<a href="#cta" class="btn-p">Demander une démo →</a>
<a href="/solutions/{{SUITE_SLUG}}.html" class="btn-o">Explorer la suite</a>
</div>
<a href="/solutions/{{SUITE_SLUG}}.html" class="suite-chip">▸ Composant de la suite {{SUITE}}</a>
</section>
<section class="sec">
<div class="stag">// Métriques clés</div>
<h2>La <em>performance</em>, chiffrée.</h2>
<div class="stats">{{STATS_HTML}}</div>
</section>
<section class="sec alt">
<div class="stag">// Capacités</div>
<h2>Ce que {{NAME}} <em>fait pour vous.</em></h2>
<p class="sd">Fonctionnalités clés, livrées en production. Chaque capacité est éprouvée en conditions réelles et maintenue sous standard Six Sigma L99.</p>
<div class="g3">{{FEATURES_HTML}}</div>
</section>
<section class="sec">
<div class="stag">// Écosystème</div>
<h2>Intégré dans <em>{{SUITE}}.</em></h2>
<p class="sd">{{NAME}} s'inscrit dans la suite {{SUITE}}, conçue pour l'interopérabilité. Chaque application de la suite communique nativement, partage données et événements, amplifie la valeur des autres.</p>
<div class="suite-box">
<div class="suite-box-l">
<h3>Suite {{SUITE}}</h3>
<p>{{SUITE_DESC}}</p>
<a href="/solutions/{{SUITE_SLUG}}.html" class="btn-o" style="padding:.6rem 1.2rem;font-size:.82rem">Voir la suite complète →</a>
</div>
<div class="suite-box-r">{{SIBLING_TAGS}}</div>
</div>
</section>
<div class="cta" id="cta">
<div class="stag" style="text-align:center;display:block">// Commencer</div>
<h2>Prêt à <em>essayer {{NAME}}</em> ?</h2>
<p>Démonstration personnalisée sur vos données. Diagnostic cas d'usage, scoping technique, proposition de déploiement en 45 minutes.</p>
<div class="btns">
<a href="/#contact" class="btn-p">Réserver une démo →</a>
<a href="/marketplace" class="btn-o">Voir le catalogue complet</a>
</div>
</div>
<footer>
<div class="foot-t">
<a class="logo" href="/"><span class="logo-dot"></span>WEVAL<span style="color:var(--a)">.</span></a>
<div class="foot-links">
<a href="/">Accueil</a>
<a href="/products/">Produits</a>
<a href="/marketplace">Marketplace</a>
<a href="/#contact">Contact</a>
<a href="https://www.linkedin.com/company/weval" target="_blank" rel="noopener" aria-label="LinkedIn" style="display:inline-flex;align-items:center;gap:.35rem"><svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M19 3a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h14zM8.339 18.337V9.886H5.67v8.451h2.669zM7.003 8.687a1.549 1.549 0 1 0 0-3.097 1.549 1.549 0 0 0 0 3.097zm11.335 9.65v-4.637c0-2.475-1.332-3.625-3.109-3.625-1.434 0-2.076.788-2.436 1.342v-1.152H10.12c.037.778 0 8.451 0 8.451h2.673v-4.72c0-.24.017-.48.088-.652.193-.479.631-.975 1.367-.975.964 0 1.35.734 1.35 1.811v4.537h2.672z"/></svg> LinkedIn</a>
</div>
</div>
<div class="foot-b">© 2026 WEVAL Consulting · Cabinet de conseil &amp; éditeur IA souveraine · Partenaire Écosystème SAP · Huawei Cloud Certified</div>
</footer>
</body></html>
HTML;
}
function build_page(string $slug): array {
if (!isset(PRODUCTS[$slug])) return ['ok' => false, 'slug' => $slug, 'error' => 'Unknown slug'];
$p = PRODUCTS[$slug];
$suite_name = $p['suite'];
if (isset(SUITES[$suite_name])) {
$suite = SUITES[$suite_name];
} else {
$found = null;
foreach (SUITE_PAGES as $sp_slug => $sp_data) {
if ($sp_data['name'] === $suite_name) {
$found = [
'slug' => $sp_slug,
'desc' => $sp_data['intro'],
'siblings' => array_map(function($a){
return isset(PRODUCTS[$a]) ? PRODUCTS[$a]['name'] : ucwords(str_replace('-', ' ', $a));
}, $sp_data['apps']),
];
break;
}
}
if (!$found) return ['ok' => false, 'slug' => $slug, 'error' => 'Unknown suite: ' . $suite_name];
$suite = $found;
}
$accent = ACCENTS[$p['accent']];
$stats_html = '';
foreach ($p['stats'] as [$v, $l]) {
$stats_html .= sprintf('<div class="stat"><div class="stat-n">%s</div><div class="stat-l">%s</div></div>',
htmlspecialchars($v), htmlspecialchars($l));
}
$features_html = '';
foreach ($p['features'] as [$title, $text]) {
$features_html .= sprintf('<div class="fcd"><h3>%s</h3><p>%s</p></div>',
htmlspecialchars($title), htmlspecialchars($text));
}
$sibling_tags = '';
foreach ($suite['siblings'] as $sib) {
$cls = ($sib === $p['name']) ? 'apptag self' : 'apptag';
$sibling_tags .= sprintf('<span class="%s">%s</span>', $cls, htmlspecialchars($sib));
}
$desc_short = mb_substr(strip_tags($p['desc']), 0, 140);
$html = get_template();
$vars = [
'{{SLUG}}' => $slug, '{{NAME}}' => $p['name'], '{{TAGLINE}}' => $p['tagline'],
'{{BADGE}}' => $p['badge'], '{{H1_A}}' => $p['h1_a'], '{{H1_B}}' => $p['h1_b'],
'{{DESC}}' => $p['desc'], '{{DESC_SHORT}}' => $desc_short,
'{{SUITE}}' => $suite_name, '{{SUITE_SLUG}}' => $suite['slug'], '{{SUITE_DESC}}' => $suite['desc'],
'{{STATS_HTML}}' => $stats_html, '{{FEATURES_HTML}}' => $features_html, '{{SIBLING_TAGS}}' => $sibling_tags,
'{{A_LIGHT}}' => $accent['light'], '{{A_DARK}}' => $accent['dark'],
'{{A_SOFT_L}}' => $accent['soft_l'], '{{A_SOFT_D}}' => $accent['soft_d'],
];
$html = strtr($html, $vars);
foreach (FORBIDDEN_TERMS as $term) {
$pattern = '/\b' . preg_quote($term, '/') . '\b/';
if (preg_match($pattern, $html)) {
return ['ok' => false, 'slug' => $slug, 'error' => "Forbidden term: $term"];
}
}
if (!str_contains($html, '<!DOCTYPE html>')) return ['ok' => false, 'slug' => $slug, 'error' => 'Missing DOCTYPE'];
if (!str_contains($html, '</html>')) return ['ok' => false, 'slug' => $slug, 'error' => 'Missing closing html'];
$target = "/var/www/html/products/{$slug}.html";
if (file_exists($target)) {
$gold_dir = '/opt/wevads/vault/gold-site-pages-' . date('Ymd');
if (!is_dir($gold_dir)) @mkdir($gold_dir, 0755, true);
@copy($target, $gold_dir . "/{$slug}-" . date('His') . '.html');
return ['ok' => false, 'slug' => $slug, 'error' => 'File exists — zero écrasement doctrine'];
}
$ok = @file_put_contents($target, $html);
if ($ok === false) return ['ok' => false, 'slug' => $slug, 'error' => 'Write failed'];
return ['ok' => true, 'slug' => $slug, 'file' => $target, 'bytes' => strlen($html), 'features' => count($p['features']), 'theme' => 'light+toggle'];
}
function scan_forbidden(string $dir = '/var/www/html'): array {
$hits = [];
$exts = ['html', 'htm'];
$rii = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS));
foreach ($rii as $f) {
if (!in_array(strtolower($f->getExtension()), $exts, true)) continue;
$path = $f->getPathname();
if (str_contains($path, '/node_modules/') || str_contains($path, '/.git/')) continue;
$content = @file_get_contents($path);
if ($content === false) continue;
foreach (['SAP Gold', 'Gold Partner'] as $t) {
$pattern = '/\b' . preg_quote($t, '/') . '\b/';
if (preg_match($pattern, $content)) $hits[] = ['file' => $path, 'term' => $t];
}
}
return $hits;
}
const SUITE_PAGES = [
'erp-intelligence' => [
'name' => 'WEVAL ERP Intelligence',
'full_name' => 'WEVAL ERP Intelligence',
'tagline' => "Les 20% manquants de votre ERP",
'hero_a' => "Votre ERP fait 80%.",
'hero_b' => "Nous faisons les <em>20% manquants</em>.",
'accent' => 'gold',
'badge' => 'SUITE - Fill-Gap ERP',
'intro' => "Suite dédiée aux entreprises avec un ERP en place (SAP, Oracle, Odoo, Salesforce, custom) qui rencontrent des limites fonctionnelles. Arsenal fournit les écrans et workflows manquants, WEVANALYTICS unifie la donnée cross-systèmes, Agents Gaps déploie des IA spécialisées par lacune business connue. Trois angles, un même objectif : amplifier la valeur de votre existant sans tout refaire.",
'value_props' => [
['Pas de remplacement', "Aucune migration ERP requise. Nous nous branchons sur votre système, comblons les manques, enrichissons la valeur."],
['Déploiement incrémental', "Activation gap par gap, agent par agent, écran par écran. ROI mesuré à chaque étape, pas de big-bang."],
['Cross-ERP natif', "Connecteurs prêts pour SAP (RFC, oData, IDoc), Oracle, Odoo, Salesforce, APIs REST. Multi-backends simultanés supportés."],
['Standards entreprise', "SSO, RBAC, audit trail complet, conformité RGPD et AI Act, hosting souverain Europe, certifications ISO 27001 en cours."],
],
'apps' => ['arsenal', 'wevanalytics', 'agents-gaps'],
],
'wevia-enterprise' => [
'name' => 'WEVIA Enterprise',
'full_name' => 'WEVIA Enterprise',
'tagline' => "L'ecosysteme d'IA souveraine pour l'entreprise",
'hero_a' => "L'IA souveraine,",
'hero_b' => "<em>orchestree de bout en bout.</em>",
'accent' => 'purple',
'badge' => 'SUITE FLAGSHIP - 11 applications',
'intro' => "Une stack complète d'IA souveraine propriété WEVAL. De l'orchestration multi-agents cross-métiers (WEVIA EM) à l'automatisation desktop (WEVIA Desk), chaque application interopère nativement pour amplifier la valeur des autres. Déploiement on-premise possible, vos données restent chez vous.",
'value_props' => [
['Souveraineté stricte', "Hosting Europe, zero exfiltration, conformité RGPD et AI Act garanties."],
['Interopérabilité native', "APIs REST, SSE streaming, events bus commun, authentification SSO unifiee."],
['Cohérence méthodologique', "Lean Six Sigma L99, DMAIC, BPMN - un meme standard qualité applique a chaque application."],
['TCO maîtrisé', "Cascade multi-modeles intelligente, GPU dedies, elasticite demande, sans lock-in vendor."],
],
'apps' => ['wevia-em', 'wevia-master', 'wevia-inference', 'wevia-life', 'wevia-white-label', 'projectflow', 'researchflow', 'boardflow', 'stackscan', 'wevia-desk'],
],
'marketing-cloud' => [
'name' => 'WEVAL Marketing Cloud',
'full_name' => 'WEVAL Marketing Cloud',
'tagline' => 'Arsenal + delivery intelligence',
'hero_a' => 'Le marketing digital,',
'hero_b' => '<em>livré ou remboursé.</em>',
'accent' => 'gold',
'badge' => 'SUITE - Plateforme marketing digital',
'intro' => 'Plateforme marketing digital complète propriété WEVAL. Envoi haute performance, intelligence IA intégrée, tracking end-to-end, optimisation automatique. Arsenal ERP Intelligence orchestre la couche business, 13 apps spécialisées couvrent delivery, warming, reputation, SMS, ads. Infrastructure qui délivre, inbox rate 97%.',
'value_props' => [
['Inbox rate garanti', 'Infrastructure PMTA + KumoMTA + Postfix tunée, Brain Engine IA 646 configs, warming automatique, monitoring RBL continu.'],
['Multicanal intégré', 'Email, SMS, ads social, affiliation - une seule stack qui orchestre tous les canaux avec attribution unifiée.'],
['Souveraineté stricte', 'Hosting EU, IPs dédiées, conformité RGPD et CAN-SPAM, zéro partage de données tiers.'],
['ROI mesurable', 'Dashboard temps réel par campagne, par audience, par canal — décisions pilotées par la donnée.'],
],
'apps' => ['arsenal', 'deliverads', 'deliverscore', 'mailstream', 'mailwarm', 'mailforge', 'outreachai', 'smsforge', 'adscontrol', 'reputationai', 'ai-sdr', 'newsletterinsight', 'emailverify', 'blacklistguard'],
],
'advisory' => [
'name' => 'WEVAL Advisory',
'full_name' => 'WEVAL Advisory',
'tagline' => 'Cabinet et expertise a la demande',
'hero_a' => 'Du diagnostic',
'hero_b' => 'au <em>run opérationnel.</em>',
'accent' => 'purple',
'badge' => 'SUITE - Cabinet de conseil',
'intro' => 'Notre cabinet de conseil. Missions cadrées, livrables mesurables, engagement au ROI. De la stratégie IA à la transformation digitale complète. Méthodologie Lean Six Sigma, BPMN, DMAIC, engagement NonReg 100%. Séniorité garantie, interventions courtes ou longues, partout en Europe et MENA.',
'value_props' => [
['Expertise senior', 'Tous nos consultants ont 10+ années d\'expérience terrain. Directeurs techniques, architectes IA, DSI transformés.'],
['Livrables mesurables', 'Chaque mission cadrée par KPIs et SLAs contractuels. ROI prouvé ou remboursement partiel négociable.'],
['Méthodologie unifiée', 'Lean Six Sigma L99, DMAIC, BPMN, standards qualité 6σ appliqués à chaque deliverable.'],
['Transfert de compétences', 'Academy intégrée, formation cloud, IA et méthodes. Vos équipes autonomes après la mission.'],
],
'apps' => ['consulting', 'consulting-pro', 'academy', 'leansixsigma', 'auditai', 'cloudcost'],
],
'productivity' => [
'name' => 'WEVAL Productivity',
'full_name' => 'WEVAL Productivity',
'tagline' => 'IA generative métier',
'hero_a' => 'Vos livrables,',
'hero_b' => '<em>générés et orchestrés.</em>',
'accent' => 'teal',
'badge' => 'SUITE - Productivite et creation',
'intro' => 'Suite d\'applications IA pour les métiers. De la proposale commerciale au contrat, du design visuel à la présentation, du contenu marketing à la traduction. Chaque app est une IA spécialisée, fine-tunable sur votre domaine métier, déployable en souveraineté.',
'value_props' => [
['Qualité constante', 'Templates et guardrails métier garantissent un niveau constant, independant de la creativite individuelle.'],
['Intégration workflow', 'Chaque app s intégré dans vos outils existants - Slack, Teams, Google Workspace, Microsoft 365.'],
['Fine-tuning métier', 'Entrainement sur votre corpus pour ton, style, contraintes sectorielles. Resultat indiscernable de votre equipe.'],
['Productivité mesurable', 'Gains 3-5x sur les taches de production, traces et reportes dans un dashboard unifie.'],
],
'apps' => ['proposalai', 'blueprintai', 'contractai', 'presentationai', 'canvasai', 'copyai', 'content-factory', 'creativefactory', 'dashboardai', 'translateai', 'meetingai', 'devforge', 'bizplan', 'esignature'],
],
'commerce-data' => [
'name' => 'WEVAL Commerce and Data',
'full_name' => 'WEVAL Commerce and Data',
'tagline' => 'E-commerce et lead intelligence',
'hero_a' => 'Du lead',
'hero_b' => 'a la <em>transaction.</em>',
'accent' => 'teal',
'badge' => 'SUITE - Commerce et données B2B',
'intro' => 'Suite dédiée au commerce digital et à l\'intelligence des données. StoreForge pour le e-commerce, StoreAI pour la personalisation, LeadForge pour la génération B2B, Scout Intelligence pour la veille. Données enrichies en continu, intégration native avec CRM et outils marketing.',
'value_props' => [
['E-commerce clé en main', 'Boutique en 5 minutes, descriptions IA, chatbot WEVIA intégré, paiement international, SEO natif.'],
['Leads B2B vérifiés', 'Base de leads qualifiés et consentis, enrichissement continu, segmentation fine par secteur et taille.'],
['Intelligence continue', 'Veille concurrentielle automatisée, détection de signaux faibles, alerting sur opportunités et menaces.'],
['Intégration CRM native', 'Connecteurs Salesforce, HubSpot, Pipedrive, Zoho — pas de silo, données synchronisées temps réel.'],
],
'apps' => ['storeforge', 'storeai', 'wevalcrm', 'formbuilder', 'leadforge', 'datainsight', 'scoutai', 'youtubefactory'],
],
'cloud-security' => [
'name' => 'WEVAL Cloud and Security',
'full_name' => 'WEVAL Cloud and Security',
'tagline' => 'Infrastructure et SOC as a Service',
'hero_a' => 'Votre infrastructure,',
'hero_b' => '<em>souveraine et surveillée.</em>',
'accent' => 'coral',
'badge' => 'SUITE - Cloud et cybersecurite',
'intro' => 'Suite cloud et cybersécurité. Hosting souverain certifié Huawei Cloud et Scaleway, monitoring 24/7, SOC as a Service, FinOps automatisé, cartographie réseau, GPU dédiés pour IA. Conformité RGPD, HDS, AI Act, ISO 27001.',
'value_props' => [
['Souveraineté certifiée', 'Hosting EU, certifications Huawei Cloud et Scaleway, conformité HDS pour données de santé.'],
['Monitoring 24/7', 'Sentinel surveille SSL, DNS, ports, RBL, OWASP en continu. Alerting Telegram, escalade automatique.'],
['FinOps intégré', 'CloudCost analyse vos factures cloud, identifie les gaspillages, optimise automatiquement le rightsizing.'],
['GPU dédiés IA', 'Infrastructure GPU A100/H100 pour inférence, training, fine-tuning — scaling à la demande.'],
],
'apps' => ['sentinel', 'cloudcost', 'deliverscore', 'inboxtest', 'emailverify', 'cloud-providers', 'huawei-cloud', 'gpu-inference'],
],
'pharma-cloud' => [
'name' => 'WEVAL Pharma Cloud',
'full_name' => 'WEVAL Pharma Cloud',
'tagline' => "Healthcare intelligence mondiale",
'hero_a' => "La santé,",
'hero_b' => "<em>compliant by design.</em>",
'accent' => 'coral',
'badge' => 'SUITE - Sciences de la vie',
'intro' => "Suite dédiée à l'industrie pharmaceutique et aux sciences de la vie. Base HCP mondiale consent-based, CRM pharma, studio de campagnes compliant, gestion du consentement B2B. Conformité RGPD, HDS, LGPD, CCPA garanties.",
'value_props' => [
['Consent-based strict', "Opt-in verifie a la source, traçabilité complete, preuve juridique opposable."],
['Couverture mondiale', "Europe, Ameriques, MENA, Asie - specialistes hospitaliers et liberaux."],
['Compliance multi-juridictions', "RGPD europeen, LGPD bresilien, CCPA californien, HDS hebergement sante."],
['Intégration CRM native', "Hooks temps reel vers Salesforce Health Cloud, Veeva, Iqvia OCE et systemes maison."],
],
'apps' => ['reachhcp', 'campaign-studio', 'consent-manager'],
],
];
function get_suite_template(): string {
return <<<'HTML2'
<!DOCTYPE html>
<html lang="fr" data-theme="light"><head>
<link rel="icon" href="/favicon.ico" type="image/x-icon">
<meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>Suite {{NAME}} - {{TAGLINE}} | WEVAL Consulting</title>
<meta name="description" content="Suite {{NAME}} - {{DESC_SHORT}}">
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=Space+Mono:wght@400;700&display=swap" rel="stylesheet">
<script>(function(){var t=localStorage.getItem('weval-theme')||'light';document.documentElement.setAttribute('data-theme',t);})();</script>
<style>
:root{--bg:#ffffff;--bg-alt:#fafbfc;--surface:#ffffff;--text:#1a1f3a;--text-soft:#5a6480;--text-dim:#8893a8;--border:rgba(26,31,58,.08);--border-mid:rgba(26,31,58,.14);--shadow:0 1px 3px rgba(26,31,58,.04),0 8px 24px rgba(26,31,58,.04);--shadow-h:0 2px 6px rgba(26,31,58,.06),0 16px 40px rgba(26,31,58,.08);--a:{{A_LIGHT}};--a-soft:{{A_SOFT_L}};--btn-p:#5b4cdb;--btn-p-h:#4a3dc4}
html[data-theme="dark"]{--bg:#05080f;--bg-alt:#080c18;--surface:#0c1222;--text:#edf2f7;--text-soft:#a8b4c8;--text-dim:#7a8ba5;--border:rgba(255,255,255,.06);--border-mid:rgba(255,255,255,.12);--shadow:0 1px 3px rgba(0,0,0,.3),0 8px 24px rgba(0,0,0,.3);--shadow-h:0 2px 6px rgba(0,0,0,.4),0 16px 40px rgba(0,0,0,.4);--a:{{A_DARK}};--a-soft:{{A_SOFT_D}};--btn-p:#7c5cfc;--btn-p-h:#9277ff}
*{margin:0;padding:0;box-sizing:border-box}html{scroll-behavior:smooth}
body{font-family:'Inter',sans-serif;background:var(--bg);color:var(--text);-webkit-font-smoothing:antialiased;transition:background .3s,color .3s}
body::before{content:'';position:fixed;inset:0;background:radial-gradient(circle at 20% 10%,var(--a-soft) 0%,transparent 40%),radial-gradient(circle at 80% 60%,var(--a-soft) 0%,transparent 45%);pointer-events:none;opacity:.6;z-index:-1}
nav{position:fixed;top:0;width:100%;padding:1rem 4%;display:flex;justify-content:space-between;align-items:center;z-index:100;backdrop-filter:blur(20px);background:color-mix(in srgb,var(--bg) 85%,transparent);border-bottom:1px solid var(--border)}
.logo{font-weight:800;font-size:1.35rem;letter-spacing:-.035em;display:flex;align-items:center;gap:.5rem;color:var(--text);text-decoration:none}
.logo-dot{width:10px;height:10px;border-radius:50%;background:var(--a);box-shadow:0 0 18px var(--a-soft)}
.nav-r{display:flex;gap:1.6rem;align-items:center}
.nav-r a{color:var(--text-soft);text-decoration:none;font-size:.86rem;font-weight:500;transition:color .25s}
.nav-r a:hover{color:var(--a)}
.btn-n{background:var(--btn-p);color:#fff;padding:.6rem 1.3rem;border-radius:8px;font-weight:600;font-size:.84rem;text-decoration:none;transition:all .2s}
.btn-n:hover{background:var(--btn-p-h)}
.theme-toggle{width:38px;height:38px;border-radius:50%;background:var(--bg-alt);border:1px solid var(--border);display:inline-flex;align-items:center;justify-content:center;cursor:pointer;transition:all .2s;color:var(--text-soft)}
.theme-toggle:hover{border-color:var(--a);color:var(--a)}
.theme-toggle svg{width:18px;height:18px}
html[data-theme="light"] .icon-sun{display:none}html[data-theme="dark"] .icon-moon{display:none}
.hero{min-height:82vh;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;padding:9rem 4% 5rem;position:relative;overflow:hidden}
.badge{display:inline-flex;align-items:center;gap:.5rem;background:var(--a-soft);border:1px solid var(--a-soft);border-radius:100px;padding:.42rem 1.05rem;font-size:.72rem;font-weight:700;color:var(--a);margin-bottom:2rem;font-family:'Space Mono',monospace;letter-spacing:.05em}
.badge::before{content:'';width:6px;height:6px;background:var(--a);border-radius:50%;animation:pulse 2s infinite}
@keyframes pulse{0%,100%{opacity:1}50%{opacity:.35}}
.suite-prefix{font-family:'Space Mono',monospace;font-size:.85rem;font-weight:600;color:var(--text-soft);text-transform:uppercase;letter-spacing:.3em;margin-bottom:1rem}
h1{font-size:clamp(2.4rem,5vw,4.2rem);font-weight:800;line-height:1.04;letter-spacing:-.04em;max-width:920px;margin-bottom:1.4rem;color:var(--text)}
h1 em{font-style:normal;color:var(--a)}
.sub{font-size:clamp(1rem,1.2vw,1.1rem);color:var(--text-soft);max-width:720px;line-height:1.65;margin-bottom:2.5rem}
.btns{display:flex;gap:1rem;flex-wrap:wrap;justify-content:center}
.btn-p{background:var(--btn-p);color:#fff;padding:.95rem 2rem;border-radius:10px;font-weight:600;font-size:.9rem;text-decoration:none;transition:all .25s;box-shadow:0 4px 12px color-mix(in srgb,var(--btn-p) 25%,transparent)}
.btn-p:hover{background:var(--btn-p-h);transform:translateY(-2px)}
.btn-o{background:transparent;color:var(--text);padding:.95rem 2rem;border-radius:10px;font-weight:500;font-size:.9rem;text-decoration:none;border:1px solid var(--border-mid);transition:all .25s}
.btn-o:hover{border-color:var(--a);color:var(--a)}
.sec{padding:5.5rem 4%;max-width:1200px;margin:0 auto}
.sec.alt{background:var(--bg-alt);max-width:none;padding-left:max(4%,calc((100% - 1200px) / 2));padding-right:max(4%,calc((100% - 1200px) / 2))}
.stag{font-family:'Space Mono',monospace;font-size:.72rem;font-weight:700;text-transform:uppercase;letter-spacing:.22em;color:var(--a);margin-bottom:1rem;display:inline-block}
h2{font-size:clamp(1.8rem,2.8vw,2.5rem);font-weight:800;letter-spacing:-.032em;line-height:1.1;margin-bottom:.9rem;max-width:720px;color:var(--text)}
h2 em{font-style:normal;color:var(--a)}
.sd{color:var(--text-soft);font-size:1rem;line-height:1.65;max-width:640px;margin-bottom:3rem}
.g2{display:grid;grid-template-columns:repeat(2,1fr);gap:1.2rem}
.vpcard{background:var(--surface);border:1px solid var(--border);border-radius:14px;padding:1.8rem;box-shadow:var(--shadow);transition:all .3s;position:relative}
.vpcard::before{content:'';position:absolute;top:0;left:0;width:3px;height:100%;background:var(--a);border-radius:14px 0 0 14px}
.vpcard h3{font-size:1.1rem;font-weight:700;margin-bottom:.6rem;color:var(--text)}
.vpcard p{font-size:.9rem;color:var(--text-soft);line-height:1.65}
.apps-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:1.2rem;margin-top:2rem}
.appcard{background:var(--surface);border:1px solid var(--border);border-radius:14px;padding:1.8rem;transition:all .3s;text-decoration:none;color:inherit;display:block;box-shadow:var(--shadow);position:relative;overflow:hidden}
.appcard:hover{border-color:var(--a);transform:translateY(-3px);box-shadow:var(--shadow-h)}
.appcard.flagship{border:2px solid var(--a);background:linear-gradient(180deg,var(--a-soft) 0%,var(--surface) 100%)}
.flagship-tag{position:absolute;top:1rem;right:1rem;background:var(--a);color:#fff;font-family:'Space Mono',monospace;font-size:.6rem;font-weight:700;padding:.22rem .55rem;border-radius:100px;letter-spacing:.08em}
.appcard h3{font-size:1.1rem;font-weight:700;margin-bottom:.4rem;color:var(--text);letter-spacing:-.01em}
.appcard .app-tagline{font-size:.82rem;color:var(--a);font-weight:600;margin-bottom:.9rem;font-family:'Space Mono',monospace}
.appcard p{font-size:.86rem;color:var(--text-soft);line-height:1.6;margin-bottom:1rem}
.appcard-link{font-size:.82rem;color:var(--a);font-weight:600;text-decoration:none;display:inline-flex;align-items:center;gap:.3rem}
.cta{text-align:center;padding:4.5rem 2rem;margin:3rem 4% 2rem;background:var(--bg-alt);border:1px solid var(--border);border-radius:22px;max-width:1080px;margin-left:auto;margin-right:auto}
.cta p{color:var(--text-soft);max-width:560px;margin:0 auto 2rem}
footer{padding:2.5rem 4% 1.5rem;max-width:1200px;margin:2rem auto 0;border-top:1px solid var(--border)}
.foot-t{display:flex;justify-content:space-between;align-items:center;margin-bottom:1rem;flex-wrap:wrap;gap:1rem}
.foot-t .logo{font-size:1.1rem}
.foot-links{display:flex;gap:1.3rem;font-size:.85rem;align-items:center;flex-wrap:wrap}
.foot-links a{color:var(--text-soft);text-decoration:none;transition:color .2s;display:inline-flex;align-items:center;gap:.35rem}
.foot-links a:hover{color:var(--a)}
.foot-b{font-size:.74rem;color:var(--text-dim);font-family:'Space Mono',monospace;letter-spacing:.04em}
.foot-b a{color:var(--a);text-decoration:none}
@media(max-width:900px){h1{font-size:2.2rem}.g2,.apps-grid{grid-template-columns:1fr}.nav-r a:not(.btn-n):not(.theme-toggle){display:none}}
</style>
</head><body>
<nav>
<a class="logo" href="/"><span class="logo-dot"></span>WEVAL<span style="color:var(--a)">.</span></a>
<div class="nav-r">
<a href="/">Accueil</a>
<a href="/products/">Produits</a>
<a href="/marketplace">Marketplace</a>
<button class="theme-toggle" onclick="(function(){var c=document.documentElement.getAttribute('data-theme')==='dark'?'light':'dark';document.documentElement.setAttribute('data-theme',c);localStorage.setItem('weval-theme',c);})()" aria-label="Basculer thème jour/nuit"><svg class="icon-sun" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4"/><path d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M6.34 17.66l-1.41 1.41M19.07 4.93l-1.41 1.41"/></svg><svg class="icon-moon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/></svg></button>
<a href="#cta" class="btn-n">Demander une demo -></a>
</div>
</nav>
<section class="hero">
<div class="badge">{{BADGE}}</div>
<div class="suite-prefix">Suite {{SUITE_CODE}}</div>
<h1>{{HERO_A}}<br>{{HERO_B}}</h1>
<p class="sub">{{INTRO}}</p>
<div class="btns">
<a href="#apps" class="btn-p">Voir les {{N_APPS}} applications -></a>
<a href="/#contact" class="btn-o">Demander une demo</a>
</div>
</section>
<section class="sec">
<div class="stag">// Pourquoi cette suite</div>
<h2>Quatre atouts, <em>une même promesse.</em></h2>
<p class="sd">Ce qui distingue la suite {{NAME}} des solutions fragmentees du marche.</p>
<div class="g2">{{VALUE_PROPS}}</div>
</section>
<section class="sec alt" id="apps">
<div class="stag">// Applications de la suite</div>
<h2>{{N_APPS}} applications, <em>interopérables.</em></h2>
<p class="sd">Chaque application est aussi consommable en standalone. Ensemble, elles constituent la suite {{NAME}} - amplification mutuelle des capacites.</p>
<div class="apps-grid">{{APPS_HTML}}</div>
</section>
<div class="cta" id="cta">
<div class="stag" style="text-align:center;display:block">// Commencer</div>
<h2>Deployer <em>{{NAME}}</em> chez vous.</h2>
<p>POC gratuit 2 semaines. MVP opérationnel en 1 mois. Deploiement Enterprise complet en 3 mois. IA souveraine, données hebergees chez vous.</p>
<div class="btns">
<a href="/#contact" class="btn-p">Réserver un POC -></a>
<a href="/marketplace" class="btn-o">Voir le catalogue complet</a>
</div>
</div>
<footer>
<div class="foot-t">
<a class="logo" href="/"><span class="logo-dot"></span>WEVAL<span style="color:var(--a)">.</span></a>
<div class="foot-links">
<a href="/">Accueil</a>
<a href="/products/">Produits</a>
<a href="/marketplace">Marketplace</a>
<a href="/#contact">Contact</a>
<a href="https://www.linkedin.com/company/weval" target="_blank" rel="noopener" aria-label="LinkedIn"><svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M19 3a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h14zM8.339 18.337V9.886H5.67v8.451h2.669zM7.003 8.687a1.549 1.549 0 1 0 0-3.097 1.549 1.549 0 0 0 0 3.097zm11.335 9.65v-4.637c0-2.475-1.332-3.625-3.109-3.625-1.434 0-2.076.788-2.436 1.342v-1.152H10.12c.037.778 0 8.451 0 8.451h2.673v-4.72c0-.24.017-.48.088-.652.193-.479.631-.975 1.367-.975.964 0 1.35.734 1.35 1.811v4.537h2.672z"/></svg> LinkedIn</a>
</div>
</div>
<div class="foot-b">&copy; 2026 WEVAL Consulting &middot; Cabinet de conseil &amp; editeur IA souveraine &middot; Partenaire Ecosysteme SAP &middot; Huawei Cloud Certified &middot; <a href="https://www.linkedin.com/company/weval" target="_blank" rel="noopener">Suivez-nous sur LinkedIn -></a></div>
</footer>
</body></html>
HTML2;
}
function build_suite_page(string $slug): array {
if (!isset(SUITE_PAGES[$slug])) return ['ok' => false, 'slug' => $slug, 'error' => 'Unknown suite slug'];
$s = SUITE_PAGES[$slug];
$accent = ACCENTS[$s['accent']];
// Value props HTML
$vp_html = '';
foreach ($s['value_props'] as [$t, $d]) {
$vp_html .= sprintf('<div class="vpcard"><h3>%s</h3><p>%s</p></div>',
htmlspecialchars($t), htmlspecialchars($d));
}
// Apps HTML — check file_exists for clickable vs roadmap card
$apps_html = '';
foreach ($s['apps'] as $app_slug) {
$page_path = "/var/www/html/products/{$app_slug}.html";
$page_exists = file_exists($page_path);
// Pull display data : prefer PRODUCTS const, else use slug-derived name
if (isset(PRODUCTS[$app_slug])) {
$p = PRODUCTS[$app_slug];
$name = $p['name'];
$tagline = strip_tags($p['tagline']);
$desc = mb_substr(strip_tags($p['desc']), 0, 160);
if (mb_strlen(strip_tags($p['desc'])) > 160) $desc .= '...';
} else {
// Derive from slug
$name = ucwords(str_replace('-', ' ', $app_slug));
$tagline = 'Application de la suite';
$desc = 'Details a venir. Partie integrante de la suite ' . $s['name'] . '.';
}
$flagship_cls = ($app_slug === 'wevia-em') ? ' flagship' : '';
$flagship_tag = ($app_slug === 'wevia-em') ? '<span class="flagship-tag">FLAGSHIP</span>' : '';
if ($page_exists) {
$apps_html .= sprintf(
'<a class="appcard%s" href="/products/%s.html">%s<h3>%s</h3><div class="app-tagline">%s</div><p>%s</p><span class="appcard-link">Voir la fiche produit -&gt;</span></a>',
$flagship_cls, htmlspecialchars($app_slug), $flagship_tag,
htmlspecialchars($name), htmlspecialchars($tagline),
htmlspecialchars($desc)
);
} else {
// Roadmap card — no link, clear expectation setting
$apps_html .= sprintf(
'<div class="appcard%s" style="cursor:default;opacity:.92">%s<h3>%s</h3><div class="app-tagline">%s</div><p>%s</p><span class="appcard-link" style="color:var(--text-dim);font-family:\'Space Mono\',monospace;font-size:.68rem;letter-spacing:.08em">INCLUS DANS LA SUITE - FICHE PRODUIT À VENIR</span></div>',
$flagship_cls, $flagship_tag,
htmlspecialchars($name), htmlspecialchars($tagline),
htmlspecialchars($desc)
);
}
}
$desc_short = mb_substr(strip_tags($s['intro']), 0, 140);
$html = get_suite_template();
$vars = [
'{{SLUG}}' => $slug, '{{NAME}}' => $s['name'], '{{SUITE_CODE}}' => $s['full_name'],
'{{TAGLINE}}' => $s['tagline'], '{{BADGE}}' => $s['badge'],
'{{HERO_A}}' => $s['hero_a'], '{{HERO_B}}' => $s['hero_b'],
'{{INTRO}}' => $s['intro'], '{{DESC_SHORT}}' => $desc_short,
'{{VALUE_PROPS}}' => $vp_html, '{{APPS_HTML}}' => $apps_html,
'{{N_APPS}}' => (string)count($s['apps']),
'{{A_LIGHT}}' => $accent['light'], '{{A_DARK}}' => $accent['dark'],
'{{A_SOFT_L}}' => $accent['soft_l'], '{{A_SOFT_D}}' => $accent['soft_d'],
];
$html = strtr($html, $vars);
foreach (FORBIDDEN_TERMS as $term) {
$pattern = '/\b' . preg_quote($term, '/') . '\b/';
if (preg_match($pattern, $html)) return ['ok' => false, 'slug' => $slug, 'error' => "Forbidden term: $term"];
}
$target_dir = '/var/www/html/solutions';
if (!is_dir($target_dir)) @mkdir($target_dir, 0755, true);
$target = "$target_dir/{$slug}.html";
if (file_exists($target)) {
$gold_dir = '/opt/wevads/vault/gold-suite-pages-' . date('Ymd');
if (!is_dir($gold_dir)) @mkdir($gold_dir, 0755, true);
@copy($target, $gold_dir . "/{$slug}-" . date('His') . '.html');
return ['ok' => false, 'slug' => $slug, 'error' => 'File exists - zero ecrasement'];
}
$ok = @file_put_contents($target, $html);
if ($ok === false) return ['ok' => false, 'slug' => $slug, 'error' => 'Write failed'];
return ['ok' => true, 'slug' => $slug, 'file' => $target, 'bytes' => strlen($html), 'apps' => count($s['apps'])];
}
// ============================================================
// PRODUCTS INDEX BUILDER (/products/index.html)
// 4 flagships + 13 produits rebrandes + 7 suites
// ============================================================
const FLAGSHIPS = [
['wevia-em', 'purple', "L'IA souveraine qui orchestre la valeur de bout en bout", "Orchestration multi-agents sur toute la value chain. 930 agents, 9 métiers, POC 2 semaines."],
['wevia-master', 'teal', "L'agent qui exécute", "Agent IA autonome propriétaire. Scanne, exécute, apprend sur votre domaine métier."],
['arsenal', 'gold', "Framework ERP Intelligence", "150+ écrans modulaires. Brain Engine IA. Comble les 20% que votre ERP ne fait pas."],
['reachhcp', 'coral', "Base HCP mondiale consent-based", "Professionnels de santé vérifiés, segmentation fine, conformité RGPD et HDS."],
];
function get_index_template(): string {
return <<<'HTMLIDX'
<!DOCTYPE html>
<html lang="fr" data-theme="light"><head>
<link rel="icon" href="/favicon.ico" type="image/x-icon">
<link rel="apple-touch-icon" href="/apple-touch-icon.png">
<meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>Produits WEVAL — {{N_PRODS}} applications IA souveraine et {{N_SUITES}} suites | WEVAL Consulting</title>
<meta name="description" content="Catalogue WEVAL : 4 applications phares, {{N_PRODS}} applications IA, {{N_SUITES}} suites métier. IA souveraine, conformité RGPD et AI Act, standard qualité Six Sigma.">
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=Space+Mono:wght@400;700&display=swap" rel="stylesheet">
<script>(function(){var t=localStorage.getItem('weval-theme')||'light';document.documentElement.setAttribute('data-theme',t);})();</script>
<style>
:root{--bg:#ffffff;--bg-alt:#fafbfc;--surface:#ffffff;--text:#1a1f3a;--text-soft:#5a6480;--text-dim:#8893a8;--border:rgba(26,31,58,.08);--border-mid:rgba(26,31,58,.14);--shadow:0 1px 3px rgba(26,31,58,.04),0 8px 24px rgba(26,31,58,.04);--shadow-h:0 2px 6px rgba(26,31,58,.06),0 16px 40px rgba(26,31,58,.08);--purple:#6f5cff;--teal:#0d9488;--gold:#b88a2e;--coral:#dc3e3e;--btn-p:#5b4cdb;--btn-p-h:#4a3dc4}
html[data-theme="dark"]{--bg:#05080f;--bg-alt:#080c18;--surface:#0c1222;--text:#edf2f7;--text-soft:#a8b4c8;--text-dim:#7a8ba5;--border:rgba(255,255,255,.06);--border-mid:rgba(255,255,255,.12);--shadow:0 1px 3px rgba(0,0,0,.3),0 8px 24px rgba(0,0,0,.3);--shadow-h:0 2px 6px rgba(0,0,0,.4),0 16px 40px rgba(0,0,0,.4);--purple:#7c5cfc;--teal:#00c9a7;--gold:#f0c674;--coral:#ff6b6b;--btn-p:#7c5cfc;--btn-p-h:#9277ff}
*{margin:0;padding:0;box-sizing:border-box}html{scroll-behavior:smooth}
body{font-family:'Inter',sans-serif;background:var(--bg);color:var(--text);-webkit-font-smoothing:antialiased;transition:background .3s,color .3s}
body::before{content:'';position:fixed;inset:0;background:radial-gradient(circle at 15% 10%,rgba(111,92,255,.06) 0%,transparent 40%),radial-gradient(circle at 85% 60%,rgba(13,148,136,.06) 0%,transparent 45%);pointer-events:none;opacity:.7;z-index:-1}
nav{position:fixed;top:0;width:100%;padding:1rem 4%;display:flex;justify-content:space-between;align-items:center;z-index:100;backdrop-filter:blur(20px);background:color-mix(in srgb,var(--bg) 85%,transparent);border-bottom:1px solid var(--border)}
.logo{font-weight:800;font-size:1.35rem;letter-spacing:-.035em;display:flex;align-items:center;gap:.5rem;color:var(--text);text-decoration:none}
.logo-dot{width:10px;height:10px;border-radius:50%;background:var(--purple);box-shadow:0 0 18px rgba(111,92,255,.25)}
.nav-r{display:flex;gap:1.6rem;align-items:center}
.nav-r a{color:var(--text-soft);text-decoration:none;font-size:.86rem;font-weight:500;transition:color .25s}
.nav-r a:hover{color:var(--purple)}
.btn-n,a.btn-n{background:var(--btn-p) !important;color:#ffffff !important;padding:.6rem 1.3rem;border-radius:8px;font-weight:600;font-size:.84rem;text-decoration:none !important;transition:all .2s;border:none;cursor:pointer;display:inline-block}
.btn-n:hover,a.btn-n:hover{background:var(--btn-p-h) !important;color:#ffffff !important;transform:translateY(-1px)}
.theme-toggle{width:38px;height:38px;border-radius:50%;background:var(--bg-alt);border:1px solid var(--border);display:inline-flex;align-items:center;justify-content:center;cursor:pointer;transition:all .2s;color:var(--text-soft)}
.theme-toggle:hover{border-color:var(--purple);color:var(--purple)}
.theme-toggle svg{width:18px;height:18px}
html[data-theme="light"] .icon-sun{display:none}html[data-theme="dark"] .icon-moon{display:none}
.hero{padding:8rem 4% 4rem;text-align:center;position:relative}
.badge{display:inline-flex;align-items:center;gap:.5rem;background:rgba(111,92,255,.08);border:1px solid rgba(111,92,255,.15);border-radius:100px;padding:.42rem 1.05rem;font-size:.72rem;font-weight:700;color:var(--purple);margin-bottom:2rem;font-family:'Space Mono',monospace;letter-spacing:.05em}
.badge::before{content:'';width:6px;height:6px;background:var(--purple);border-radius:50%;animation:pulse 2s infinite}
@keyframes pulse{0%,100%{opacity:1}50%{opacity:.35}}
h1{font-size:clamp(2.5rem,5vw,4.3rem);font-weight:800;line-height:1.04;letter-spacing:-.04em;max-width:960px;margin:0 auto 1.5rem;color:var(--text)}
h1 em{font-style:normal;background:linear-gradient(135deg,var(--purple),var(--teal));-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text}
.sub{font-size:clamp(1rem,1.2vw,1.1rem);color:var(--text-soft);max-width:720px;margin:0 auto 3rem;line-height:1.65}
.kpis{display:inline-flex;gap:3rem;flex-wrap:wrap;justify-content:center;margin-top:1rem}
.kpi{text-align:center}
.kpi-n{font-family:'Space Mono',monospace;font-size:1.8rem;font-weight:700;color:var(--purple)}
.kpi-l{font-size:.72rem;color:var(--text-soft);text-transform:uppercase;letter-spacing:.12em;margin-top:.3rem}
.sec{padding:5rem 4%;max-width:1200px;margin:0 auto}
.sec.alt{background:var(--bg-alt);max-width:none;padding-left:max(4%,calc((100% - 1200px)/2));padding-right:max(4%,calc((100% - 1200px)/2))}
.stag{font-family:'Space Mono',monospace;font-size:.72rem;font-weight:700;text-transform:uppercase;letter-spacing:.22em;margin-bottom:1rem;display:inline-block}
.stag.p{color:var(--purple)}.stag.t{color:var(--teal)}.stag.g{color:var(--gold)}.stag.c{color:var(--coral)}
h2{font-size:clamp(1.8rem,2.8vw,2.6rem);font-weight:800;letter-spacing:-.032em;line-height:1.1;margin-bottom:.9rem;color:var(--text)}
h2 em{font-style:normal}
.sd{color:var(--text-soft);font-size:1rem;line-height:1.65;max-width:680px;margin-bottom:3rem}
.flag-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:1.2rem;margin-top:1.5rem}
.flag-card{background:var(--surface);border:2px solid var(--border);border-radius:16px;padding:2rem;transition:all .3s;text-decoration:none;color:inherit;display:block;box-shadow:var(--shadow);position:relative;overflow:hidden}
.flag-card::before{content:'';position:absolute;top:0;left:0;right:0;height:3px;background:var(--accent)}
.flag-card.p{--accent:var(--purple)}.flag-card.t{--accent:var(--teal)}.flag-card.g{--accent:var(--gold)}.flag-card.c{--accent:var(--coral)}
.flag-card:hover{transform:translateY(-4px);box-shadow:var(--shadow-h);border-color:var(--accent)}
.flag-tag{display:inline-flex;align-items:center;gap:.35rem;font-family:'Space Mono',monospace;font-size:.64rem;font-weight:700;letter-spacing:.15em;color:var(--accent);text-transform:uppercase;margin-bottom:1rem}
.flag-tag::before{content:'';width:6px;height:6px;background:var(--accent);border-radius:50%}
.flag-card h3{font-size:1.5rem;font-weight:800;letter-spacing:-.02em;margin-bottom:.4rem;color:var(--text)}
.flag-card .flag-tagline{font-size:.85rem;color:var(--accent);font-weight:600;font-family:'Space Mono',monospace;margin-bottom:.9rem}
.flag-card p{font-size:.92rem;color:var(--text-soft);line-height:1.6;margin-bottom:1rem}
.flag-card-link{font-size:.82rem;color:var(--accent);font-weight:600;text-decoration:none;display:inline-flex;align-items:center;gap:.3rem}
.prod-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:1rem;margin-top:2rem}
.prod-card{background:var(--surface);border:1px solid var(--border);border-radius:12px;padding:1.4rem;transition:all .25s;text-decoration:none;color:inherit;display:block;box-shadow:var(--shadow)}
.prod-card:hover{border-color:var(--purple);transform:translateY(-2px);box-shadow:var(--shadow-h)}
.prod-card h4{font-size:1rem;font-weight:700;margin-bottom:.3rem;color:var(--text);letter-spacing:-.01em}
.prod-card .suite-tag{font-size:.66rem;font-family:'Space Mono',monospace;font-weight:600;color:var(--text-dim);text-transform:uppercase;letter-spacing:.08em;margin-bottom:.55rem;display:block}
.prod-card p{font-size:.82rem;color:var(--text-soft);line-height:1.55}
.suite-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:1rem;margin-top:2rem}
.suite-tile{background:var(--surface);border:1px solid var(--border);border-radius:14px;padding:1.6rem 1.4rem;text-decoration:none;color:inherit;display:block;transition:all .25s;box-shadow:var(--shadow);position:relative;overflow:hidden;min-height:190px}
.suite-tile::before{content:'';position:absolute;top:0;left:0;width:100%;height:3px;background:var(--accent)}
.suite-tile.p{--accent:var(--purple)}.suite-tile.t{--accent:var(--teal)}.suite-tile.g{--accent:var(--gold)}.suite-tile.c{--accent:var(--coral)}
.suite-tile:hover{transform:translateY(-3px);border-color:var(--accent);box-shadow:var(--shadow-h)}
.suite-tile h4{font-size:1.02rem;font-weight:700;color:var(--text);margin-bottom:.5rem;letter-spacing:-.01em}
.suite-tile .suite-cnt{display:inline-block;font-family:'Space Mono',monospace;font-size:.66rem;font-weight:700;color:#ffffff;background:var(--accent);padding:.22rem .6rem;border-radius:4px;margin-bottom:.9rem;letter-spacing:.08em;box-shadow:0 2px 6px color-mix(in srgb,var(--accent) 30%,transparent)}
.suite-tile p{font-size:.82rem;color:var(--text-soft);line-height:1.55}
.cta{text-align:center;padding:4.5rem 2rem;margin:3rem 4% 2rem;background:linear-gradient(135deg,rgba(111,92,255,.04),rgba(13,148,136,.04));border:1px solid var(--border);border-radius:22px;max-width:1100px;margin-left:auto;margin-right:auto}
.cta p{color:var(--text-soft);max-width:560px;margin:0 auto 2rem}
.btn-p{background:var(--btn-p);color:#fff;padding:.95rem 2rem;border-radius:10px;font-weight:600;font-size:.9rem;text-decoration:none;transition:all .25s;display:inline-flex;align-items:center;gap:.4rem;box-shadow:0 4px 12px rgba(91,76,219,.25)}
.btn-p:hover{background:var(--btn-p-h);transform:translateY(-2px)}
.btn-o{background:transparent;color:var(--text);padding:.95rem 2rem;border-radius:10px;font-weight:500;font-size:.9rem;text-decoration:none;border:1px solid var(--border-mid);transition:all .25s;display:inline-flex;align-items:center;gap:.4rem}
.btn-o:hover{border-color:var(--purple);color:var(--purple)}
.btns{display:flex;gap:1rem;flex-wrap:wrap;justify-content:center}
footer{padding:2.5rem 4% 1.5rem;max-width:1200px;margin:2rem auto 0;border-top:1px solid var(--border)}
.foot-t{display:flex;justify-content:space-between;align-items:center;margin-bottom:1rem;flex-wrap:wrap;gap:1rem}
.foot-t .logo{font-size:1.1rem}
.foot-links{display:flex;gap:1.3rem;font-size:.85rem;align-items:center;flex-wrap:wrap}
.foot-links a{color:var(--text-soft);text-decoration:none;transition:color .2s;display:inline-flex;align-items:center;gap:.35rem}
.foot-links a:hover{color:var(--purple)}
.foot-b{font-size:.74rem;color:var(--text-dim);font-family:'Space Mono',monospace;letter-spacing:.04em}
.foot-b a{color:var(--purple);text-decoration:none}
@media(max-width:900px){.flag-grid{grid-template-columns:1fr}.prod-grid{grid-template-columns:1fr}.suite-grid{grid-template-columns:1fr 1fr}.nav-r a:not(.btn-n):not(.theme-toggle){display:none}}
@media(max-width:600px){.suite-grid{grid-template-columns:1fr}.kpis{gap:1.5rem}}
</style>
</head><body>
<nav>
<a class="logo" href="/"><span class="logo-dot"></span>WEVAL<span style="color:var(--purple)">.</span></a>
<div class="nav-r">
<a href="/">Accueil</a>
<a href="/products/">Produits</a>
<a href="/marketplace">Marketplace</a>
<button class="theme-toggle" onclick="(function(){var c=document.documentElement.getAttribute('data-theme')==='dark'?'light':'dark';document.documentElement.setAttribute('data-theme',c);localStorage.setItem('weval-theme',c);})()" aria-label="Basculer thème jour/nuit"><svg class="icon-sun" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4"/><path d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M6.34 17.66l-1.41 1.41M19.07 4.93l-1.41 1.41"/></svg><svg class="icon-moon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/></svg></button>
<a href="#flagships" class="btn-n">Voir les flagships &rarr;</a>
</div>
</nav>
<section class="hero">
<div class="badge">Catalogue produits WEVAL</div>
<h1>{{N_PRODS}} applications, <em>{{N_SUITES}} suites.</em><br>Une stack IA souveraine.</h1>
<p class="sub">De l'orchestration multi-agents à l'automatisation bureautique, de l'intelligence pharmaceutique au marketing haute performance. Tout est propriété WEVAL, déployable chez vous, conforme RGPD et AI Act.</p>
<div class="kpis">
<div class="kpi"><div class="kpi-n">{{N_PRODS}}</div><div class="kpi-l">Applications</div></div>
<div class="kpi"><div class="kpi-n">{{N_SUITES}}</div><div class="kpi-l">Suites métier</div></div>
<div class="kpi"><div class="kpi-n">4</div><div class="kpi-l">Flagships</div></div>
<div class="kpi"><div class="kpi-n">6sigma</div><div class="kpi-l">Qualité 6σ</div></div>
</div>
</section>
<section class="sec" id="flagships">
<div class="stag p">// Flagships</div>
<h2>Quatre <em style="color:var(--purple)">applications phares,</em> au cœur de notre offre.</h2>
<p class="sd">Quatre applications structurantes. Chacune se suffit à elle-même. Ensemble, elles forment le cœur de la proposition de valeur WEVAL.</p>
<div class="flag-grid">{{FLAGSHIPS_HTML}}</div>
</section>
<section class="sec alt" id="catalogue">
<div class="stag t">// Toutes les applications</div>
<h2>{{N_PRODS}} applications, <em style="color:var(--teal)">prêtes à déployer.</em></h2>
<p class="sd">Notre gamme complète dapplications IA. Chaque fiche présente le positionnement, les capacités clés, les métriques dusage et lintégration dans une suite. Toutes sont éprouvées en production et maintenues sous standard qualité Six Sigma.</p>
<div class="prod-grid">{{PRODUCTS_HTML}}</div>
</section>
<section class="sec" id="suites">
<div class="stag g">// Suites métier</div>
<h2>{{N_SUITES}} suites pour <em style="color:var(--gold)">couvrir tous les métiers.</em></h2>
<p class="sd">Chaque application est aussi consommable en standalone. Regroupées en suites, elles amplifient mutuellement leur valeur. Choisissez l'entrée qui colle à votre contexte : par produit ou par suite.</p>
<div class="suite-grid">{{SUITES_HTML}}</div>
</section>
<div class="cta">
<h2>Prêt à <em style="color:var(--purple)">tester</em> ?</h2>
<p>Démonstration personnalisée sur vos données. Diagnostic cas d'usage, scoping technique, proposition POC en 45 minutes. POC gratuit 2 semaines. MVP 1 mois. Déploiement Enterprise 3 mois.</p>
<div class="btns">
<a href="/#contact" class="btn-p">Réserver un POC -&gt;</a>
<a href="/marketplace" class="btn-o">Voir la marketplace</a>
</div>
</div>
<footer>
<div class="foot-t">
<a class="logo" href="/"><span class="logo-dot"></span>WEVAL<span style="color:var(--purple)">.</span></a>
<div class="foot-links">
<a href="/">Accueil</a>
<a href="/products/">Produits</a>
<a href="/marketplace">Marketplace</a>
<a href="/#contact">Contact</a>
<a href="https://www.linkedin.com/company/weval" target="_blank" rel="noopener" aria-label="LinkedIn"><svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M19 3a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h14zM8.339 18.337V9.886H5.67v8.451h2.669zM7.003 8.687a1.549 1.549 0 1 0 0-3.097 1.549 1.549 0 0 0 0 3.097zm11.335 9.65v-4.637c0-2.475-1.332-3.625-3.109-3.625-1.434 0-2.076.788-2.436 1.342v-1.152H10.12c.037.778 0 8.451 0 8.451h2.673v-4.72c0-.24.017-.48.088-.652.193-.479.631-.975 1.367-.975.964 0 1.35.734 1.35 1.811v4.537h2.672z"/></svg> LinkedIn</a>
</div>
</div>
<div class="foot-b">&copy; 2026 WEVAL Consulting &middot; Cabinet de conseil &amp; editeur IA souveraine &middot; Partenaire Ecosysteme SAP &middot; Huawei Cloud Certified &middot; <a href="https://www.linkedin.com/company/weval" target="_blank" rel="noopener">Suivez-nous sur LinkedIn -&gt;</a></div>
</footer>
</body></html>
HTMLIDX;
}
function build_products_index(): array {
// Build FLAGSHIPS html (fetch page data from /products/*.html)
$flag_html = '';
$class_map = ['purple' => 'p', 'teal' => 't', 'gold' => 'g', 'coral' => 'c'];
foreach (FLAGSHIPS as [$slug, $color, $tagline, $desc]) {
$page = "/var/www/html/products/{$slug}.html";
if (!file_exists($page)) continue;
// Get display name from PRODUCTS const or derive
$name = isset(PRODUCTS[$slug]) ? PRODUCTS[$slug]['name'] : ucwords(str_replace('-', ' ', $slug));
$cls = $class_map[$color] ?? 'p';
$flag_html .= sprintf(
'<a class="flag-card %s" href="/products/%s.html"><div class="flag-tag">FLAGSHIP</div><h3>%s</h3><div class="flag-tagline">%s</div><p>%s</p><span class="flag-card-link">Voir la fiche produit -&gt;</span></a>',
$cls, htmlspecialchars($slug),
htmlspecialchars($name), htmlspecialchars($tagline), htmlspecialchars($desc)
);
}
// Build PRODUCTS grid (only rebranded ones from PRODUCTS const, excluding flagships already shown)
$flagship_slugs = array_column(FLAGSHIPS, 0);
$prod_html = '';
$prod_count = 0;
foreach (PRODUCTS as $slug => $p) {
if (in_array($slug, $flagship_slugs, true)) continue;
$page = "/var/www/html/products/{$slug}.html";
if (!file_exists($page)) continue;
$desc_short = mb_substr(strip_tags($p['desc']), 0, 120);
if (mb_strlen(strip_tags($p['desc'])) > 120) $desc_short .= '...';
$prod_html .= sprintf(
'<a class="prod-card" href="/products/%s.html"><span class="suite-tag">%s</span><h4>%s</h4><p>%s</p></a>',
htmlspecialchars($slug), htmlspecialchars($p['suite']),
htmlspecialchars($p['name']), htmlspecialchars($desc_short)
);
$prod_count++;
}
// Build SUITES grid
$accent_map = ['purple' => 'p', 'teal' => 't', 'gold' => 'g', 'coral' => 'c'];
$suite_html = '';
$suite_count = 0;
// 2 legacy SUITES first (wevia-enterprise, pharma-cloud) then extended SUITE_PAGES
foreach (SUITE_PAGES as $slug => $s) {
$page = "/var/www/html/solutions/{$slug}.html";
if (!file_exists($page)) continue;
$cls = $accent_map[$s['accent']] ?? 'p';
$n_apps = count($s['apps']);
$intro_short = mb_substr(strip_tags($s['intro']), 0, 110) . '...';
$suite_html .= sprintf(
'<a class="suite-tile %s" href="/solutions/%s.html"><div class="suite-cnt">%d APPS</div><h4>%s</h4><p>%s</p></a>',
$cls, htmlspecialchars($slug), $n_apps,
htmlspecialchars($s['name']), htmlspecialchars($intro_short)
);
$suite_count++;
}
$html = get_index_template();
$total_prods = count(FLAGSHIPS) + $prod_count;
$vars = [
'{{N_PRODS}}' => (string)$total_prods,
'{{N_SUITES}}' => (string)$suite_count,
'{{FLAGSHIPS_HTML}}' => $flag_html,
'{{PRODUCTS_HTML}}' => $prod_html,
'{{SUITES_HTML}}' => $suite_html,
];
$html = strtr($html, $vars);
// Doctrine 108 check
foreach (FORBIDDEN_TERMS as $term) {
$pattern = '/\b' . preg_quote($term, '/') . '\b/';
if (preg_match($pattern, $html)) {
return ['ok' => false, 'error' => "Forbidden term: $term"];
}
}
return ['ok' => true, 'html' => $html, 'bytes' => strlen($html),
'flagships' => count(FLAGSHIPS), 'products' => $prod_count, 'suites' => $suite_count];
}
if (PHP_SAPI !== 'cli') { http_response_code(403); echo "CLI only"; exit; }
$action = $argv[1] ?? 'help';
switch ($action) {
case 'build':
$slug = $argv[2] ?? null;
if (!$slug) { echo "Usage: build SLUG\n"; exit(1); }
echo json_encode(build_page($slug), JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE) . "\n";
break;
case 'build_all':
$ok = 0; $fail = 0;
foreach (array_keys(PRODUCTS) as $slug) {
$r = build_page($slug);
if ($r['ok']) { $ok++; } else { $fail++; }
echo sprintf("[%s] %-20s %s\n", $r['ok'] ? 'OK' : 'XX', $slug,
$r['ok'] ? ($r['bytes'] . 'B, ' . $r['features'] . ' features, theme=' . $r['theme']) : $r['error']);
}
echo sprintf("\n=== %d OK · %d FAIL ===\n", $ok, $fail);
break;
case 'list':
foreach (PRODUCTS as $s => $p) echo sprintf("%-20s | %-25s | %s\n", $s, $p['suite'], $p['tagline']);
break;
case 'scan_forbidden':
$hits = scan_forbidden('/var/www/html');
if (!$hits) { echo "Aucune occurrence interdite trouvée.\n"; exit(0); }
foreach ($hits as $h) echo sprintf("FOUND: %s in %s\n", $h['term'], $h['file']);
echo sprintf("\n=== %d fichiers à nettoyer ===\n", count($hits));
break;
case 'validate':
$slug = $argv[2] ?? null;
if (!$slug) { echo "Usage: validate SLUG\n"; exit(1); }
$target = "/var/www/html/products/{$slug}.html";
if (!file_exists($target)) { echo "NOT FOUND: $target\n"; exit(1); }
$c = file_get_contents($target);
$report = [
'exists' => true, 'size' => strlen($c),
'has_doctype' => str_contains($c, '<!DOCTYPE html>'),
'has_title' => str_contains($c, '<title>'),
'has_og' => str_contains($c, 'og:title'),
'has_suite_link' => str_contains($c, '/solutions/'),
'has_theme_toggle' => str_contains($c, 'weval-theme'),
'light_by_default' => str_contains($c, 'data-theme="light"'),
'forbidden_hits' => [],
];
foreach (FORBIDDEN_TERMS as $t) {
$pattern = '/\b' . preg_quote($t, '/') . '\b/';
if (preg_match($pattern, $c)) $report['forbidden_hits'][] = $t;
}
$report['doctrine_108_pass'] = empty($report['forbidden_hits']);
echo json_encode($report, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES) . "\n";
break;
case 'build_suite':
$slug = $argv[2] ?? null;
if (!$slug) { echo "Usage: build_suite SLUG\n"; exit(1); }
echo json_encode(build_suite_page($slug), JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE) . "\n";
break;
case 'build_all_suites':
$ok = 0; $fail = 0;
foreach (array_keys(SUITE_PAGES) as $slug) {
$r = build_suite_page($slug);
if ($r['ok']) { $ok++; } else { $fail++; }
echo sprintf("[%s] %-20s %s\n", $r['ok'] ? 'OK' : 'XX', $slug,
$r['ok'] ? ($r['bytes'] . 'B, ' . $r['apps'] . ' apps') : $r['error']);
}
echo sprintf("\n=== %d OK - %d FAIL ===\n", $ok, $fail);
break;
default:
case 'build_index':
$r = build_products_index();
if (!$r['ok']) { echo json_encode($r) . "\n"; exit(1); }
$target = '/var/www/html/products/index.html';
if (file_exists($target)) {
$gold_dir = '/opt/wevads/vault/gold-products-index-' . date('Ymd');
if (!is_dir($gold_dir)) @mkdir($gold_dir, 0755, true);
@copy($target, $gold_dir . "/index-builder-" . date('His') . '.html');
}
// Write alongside — caller must unlock chattr + move to target
$tmp = '/opt/weval-l99/tmp-index.html';
file_put_contents($tmp, $r['html']);
echo json_encode(['ok' => true, 'tmp' => $tmp, 'bytes' => $r['bytes'], 'flagships' => $r['flagships'], 'products' => $r['products'], 'suites' => $r['suites']], JSON_UNESCAPED_SLASHES) . "\n";
break;
echo "wevia-site-builder.php v3 (light+toggle, EM flagship, suites, LinkedIn)\n";
echo " build SLUG | build_all | build_suite SLUG | build_all_suites\n";
echo " list | scan_forbidden | validate SLUG\n";
}