# 13 — Les cartes : bloc `::map`, fondation `@recit/geo` et format `atlas` (maps.recit.dev)

**Statut : accepté · Phase : P15 · Mis à jour : 24/10/2026.**

Ce document pousse l'idée « cartes.recit.dev » de `sites/plans/pages/archive/BACKLOG_IDEA.md` : «
Markdown permettant d'afficher une carte, sous différentes formes, sous différents pays ». Il suit
la même structure que `08-formats.md` et dépend de `02-architecture.md` (modèle `Story`), de
`09-langues-et-json.md` (JSON typé, langues) et de `07-domaines.md` (sites). Chaque choix porte une
**recommandation**. Les questions 1, 2, 3, 5 et 6 du §8 ont été tranchées le 24/10/2026, sans
l'utilisateur et à sa demande (décisions réversibles) ; la question 4 reste ouverte.

Placement, ports, domaines et règles communes aux plans 10 à 14 : `06-roadmap.md`, section « Backlog
: plans 10 à 14 ». En résumé : un **lot avancé en P6**, limité au bloc `::map` statique (régions et
marqueurs, sans `worldview` ni choroplèthe, sans source `data=` : seul le `DataTable` de
`@recit/data` y sert, pour le tableau accessible), puis **P15 Atlas** après la 1.0. Le format
`atlas` est retenu (P15, question 1, tranchée) ; les points de vue sur les frontières (`worldview`,
Natural Earth par défaut) et la carte interactive (MapLibre) sont des **options** ultérieures
(questions 2 et 3, tranchées). Le type `Place` appartient au plan 12 : ce plan l'importe. Il n'y a
pas de commande de géocodage en v1 : les coordonnées sont écrites par l'auteur.

## 1. L'idée en une phrase

**Une carte s'écrit en Markdown comme un graphique : des coordonnées et des données dans la source,
une carte identique sur le web, dans une slide, dans un PDF, dans une vidéo et dans une story, sans
appel réseau et sans tuile tierce par défaut.**

### Ce que cela apporte à Récit

- **« Écrire une fois, raconter partout » appliqué à la géographie.** Aujourd'hui, une carte est une
  capture d'écran figée, non traduisible et sous licence floue. Avec Récit, elle devient une
  **donnée** : la même directive `::map` produit un SVG net à l'impression (`report`, `book`), une
  slide (`deck`), un plan avec mouvement de caméra (`motion`), une carte 9:16 (`stories`) et une
  figure de doc (`docs`).
- **Deux niveaux, comme `@recit/data`.**
  1. Un **bloc transverse** `::map` / `:::map`, utilisable dans tous les formats (comme `::chart`).
  2. Un **format** `atlas` (« story map ») où **une scène = une vue de carte** (emprise, couches,
     texte), lu au défilement. C'est le récit géographique : un voyage, une tournée, une
     implantation, une étude régionale.
- **« Sous différents pays » : les deux lectures sont retenues** (question 3, tranchée le 24/10) :
  - une carte **d'un pays et de ses régions** (`region=FR level=admin1`), couverte dès le lot P6 ;
  - un **point de vue** sur les frontières disputées (`worldview=`), pour qu'une carte ne soit pas
    politiquement fausse dans le pays où elle est publiée. Option, après le lot P6, avec Natural
    Earth (de facto) par défaut.
