diff --git a/kanban/cards/5-planifie/055-carte-hors-ligne-tile-packs-mapbox.md b/kanban/cards/5-planifie/055-carte-hors-ligne-tile-packs-mapbox.md
index 9b94e41..504d2c6 100644
--- a/kanban/cards/5-planifie/055-carte-hors-ligne-tile-packs-mapbox.md
+++ b/kanban/cards/5-planifie/055-carte-hors-ligne-tile-packs-mapbox.md
@@ -8,6 +8,8 @@ src: analyse du code le 2026-09-04 — MapProvider, flutter_map, mapbox_maps_flu
---
Aujourd'hui aucune carte ne fonctionne hors ligne, et ce n'est pas une question de données : MapDTO porte déjà points, centerLatitude, zoom et iconResourceId, et les icônes sont téléchargées avec la visite. C'est le fond qui manque — les tuiles sont chargées en réseau, sans cache.
Le GPS, lui, n'est pas le problème : geolocator ^13.0.0 lit le GNSS, qui est autonome. Seule réserve à annoncer au client : sans A-GPS, le premier point peut demander 30 à 60 s sous couvert forestier.
-Le chemin court existe déjà dans le pubspec : mapbox_maps_flutter ^2.0.0 expose OfflineManager (style packs) et TileStore (tile regions) — on télécharge une emprise bornée au moment du téléchargement de la visite. Pour un domaine comme le Fourneau Saint-Michel, quelques dizaines de Mo. MapProvider.MapBox existe déjà côté modèle.
+Le chemin court existe déjà dans le pubspec : la version résolue est 2.8.0 (pas 2.0.0 comme le laisse croire la contrainte), et le paquet installé contient bien OfflineManager, TileStore, StylePackLoadOptions, TileRegionLoadOptions et TileRegion — vérifié dans le cache pub, pas supposé. On télécharge une emprise bornée au moment du téléchargement de la visite ; pour un domaine comme le Fourneau, quelques dizaines de Mo.
+✅ Mapbox est désormais le fournisseur par défaut (04/09) : le null retombait sur Google dans map_page.dart (deux endroits) et map_config.dart. ⚠️ Effet de bord à surveiller — les sections carte existantes de MDLF et Fort Saint-Héribert dont le mapProvider est null basculent silencieusement de Google à Mapbox. Le token est déjà en place, en dur dans main.dart:60.
+⚠️ Ce n'est pas gratuit, et le compteur est le mauvais : ce qui coûte n'est pas la surface de l'emprise mais le nombre de téléchargements — un tile pack par visiteur. La facture monte donc avec la fréquentation, c'est-à-dire avec le succès du client. Grille à vérifier chez Mapbox, ligne « tile packs » et pas seulement « map loads ». C'est exactement ce calcul que supprime v2/plan-illustre-plan.md.
⛔ Google est une impasse, et pas seulement techniquement. Le SDK Maps pour Android n'expose aucune API de tuiles hors ligne — les « zones hors connexion » sont une fonction de l'app Google Maps, pas du SDK intégrable. Et le code n'utilise même pas ce SDK pour les sections carte : il passe par flutter_map sur https://mt1.google.com/vt/lyrs=m&x={x}&y={y}&z={z}, un endpoint non documenté dont la mise en cache est explicitement interdite. Conclusion : Mapbox devient le fournisseur du mode hors ligne, Google reste en ligne seulement.
⚠️ Tant que ce chantier n'est pas fait, SectionType.Map reste volontairement hors de offlineCapableSectionTypes (downloadConfiguration.dart) : l'ajouter donnerait une carte grise, ce qui est pire que ne pas la proposer. Une fois les tuiles packagées, c'est une ligne à ajouter dans cette constante.
diff --git a/kanban/cards/5-planifie/057-plan-illustre-georeference-3e-fournisseur.md b/kanban/cards/5-planifie/057-plan-illustre-georeference-3e-fournisseur.md
index 7d53970..e64beb2 100644
--- a/kanban/cards/5-planifie/057-plan-illustre-georeference-3e-fournisseur.md
+++ b/kanban/cards/5-planifie/057-plan-illustre-georeference-3e-fournisseur.md
@@ -1,12 +1,15 @@
---
-title: Plan illustré géoréférencé — un 3e fournisseur de carte
+title: Plan illustré — un 3e fournisseur de carte, sans tuiles
area: manager backend visitapp
horizon: v2
tags: carto, offline, manager-app
-flag: good | hors ligne par construction, et c'est ce qu'un musée dessine déjà
-src: analyse du code le 2026-09-04 — MapProvider n'a que Google et MapBox
+flag: good | le seul chemin vers une carte hors ligne sans coût tiers
+src: v2/plan-illustre-plan.md — conçu le 2026-09-04
---
-Un musée de plein air ne distribue pas un fond OpenStreetMap, il distribue son plan dessiné. Aujourd'hui MapProvider ne connaît que Google et MapBox : il n'existe aucun moyen de téléverser une image de plan et d'y placer les points.
-Ce qu'il faut : une troisième valeur de MapProvider, une ressource image portée par la section, et un calage — deux points d'ancrage suffisent (coin haut-gauche / bas-droit en coordonnées réelles) pour projeter un GeoPoint sur l'image et y afficher la position du visiteur.
-Pourquoi c'est le meilleur des trois : aucune tuile, donc hors ligne par construction — l'image part avec la visite comme n'importe quelle ressource, et le mécanisme de téléchargement n'a rien de nouveau à apprendre. Le rendu est aussi plus lisible qu'un fond routier sur un site de plusieurs dizaines de bâtiments.
-Périmètre réel : c'est le plus gros des trois chemins carto — backend (modèle + migration), manager-app (téléversement du plan et pose des ancres), mymuseum-visitapp et visitapp-web (rendu). À faire après Carte hors ligne — tile packs Mapbox, qui débloque le besoin immédiat avec un fond classique.
+Un musée de plein air ne distribue pas un fond OpenStreetMap, il distribue son plan dessiné. Conception complète, modèle de données et périmètre par repo : DOCS/v2/plan-illustre-plan.md. Rien n'est implémenté.
+La décision qui structure tout : les repères se posent directement sur l'image, à la main, et c'est cette position qui fait foi — un plan dessiné n'étant ni à l'échelle ni orienté au nord, projeter des GeoPoint depuis leurs coordonnées les ferait tomber à côté des bâtiments. Le calage GPS ne sert qu'à afficher le visiteur, et devient donc facultatif.
+⚠️ Deux affirmations de la première version de cette carte étaient fausses, corrigées le 04/09 : on ne projette pas les repères, et deux points d'ancrage ne suffisent pas — il en faut trois pour une transformation affine qui absorbe rotation et étirement, et pour pouvoir vérifier le calage au lieu de diluer l'erreur.
+✅ Le calage se fait assis : cliquer le même angle de bâtiment sur le plan puis sur une carte réelle en regard. GeolocInputContainer ouvre déjà un FlutterLocationPicker (vraie carte, recherche d'adresse) — le composant est écrit, il faut le mettre à côté du plan. Plus besoin de prestation d'installation.
+✅ Hors ligne gratuit : le plan est une Resource, une ligne dans GetReferencedResourceIds() et le pipeline existant l'embarque. Aucun tiers, aucun quota — contrairement aux tile packs Mapbox, facturés par visiteur.
+⚠️ Conséquence web à trancher : visitapp-web reste sur Leaflet (lot E, W1), et mapProviderMobileOnlyNote le dit déjà au client. Pour un plan illustré c'est bloquant — le plan est le produit. Soit on porte le rendu en CSS dans la foulée, soit le plan Essentiel, web-only, n'y a pas droit.
+Livrable qui se vend seul : le plan sans calage — téléversement, pose des repères, rendu, hors ligne. C'est le produit que les audioguides vendent depuis trente ans.
diff --git a/v2/plan-illustre-plan.md b/v2/plan-illustre-plan.md
new file mode 100644
index 0000000..47905d1
--- /dev/null
+++ b/v2/plan-illustre-plan.md
@@ -0,0 +1,164 @@
+# Plan illustré — un 3ᵉ fournisseur de carte, sans tuiles
+
+> **Contexte** : conception du 2026-09-04, déclenchée par la demande du **Fourneau Saint-Michel**
+> (musée de plein air, plusieurs dizaines de bâtiments, réseau quasi absent). Fait suite à l'analyse
+> carto du même jour, qui a établi que ni Google ni Mapbox ne donnent une carte hors ligne gratuite.
+>
+> Maquette et diagramme :
+>
+> ⚠️ **Rien n'est implémenté.** Ce document est la conception, pas un état d'avancement.
+
+---
+
+## Pourquoi ce troisième fournisseur existe
+
+`MapProvider` ne connaît que `Google` et `MapBox`. Les deux chargent leurs tuiles en réseau, et
+aucun des deux ne donne un fond hors ligne gratuit :
+
+| Fournisseur | Hors ligne | Coût |
+|---|---|---|
+| Google | ❌ Aucune API de tuiles hors ligne dans le SDK Android. Les « zones hors connexion » sont une fonction de l'app grand public, pas du SDK. De plus le code passe par `flutter_map` sur `https://mt1.google.com/vt/…`, un endpoint non documenté dont la mise en cache est interdite | — |
+| Mapbox | ✅ `OfflineManager` + `TileStore`, présents dans `mapbox_maps_flutter 2.8.0` (version résolue) | ⚠️ **Un tile pack par visiteur** : le compteur monte avec la fréquentation, donc avec le succès du client. Grille à vérifier chez Mapbox |
+| Plan illustré | ✅ **Par construction** — l'image est une `Resource`, elle part avec la visite | ✅ Aucun tiers. Le coût se déplace sur notre propre stockage : quelques Mo par visite téléchargée, prévisible |
+
+Le plan illustré est aussi **ce qu'un musée de plein air possède déjà** : un plan dessiné, plus
+lisible qu'un fond routier sur cinquante bâtiments.
+
+---
+
+## La décision qui structure tout le reste
+
+Un plan de musée est stylisé, pas à l'échelle, rarement orienté au nord. **Ne pas projeter les
+repères depuis leurs coordonnées GPS** — ils tomberaient à côté des bâtiments dessinés.
+
+> **Les repères se posent directement sur l'image, à la main, et c'est cette position qui fait foi.**
+> Le calage GPS ne sert qu'à afficher **le visiteur** — la seule donnée qui traverse la frontière
+> entre le terrain et le dessin.
+
+⚠️ **Correction par rapport à la première note du 2026-09-04** : celle-ci disait « deux points
+d'ancrage suffisent pour projeter un `GeoPoint` sur l'image ». Les deux moitiés étaient fausses —
+on ne projette pas les repères, et deux points ne suffisent pas (voir plus bas).
+
+Conséquence directe : **le calage est facultatif**. Un lieu qui ne veut pas de position visiteur
+téléverse son plan, pose ses repères, et c'est fini. Deux niveaux d'effort, deux produits vendables.
+
+### Trois points de calage, pas deux
+
+Deux points donnent une échelle et une translation — suffisant seulement si le plan est à l'échelle
+et orienté au nord, ce qu'un plan dessiné n'est presque jamais. Trois points donnent une
+transformation affine, qui absorbe la rotation et l'étirement. Le quatrième n'apporte rien tant
+qu'on ne veut pas corriger de perspective.
+
+Raison de terrain en plus : trois croix bien réparties permettent de **vérifier** le calage. Avec
+deux, toute erreur de relevé se répartit silencieusement sur toute l'image.
+
+---
+
+## Modèle de données — additif, aucune colonne existante modifiée
+
+| Champ | Où | Note |
+|---|---|---|
+| `MapProvider.IllustratedPlan` | `DTOs/SubSection/MapDTO.cs` | Troisième valeur, **position 2**. Les lignes existantes gardent 0 et 1, rien à migrer. ⚠️ À répercuter **à la main** dans `manager_api_new/lib/model/map_provider.dart` — la règle « pas de regénération du client » s'applique |
+| `PlanResourceId` / `PlanResource` | `Data/SubSection/SectionMap.cs` | Exactement sur le modèle de `IconResourceId` / `IconResource`, déjà présents dans la même classe. C'est ce parallèle qui rend le hors ligne gratuit |
+| `PlanX`, `PlanY` | `GeoPoint` (dans `SectionMap.cs`) | `double?` **normalisés 0→1**, pas des pixels : le plan peut être ré-encodé ou redimensionné sans invalider un repère |
+| `PlanAnchors` | `Data/SubSection/SectionMap.cs` | `[{planX, planY, latitude, longitude}]` en `jsonb`, comme `MapCategories` l'est déjà. Nul si le lieu ne veut pas de position visiteur |
+
+---
+
+## Le geste dans manager-app
+
+Écran concerné : `lib/Screens/Configurations/Section/SubSection/Map/map_config.dart` (481 lignes).
+
+1. **Choisir « Plan illustré »** — une valeur de plus dans `map_providers`, servie par le
+ `SingleSelectContainer` existant. Le choix masque les réglages Google/Mapbox et fait apparaître
+ la zone de plan.
+2. **Téléverser le plan** — `ResourceInputContainer`, déjà utilisé juste à côté pour l'icône.
+ Passe par la médiathèque, le quota et la compression 2560 px livrée en C4.
+3. **Poser les repères** — le plan s'affiche, on clique, un repère apparaît ; la liste des
+ `GeoPoint` existants est à côté et on y fait glisser un point déjà rempli. **Seul écran vraiment
+ neuf du chantier.**
+4. **Caler** (facultatif) — voir ci-dessous.
+
+### Le calage se fait assis, en deux clics par ancre
+
+**Personne ne va relever de coordonnées sur le terrain.** Le geste est : *cliquer le même angle de
+bâtiment deux fois* — une fois sur le plan dessiné, une fois sur une carte réelle affichée juste à
+côté. L'outil déduit les coordonnées du second clic. Aucun chiffre n'est jamais tapé.
+
+✅ **Le composant existe déjà** : `GeolocInputContainer` (`lib/Components/geoloc_input_container.dart`)
+ouvre un `FlutterLocationPicker` — vraie carte, recherche d'adresse, centrée sur Namur
+(50.429333, 4.891434) par défaut. C'est déjà lui qui sert à poser le point central d'une section
+carte. Le calage n'invente rien : il appelle deux fois le même composant dans un écran qui les met
+en regard.
+
+⚠️ **i18n obligatoire** : tout texte de cet écran passe par `AppLocalizations`, FR/EN/NL.
+
+---
+
+## Le rendu — aucun SDK de carte
+
+Une image, des repères positionnés en pourcentage par-dessus, un conteneur qui zoome.
+
+- **`mymuseum-visitapp`** : une `PlanView` à côté de `GoogleMapView` et `MapBoxView`
+ (`lib/Screens/Sections/Map/`). `InteractiveViewer` enveloppant un `Stack` donne le pincer-zoomer
+ et le déplacement sans écrire une ligne.
+- **`visitapp-web`** : le même rendu en CSS (`transform`). À écrire **après** le Flutter, qui reste
+ la référence de comportement.
+
+Ni `flutter_map`, ni `google_maps_flutter`, ni `mapbox_maps_flutter` : donc ni jeton, ni quota, ni
+compte à surveiller.
+
+La position du visiteur est un repère de plus, calculé à l'affichage par la transformation affine,
+et **masqué dès qu'il sort du cadre du plan** — un visiteur au parking ne doit pas voir son point
+collé au bord de l'image.
+
+Le GPS lui-même ne pose pas de problème : `geolocator ^13.0.0` lit le GNSS, autonome sans réseau.
+Seule réserve à annoncer au client : sans A-GPS, le premier point peut demander 30 à 60 s sous
+couvert forestier.
+
+### Ce que le hors ligne gagne
+
+Le plan est une `Resource`. Une ligne dans `SectionMap.GetReferencedResourceIds()`, à côté de
+`ResourceId(IconResourceId)`, et le pipeline de téléchargement existant l'embarque — **aucun
+mécanisme neuf**. `SectionType.Map` peut alors entrer dans `offlineCapableSectionTypes`
+(`mymuseum-visitapp/lib/Services/downloadConfiguration.dart`) pour ce fournisseur.
+
+---
+
+## ⚠️ La conséquence côté web
+
+`mapProviderMobileOnlyNote` prévient déjà le client que le fournisseur de carte ne vaut que pour le
+mobile et la borne, parce que **`visitapp-web` reste sur Leaflet** (décision du lot E, W1, le
+2026-08-11). Pour un plan illustré cette note devient gênante : le plan **est** le produit, pas un
+réglage de fond.
+
+Deux issues, à trancher : porter le rendu en web dans la foulée (c'est du CSS, quelques heures), ou
+assumer que le plan est une fonctionnalité d'app mobile et le dire à la vente. ⚠️ Le plan
+**Essentiel étant web-only**, la seconde option lui interdit le plan illustré.
+
+---
+
+## Ordre d'exécution
+
+`manager-service` → `manager_api_new` → `manager-app` → `mymuseum-visitapp` → `visitapp-web`.
+Rien ne peut être configuré tant que le modèle n'existe pas.
+
+| Repo | Travail | Ampleur |
+|---|---|---|
+| `manager-service` | Enum, 4 champs, une migration, une ligne dans `GetReferencedResourceIds` | petit |
+| `manager_api_new` | Enum et champs répercutés **à la main** | petit |
+| `manager-app` | Écran de pose des repères et du calage (le picker de carte est déjà écrit) | **le gros morceau** |
+| `mymuseum-visitapp` | `PlanView` + projection GPS | moyen |
+| `visitapp-web` | Le même rendu en CSS | moyen |
+
+### Un raccourci pour valider vite
+
+Une `PlanView` dans `mymuseum-visitapp` avec un plan et des repères **en dur** valide le rendu et le
+pincer-zoomer en une heure, avant d'engager la migration. À faire si on veut voir quelque chose
+bouger avant de toucher au schéma.
+
+### Ce qui peut être livré en premier et se vendre seul
+
+**Le plan sans calage** : téléversement, pose des repères, rendu, hors ligne. Ni transformation
+affine, ni position visiteur — et un musée de plein air a déjà le produit complet que les
+audioguides vendent depuis trente ans. Le calage GPS se greffe après sans rien casser.