diff --git a/.gitignore b/.gitignore
index 1f4f087..3a18863 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,3 +6,4 @@ builds/
# Textures que Godot extrait des .glb a l import : regenerees, non versionnees
game/presentation/cockpit/assets/models/*.png
+game/world/wrecks/assets/**/*.png
diff --git a/docs/ASSET_LICENSES.md b/docs/ASSET_LICENSES.md
new file mode 100644
index 0000000..2ffca5a
--- /dev/null
+++ b/docs/ASSET_LICENSES.md
@@ -0,0 +1,49 @@
+# Registre des licences de ressources externes
+
+Registre exigé par `GAME_DESIGN_PLAN.md` §19 : chaque ressource tierce (modèle,
+texture, son, police) a une entrée ici avant d'entrer dans le dépôt ou dans une
+build. Une ressource dont la licence interdit la diffusion commerciale est
+marquée `À REMPLACER AVANT COMMERCIALISATION` et doit sortir du projet avant
+toute vente, précommande, financement participatif ou page store payante.
+
+Statuts possibles : `OK commercial`, `À VÉRIFIER`, `À REMPLACER AVANT
+COMMERCIALISATION`, `RETIRÉ`.
+
+## Modèles 3D
+
+### MV Hebat Allah — `OK commercial` (crédit obligatoire)
+
+- Source : https://sketchfab.com/3d-models/shipwreck-mv-hebat-allah-3a5306f3961146729d054ee42bc063e5
+- Auteur : Holger Buss (`holger.buss`), Sketchfab.
+- Licence : **CC BY 4.0**. Usage commercial et dérivés autorisés à condition de
+ créditer l'auteur. Crédit à inscrire dans l'écran des crédits :
+ « MV Hebat Allah shipwreck scan by Holger Buss (sketchfab.com), CC BY 4.0,
+ modified ».
+- Contenu d'origine : scan photogrammétrique d'un caboteur de 44 m coulé
+ volontairement en mer Rouge (2004). 2 375 184 triangles, 109 morceaux, une
+ texture 8K. Fichier brut conservé hors dépôt dans
+ `C:\Users\olivi\Assets\hebat_allah\raw\`, jamais committé.
+- Dérivés committés (`game/world/wrecks/assets/hebat_allah/`) : coque remise à
+ l'échelle sur 44 m, jupe de sédiment coupée à 3 m, soupe de triangles fusionnée
+ par distance, fragments isolés retirés, surface refermée par remesh voxel
+ 0,4 m, LOD0 58 k triangles et LOD1 14,5 k avec UV refaits, albédo rebaké en 2K
+ puis neutralisé (le canal rouge du scan est inexploitable, la teinte est
+ reconstruite depuis la luminance), collision trimesh séparée de 2,9 k
+ triangles. Pipeline reproductible : `scripts/assets/hebat_allah_prepare_albedo.py`
+ puis `scripts/assets/hebat_allah_blender_pipeline.py`.
+- Usage dans le projet : kit « acier du XXe siècle », site des hauts-fonds
+ ensoleillés (`game/world/sites/sunlit_shallows_environment.tscn`).
+
+## Modèles du cockpit — `À VÉRIFIER` (polices seulement)
+
+- `game/presentation/cockpit/assets/models/*.glb` : générés par scripts Blender
+ écrits pour le projet, aucune ressource tierce (voir
+ `docs/briefs/cockpit-modeles-integration.md`). Modèles : `OK commercial`.
+- Polices rendues en texture dans les cadrans et étiquettes : Arial et Impact,
+ polices système Windows. Point de licence à vérifier avant diffusion ; prévoir
+ une police libre (SIL OFL) en remplacement si nécessaire.
+
+## Images de référence
+
+- `docs/visual_targets/cockpit-objective-v1.jpg` : générée pour le projet,
+ référence interne non distribuée dans les builds. Pas de contrainte.
diff --git a/game/world/sites/sunlit_shallows_environment.tscn b/game/world/sites/sunlit_shallows_environment.tscn
index a34ac31..1cfd129 100644
--- a/game/world/sites/sunlit_shallows_environment.tscn
+++ b/game/world/sites/sunlit_shallows_environment.tscn
@@ -1,6 +1,7 @@
-[gd_scene load_steps=3 format=3]
+[gd_scene load_steps=4 format=3]
[ext_resource type="Script" path="res://game/world/sites/sunlit_shallows_environment.gd" id="1_environment"]
+[ext_resource type="PackedScene" path="res://game/world/wrecks/hebat_allah_wreck.tscn" id="2_wreck"]
[sub_resource type="Environment" id="EnvironmentSunlitShallows"]
background_mode = 1
@@ -62,3 +63,7 @@ transform = Transform3D(1, 0, 0, 0, 0.9962, 0.0872, 0, -0.0872, 0.9962, 0, -30,
fov = 72.0
near = 0.1
far = 400.0
+
+[node name="HebatAllahWreck" parent="." instance=ExtResource("2_wreck")]
+position = Vector3(-8, -41, -62)
+rotation_degrees = Vector3(0, 55, 3)
diff --git a/game/world/wrecks/assets/hebat_allah/hebat_allah_collision.glb b/game/world/wrecks/assets/hebat_allah/hebat_allah_collision.glb
new file mode 100644
index 0000000..037d368
Binary files /dev/null and b/game/world/wrecks/assets/hebat_allah/hebat_allah_collision.glb differ
diff --git a/game/world/wrecks/assets/hebat_allah/hebat_allah_visual.glb b/game/world/wrecks/assets/hebat_allah/hebat_allah_visual.glb
new file mode 100644
index 0000000..2ba1c4c
Binary files /dev/null and b/game/world/wrecks/assets/hebat_allah/hebat_allah_visual.glb differ
diff --git a/game/world/wrecks/hebat_allah_wreck.tscn b/game/world/wrecks/hebat_allah_wreck.tscn
new file mode 100644
index 0000000..8e76947
--- /dev/null
+++ b/game/world/wrecks/hebat_allah_wreck.tscn
@@ -0,0 +1,12 @@
+[gd_scene load_steps=4 format=3]
+
+[ext_resource type="Script" path="res://game/world/wrecks/wreck_actor.gd" id="1_wreck_actor"]
+[ext_resource type="PackedScene" path="res://game/world/wrecks/assets/hebat_allah/hebat_allah_visual.glb" id="2_visual"]
+[ext_resource type="PackedScene" path="res://game/world/wrecks/assets/hebat_allah/hebat_allah_collision.glb" id="3_collision"]
+
+[node name="HebatAllahWreck" type="StaticBody3D"]
+script = ExtResource("1_wreck_actor")
+visual_scene = ExtResource("2_visual")
+collision_scene = ExtResource("3_collision")
+lod_switch_distance_m = 45.0
+sonar_reflectivity = 0.9
diff --git a/game/world/wrecks/wreck_actor.gd b/game/world/wrecks/wreck_actor.gd
new file mode 100644
index 0000000..9dd8d30
--- /dev/null
+++ b/game/world/wrecks/wreck_actor.gd
@@ -0,0 +1,65 @@
+class_name WreckActor
+extends StaticBody3D
+
+## A wreck resting on a site: two visual levels of detail from one glTF and a
+## separate, much lighter trimesh collision. The sonar reads the body's
+## metadata, so this node is the one owner of how a wreck echoes.
+
+const LOD0_NODE_NAME := "WreckLOD0"
+const LOD1_NODE_NAME := "WreckLOD1"
+const COLLISION_NODE_NAME := "WreckCollision"
+const COLLISION_SHAPE_NAME := "Collision"
+const VISUAL_NAME := "Visual"
+## Hysteresis around the LOD handover so a hovering submarine never flickers.
+const LOD_MARGIN_M := 4.0
+
+@export var visual_scene: PackedScene
+@export var collision_scene: PackedScene
+## Beyond this distance the coarse LOD is drawn instead of the detailed one.
+@export_range(10.0, 400.0, 1.0) var lod_switch_distance_m := 45.0
+@export_range(0.0, 1.0, 0.01) var sonar_reflectivity := 0.9
+
+
+func _ready() -> void:
+ set_meta("sonar_material", SonarMaterial.Value.METAL)
+ set_meta("sonar_reflectivity", sonar_reflectivity)
+ _build_visual()
+ _build_collision()
+
+
+func _build_visual() -> void:
+ if visual_scene == null:
+ push_error("WreckActor %s has no visual scene" % name)
+ return
+ var visual := visual_scene.instantiate() as Node3D
+ visual.name = VISUAL_NAME
+ add_child(visual)
+ var lod0 := visual.find_child(LOD0_NODE_NAME, true, false) as MeshInstance3D
+ var lod1 := visual.find_child(LOD1_NODE_NAME, true, false) as MeshInstance3D
+ if lod0 == null or lod1 == null:
+ push_error("WreckActor %s visual scene lacks %s or %s" % [
+ name, LOD0_NODE_NAME, LOD1_NODE_NAME
+ ])
+ return
+ lod0.visibility_range_end = lod_switch_distance_m
+ lod0.visibility_range_end_margin = LOD_MARGIN_M
+ lod1.visibility_range_begin = lod_switch_distance_m
+ lod1.visibility_range_begin_margin = LOD_MARGIN_M
+
+
+func _build_collision() -> void:
+ if collision_scene == null:
+ push_error("WreckActor %s has no collision scene" % name)
+ return
+ var source := collision_scene.instantiate() as Node3D
+ var collision_mesh := source.find_child(COLLISION_NODE_NAME, true, false) as MeshInstance3D
+ if collision_mesh == null or collision_mesh.mesh == null:
+ push_error("WreckActor %s collision scene lacks %s" % [name, COLLISION_NODE_NAME])
+ source.free()
+ return
+ var shape := CollisionShape3D.new()
+ shape.name = COLLISION_SHAPE_NAME
+ shape.shape = collision_mesh.mesh.create_trimesh_shape()
+ shape.transform = collision_mesh.transform
+ source.free()
+ add_child(shape)
diff --git a/scripts/assets/hebat_allah_blender_pipeline.py b/scripts/assets/hebat_allah_blender_pipeline.py
new file mode 100644
index 0000000..e0b52c0
--- /dev/null
+++ b/scripts/assets/hebat_allah_blender_pipeline.py
@@ -0,0 +1,272 @@
+"""Blender pipeline turning the raw MV Hebat Allah photogrammetry scan into the
+game-ready wreck assets committed under game/world/wrecks/assets/hebat_allah/.
+
+Run headless with Blender 5.2:
+
+ WRECK_RAW_DIR=
+ WRECK_OUT_DIR=