- **Fidèle aux règles du projet.** Aucun chiffre écrit en dur dans une choroplèthe (règle « aucune
  métrique inventée » d'emaki), aucune devinette géographique (pas de géocodage implicite), une
  seule stack (d3-geo est déjà dans le lockfile), licences des données listées dans `NOTICE.md`.
- **Lien avec les autres idées du backlog.** Le type `Place` (adresse structurée + coordonnées
  facultatives) est défini une seule fois par le plan 12 et livré avec `calendar` (P10). Ce plan
  l'importe pour la vue carte de l'annuaire et des événements, sans le redéfinir.

## 2. Ce que la recherche a appris

### 2.1 Ce que le dépôt fournit déjà

Vérifié dans `pnpm-lock.yaml` :

| Paquet                                                                                                                      | Présent ?      | Par qui                                                         | Licence |
| --------------------------------------------------------------------------------------------------------------------------- | -------------- | --------------------------------------------------------------- | ------- |
| `d3-geo` 3.1.1 (+ `@types/d3-geo` 3.1.0)                                                                                    | oui, transitif | `d3` 7.9.0 ← `mermaid` (`packages/site`, `packages/components`) | ISC     |
| `d3-scale` 4.0.2, `d3-scale-chromatic` 3.1.0, `d3-dsv` 3.0.1                                                                | oui, transitif | même chaîne                                                     | ISC     |
| `commander` 2.20.3 (seule dépendance de `topojson-client`)                                                                  | oui, transitif | une autre chaîne ; `@recit/cli` utilise `commander` 14.0.3      | MIT     |
| `remark-directive` 3.0.1, `hastscript`, `hast-util-to-html`, `happy-dom`                                                    | oui            | `packages/core`, tests                                          | MIT     |
| `topojson-client`, `world-atlas`, `maplibre-gl`, `leaflet`, `pmtiles`, `@turf/*`, `@observablehq/plot`, `jsdom`, `linkedom` | **non**        | —                                                               | —       |

Conséquence : déclarer `d3-geo`, `d3-scale` et `d3-scale-chromatic` en dépendances directes,
épinglées sur les versions du lockfile, **n'ajoute aucun paquet au graphe**. `topojson-client` (ISC)
serait nouveau, et ferait de `commander` 2.x une dépendance de nos packages publiés, à côté de
`commander` 14.0.3 de `@recit/cli` : deux versions majeures du même paquet. On ne l'ajoute donc pas
(D8).

### 2.2 Rendu statique SVG (d3-geo)

- `geoPath(projection)` renvoie une chaîne `d` SVG par des fonctions pures, **sans DOM** : émise en
  JSX côté SSR ou en hast, elle sert le build, Remotion et Paged.js.
- Projections fournies : `geoEqualEarth`, `geoNaturalEarth1`, `geoMercator`, `geoConicConformal`
  (proche du Lambert 93 pour la France), `geoAlbers`, `geoAlbersUsa`, `geoOrthographic`,
  `geoAzimuthalEqualArea`. `projection.fitExtent` cadre automatiquement sur une emprise.
- **Piège du sens des anneaux.** d3-geo attend des anneaux extérieurs dans le sens horaire
  (géométrie sphérique) ; la RFC 7946 impose l'inverse. Un GeoJSON conforme peut donc « remplir le
  globe sauf le polygone ». Parade : un utilitaire `rewind` maison (si `geoArea(f) > 2π`, on
  inverse), sans `@turf/rewind`. **À vérifier** avant GE3 : ce point est repris de mémoire du README
  d3-geo, pas relu.
- **Encarts** (DROM français, Alaska et Hawaï) : `geoAlbersUsa` les gère pour les États-Unis ;
  ailleurs, ils sont à faire à la main. `d3-composite-projections` serait une dépendance de plus :
  encarts maison reportés en phase ultérieure.

### 2.3 Données de fond

- **Natural Earth** : **domaine public**, aucune attribution obligatoire (« Made with Natural Earth
  » conseillé). Admin-0 (pays), admin-1 (régions, au 10m), Populated Places (villes).
- Depuis la v5 (déc. 2021), étendue en 5.1.0 (2022-05-04), Natural Earth publie des variantes **«
  point of view »** Admin-0 pour plusieurs dizaines de pays : le tracé par défaut suit le contrôle
  de fait, les POV suivent la position de droit du pays concerné. La liste exacte des POV de 5.1.x
  reste à relever.
- `world-atlas` (ISC) fournit des TopoJSON prêts mais repose sur Natural Earth 4.1.0, **sans POV**.
- **Pièges ISO** : `ISO_A3` vaut `-99` pour quelques pays (historiquement France et Norvège).
  Joindre sur `ISO_A3_EH` ou `ADM0_A3`, et signaler les clés non appariées.
- **Noms localisés** : `Intl.DisplayNames(lang, { type: "region" })`, inclus dans la plateforme,
  sans données à embarquer. Les champs `NAME_xx` de Natural Earth servent de secours.

### 2.4 Cartes glissantes (interactives)

|                   | MapLibre GL JS                                                        | Leaflet                               |
| ----------------- | --------------------------------------------------------------------- | ------------------------------------- |
| Licence           | BSD-3                                                                 | BSD-2                                 |
| Rendu             | tuiles vectorielles, WebGL2, styles JSON                              | tuiles raster (vectoriel par plugins) |
| Poids             | lourd, à mesurer avant tout chiffre, chargement paresseux obligatoire | léger                                 |
| Sources de tuiles | OpenFreeMap, PMTiles auto-hébergé                                     | en pratique tuiles raster OSM         |

Règles des sources de tuiles :

- **tile.openstreetmap.org** : best-effort sans SLA ; préchargement, archives de tuiles et usage
  hors ligne **interdits** ; User-Agent distinct, Referer valide, cache respecté, attribution
  visible. Nos exports PDF, PNG et vidéo et les captures de CI seraient du téléchargement en masse :
  **à exclure**.
- **OpenFreeMap** : MIT, données OSM, sans clé sur l'instance publique (financée par dons) ;
  attribution **obligatoire**, y compris à l'impression et en vidéo (« OpenFreeMap © OpenMapTiles
  Data from OpenStreetMap ») ; limites hors ligne et de parallélisme documentées ; auto-hébergeable.
- **Protomaps PMTiles** : basemap « ODbL Produced Work », attribution OSM obligatoire. Un seul
  fichier statique servi par requêtes HTTP Range, découpable par région (`pmtiles extract`,
  `--maxzoom`), hébergeable **avec le site** : aucune fuite d'IP vers un tiers.
- **Vie privée** : toute tuile tierce transmet l'IP du visiteur à l'hébergeur des tuiles.

### 2.5 Géocodage

**Nominatim** public : 1 requête/s au plus, cache obligatoire, géocodage en masse déconseillé,
User-Agent identifiant, attribution OSM et données ODbL (share-alike). Conclusion : **aucun
géocodage au build ni au rendu**.

### 2.6 Syntaxes existantes

- **GitHub** rend les blocs ` ```geojson ` et ` ```topojson ` en carte interactive : Récit doit les
  honorer, pour qu'une source reste lisible sur GitHub.
