Commit graph

61 commits

Author SHA1 Message Date
isUnknown
1cbb843c89 Feat: ajustements UI white-paper, home, portfolio + icône download
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 11:21:05 +01:00
isUnknown
fcca068868 Fix: navigation sous-pages blog/white-papers + singleSlug
All checks were successful
Deploy / Deploy to Production (push) Successful in 25s
- App.svelte : flèches clavier bloquées sur sous-page (ArrowLeft → history.back())
- Blog/WhitePapers : reset de articleData/itemData après 1100ms (post-transition)
  pour éviter le flash pendant l'animation de changement de slide
- WhitePapers : singleSlug jamais resetté (pré-affiché à l'arrivée sur la slide)
- WhitePapers : $effect sur isActive pour replaceState + openItem si itemData null
- WhitePapers/Blog : handlePopState ignore les popstate hors de la page courante

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 07:36:43 +01:00
isUnknown
9f8854efa5 Fix: suppression du timing check (faux positifs sur desktop)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 07:15:44 +01:00
isUnknown
67d8159787 Feat: sécurisation formulaire white paper + stockage leads
- Honeypot, timing check, rate limiting IP, validation serveur
- Déduplication par email : enrichissement des champs vides si contact existant
- Blueprint white-paper : onglet "Contacts intéressés" (champ structure contactDatabase)
- Blueprint site.yml : ajout onglet "Données d'usage" pour vue globale des leads
- Route externalisée dans site/config/routes/download-white-paper.php
- isDownloadable côté client (prénom, nom, email valide, consentement)
- Cursor : pas de hover sur boutons disabled
- Buttons : hover désactivé si disabled

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 07:11:00 +01:00
isUnknown
974067d986 Refactor: WhitePaper — redesign layout + suppression préfixes wp-
- Nouveau layout desktop : flex row avec catch-area (label + titre) et form-area (formulaire)
- Mobile : height 100vh non-scrollable, overlay formulaire déclenché au clic
- Tablet : grid 2 colonnes
- Suppression des préfixes wp- sur toutes les classes (CSS scopé Svelte)
- white-paper.json.php : intro via ->inline() pour texte brut

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-18 18:48:50 +01:00
isUnknown
d4f05d6157 Feat: Livres blancs — nouveau template collection + livre blanc individuel
- Blueprints white-papers / white-paper (intro, cover, PDF, date)
- Templates PHP + JSON API (liste avec singleSlug, détail avec fileUrl)
- Route POST (:any)/(:any)/download pour le téléchargement gated
- Panel : entrée white-papers ajoutée au menu après blog
- collection.css : styles partagés extraits de Blog (collection-*)
- Blog.svelte : classes renommées blog-* → collection-*
- WhitePapers.svelte : vue liste, URLs dynamiques via data.uri
- WhitePaper.svelte : vue détail deux colonnes + formulaire de téléchargement
- i18n : clés white paper (label, form, consentement, statuts)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-18 17:37:22 +01:00
isUnknown
c6fa61c77b Feat: footer reveal — page-scrollable-footer intégré aux vues
All checks were successful
Deploy / Deploy to Production (push) Successful in 25s
- Footer renommé page-scrollable-footer, positionné en dernier enfant
  de .page-container dans About, Blog et Article
- Marges négatives pour aligner le footer pleine largeur (about / blog)
- Retrait du footer global fixe de App.svelte

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-18 12:14:59 +01:00
isUnknown
b3b0580ab1 Feat: footer reveal + refactor page About
All checks were successful
Deploy / Deploy to Production (push) Successful in 24s
- Footer global fixé en bas (App.svelte), masqué par le contenu des slides
- margin-bottom sur .page-scrollable pour l'effet footer reveal (about, blog, article)
- About : champ intro remplacé par heading (text) + subtitle (writer), blueprint + API + vue mis à jour
- LanguageSwitcher : div → button avec hitbox élargie
- i18n : clé our_team (fr: NOTRE ÉQUIPE / en: OUR TEAM)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-17 10:00:53 +01:00
isUnknown
61607f8cd7 Feat: page À propos — redesign complet avec carrousel équipe
All checks were successful
Deploy / Deploy to Production (push) Successful in 5m23s
- Fix about.json.php : lecture des vrais champs Kirby (intro writer,
  body blocks, files template member) — corrige le bug [object Object]
- About.svelte : redesign fidèle à la source (intro centrée, blocs
  mission/manifeste avec bordure verte, carrousel équipe horizontal
  3/2/1 items selon breakpoint, swipe tactile, prev/next + pagination)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-13 10:39:24 +01:00
isUnknown
773be2840c Feat: swipe gauche/droite sur Play mobile
All checks were successful
Deploy / Deploy to Production (push) Successful in 19s
Même logique que les touches fléchées : navigation entre jeux,
aux limites passage à la slide précédente/suivante via slideTo.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-13 09:31:43 +01:00
isUnknown
44912c1d2f Fix: Play mobile layout adjustments
All checks were successful
Deploy / Deploy to Production (push) Successful in 23s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-13 09:21:50 +01:00
isUnknown
4eb495c021 Refactor: header sémantique + backdrop limité à expertise/about/blog
- Header : <nav> enveloppée dans <header> (landmark sémantique)
- Backdrop navbar restreint aux slides about et blog (scroll > 100px)
- Portfolio : $effect navbar backdrop supprimé + import navigation retiré

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-13 09:06:14 +01:00
isUnknown
0a346040a2 Fix: portfolio mobile layout adjustments
All checks were successful
Deploy / Deploy to Production (push) Successful in 19s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-12 19:33:01 +01:00
isUnknown
e45380258b Feat: portfolio polish + font Danzza Light
- App.svelte : classe active sur la slide courante
- Portfolio : flèches PNG custom, <output> pour le compteur, transition gallery mobile avec délai à l'entrée seulement
- fonts.css : @font-face Danzza Light + classe .font-face-danzza-light corrigée

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-12 19:28:44 +01:00
isUnknown
ae86f0ce1c Feat: Portfolio mobile — background image + gallery animation + arrows/counter
- Background fixe mobile (BG GAME MOBILE.png, position bottom)
- GalleryAnimation en plein écran sur mobile (position fixed, opacité 0.8)
- Arrows + compteur 01/05 ajoutés (desktop grid-area 18/16, mobile 18/15)
- Layout mobile : mockup centré, texte par-dessus, keywords masqués, nav horizontale 75px
- Séparation desktop-only / mobile-only pour la galerie

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-12 18:37:58 +01:00
isUnknown
a0798e71d0 Feat: navbar frosted glass au scroll
- navigation.svelte.js : ajout isScrolled + setScrolled()
- Header : scroll listener (capture) sur .page-scrollable > 100px,
  reset au changement de slide, classe navbar--scrolled conditionnelle,
  transition 0.4s sur background-color et backdrop-filter
- Expertise : $effect notifie quand currentItem > 0
- Portfolio : $effect notifie quand currentIndex > 0

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-12 15:05:25 +01:00
isUnknown
517143fe60 Feat: intégration multilingue FR/EN (i18n)
All checks were successful
Deploy / Deploy to Production (push) Successful in 18s
- Ajout de src/i18n/index.js : dictionnaire centralisé + fonction t(key, vars)
- Ajout de LanguageSwitcher.svelte : toggle FR/EN avec persistance localStorage
- Router : normalizePath strip /en/, apiPrefix() pour les fetches, détection langue (URL > localStorage > navigator)
- Tous les composants (Header, Menu, Footer, Article, Blog, Play) migrent vers t() depuis @i18n
- Blog : navigation interne (fetch, history, getSlugFromUrl) locale-aware

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-12 11:57:59 +01:00
isUnknown
3bd410cc02 Fix: footer repositionné sous l'article via article-wrapper
Le footer était auto-placé par la CSS Grid golden-grid avant l'article.
Wrap article + footer dans .article-wrapper qui porte le grid-area.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-12 11:38:01 +01:00
isUnknown
3a2b5a2f57 Perf: optimisation vidéos page expertise
All checks were successful
Deploy / Deploy to Production (push) Successful in 21s
- Vidéos recompressées (CRF 23, faststart) : 13MB → 3.4MB et 3.7MB
- Champs Kirby dynamiques pour vidéo normale et inverse
- Sources dynamiques via data.backgroundVideo / data.backgroundVideoReverse

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-11 15:54:49 +01:00
isUnknown
2373b81db7 Perf: optimisation vidéos page d'accueil
- Vidéos recompressées (CRF 23, faststart, full res/fps) : 22MB → 5.8MB et 4.8MB
- Champs Kirby dynamiques pour vidéo desktop/mobile + posters
- Source vidéo dynamique via data.backgroundVideo (corrige le hardcode)
- Lecture déclenchée sur canplay plutôt qu'immédiatement (évite freeze)
- preload="auto" pour un buffering plus agressif

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-11 15:39:19 +01:00
isUnknown
0233a6a4a4 Feat: footer sémantique dans Blog, About et Article
All checks were successful
Deploy / Deploy to Production (push) Successful in 19s
Refonte complète du Footer (sémantique propre, données dynamiques depuis
le store site, bouton subscribe avec l'animation .button partagée).
Intégré dans About, Blog et Article. Scroll-to-top au départ de About et Blog.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-11 10:57:52 +01:00
isUnknown
eef95f10d6 Feat: background fixe partagé entre About et Blog
All checks were successful
Deploy / Deploy to Production (push) Successful in 21s
Ajout d'un calque position:fixed avec BACKGROUND2 derrière toutes les slides.
About et Blog (transparents) le laissent apparaître naturellement.
Les autres slides (opaques) le recouvrent sans changement.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-11 10:33:03 +01:00
isUnknown
1a036774f8 Fix: styles article-body — padding, alignement, typographie
All checks were successful
Deploy / Deploy to Production (push) Successful in 5m21s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-10 19:31:56 +01:00
isUnknown
3c5b4f76dd Feat: header article avec date + boutons de partage, share section bas de page, golden-grid conditionnel
All checks were successful
Deploy / Deploy to Production (push) Successful in 18s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-10 19:19:05 +01:00
isUnknown
b9631b8c53 Fix: remplacer custom media queries par valeurs en dur, retirer postcss-custom-media
All checks were successful
Deploy / Deploy to Production (push) Successful in 5m23s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-10 18:55:37 +01:00
isUnknown
93308bbb65 Fix: blog — date published, intro sans excerpt, styles card affinés
All checks were successful
Deploy / Deploy to Production (push) Successful in 19s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-10 17:45:11 +01:00
isUnknown
0505cc7b8e Feat: pages Article + navigation blog/article interne
All checks were successful
Deploy / Deploy to Production (push) Successful in 19s
- Router: findSlideIndex() avec fallback parent path
  (/blog/slug → /blog) pour sub-pages
- article.json.php: réécriture — date, intro, cover, body (blocks→HTML),
  related articles (fallback siblings si vide)
- Article.svelte: sous-composant — topbar date+retour, titre Terminal,
  intro, cover, body rich text (styles :global pour blocks Kirby),
  related articles grid, responsive
- Blog.svelte: gère deux modes (liste + article) —
  intercepte les clics article via stopPropagation (avant le router),
  fetch article data, pushState pour URL, popstate pour back/forward,
  direct navigation /blog/slug sur mount

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-10 16:55:34 +01:00
isUnknown
3ab4b21e8c Feat: implémentation front page Blog
- blog.json.php : réécriture — intro (writer), featured (pages field),
  articles triés par date desc (featured exclu de la liste)
- layout.css : .page-scrollable + .page-container (styles génériques
  pour pages scrollables type blog/article)
- Blog.svelte : page scrollable avec header intro, article featured
  (image large + excerpt), liste articles avec dividers, responsive
  mobile/tablet via @custom-media

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-10 16:47:49 +01:00
isUnknown
34635f7982 Fix: navigation clavier Play — capture phase + stopImmediatePropagation
All checks were successful
Deploy / Deploy to Production (push) Successful in 18s
- Handler enregistré en { capture: true } → s'exécute avant App.svelte
- stopImmediatePropagation quand navigation interne (pas aux limites)
  → empêche App de changer de slide en même temps
- Aux limites : aucune interception → App gère naturellement la slide adjacente
- Supprimé : slideTo import, prevSlidePath/nextSlidePath (inutiles)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-10 09:18:44 +01:00
isUnknown
fdab621b48 Feat: navigation clavier + routing ancre sur Play
- ArrowRight/Left : navigue entre les jeux
  aux limites (premier/dernier), passe à la slide prev/next
- Ancres URL (#slug) : set à chaque changement de jeu,
  restaurées au chargement, effacées quand on quitte la slide

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-10 09:03:10 +01:00
isUnknown
90f155b679 Fix: blueprint game + styles carrousel Play
- playLink renommé et translate: false sur playLink + backgroundColor
- button { border: none } dans buttons.css
- Largeur vignettes via :global(img) sur l'élément image
  (découple la taille du bouton de celle de l'image)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-10 09:01:58 +01:00
isUnknown
66767f0136 Feat: breakpoints CSS en @custom-media via postcss-custom-media
- postcss.config.js: plugin postcss-custom-media
- variables.css: @custom-media --mobile / --tablet / --tablet-only
- Remplacement de tous les max-width: 700px et 912px hardcodés
  par @media (--mobile), (--tablet), (--tablet-only)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-10 08:34:37 +01:00
isUnknown
0ea4bfe539 Feat: images responsives mockup Portfolio via ResponsivePicture
- Config: presets mockup + mockup-webp (350/480/700/960w)
- portfolio.json.php: expose mockupSrcset + mockupWebp
- Portfolio.svelte: remplace <img> par ResponsivePicture
  sizes="(max-width: 700px) 90vw, 25vw"

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-10 08:12:20 +01:00
isUnknown
11a2c623cb Feat: images responsives vignettes Play + composant ResponsivePicture
- Config: presets thumbnail + thumbnail-webp (170/255/355/510/710w)
- play.json.php: expose thumbnailSrcset + thumbnailWebp
- Nouveau composant ResponsivePicture.svelte (src, srcset, webp, sizes, alt, cls)
- Play.svelte: utilise ResponsivePicture dans le carousel
  sizes="clamp(170px, 18.41vw, 355px)"

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-10 08:08:34 +01:00
isUnknown
600ce937a3 Feat: transitions Play soignées — exit/enter directionnel + bg crossfade + game-preview
All checks were successful
Deploy / Deploy to Production (push) Successful in 17s
- Phase exiting (300ms) : featured + game-preview glissent/fondent dans slideDir
- Phase entering (350ms) : nouvel contenu entre depuis la direction opposée
- Swap currentIndex à 300ms : carousel grossit + bg crossfade simultanés
- Ajout game-preview (image preview côté droit, grid-area 3/13)
- Ajout preview dans le template JSON PHP
- Masqué sur mobile

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-09 19:24:41 +01:00
isUnknown
bbab752fd6 Fix: suppression de la classe slide en doublon dans toutes les vues
All checks were successful
Deploy / Deploy to Production (push) Successful in 18s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-09 18:54:51 +01:00
isUnknown
5eaf99f7cd Feat: page Play — backgroundColor, playLink, play-icon + fix slug jouer
All checks were successful
Deploy / Deploy to Production (push) Successful in 5m22s
- Renommage dossier content 3_play → 3_jouer (slug /jouer)
- Champ backgroundColor (code-editor) dans game.yml + exposé en API
- playLinks simplifié en champ url simple → playLink dans l'API
- Variable CSS --background-color sur la section .play
- Bouton "Jouer" avec icône play-icon (SVG data URI dans buttons.css)
- Plugin sylvainjule/code-editor ajouté via composer

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-09 18:41:05 +01:00
isUnknown
3cafcf3167 Feat: lignes courbes SVG sur Play + refonte blueprint game
- Play.svelte : ajout overlay SVG (background-play), suppression des vertical-line
- game.yml : restructuration du blueprint
- Header.svelte : modifications mineures

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 14:18:38 +01:00
isUnknown
69859cc60f Refactor: snake_case → camelCase dans blueprints, templates et vues
- Blueprints : renommage des champs (member_name, related_articles,
  background_video, play_links, images_gallery, external_links) et
  des noms de sections
- Templates JSON PHP : clés de sortie et appels ->method() en camelCase
- Vues Svelte (Play, Portfolio) : accès aux données alignés

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 13:40:33 +01:00
isUnknown
d8a0fde34c Upgrade Svelte 5.0.0 → 5.53.7 + fix Cursor class syntax
All checks were successful
Deploy / Deploy to Production (push) Successful in 18s
- Mise à jour de Svelte vers 5.53.7 pour supporter la syntaxe tableau/objet sur l'attribut class
- Cursor.svelte : class={[...]} avec états onTarget et onClick
- blueprints : catchphrase → catchPhrase
- buttons.css : suppression cursor: pointer
- Portfolio.svelte : scale hover nav item

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-09 13:20:28 +01:00
isUnknown
c41eec0385 style button and earth icon variant
All checks were successful
Deploy / Deploy to Production (push) Successful in 16s
2026-03-09 11:57:28 +01:00
isUnknown
802a3ed5bf Feat: couleur d'arrière-plan dynamique sur GalleryAnimation (galleryBackgroundColor)
All checks were successful
Deploy / Deploy to Production (push) Successful in 19s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-06 18:22:50 +01:00
isUnknown
6151dd5a31 Feat: page Jouer renommée Play + vue implémentée
All checks were successful
Deploy / Deploy to Production (push) Successful in 20s
Renommage jouer → play (blueprint, template, txt, vue)
API play.json.php : title, lettering, description, thumbnail,
background_image, play_links par jeu enfant listed()
Vue Play.svelte :
- Fond image avec crossfade (transition opacity sur .play-bg)
- Section principale (.play-featured) : glissé/fondu au changement de jeu
  via --slide-dir CSS var + classes is-out
- Carrousel nav (ul > li > button) : thumbnail + titre, active bordure verte
- Jeu sans play_links → bouton "Coming soon" désactivé
- Layout golden-grid, mobile adapté

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-06 17:58:29 +01:00
isUnknown
3ce350d2d7 portfolio > nav : increase gap between items
All checks were successful
Deploy / Deploy to Production (push) Successful in 19s
2026-03-06 17:39:22 +01:00
isUnknown
7bc6451ae5 Fix: classe active sur le li au lieu du button dans la nav Portfolio
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-06 17:38:25 +01:00
isUnknown
594d53f50e Refactor: sémantique nav Portfolio — ul > li > button
- nav > ul[role=list] > li > button
- aria-current sur l'item actif
- aria-label={project.title} sur le button (le texte visible est le numéro)
- alt="" sur la vignette (décorative, le titre est porté par aria-label)
- aria-hidden sur le numéro (redondant avec aria-label)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-06 17:32:22 +01:00
isUnknown
0b19589288 Tweak: ajustements style Portfolio
All checks were successful
Deploy / Deploy to Production (push) Successful in 20s
- Catchphrase en gradient-blue + Danzza Medium
- Titre en font-size-title-main + uppercase
- Description en font-size-subtitle
- Numéro nav après la vignette, align-items flex-start
- Vignette active scale(1.5) translateX(-20%)
- padding-right nav sidebar augmenté
- grid-area portfolio-text réduit d'une colonne

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-06 16:42:25 +01:00
isUnknown
436a4371da Fix: is-animated et ancre URL au chargement
All checks were successful
Deploy / Deploy to Production (push) Successful in 21s
is-animated : double rAF garantit un paint avec le bon translateX
avant d'activer la transition (évite l'animation parasite au load).

Ancre : capture du hash synchrone à la création du composant +
flag wasActive pour que clearAnchor() ne s'exécute pas au montage
quand isActive est encore false (slides non initialisées).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-06 12:23:47 +01:00
isUnknown
37b6ca7a5f Feat: ancres URL par projet dans la page Portfolio
- Navigation scroll/clavier → history.replaceState('#slug')
- Clic sidebar → idem
- Chargement avec #slug dans l'URL → affiche le bon projet directement
- Quitter la slide Portfolio → efface le hash

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-06 12:17:58 +01:00
isUnknown
0b563b4697 Feat: page Portfolio avec galerie animée, navigation par scroll/touch/clavier
All checks were successful
Deploy / Deploy to Production (push) Successful in 18s
- Composable useScrollNav partagé entre Expertise et Portfolio (wheel/touch/clavier)
- GalleryAnimation : 3 colonnes CSS défilantes infinies avec décalage et delay
- Portfolio : golden grid, mockup centré, infos projet, sidebar vignettes navigables
- API portfolio.json.php alignée sur blueprint project.yml (catchphrase, images_gallery, mockup, keywords, external_links)
- Variable --ease-standard partagée dans variables.css
- Alias @composables ajouté dans vite.config.js
- Refactor Expertise pour utiliser le composable (comportement identique)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-05 17:13:50 +01:00