# Catan — pack d'assets

Assets récupérés le 2026-08-01 pour le projet de jeu web Catan.
Cartes développement 6e édition ajoutées le 2026-08-02.

## D'où ça vient

Il n'existe **aucune source publique d'art Catan officiel en vraie HD**. Le meilleur
gisement accessible, ce sont les **PDF de règles officiels** hébergés par Catan Studio
sur `catan.com` : les illustrations y sont intégrées comme bitmaps individuels
(hexagones, cartes, pièces de cadre) et sont extractibles telles quelles — sauf les
cartes développement, qui demandent un rendu de page (voir plus bas).

PDF utilisés (tous depuis <https://www.catan.com/understand-catan/game-rules>) :

| Tag interne | Fichier | Édition | À utiliser ? |
|---|---|---|---|
| `base`      | `CN3081 CATAN–The Game Rulebook secure (1).pdf` | 6e éd. 2025 | **oui** |
| `ed6_56`    | `CN3082 CATAN – 5-6 Rulebook 2025 reduced.pdf`  | 6e éd. 2025 | **oui** |
| `ed6_tb`    | `CN3089 CATAN – T&B Rulebook.pdf`               | 6e éd. 2025 | **oui** |
| `ed6_ep`    | `CN3085 CATAN – E&P Rulebook.pdf`               | 6e éd. 2025 | **oui** |
| `old_base`  | `catan_base_rules_2020_200707.pdf`              | 5e éd. (règles + almanach) | non — voir plus bas |
| `anniv25`   | `catan-25th-rules_eng-200313.pdf`               | 25e anniversaire (art 5e éd.) | non — voir plus bas |

Le post Reddit qui listait les PDF 6e édition :
<https://www.reddit.com/r/Catan/comments/1jpevhu/6th_edition_rulebooks_are_online/>

## Ne pas repartir des livrets 5e édition

`old_base` (livret 2020) et `anniv25` portent **l'art de la 5e édition**, qui n'est pas
celui de la boîte que ce projet reproduit. Le jeu a été entièrement redessiné en 2025 :
cadres, illustrations et jusqu'aux noms de cartes. Deux exemples qui suffisent à les
disqualifier :

- la carte que la 5e édition appelle *Year of Plenty* / « Année d'abondance » s'appelle
  **Invention** en 6e édition (et en VF officielle) ;
- la tuile *Longest Road* de la 5e édition est devenue **Longest Route** en 6e ;
- les 5 cartes Point de Victoire de la 5e édition portaient chacune un bâtiment nommé
  (Bibliothèque, Marché, Chapelle, Université, Grand Hall) ; le livret 2025 n'en montre
  plus qu'une seule illustration et ne nomme plus aucun bâtiment.

Ces deux PDF restent dans `raw/` parce que certaines images n'ont pas d'équivalent isolé
en 6e édition, mais **rien de neuf ne doit en sortir**. Plus rien de la 5e édition n'est
affiché : les 5 cartes Point de Victoire nommées ont été remplacées par l'illustration
unique `img/dev/ed6_point_victoire.png` dans `regles.html`, et par le médaillon
`img/dev/ed6_point_victoire_icone.png` dans le jeu (voir plus bas). Les fichiers
`img/dev/vp_*.png` (Bibliothèque, Marché, Chapelle, Université, Grand Hall) ne sont plus
référencés nulle part et peuvent être supprimés.

## Résolutions réellement disponibles

- **Hexagones terrain** : max **289 × 332 px** (rulebook Traders & Barbarians 6e éd.).
  C'est le plafond. Les autres livrets plafonnent à 247 × 247 ou 177 × 177.
- **Cartes ressources** : max **239 × 340 px** (livret de base 6e éd.).
- **Pictogrammes de matière** (les dessins détourés des cadres « coût de
  construction ») : la couleur plafonne à **63 × 54 … 81 × 55 px**, mais le
  masque qui les détoure fait 1,57× cette taille — livrés à la taille du masque,
  jusqu'à 127 × 88. Voir « Les pictogrammes de matière » plus bas.
- **Cartes développement** : les 5 cartes 6e éd. sortent en **367 × 546 px**, mais
  *par rendu de page*, pas par extraction — voir « Les cartes développement » plus
  bas. Livrées en 260 × 387 dans `img/dev/ed6_*`.
- **Tuiles bonus (Route la plus longue, Armée la plus grande)** : même histoire,
  **542 × 617 px** au rendu, livrées en 280 × 319.
- **Pièces de cadre maritime (ports)** : jusqu'à **915 × 284 px**.
- **Jetons chiffres, colons, villes, routes, voleur** : **jamais isolés** dans les PDF.
  Ils n'existent que noyés dans des rendus de plateau. → régénérés en SVG (voir plus bas).

## Contenu

```
img/hex/      12 hexagones reconstruits, PNG RGBA 300×346, pointy-top, liseré de
              sable compris (voir plus bas), fond transparent
              forest hills pasture fields mountains desert sea
              + variantes _2 pour 5 des 6 terrains (varier le plateau)
img/card/      5 cartes ressources 6e éd. recadrées au bord du carton (voir plus
              bas), PNG RGBA 240×356, coins arrondis
              res_dos.png — le dos commun, rendu depuis CN3081 (voir plus bas)
              + 3 cadres vierges + carte coûts de construction
img/res/       5 pictogrammes de matière (brick lumber wool grain ore), PNG RGBA
              détourés, hauteur commune 88 px — les vignettes des cadres « coût
              de construction » des pages 8 et 9 (voir plus bas). C'est ce que
              montrent les boutons de construction du jeu, à la place du coût en
              toutes lettres
img/dev/      ed6_*  les visuels 6e éd. rendus depuis CN3081, coins arrondis —
                     c'est ce qu'affiche regles.html :
                     5 cartes développement, PNG RGBA 260×387 (monopole, routes,
                     invention, chevalier, point_victoire)
                     2 tuiles bonus, PNG RGBA 280×319 (route_longue,
                     armee_grande)
                     ed6_dos.png — le dos commun (voir plus bas)
                     ed6_point_victoire_icone.png — le médaillon au laurier de la
                     page 9, PNG RGBA 149×149 détouré (voir plus bas) ; c'est lui
                     que le jeu montre, pas le carton
              vp_*, knight_art, card_frame_*, shield_special : reliquats 5e éd.,
                     conservés mais à ne pas réutiliser (voir plus haut)
img/frame/    sea_ring.png — LE cadre maritime du jeu, découpé dans le plateau
              officiel (pages 4 et 5 du livret de base fusionnées, île détourée)
              sea_port.png — 350×210, le gros plan de port de regles.html, bâti
                     par tools/build_ports.py : les tuiles sont posées sous le
                     cadre comme le fait js/render.js, puis on rogne autour de la
                     barque de l'arête 18. C'est le port 2:1 bois parce que sa
                     voile est la seule du cadre à se lire franchement à
                     l'endroit — les autres suivent la rotation de leur segment.
                     Un rognage direct de sea_ring.png ne marche pas : montrer
                     les deux pontons oblige à monter jusqu'à la plage, donc à
                     mordre sur le trou central de l'anneau, et le parchemin de
                     la feuille se voit alors au travers dans un beige presque
                     celui du sable
              port_any / lumber / brick / wool / grain / ore .png — 164×164, même
                     script : la barque de chacun des 6 types, redressée du
                     multiple de 60° qui remet sa voile d'aplomb, puis cadrée sur
                     le milieu de la voile — repérée à sa couleur, et réduite à
                     sa plus grande tache d'un seul tenant, sans quoi le fanion
                     et l'écume tirent le centre de 15 px et décadrent la moitié
                     des pastilles. Ce sont les pastilles de la rangée des ports
                     de regles.html. Le générique vient de l'arête 8 et non d'un
                     des trois autres ports 3:1 : les barques ne voguent pas
                     toutes du même bord, et c'est la seule des quatre dont la
                     coque déborde de la voile vers la droite, proue à droite,
                     comme les cinq spécialisées. Les arêtes 1, 11 et 21 l'ont en
                     miroir — un écart qu'aucune rotation ne rattrape
              les 21 bandes de cadre décoratives des livrets sont en réserve
                     (unused/frame/) : voiles sans taux imprimé, fond blanc
img/board/     8 plateaux complets et schémas de mise en place
img/token/    11 jetons chiffres SVG (2-12 + jeton vierge)
img/piece/    19 pions SVG : colon / ville / route × 6 couleurs + voleur
raw/          592 images brutes extraites, classées par PDF source
raw/_pdf/     CN3081.pdf — le livret de base 6e éd. lui-même, dont build_dev.py a
              besoin (il le retélécharge tout seul s'il manque)
raw/_font/    Georgia-Bold.ttf, dont build_token.py grave les chiffres (il la
              recopie tout seul depuis les polices système si elle manque)
tools/        build_hex.py, build_card.py — refabriquent img/hex/ et img/card/
              depuis raw/
              build_dev.py — refabrique img/dev/ed6_* (cartes, tuiles et
              médaillon) depuis raw/_pdf/CN3081.pdf
              build_back.py — refabrique les deux dos, même source
              build_res.py — refabrique img/res/, même source
              build_piece.js — refabrique img/piece/ depuis js/pieces.js
              build_token.py — refabrique img/token/ et js/tokens.js depuis
              raw/_font/
              build_ports.py — refabrique les visuels de ports de regles.html
              (img/frame/sea_port.png et port_*.png) depuis sea_ring.png
```

## Les tuiles — le liseré de sable est invisible dans les livrets

Chaque tuile du vrai jeu porte un **liseré de sable** tout autour du dessin de
terrain ; c'est lui qui dessine le réseau beige entre les hexagones du plateau.

Le piège : dans les livrets, ce liseré a **exactement la couleur du fond de page**
— (246,215,154) contre (247,217,156) relevé sur le plateau. Un détourage qui
cherche « où s'arrête le fond uni » coupe donc au ras du dessin de terrain et
avale le liseré. C'est ce qui avait été fait au premier passage : les hexagones
s'assemblaient bord à bord sans le moindre joint, et le long de la côte le dessin
mordait sur la plage du cadre.

Le bord réel de la tuile est introuvable dans le livret, mais il se calcule. Sur
le plateau officiel assemblé (livret de base, pages 4+5), le dessin de terrain
s'arrête à **0,908 de l'apothème** de la tuile — médiane sur 99 arêtes des 19
tuiles, écart interquartile 0,896–0,912. Le rayon vrai vaut donc `R_dessin /
0,908` : pour les bitmaps 289×332 du livret T&B, dessin de rayon ~145 px, tuile
de rayon ~160 px. Le joint entre deux cartons est un trait de ~2 px à
(218,186,130), dont chaque tuile porte la moitié.

`tools/build_hex.py` refait le pack à partir de `raw/` en appliquant tout ça :
il mesure le dessin, en déduit le bord, garde le beige de la page comme liseré
(même couleur, rien à repeindre), pose le demi-joint et masque à l'hexagone.
Le rendu peut alors poser les tuiles bord à bord sans rien tracer par-dessus.

## Les cartes ressources — le piège inverse

Les bitmaps de cartes du livret sont l'illustration **avant découpe** : une nappe
de crème à coins vifs qui déborde du carton. Le fond de page du livret de base
étant blanc, le détourage n'a rien eu à couper et s'est arrêté au bord du
bitmap — la carte a donc gardé une bordure crème trop large (14,6 % de la
largeur au lieu de ~11 %).

Le vrai bord se recale sur le visuel officiel des 5 cartes ressources, où la
bordure de crème est **d'épaisseur constante sur les quatre côtés** : ~42 px sur
les côtés et ~45 px en haut pour une carte large de ~595 px. Soit **7 % de la
largeur** — et mécaniquement ~4,7 % de la hauteur, puisque c'est la même
épaisseur rapportée à l'autre dimension. Le gabarit de carte vierge du livret
T&B (`raw/ed6_tb/p03_x6558_272x389.png`) confirme le principe : 29 px de bordure
pile sur les quatre côtés, soit 10,7 % / 7,5 %.

Un cadre orné de 165 × 258 donne donc un carton de 192 × 285, contre 239 × 340
de bitmap brut : ~24 px de crème en trop en largeur, ~55 px en hauteur.
`tools/build_card.py` fait le recadrage et pose les coins arrondis (rayon 5,5 %
de la largeur).

À noter, le livret de base se contredit sur ce point : son propre rendu des
cartes en présentoir, page 7 (`raw/base/p07_x5530_289x192.png`), montre une
bordure bien plus large — carton à `x = 52`, cadre à `x = 61`, soit 13 % de la
largeur. C'est le visuel officiel des cartes qui fait foi ici, pas ce rendu.

Les anciennes cartes développement 5e éd. (`img/dev/vp_*`) sont laissées telles
quelles, à 11,6 % / 9,7 % de marge. Elles ont sans doute le même excédent, mais
leur bord n'est pas mesurable : le grand médaillon en relief du bas déborde du
cadre orné, la détection le prend pour de l'encre et le recadrage rogne dans le
carton. Les cartes 6e éd. n'ont pas ce problème, elles se recadrent sur leur
liseré imprimé (voir juste en dessous).

## Cartes développement et tuiles bonus — extraire ne marche pas, il faut rendre

Le premier passage avait conclu que Monopole, Invention et Construction de routes
« n'ont aucune image exploitable, leur zone d'art ressort noire ». C'est faux : les
trois cartes existent dans les livrets, et en 6e édition par-dessus le marché. Ce
qui est vrai, c'est qu'**aucune extraction d'XObjects ne peut les sortir**, et pour
deux raisons différentes selon l'édition :

- **5e édition** (`old_base`, `anniv25`) : la carte est bien un seul bitmap, mais sa
  fenêtre d'art est *transparente* — l'illustration est un XObject distinct posé
  dessous. Extraite à plat, sans son masque, la fenêtre ressort noire. D'où le
  fameux « art noir » ; l'art du Chevalier, lui, avait été retrouvé parce qu'il
  traînait isolé sur la même page (`raw/old_base/p05_x611_135x135.png`).
- **6e édition** (`base`, page 3) : la carte est un **damier de petits JPEG** — des
  tuiles de 26 × 24, 52 × 53, 26 × 132 px assemblées par le contenu de page. Et son
  titre comme son texte de règle sont du *texte PDF*, pas de l'image. Une extraction
  ne rend que des confettis.

Dans les deux cas la parade est la même : **rendre la page** plutôt qu'extraire ses
images. Le moteur PDF recompose tuiles, masques et texte. `tools/build_dev.py` fait
ça sur la rangée de la page 3 de CN3081 (« 25 development cards ») :

- les 5 cartes sont à `y 401,55 → 471,56 pt`, larges de `48,87 pt`, au pas de
  `77,50 pt` — dans l'ordre Monopole, Construction de routes, Invention, Chevalier,
  Point de Victoire ;
- rendu à `8×`, soit ~3× la densité native des tuiles. Le gain est réel sur le titre
  et le texte, qui sont vectoriels ; l'illustration, elle, plafonne à ~129 px de
  large et n'est qu'agrandie ;
- le bord du carton se trouve sur le **liseré brun imprimé**, pas sur la limite avec
  le fond de page : le carton (255,253,231 environ) et le fond du livret sont deux
  crèmes quasi identiques, un détourage sur « où s'arrête le fond » ne trouve rien.
  On seuille donc l'encre et on prend sa boîte — 367 × 546 px pour les cinq cartes,
  au pixel près ;
- coins arrondis à 4,5 % de la largeur (mesuré sur le profil du coin), sortie en
  260 × 387, soit 2× la taille d'affichage de `regles.html` sur écran hi-DPI.

Les **2 tuiles bonus** (« 2 bonus victory point tiles ») sont deux rangées plus haut sur
cette même page 3, à `y 174,75 → 251,75 pt`, larges de `67,75 pt`, à `x 286,125` et
`365,75`. Même traitement, à une nuance près : elles portent une **ombre portée**, que le
seuil d'encre des cartes (18) prend pour du carton et qui décale la boîte de plusieurs
points. Il faut monter à **150**, où seul le vert sombre du carton passe encore — les
deux tuiles tombent alors sur `542 × 617 px` pile. Coins bien moins arrondis que les
cartes, 2 % de la largeur ; sortie en 280 × 319.

Les **2 dos de cartes** — la face commune du paquet développement et celle du paquet
ressources — ouvrent chacun leur rangée d'inventaire sur cette même page 3, sous la
légende « card back » : à `x 67,13 → 113,13 pt` / `y 402,75 → 470,75` pour le dos
développement, `x 67,00 → 113,38` / `y 511,00 → 579,25` pour le dos ressources. Même
carrelage, donc même parade ; `tools/build_back.py` s'en charge. Le piège propre à ces
deux-là est la **place** : chacun est coincé entre le titre de sa rangée (3,1 pt
au-dessus) et sa légende (2,5 pt en dessous). La marge de rendu fixe de 4 pt que prend
`build_dev.py` ferait entrer du texte dans la fenêtre, et le seuil d'encre — qui cherche
un liseré et ne sait pas reconnaître un jambage — étirerait la boîte jusqu'aux lettres.
D'où une marge ramenée à 1,5 pt. Les deux cartons tombent alors sur ~46 × 68 pt, soit un
rapport de 0,68 : celui d'une carte Catan réelle (55 × 80 mm) à 1 % près, ce qui confirme
qu'on tient bien le bord et pas une ombre. Sortie en 240 × 355, coins à 5,5 % comme les
cartes ressources dont ils partagent le format.

Le même « rendre au lieu d'extraire » vaut pour tout ce qui résisterait ailleurs dans
les livrets 2025 : avant de conclure qu'un visuel n'existe pas, rendre la page.

## Le médaillon Point de victoire — l'exception qui s'extrait

Le disque rouge au laurier d'or qui illustre le paragraphe *Victory Point* de la **page
9** est le seul signe officiel du point de victoire hors du carton de la carte. C'est lui
que le jeu affiche à côté du score, `img/dev/ed6_point_victoire_icone.png`.

Ici, et à l'inverse de tout ce qui précède, il faut **extraire et surtout pas rendre** :
c'est un vrai bitmap isolé (xref 6465), qu'il suffit de prendre. Le rendre cuirait dans
l'image la crème du fond de page et l'ombre portée du médaillon — deux choses dont une
pastille d'interface n'a que faire.

Trois détails qui font perdre du temps si on ne les connaît pas :

- l'**ombre portée est une seconde copie du même dessin**, presque noire, posée dessous
  et large de quelques centièmes de point (xref 6467, bbox `522,82 → 558,55` contre
  `522,89 → 558,49`). Prendre le mauvais xref donne un médaillon noir ;
- le **masque de transparence annoncé (SMask xref 6464) est opaque de part en part** —
  255 partout, vérifié. C'est un leurre : le médaillon est un JPEG **carré sur fond
  blanc**, invisible dans le livret puisque la page est crème, et parfaitement visible
  sur le bleu de nuit du panneau. Appliquer docilement le masque déclaré donne un carré
  blanc à disque rouge. Le détourage est donc à faire soi-même, et c'est un cercle
  tracé : le disque est **inscrit bord à bord**, l'encre court de la colonne 1 à la
  colonne 94 sur 95. Surtout pas de détourage par la couleur — le blanc du fond et le
  blanc de l'emblème central sont le même, le soleil ressortirait troué ;
- la **couleur plafonne à 95 × 95**. On sort tout de même en 149, où le bord tracé du
  disque est franc plutôt que crénelé. C'est le seul exemplaire dans CN3081 — la page 11
  porte bien un bitmap carré de 149 px, mais c'est l'hexagone de désert.

`tools/build_dev.py` s'en charge, en même temps que les cartes.

## Les pictogrammes de matière — le masque est plus grand que la couleur

Les cadres « BUILDING COST » des **pages 8 et 9** portent les seuls dessins de
matière **détourés** du livret : argile et bois pour la route, plus laine et blé
pour la colonie (page 8) ; blé et minerai pour la ville et la carte
développement (page 9). Partout ailleurs, une ressource est une carte entière —
illustration dans un cadre orné —, qui ne se réduit pas à seize pixels. Ces
vignettes-là sont dessinées pour être lues petites : c'est exactement ce qu'il
faut sur un bouton, et c'est ce que `tools/build_res.py` en tire, dans
`img/res/`.

Comme le médaillon, et à l'inverse des cartes développement, **il faut extraire
et surtout pas rendre** : ce sont de vrais bitmaps isolés, et le rendu cuirait
dans l'image la crème du fond de page, alors que les boutons du jeu sont sur du
sable. Ils ne sont pas dans `raw/` : l'extraction qui l'a rempli avait un
plancher de taille, et aucune des cinq ne l'atteint.

Trois choses à savoir :

- **Le masque de transparence est plus grand que la couleur**, d'environ 1,57×
  — 63 × 54 de couleur pour 99 × 84 de masque sur l'argile, et le même rapport
  pour les cinq. C'est donc le contour qui est net et la couleur qui est floue.
  On sort à la taille du masque : le bord est alors exact, et la couleur — qui
  n'a de toute façon rien à dire à cette échelle — est simplement agrandie.
  À ne pas confondre avec le médaillon de la page 9, dont le SMask déclaré est
  opaque de bout en bout et ne masque rien ; ici les masques sont réels, et le
  script se plaint si l'un d'eux se révèle plein.
- **Les cinq n'ont pas la même hauteur, et il ne faut pas les y ramener.** Le
  minerai est un galet couché, le blé une gerbe debout : dans le livret, la
  gerbe fait 21,0 pt de haut contre 14,7 au galet. Les cinq bitmaps sont posés à
  la même densité — ~2,665 px/pt, vérifié sur les huit placements des deux
  pages —, si bien que leurs tailles natives portent déjà l'échelle relative
  juste. `build_res.py` la contrôle et se plaint au-delà de 2 % d'écart.
- **D'où la bande commune.** Une image se dimensionne en hauteur
  (`height: 1.5em`), et cette hauteur est justement ce qui les distingue :
  ainsi calées, les cinq redeviennent égales et le blé grossit comme un rocher.
  Chacune est donc posée, centrée, dans un cadre transparent de 88 px de haut —
  la plus haute des cinq —, largeur inchangée. Toutes ont alors la même hauteur
  d'image, la feuille de style peut la fixer d'un seul chiffre, et le vide
  au-dessus et au-dessous du galet lui rend sa taille exacte. Le centrage vient
  du livret : dans le cadre de la ville, blé et minerai partagent le même axe
  (milieu à 82,9 pt pour les deux).

Aucun exemplaire plus grand ailleurs — les autres livrets 6e éd. n'ont pas de
cadre de coût, et les seuls autres dessins de ces matières sont ceux des cartes
ressources, noyés dans leur paysage et impossibles à détourer proprement.

## Le cadre maritime — deux pièges

`img/frame/sea_ring.png` vient de l'illustration du plateau assemblé, étalée sur les
pages 4 et 5 du livret de base. Deux choses à savoir si on la redécoupe un jour :

1. **Les deux moitiés se chevauchent de 6 px**, elles ne s'aboutent pas. Le PDF donne
   les rectangles de placement : image de gauche à `x 164.745 … 595.065 pt` sur la
   page 4, image de droite à `x -1.095 … 384.825 pt` sur la page 5, pages de 594 pt
   de large — soit 2,16 pt de recouvrement, à 2,64 px/pt. Collées bout à bout, une
   bande verticale coupe les jetons près de la jointure.
2. **L'échelle se cale sur les jetons chiffres, pas sur la limite terre/eau.** Les 18
   jetons forment un réseau régulier : 318 px entre deux hexagones d'une même ligne
   (√3 rayon) et 275 px entre deux lignes (1,5 rayon), soit **183,5 px par rayon**,
   centre du plateau à (1072,5 ; 927,5) et hexagone extérieur de rayon 5,848.
   Se fier au contour de l'eau donne 199 px/rayon — 8 % de trop, parce que **la plage
   appartient au cadre et non aux tuiles**. Avec cette erreur, le découpage mange la
   plage sur tout le pourtour.

Les 9 ports sont relevés sur cette même image (détection des voiles, accrochage à
l'arête côtière la plus proche **en angle** depuis le centre — pas en distance, les
barques étant loin au large). Ils tombent sur les arêtes 1, 4, 8, 11, 14, 18, 21, 24
et 28 de `D.COAST`, espacées 3-4-3-3-4-3-3-4-3 : aucun port ne partage de sommet.

## Les 6 segments du cadre

Le livret décrit deux mises en place. Page 4, la standard : « Match the numbers at
the puzzle piece ends ». Page 11, la **variable** — celle que le jeu utilise, puisque
les hexagones sont tirés au sort : « **Shuffle and connect** the puzzle piece ends of
the sea frame pieces ». Les ports voyagent donc avec leur segment, **type imprimé
compris** : il n'y a pas de tirage de types séparé, et rien n'est redessiné sur les
voiles.

L'image n'est pas découpée en 6 fichiers : le rendu rogne un secteur de 60° par côté
et fait tourner l'image entière de (côté − segment) × 60°. Le littoral et le bord
extérieur étant tous deux invariants par rotation de 60°, les segments se raccordent
quel que soit le tirage — vérifié sur les 720 permutations dans `test/headless.js`.

**Le joint n'est pas au coin de l'hexagone** mais à `SEAM_DEG = −6,5874°` (+ 60° × k),
c'est-à-dire au sommet de littoral voisin du coin. C'est imposé par l'illustration :
le port posé sur l'arête du coin a sa barque exactement dans l'axe, une découpe au
coin la trancherait en deux.

Taux relevés un par un sur les voiles : **3:1** aux arêtes 1, 8, 11 et 21 ; **2:1**
laine (4), argile (14), bois (18), blé (24), minerai (28). Soit la répartition
officielle, 4 génériques et 5 spécialisés.

## Ce qui a été généré et pas trouvé

`img/token/` et `img/piece/` sont **des créations, pas des extractions** — les originaux
n'existent nulle part en fichier isolé. SVG vectoriel, donc net à n'importe quelle
taille. Les jetons respectent le code officiel : 6 et 8 en rouge, points de probabilité
sous le chiffre (1 point pour 2 et 12, jusqu'à 5 pour 6 et 8).

Le chiffre est **gravé en tracé, pas posé en `<text>`**, et c'est volontaire. Un SVG
chargé en `<img>` ne voit pas les webfonts de la page : il retombe sur la police
système du visiteur. La première version demandait Georgia — dont les chiffres sont
elzéviriens, c'est-à-dire de hauteurs inégales et avec des descendantes. Le 3, le 4,
le 5 et le 9 plongeaient de 0,180 em sous la ligne de base et venaient toucher les
points, quand le 2 s'arrêtait à la hauteur d'x et laissait un grand vide ; l'écart
au-dessus des points allait de 6,3 à 13,6 sur un jeton de 100.

Georgia reste, parce que c'est elle qu'on voulait : elle possède bel et bien des
chiffres alignés, simplement pas par défaut. `build_token.py` va les chercher par sa
fonction OpenType `lnum` — hauteur uniforme de 0,708 em, plus une seule descendante —
et les grave en `<path>` : hauteur unique de 30, ligne de base unique, écart résiduel
de 0,77 qui n'est plus que le surpassement optique des panses rondes.

Le plateau avait le même défaut, hérité du même `Georgia` mais posé au `fillText`. Il
était incorrigible sur place : le canvas 2D n'expose aucun équivalent de
`font-feature-settings`, donc aucun moyen de réclamer les chiffres alignés d'une
police qui en possède. `build_token.py` sort donc aussi `js/tokens.js`, que
`js/render.js` rejoue — exactement le montage de `js/pieces.js` pour les pions. Le
plateau et la page de règles partagent maintenant le tracé au centième près.

**Ces SVG et ce js/tokens.js sont des sorties**, comme `img/piece/` — pour changer
l'allure d'un jeton, ce sont les constantes en tête de `tools/build_token.py`.

`img/piece/` n'est plus dessiné à la main : les pions du jeu sont des solides de bois,
décrits en volume dans `js/pieces.js` et projetés en isométrie. `tools/build_piece.js`
en tire les 19 SVG, et `js/render.js` peint la même géométrie sur le plateau — les
règles et le jeu montrent donc exactement la même pièce. **Ces SVG sont des sorties :
les retoucher à la main serait perdu au prochain `node tools/build_piece.js`.** Pour
changer l'allure d'un pion, c'est `js/pieces.js` qu'on ouvre.

## Droits

L'art extrait est la propriété de Catan GmbH / Catan Studio. Les PDF sont distribués
publiquement et gratuitement par l'éditeur, mais ça ne vaut pas licence de
redistribution. OK pour un usage privé sur le NAS ; à remplacer par de l'art original
si le jeu devait être publié.

Même réserve pour Georgia, propriété de Microsoft : `raw/_font/Georgia-Bold.ttf` est
une copie de la police système, et les chiffres des jetons en sont des tracés. Rien à
signaler pour un usage privé, mais graver une police propriétaire dans des fichiers
servis publiquement, c'est la redistribuer. Le jour où ça compterait, basculer `FONT`
sur `« gelasio »` en tête de `tools/build_token.py` et relancer : Gelasio est sous
licence SIL OFL, à métriques compatibles avec Georgia, et le script la télécharge
tout seul.

Alternatives sous licence libre repérées si besoin un jour :
- <https://github.com/appmancer/TheSourceFilesOfCatan> — tuiles SVG, CC-BY 4.0
- <https://opengameart.org/content/hexagon-tiles-93x> — tuiles hexagonales génériques
- <https://skullreaper.itch.io/catan-like-hex-tiles>