- **Obsidian Leaflet** (bloc ` ```leaflet `, clés YAML `lat`, `long`, `defaultZoom`, `marker:`) et
  **Obsidian Map View** (`location: [lat, lon]` en frontmatter) montrent qu'un modèle déclaratif
  clé/valeur suffit aux auteurs.
- **react-simple-maps** (MIT, sur d3-geo, peu maintenu) valide l'approche « d3-geo + JSX » sans
  justifier une dépendance.
- Mermaid n'a pas de type « carte ».

### 2.7 Correction à apporter à `08-formats.md`

`08-formats.md` §0 présentait Observable Plot comme un « rendu SVG sans DOM » (corrigé le 24/10).
C'était inexact : en SSR, Plot demande qu'on lui fournisse un `document` virtuel (linkedom ou
jsdom), et sa doc réserve le SSR aux petits graphiques. Ce point touche `@recit/data` (P6) et la
question ouverte n° 10 de `06-roadmap.md`. Proposition (D9) : unifier graphiques et cartes sur d3
sans DOM. **Tranché le 24/10** (06, question 10) : d3 sans DOM. `03-packaging.md` §6 et
`08-formats.md` §0 et R1 sont mis à jour dans le même changement.

### 2.8 Sources

- Politique des tuiles OSM : https://operations.osmfoundation.org/policies/tiles/
- Politique Nominatim : https://operations.osmfoundation.org/policies/nominatim/
- OpenFreeMap : https://openfreemap.org/
- Protomaps : https://docs.protomaps.com/basemaps/downloads
- MapLibre GL JS : https://github.com/maplibre/maplibre-gl-js
- Natural Earth, conditions : https://www.naturalearthdata.com/about/terms-of-use/
- Natural Earth, frontières disputées :
  https://www.naturalearthdata.com/about/disputed-boundaries-policy/
- world-atlas : https://github.com/topojson/world-atlas
- GitHub, blocs geojson/topojson :
  https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/creating-diagrams
- Obsidian Leaflet : https://github.com/javalent/obsidian-leaflet
- Observable Plot, SSR : https://observablehq.com/plot/getting-started
- d3-geo : https://github.com/d3/d3-geo
- Fichiers locaux : `pnpm-lock.yaml`, `packages/core/package.json`,
  `sites/plans/pages/08-formats.md`

## 3. Décisions proposées

Format des décisions : chaque décision donne les options et une recommandation.

| #   | Sujet                 | Options                                                           | Recommandation                                                                                                                                                                                                                                                              |
| --- | --------------------- | ----------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| D1  | Nom du site           | `cartes.recit.dev` (backlog), `maps.recit.dev`, `atlas.recit.dev` | **maps.recit.dev**, en anglais selon la règle commune de `07-domaines.md` §2 (06, « Backlog »). `cartes.recit.dev` (mot du backlog) et `atlas.recit.dev` (nom technique) redirigent en 301. « Cartes » reste le titre de la version fr du site                              |
| D2  | Bloc ou format        | bloc transverse seul ; format seul ; les deux                     | **Bloc d'abord**, `::map` + `@recit/geo` (fondation, utile partout). Le format `atlas` (une scène = une vue) vient en P15 (tranché, question 1)                                                                                                                             |
| D3  | Nom du format         | `map`, `maps`, `atlas`                                            | **`atlas`** : distinct de la directive `::map` et de `Map` de JavaScript, et parlant (« un atlas raconté »)                                                                                                                                                                 |
| D4  | Rendu par défaut      | SVG statique ; tuiles interactives                                | **SVG statique au build**, sans réseau, partout. MapLibre seulement en option, en phase ultérieure, et seulement sur le web                                                                                                                                                 |
| D5  | Données de fond       | `world-atlas` ; Natural Earth 5.1.x régénéré                      | **Natural Earth 5.1.x**, converti par un script figé dans le dépôt. Variantes POV seulement avec l'option `worldview`. Poids **mesuré** avant de choisir entre assets livrés dans le package npm et assets générés chez l'auteur                                            |
| D6  | Pays et frontières    | `worldview` lié à `lang` ; explicite                              | **Option (question 3, tranchée)**, après le lot P6 : explicite, `worldview=default` (de facto Natural Earth). La langue ne choisit jamais une position politique                                                                                                            |
| D7  | Géocodage             | en ligne au build ; gazetteer hors ligne ; jamais                 | **Coordonnées écrites dans la source** (tranché le 24/10). Pas de commande de géocodage en v1. Plus tard, en option : gazetteer hors ligne (Natural Earth Populated Places) pour `place=`, et `recit geocode` du plan 12, qui écrit dans le compagnon JSON. Jamais au rendu |
| D8  | TopoJSON              | `topojson-client` au build ; GeoJSON préconverti                  | **GeoJSON préconverti** dans les assets, sans option `topojson-client` (il ajouterait `commander` 2.x à côté de `commander` 14)                                                                                                                                             |
| D9  | Base de `@recit/data` | Observable Plot ; d3 sans DOM                                     | **Tranché le 24/10 (06, question 10) : d3 sans DOM** (`d3-scale`, `d3-shape`, déjà présents), pour que graphiques et cartes partagent échelles, palettes et rendu SSR                                                                                                       |

### 3.1 Syntaxe du bloc `::map` (dans tous les formats)

Remark-directive, déjà dans `packages/core`. Même grammaire que `::chart{data=…}` de
`08-formats.md`. Le plugin vit dans `@recit/geo` ; le cœur ne garde que le nom `map` dans son
registre de directives (règle commune de 06, « Backlog »). En JSON, la carte reste une directive
dans le `body` de la scène (pas de champ `blocks` en v1).

**Lot P6** : `::map` et `:::map` avec `region`, `level`, `projection`, `caption`, et `::marker` en
`lat`/`lon`. **P15** : choroplèthe (`data`, `key`, `value`, `scheme`, `source`), `::route`,
`::area`, blocs `geojson`. **Options** : `worldview`, `place=` (gazetteer), `mode=tiles`. L'exemple
ci-dessous montre l'ensemble.

````md
---
title: Lorem Ipsum Quarterly
format: report
lang: en
data:
  sales: ./data/sales-by-country.csv
  venues: ./data/venues.csv
---

--- id=world

## Lorem by country

::map{data=sales key=country value=revenue projection=equal-earth region=world scheme=sequential caption="Lorem ipsum dolor sit amet" source="Lorem dataset"}

--- id=france

## Ipsum in France

:::map{region=FR level=admin1 projection=conic-conformal height=480 caption="Dolor sit amet"}
::marker{lat=48.8566 lon=2.3522 label="Lorem"}
::marker{place="Lyon, FR" label="Ipsum"}
::route{from="Lorem" to="Ipsum" style=dashed}
:::

--- id=venues

## Dolor venues

::map{data=venues mode=points lat=lat lon=lon label=name region=FR}

```geojson
{ "type": "FeatureCollection", "features": [] }
```
````

| Élément                                             | Rôle                                                                                                                                                                                              |
| --------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `::map{…}`                                          | carte simple (feuille). `mode` = `choropleth` \| `points` \| `route` \| `tiles`, déduit si absent. Ce n'est pas `kind`, réservé au discriminant des documents JSON (`09-langues-et-json.md` §2.2) |
| `:::map{…}` … `:::`                                 | carte composée de couches (`::marker`, `::route`, `::area`, blocs `geojson`)                                                                                                                      |
| `region`                                            | `world`, un code ISO 3166-1 alpha-2 (`FR`), ou une emprise `[w,s,e,n]`                                                                                                                            |
| `level`                                             | `admin0` (pays) ou `admin1` (régions d'un pays)                                                                                                                                                   |
| `worldview`                                         | option : `default` ou un code ISO (variante POV Natural Earth)                                                                                                                                    |
| `projection`                                        | liste **fermée** : `equal-earth`, `natural-earth`, `mercator`, `conic-conformal`, `albers`, `albers-usa`, `orthographic`, `azimuthal-equal-area`                                                  |
| `data key value`                                    | P15 : jointure avec une source de `@recit/data` (alpha-2 ou alpha-3). Seule source autorisée des valeurs d'une choroplèthe                                                                        |
| `scheme`                                            | tokens de thème (`sequential`, `diverging`, dérivés de la teinte unique), sinon un nom `d3-scale-chromatic`                                                                                       |
| `::marker{lat lon label}` / `::marker{place label}` | point. `place` (option) résolu par le gazetteer hors ligne au build                                                                                                                               |
| `::route{from to style}`                            | ligne, tracée en grand cercle (géodésique par défaut). `from`/`to` = libellés de marqueurs ou coordonnées                                                                                         |
| `::area{src}`                                       | polygone fourni par l'auteur (GeoJSON local)                                                                                                                                                      |
| ` ```geojson ` / ` ```topojson `                    | rendus avec les options par défaut (compatibles GitHub) ; dans un `:::map`, ils deviennent une couche                                                                                             |
| `caption`, `source`                                 | légende et source. `source` **obligatoire** pour une choroplèthe                                                                                                                                  |
| frontmatter `geo:`                                  | position par défaut d'une scène ou d'une story (`geo: [48.85, 2.35]`), à la manière d'Obsidian Map View                                                                                           |

Règles :

- une projection, une région, une clé de jointure ou un `place` inconnus produisent une erreur avec
  numéro de ligne (`report.md:14 ::map: region "FX" unknown (did you mean "FR"?)`) ;
- aucune valeur numérique inline dans une choroplèthe : `value` vient de `data=`, sinon erreur ;
- une clé de donnée sans pays correspondant donne un avertissement (erreur avec `--strict`) ;
- latitude hors de [-90, 90] ou longitude hors de [-180, 180] : erreur ; inversion probable
  latitude/longitude (point hors de `region`) : avertissement ;
- la légende, le titre SVG et le résumé accessible sont **générés depuis les données**.

### 3.2 Retenu, P15 : le format `atlas` (une scène = une vue)

Format retenu le 24/10 (question 1), pour P15. L'attribut d'emprise de scène s'appelle `camera=` (et
non `view=`, qui désigne ailleurs la vue d'affichage : `view:` du frontmatter, prop `view` de
`StoryEmbed`).

**Promesse.** Un récit géographique s'écrit en Markdown, une vue par scène. Au défilement, la carte
reste en place et la caméra passe d'une vue à l'autre ; le texte de chaque scène défile à côté. La
même source devient un deck (une vue = une slide), une vidéo (une vue = un plan avec mouvement de
caméra) ou une story 9:16.

```md
---
title: Lorem Tour
format: atlas
lang: en
data:
  stops: ./data/stops.csv
atlas:
  projection: conic-conformal
  basemap: land        # land | admin0 | admin1 | none | tiles (later)
  worldview: default
  layout: side         # side | overlay | full
---

--- id=start camera=FR

# Lorem ipsum

Dolor sit amet, consectetur adipiscing elit.

--- id=paris camera="[2.2,48.8,2.5,48.95]" duration=4s

## Lorem in Paris

::marker{lat=48.8566 lon=2.3522 label="Lorem"}

Sed do eiusmod tempor incididunt ut labore.

--- id=route camera=FR

## From Lorem to Ipsum

::route{from="Lorem" to="Ipsum" reveal=draw}
::marker{place="Lyon, FR" label="Ipsum"}

--- id=stops camera=FR

## Every stop

::map{data=stops mode=points lat=lat lon=lon label=name}

:::notes
Lorem ipsum notes for the presenter.
:::
```

| Élément              | Rôle                                                                                   |
| -------------------- | -------------------------------------------------------------------------------------- |
| frontmatter `atlas:` | projection, fond, point de vue et mise en page par défaut pour toute la story          |
| `--- camera=…`       | emprise de la scène : code ISO, `world`, emprise `[w,s,e,n]` ou `center=lat,lon zoom=` |
| couches de la scène  | `::marker`, `::route`, `::area`, `::map{data}` s'ajoutent à la vue de la scène         |
| `reveal=`            | `draw` (tracé progressif), `fade`, `none` : transitions pilotées par la scène          |
| `duration=`          | durée du plan pour le pont motion (modèle `Scene.durationMs`)                          |
| `:::notes`           | notes, comme dans le deck                                                              |

Règles :

- une scène sans `camera` hérite de la précédente ; la première scène sans `camera` prend l'emprise
  de toutes ses couches ;
- une transition entre deux vues interpole la projection (rotation, échelle, translation) : aucune
  tuile n'est chargée pendant la transition ;
- les mêmes règles d'erreur que `::map` (§3.1).

### Composants

`AtlasRoot` (lecteur au défilement), `AtlasView` (une vue, SVG), `GeoMap` (carte autonome, le même
composant que la directive), `MapLegend`, `DataTable` de `@recit/data` (alternative accessible, pas
de composant propre aux cartes), `MapCaption`. Utilisables en MDX via `<GeoMap … />` et
`<StoryEmbed slug="lorem-tour" format="atlas" view="side" />`.

### 3.3 Schéma JSON typé

Dans `@recit/core/schema` (zod 4, `zod/mini` côté navigateur), JSON Schema générés par
`z.toJSONSchema` et publiés sur `https://recit.dev/schema/v1/atlas.json` (comme les autres formats
de `09-langues-et-json.md` §2.1).

- `Place` : **importé** du plan 12 (D6), sans redéfinition. Adresse structurée, `geo` facultatif,
  `address` libre pour l'affichage seulement. Une carte ignore un `Place` sans `geo`
  (avertissement).
- `MapBlock = { type: "map", mode?, region?, level?, worldview?, projection?, data?, key?, value?, scheme?, layers?: Layer[], caption?: Localized, source?: string }`.
- `Layer = Marker | Route | Area | GeoJsonLayer` ;
  `Marker = { type: "marker", lat, lon } | { type: "marker", place }` avec `label?: Localized` ;
  `Route = { type: "route", from, to, style?, reveal? }`.
- `AtlasSource` (option) rejoint l'union discriminée `StorySourceSchema` comme ajout compatible en
  v1 (règle de versionnement de 06, « Backlog ») ; une scène JSON contient
  `{ id, camera, layers?, body?, notes?, durationMs? }`.
- En dehors d'`atlas`, une carte reste une directive dans le `body` d'une scène deck, report ou docs
  : `MapBlock` valide la directive, sans champ `blocks` dans `SceneSource`.

Ligne à ajouter au tableau « Champs typés par format » de `09-langues-et-json.md` §2.3 :

| Format  | Une scène JSON contient                                                                                    | Exemple de champ localisable             |
| ------- | ---------------------------------------------------------------------------------------------------------- | ---------------------------------------- |
| `atlas` | `camera` (code ISO, emprise ou centre), `layers` (marqueurs, tracés, zones), `body`, `notes`, `durationMs` | `label` d'un marqueur, `caption`, `body` |

Coordonnées, emprises, codes ISO, valeurs et `worldview` ne sont **jamais** localisables.

Exemple de scène JSON :

```json
{
  "id": "paris",
  "camera": [2.2, 48.8, 2.5, 48.95],
  "layers": [{ "type": "marker", "lat": 48.8566, "lon": 2.3522, "label": { "en": "Lorem", "fr": "Lorem FR" } }],
  "body": { "en": "Sed do eiusmod tempor.", "fr": "Sed do eiusmod tempor (fr)." }
}
```

Équivalence testée comme pour les autres formats : `compile(md) == compile(toJson(md))`.

### 3.4 Ce que la langue change

Ligne à ajouter au tableau de `09-langues-et-json.md` §5 :

| Domaine            | Règle                                                                                                                                                                                                                                                                                                                                |
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `atlas` et `::map` | noms de pays et de régions par `Intl.DisplayNames` (repli `NAME_xx` de Natural Earth) ; valeurs et légendes par `Intl.NumberFormat` ; libellés de marqueurs via `Localized` ; en RTL, la légende et le panneau de texte basculent par propriétés CSS logiques, la carte ne se retourne jamais ; `worldview` indépendant de la langue |

### 3.5 Rendu dans les autres formats

| Format     | Ce que devient une carte                                                                                                                                                                                                          | Phase        |
| ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ |
| `docs`     | figure SVG dans une page du framework de sites, `<details>` avec le tableau                                                                                                                                                       | lot P6       |
| `report`   | figure SVG ; en PDF via `@recit/paged`, vectorielle, avec la source en légende                                                                                                                                                    | lot P6       |
| `deck`     | figure dans une slide ; pont atlas → deck (P15) : une vue = une slide                                                                                                                                                             | lot P6 / P15 |
| `book`     | figure numérotée, table des figures ; jamais de tuiles                                                                                                                                                                            | P15          |
| `motion`   | blocs `map` dans `@recit/motion-blocks` : caméra (interpolation de projection en fonction de la frame), tracé progressif (`stroke-dashoffset`), apparition des classes d'une choroplèthe. Pont atlas → motion : une vue = un plan | P15          |
| `stories`  | une vue = une carte 9:16 ; export PNG par le chemin d'export d'images existant                                                                                                                                                    | P15          |
| `calendar` | vue carte des événements qui ont un `Place` avec `geo` (facultative)                                                                                                                                                              | P15          |
| `toon`     | aucun pont promis : pas de correspondance fermée                                                                                                                                                                                  | —            |

Ponts à ajouter au tableau de `08-formats.md` §0 (correspondances fermées uniquement) :

| De → vers                                                 | Correspondance                                                                    | Phase  |
| --------------------------------------------------------- | --------------------------------------------------------------------------------- | ------ |
| atlas → deck                                              | une vue → une slide, couches gardées, texte soumis aux règles de densité          | P15    |
| atlas → motion                                            | une vue → un plan, transition = interpolation de projection, `reveal` → animation | P15    |
| atlas → stories                                           | une vue → une carte 9:16                                                          | P15    |
| formats de la liste fermée de `15-export-pdf.md` §1 → PDF | `::map` en SVG, imprimé par la CLI et `@recit/paged`                              | lot P6 |

Une carte `mode=tiles` se replie **automatiquement** sur le rendu statique (fond Natural Earth et
couches) dans tout format non web, avec un avertissement si le style dépendait des tuiles.

### 3.6 Accessibilité

`<figure>` + `<svg role="img" aria-labelledby>` avec `<title>` et `<desc>` (résumé généré depuis les
données, comme `::chart`) + `<figcaption>` + `<details>` contenant un `DataTable` de `@recit/data`
(une ligne par région ou marqueur, valeur formatée par `Intl`). La couleur ne porte jamais seule
l'information : légende avec seuils explicites, palettes lisibles par les daltoniens, motifs en
option pour l'impression en noir et blanc. Pour MapLibre (plus tard) : contrôles au clavier, et le
tableau reste l'alternative de référence.

## 4. Packages, site, exemples et e2e

### 4.1 Packages

| Package                          | Groupe                             | Statut | Publié | Source  | Contenu                                                                                                                                                                                                                                                                                                                   | Dépendances notables                                                                                                                                                                             |
| -------------------------------- | ---------------------------------- | ------ | ------ | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `@recit/geo`                     | fondations (`packages/geo`)        | 📅 P6  | oui    | nouveau | projections (liste fermée), `rewind`, assets Natural Earth versionnés (110m et 50m, admin-1 par pays), composants SSR `GeoMap`, `MapLegend` (le tableau accessible est le `DataTable` de `@recit/data`), plugin remark `::map`. P15 : jointure ISO et rapport des clés non appariées. Options : gazetteer hors ligne, POV | `d3-geo` 3.1.1, `d3-scale` 4.0.2, `d3-scale-chromatic` 3.1.0 (déjà dans le lockfile), `@recit/core`, `@recit/data` dès P6 (`DataTable` du tableau accessible ; jointure `data=` à partir de P15) |
| `@recit/atlas`                   | formats (`packages/formats/atlas`) | 📅 P15 | oui    | nouveau | format `atlas` (retenu, question 1), lecteur au défilement, `AtlasRoot`, `AtlasView`, ponts vers deck, motion, stories                                                                                                                                                                                                    | `@recit/geo`, `@recit/core`, `@recit/theme`                                                                                                                                                      |
| `@recit/geo/tiles` (sous-chemin) | —                                  | option | oui    | nouveau | option, plus tard (question 2) : île cliente MapLibre, chargée paresseusement, web seulement                                                                                                                                                                                                                              | `maplibre-gl`, `pmtiles` en dépendances **optionnelles** (peer)                                                                                                                                  |

Pourquoi une fondation et non un sous-chemin de `@recit/data` : `@recit/geo` a une raison d'être
installé seul (une carte dans une doc sans données tabulaires) et embarque des assets lourds que
`report` sans carte ne doit pas tirer. Il dépend de `@recit/data` (dès P6, pour le `DataTable` ; la
jointure arrive en P15), jamais l'inverse ; aucun format n'est importé (`scope:foundation`). À
reporter : `@recit/geo` dans le glob des fondations de `03-packaging.md` §1, `@recit/geo` et
`@recit/atlas` dans 03 §6 et dans les noms npm à réserver, `README.md` (« Règles du cœur ») règle 2,
et la ligne Récit de NOTICE.md.

Réutilisé tel quel :

- `remark-directive` et le pipeline unified de `@recit/core` (directives, numéros de ligne) ;
- loaders CSV/JSON de `@recit/data` (`d3-dsv` déjà présent) ;
- pour le PDF et les PNG, la CLI, qui imprime ou capture la vue de la carte par
  `@recit/paged/runner` (Chromium de Playwright, pair optionnel) ; `@recit/geo` n'importe pas
  `@recit/paged` ; `@recit/motion-render` (Remotion) pour les plans vidéo ;
- tokens de `@recit/theme` pour les palettes (teinte unique Q07, dégradés séquentiels et
  divergents).

Rejetés : Leaflet (doublon de MapLibre, centré raster), Observable Plot pour les cartes (DOM virtuel
en SSR), `@turf/*`, `world-atlas` (pas de POV), `resvg`, `sharp`, géocodeurs en ligne au build.

Génération des assets : un script `packages/geo/scripts/build-assets.ts` télécharge une version
**épinglée** de Natural Earth, simplifie et convertit en GeoJSON, puis écrit les fichiers versionnés
dans `packages/geo/assets/`. Les outils de conversion (topojson-server, topojson-simplify, ISC) ne
sont que des `devDependencies` du script, ou bien l'on part d'assets préconstruits (à décider au lot
P6). Le poids des assets est **mesuré** (GE2) avant de choisir s'ils sont livrés dans le package npm
ou générés chez l'auteur ; aucun chiffre n'est écrit dans ce plan avant la mesure.

### 4.2 Site maps.recit.dev

Lignes à ajouter dans `07-domaines.md` :

| Domaine            | Rôle                                 | Dossier      | Contenu                                                                                           | Phase |
| ------------------ | ------------------------------------ | ------------ | ------------------------------------------------------------------------------------------------- | ----- |
| **maps.recit.dev** | format `atlas` (P15) et bloc `::map` | `sites/maps` | hero = un atlas Lorem jouable (France puis monde) ; galerie des formes de carte, démo multilingue | P15   |

| Alias              | Cible          | Pourquoi                                |
| ------------------ | -------------- | --------------------------------------- |
| `cartes.recit.dev` | maps.recit.dev | mot du backlog (règle commune de 07 §2) |
| `atlas.recit.dev`  | maps.recit.dev | nom technique du format                 |

| Site             | Projet Vercel | Racine du projet | Build                                                                              | Ouverture |
| ---------------- | ------------- | ---------------- | ---------------------------------------------------------------------------------- | --------- |
| `maps.recit.dev` | `recit-maps`  | `sites/maps`     | `nx run maps:build`. Les SVG sont générés au build, les PNG et MP4 d'exemple en CI | P15       |

- **Port local** : **3013**, d'après la table d'attribution unique de `07-domaines.md` §4
  (components 3010, form 3011, directory 3012, maps 3013, ai 3014). Ajouter `"maps"` à `SiteId` et à
  la table `SITES` (seule source des liens inter-sites).
- Si la décision sur `atlas` (24/10, réversible) était revue, maps.recit.dev reste la vitrine d'un
  bloc, dans la catégorie « site d'outil » de `07-domaines.md` §1.
- **Composants site-kit** (aucun nouveau composant de site-kit) :

| Composant       | Rôle                                                                | Exemple sur maps.recit.dev                                                                                               |
| --------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
| `FormatHero`    | démo jouable écrite dans le format                                  | l'atlas `atlas-tour` en mode `side`, source dépliable                                                                    |
| `SourceToggle`  | rendu / Markdown / JSON                                             | la même carte vue en `::map`, en JSON et en SVG                                                                          |
| `LocaleDemo`    | même source en en et fr                                             | noms de pays par `Intl.DisplayNames`, en `ar` pour montrer le RTL                                                        |
| `FormatGallery` | galerie des cas                                                     | choroplèthe monde, régions d'un pays, points, tracé, `worldview`                                                         |
| `ExportPanel`   | exports (composant unique de `@recit/site-kit`, lit `exports.json`) | PDF, PNG 9:16, MP4 (générés en CI), variantes `kind` de `ExportManifestSchema` (`@recit/core`), ajoutées dans leur phase |
| `BridgeCard`    | ponts                                                               | atlas → deck, motion, stories                                                                                            |
| `TemplateCard`  | gabarits                                                            | `npm create recit -- --template atlas-tour`                                                                              |
| `DocsLinks`     | renvoi                                                              | `docs.recit.dev/atlas/…` et `docs.recit.dev/components/map`                                                              |

- Règle anti-doublon : aucune doc sur maps.recit.dev, renvoi vers docs.recit.dev › Formats › Atlas
  et › Components › Map (section unique des blocs transverses). La vitrine est écrite en `atlas` si
  le format existe, en en et en fr.
- Icône : `brand/formats/fmt-atlas-{icon,color,dark,light,stacked}.svg`, dans la teinte unique.

### 4.3 Exemples et e2e

| Exemple                | Paquet                      | Contenu                                                                                            |
| ---------------------- | --------------------------- | -------------------------------------------------------------------------------------------------- |
| `examples/map-country` | `recit-example-map-country` | lot P6 : page `docs` et `report` d'une page, régions d'un pays (`admin1`), marqueurs `lat`/`lon`   |
| `examples/map-world`   | `recit-example-map-world`   | lot P6 : monde en `admin0` avec marqueurs ; P15 : choroplèthe sur données Lorem générées           |
| `examples/atlas-tour`  | `recit-example-atlas-tour`  | P15 : format `atlas`, tournée Lorem en cinq vues, en en et fr (`atlas-tour.fr.md`), JSON compagnon |

Nommage : `map` est un bloc, pas un format ; la règle commune (06, « Backlog ») autorise
`examples/<bloc ou outil>-*`. Données Lorem uniquement, générées par script, jamais de chiffres
réels. Lieux = villes réelles seulement comme coordonnées (domaine public via Natural Earth),
libellés en Lorem. Une carte pour le gabarit lebrocoli.fr serait une section optionnelle du dossier
unique `examples/scenario-lebrocoli` (plan 14), jamais un second dossier.

`e2e/atlas.e2e.ts` et `e2e/map-block.e2e.ts` avec captures :

- choroplèthe en clair et sombre, en en et fr, mobile ;
- vue `admin1`, marqueurs, tracé ;
- défilement de l'atlas (une capture par vue) ;
- **aucune requête réseau** pendant le rendu (interception Playwright qui fait échouer le test) ;
- PDF rendu page par page en PNG (goldens), golden PNG d'un plan motion ;
- erreurs avec numéro de ligne (région inconnue, valeur inline, coordonnées hors bornes) ;
- axe sans violation sur la figure et le tableau.

## 5. Sécurité, vie privée, licences

- **Aucune requête réseau par défaut**, ni au build ni au rendu : le fond, le gazetteer et les
  données sont locaux. Le rendu statique ne transmet donc l'IP du visiteur à personne.
- **Tuiles en opt-in explicite** (`mode=tiles`, option) : OpenFreeMap ou PMTiles auto-hébergé ;
  jamais `tile.openstreetmap.org`. La doc et la page vie privée du site signalent la transmission de
  l'IP à l'hébergeur des tuiles. Attribution visible imposée par le composant, non désactivable.
- **Aucun géocodage implicite**, et aucune commande de géocodage en v1 (tranché le 24/10). Plus
  tard, le seul géocodage sera `recit geocode` du plan 12 : 1 requête/s, cache local, User-Agent
  Récit, attribution ODbL, résultat écrit dans le compagnon JSON (jamais dans la source) et relu par
  l'auteur.
- **Frontières.** Politique documentée sur docs.recit.dev : Natural Earth de facto par défaut,
  `worldview=` pour les positions de droit nationales. Récit ne tranche aucun différend.
- **Données personnelles.** Un marqueur peut désigner un domicile : avertissement de lint si un
  `::marker` porte `person=true` sans `consent=true`, arrondi optionnel des coordonnées
  (`precision=`). Exemples sans aucune adresse de personne.
- **Sources de l'auteur.** `source=` obligatoire pour une choroplèthe ; une source de données non
  Natural Earth (IGN Admin Express, GADM…) porte un champ `license` reporté dans la légende.

Lignes à prévoir dans `NOTICE.md`, « What comes from where » : étendre la ligne des formats à
`formats/{…,atlas}` et ajouter `packages/geo` (fondation, code original).

« Third-party assets » :

| Item                                                          | Used in                                  | License / terms                                                                          |
| ------------------------------------------------------------- | ---------------------------------------- | ---------------------------------------------------------------------------------------- |
| Natural Earth 5.1.x (admin-0, admin-1, POV, populated places) | `packages/geo/assets`                    | Public domain ; « Made with Natural Earth » cité par courtoisie                          |
| d3-geo, d3-scale, d3-scale-chromatic                          | `@recit/geo`                             | ISC                                                                                      |
| topojson-server, topojson-simplify (si retenus)               | `packages/geo/scripts` (devDependencies) | ISC                                                                                      |
| maplibre-gl (option)                                          | `@recit/geo/tiles`                       | BSD-3-Clause                                                                             |
| pmtiles (option)                                              | `@recit/geo/tiles`                       | BSD-3-Clause                                                                             |
| OpenFreeMap styles et tuiles (option)                         | `@recit/geo/tiles`                       | MIT ; attribution « OpenFreeMap © OpenMapTiles Data from OpenStreetMap » obligatoire     |
| Données OpenStreetMap via tuiles (option)                     | `@recit/geo/tiles`                       | ODbL 1.0, attribution obligatoire. Nominatim : ligne unique du plan 12 (`recit geocode`) |
| Protomaps basemap (option)                                    | extraction PMTiles des sites             | ODbL Produced Work, attribution OSM                                                      |

## 6. Phases

Placement dans `06-roadmap.md` (« Backlog : plans 10 à 14 ») : **lot avancé en P6**, puis **P15
Atlas** après la 1.0, et des options. Rien en P4 ni en P5. Identifiants de tâches : `GE` pour
`@recit/geo`, `AT` pour `atlas` (préfixe + numéro, comme R1 ou ST1 dans `08-formats.md`). La
décision Plot ou d3 (06, question 10) est prise : d3 sans DOM (24/10).

### Lot P6 — Bloc `::map` statique (M)

- [ ] GE1 — `packages/geo` : squelette tsdown, exports `types`/`development`/`default`, tag nx
      `scope:foundation`, version plan, nom npm réservé.
- [ ] GE2 — Script d'assets Natural Earth épinglé : monde 110m et 50m, admin-1 par pays. **Mesure du
      poids** des assets avant de choisir leur mode de livraison (package npm ou génération chez
      l'auteur).
- [ ] GE3 — Projections (liste fermée), `fitExtent`, `rewind` (point à vérifier dans le README
      d3-geo). Tests unitaires (anneaux inversés, emprises).
- [ ] GE4 — Schémas `MapBlock` et `Layer` (marqueurs) dans `@recit/core/schema`, JSON Schema
      générés. `Place` est importé du plan 12 à partir de P10.
- [ ] GE5 — Plugin remark `::map` / `:::map` / `::marker` (`lat`/`lon`), nom `map` dans le registre
      de directives, erreurs avec numéro de ligne.
- [ ] GE6 — Composants SSR `GeoMap`, `MapLegend`, tableau accessible par `DataTable` (§3.6),
      palettes depuis `@recit/theme`.
- [ ] GE7 — Intégration docs, report, deck ; PDF par la CLI (`@recit/paged`).
- [ ] GE8 — `examples/map-country`, `examples/map-world` ; `sites/docs` › Components › Map.
- [ ] Tests : goldens SVG et PDF, e2e sans réseau, erreurs, axe.

**Sortie :**

- la même source rend une carte identique en web et en PDF, sans aucune requête réseau ;
- une région, une projection ou des coordonnées invalides sont refusées avec numéro de ligne ;
- les deux exemples s'affichent en en et en fr.

### P15 — Choroplèthe, mouvement, atlas et maps.recit.dev (L)

- [ ] GE9 — Choroplèthe : jointure ISO (`ISO_A3_EH`/`ADM0_A3`) avec `@recit/data`, rapport des clés
      non appariées, `source=` obligatoire, aucune valeur inline. Tests (`-99`, clés orphelines).
- [ ] GE10 — `::route`, `::area`, blocs `geojson`.
- [ ] GE11 — Blocs `map` dans `@recit/motion-blocks` : caméra (interpolation de projection), tracé
      progressif, apparition des classes, fonctions pures de la frame. Vue 9:16 pour `stories`.
- [ ] AT1 — `packages/formats/atlas` : `"atlas"` ajouté à `StoryFormat` comme ajout compatible en
      v1, section `atlas:` de `recit.config.ts`, attribut de scène `camera=`.
- [ ] AT2 — Lecteur au défilement `AtlasRoot`, `AtlasView`, mises en page `side`, `overlay`, `full`,
      navigation clavier, `prefers-reduced-motion` respecté.
- [ ] AT3 — `examples/atlas-tour` en en et fr, avec JSON compagnon ; équivalence md ⇄ JSON testée.
- [ ] AT4 — `sites/maps` (maps.recit.dev, port 3013, projet Vercel `recit-maps`, alias `cartes` et
      `atlas`) ; `sites/docs` › Formats › Atlas ; icône `fmt-atlas-*`.
- [ ] AT5 — Ponts atlas → deck, motion, stories ; vue carte facultative de `calendar` pour les
      événements dont le `Place` a un `geo`.
- [ ] Tests : goldens PNG, déterminisme, e2e par vue, mobile, RTL, sans réseau, chaque pont.

**Sortie :**

- une choroplèthe sans `data=` ou sans `source=` est refusée avec numéro de ligne ;
- une `::map` d'un exemple produit un plan MP4 et une carte 9:16 sans nouvelle dépendance de rendu ;
- `examples/atlas-tour` se lit au défilement et au clavier, en en et en fr, et produit un deck, un
  MP4 et une story ;
- maps.recit.dev est en ligne.

### Options, plus tard (questions 2 et 3, tranchées)

- [ ] GE12 — `worldview` (défaut : Natural Earth de facto) et variantes POV de Natural Earth, après
      relevé de la liste exacte des POV de 5.1.x.
- [ ] GE13 — Sous-chemin `@recit/geo/tiles` (option) : île MapLibre chargée paresseusement
      (`React.lazy`), web seulement, jamais sur le chemin d'entrée ; sources OpenFreeMap
      (attribution imposée) et PMTiles auto-hébergé ; repli statique automatique hors web ;
      `size-limit`.
- [ ] GE14 — Gazetteer hors ligne pour `::marker{place=…}` ; encarts maison (DROM).

**Sortie :** chaque option retenue a son exemple, ses goldens et ses lignes NOTICE.md ; le bundle
d'entrée ne grossit pas (`size-limit`).

## 7. Risques

| Risque                                                                     | Parade                                                                                                  |
| -------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- |
| Frontières disputées jugées fausses dans un pays                           | `worldview=` en option, de facto par défaut, politique documentée, aucune position déduite de la langue |
| Polygones inversés (sens des anneaux)                                      | `rewind` systématique et tests sur GeoJSON RFC 7946                                                     |
| Poids des assets admin-1 et 10m                                            | 110m par défaut, admin-1 découpé par pays, poids mesuré en GE2 avant de choisir le mode de livraison    |
| Coupure ou changement des règles des tuiles tierces                        | statique par défaut ; tuiles en option ; PMTiles auto-hébergé                                           |
| Fuite d'IP vers un tiers                                                   | aucun réseau par défaut ; opt-in documenté                                                              |
| Bundle alourdi par MapLibre                                                | sous-chemin optionnel, chargement paresseux, `size-limit`                                               |
| Clés ISO non appariées (`-99`, codes historiques)                          | jointure sur `ISO_A3_EH`/`ADM0_A3`, rapport des clés orphelines                                         |
| Licence d'une source de l'auteur (GADM, restrictions commerciales)         | champ `license`, lint, mention en légende                                                               |
| Inversion latitude/longitude                                               | lint (bornes, point hors région)                                                                        |
| Deux moteurs de graphiques (Plot dans `@recit/data`, d3 dans `@recit/geo`) | écarté : d3 sans DOM pour les deux (06, question 10, tranchée le 24/10), reporté dans 03 et 08          |
| Périmètre : un format de plus avant la 1.0                                 | seul le bloc statique en lot P6 ; `atlas` retenu pour P15, après la 1.0                                 |

## 8. Questions ouvertes

Les questions communes au backlog (domaine `cartes` en français et doublon de la ligne du backlog,
le brocoli, l'exception lebrocoli.fr, « Pet », « skills », « projet basic ») sont regroupées une
seule fois dans `06-roadmap.md`, « Questions ouvertes ». Le choix Plot ou d3 y est la question 10
(tranchée : d3 sans DOM). Le géocodage est la question 7 du plan 12 (tranchée : coordonnées écrites
par l'auteur, pas de commande en v1). Les lieux réels ou fictifs de l'exemple lebrocoli.fr et le
second nom de la ligne « cartes.recit.dev | cartes.recit.dev » restent à l'utilisateur (06, « À
l'utilisateur »). Les questions ci-dessous ont été tranchées le 24/10/2026, sans l'utilisateur et à
sa demande (décisions réversibles), sauf la 4 :

1. ~~**Format** : un vrai format `atlas`, ou seulement le bloc `::map` + `@recit/geo` avec un site
   vitrine ? Le nom `atlas` convient-il ?~~ Tranché (24/10) : bloc `::map` d'abord (lot P6), format
   `atlas` en P15.
2. ~~**Interactif** : faut-il prévoir MapLibre en option, ou s'en tenir au SVG statique ?~~ Tranché
   (24/10) : MapLibre plus tard, en option ; SVG statique par défaut.
3. ~~**« Sous différents pays »** : régions d'un pays, points de vue sur les frontières, ou les deux
   ? Quel `worldview` par défaut ?~~ Tranché (24/10) : les régions d'un pays, plus l'option
   `worldview`, avec Natural Earth par défaut.
4. **Formes de carte** attendues : choroplèthe, points, tracés suffisent-ils, ou faut-il aussi
   cartes en cercles proportionnels, cartogrammes, cartes de chaleur ?
5. ~~**Sources hors Natural Earth** (IGN Admin Express sous Licence Ouverte, GADM) : autorisées avec
   un champ `license` obligatoire ?~~ Tranché (24/10) : Natural Earth seul en v1 ; les autres
   sources (avec `license` obligatoire) plus tard.
6. ~~**Placement** : bloc statique en lot avancé de P6, puis P15 Atlas après la 1.0 : d'accord ?~~
   Tranché (24/10) : oui (ordre du backlog accepté, 06 question 14).
