diff --git a/module/actor.js b/module/actor.js
index 9df2bd1c..ee1e39af 100644
--- a/module/actor.js
+++ b/module/actor.js
@@ -1163,26 +1163,6 @@ export class RdDActor extends Actor {
     return tmrInnaccessibles.map(it => it.data.coord);
   }
 
-  /* -------------------------------------------- */
-  displayTMRQueueSouffleInformation() {
-    let messages = [];
-    for (let item of this.data.items) {
-      if (EffetsDraconiques.isUrgenceDraconique(item)) {
-        messages.push("Vous souffrez d'une Urgence Draconique : " + item.data.description);
-      }
-      if (EffetsDraconiques.isPeriple(item)) {
-        messages.push("Vous souffrez du Souffle Périple. Vous devez gérer manuellement le détail du Périple.
" + item.data.description);
-      }
-    }
-
-    if (messages.length > 0) {
-      ChatMessage.create({
-        whisper: ChatUtility.getWhisperRecipientsAndGMs(game.user.name),
-        content: "RAPPEL !
" + messages.join('
')
-      });
-    }
-  }
-
   /* -------------------------------------------- */
   getTMRRencontres() {
     return this.data.data.reve.rencontre;
diff --git a/module/rdd-tmr-dialog.js b/module/rdd-tmr-dialog.js
index 4f876aa2..cbc1aafe 100644
--- a/module/rdd-tmr-dialog.js
+++ b/module/rdd-tmr-dialog.js
@@ -108,6 +108,11 @@ export class RdDTMRDialog extends Dialog {
     this._createTokens();
   }
 
+  removeToken(tmr, casetmr) {
+    this._removeTokens(t => t.coordTMR() == tmr.coord && t.caseSpeciale?._id == casetmr._id);
+    this.updateTokens()
+  }
+
   /* -------------------------------------------- */
   _getTokensCasesTmr() {
     return this.casesSpeciales.map(c => this._tokenCaseSpeciale(c)).filter(token => token);
@@ -142,7 +147,7 @@ export class RdDTMRDialog extends Dialog {
   async activateListeners(html) {
     super.activateListeners(html);
 
-    document.getElementById("tmrrow1").insertCell(1).append(this.pixiApp.view);
+    document.getElementById("tmrrow1").insertCell(0).append(this.pixiApp.view);
 
     if (this.viewOnly) {
       html.find('#lancer-sort').remove();
@@ -168,7 +173,6 @@ export class RdDTMRDialog extends Dialog {
     let tmr = TMRUtility.getTMR(this.actor.data.data.reve.tmrpos.coord);
     await this.manageRencontre(tmr, () => {
       this.postRencontre(tmr);
-      this.actor.displayTMRQueueSouffleInformation();
     });
   }
 
@@ -571,10 +575,20 @@ export class RdDTMRDialog extends Dialog {
       });
     }
   }
-
-  removeToken(tmr, casetmr) {
-    this._removeTokens(t => t.coordTMR() == tmr.coord && t.caseSpeciale?._id == casetmr._id);
-    this.updateTokens()
+  /* -------------------------------------------- */
+  async purifierPeriple(tmr) {
+    if (EffetsDraconiques.periple.find(this.casesSpeciales, tmr.coord)) {
+      await this._conquerir(tmr, {
+        difficulte: EffetsDraconiques.periple.getDifficulte(tmr),
+        action: 'Purifier ' + TMRUtility.getTMRDescr(tmr.coord),
+        onConqueteReussie: r => EffetsDraconiques.periple.onVisiteSupprimer(r.actor, tmr, (casetmr) => this.removeToken(tmr, casetmr)),
+        onConqueteEchec: r => {
+          this.souffleSiEchecTotal(rollData);
+          this.close()
+        },
+        canClose: false
+      });
+    }
   }
 
   /* -------------------------------------------- */
@@ -648,6 +662,7 @@ export class RdDTMRDialog extends Dialog {
 
   async validerVisite(tmr) {
     await EffetsDraconiques.pelerinage.onVisiteSupprimer(this.actor, tmr, (casetmr) => this.removeToken(tmr, casetmr));
+    await EffetsDraconiques.urgenceDraconique.onVisiteSupprimer(this.actor, tmr, (casetmr) => this.removeToken(tmr, casetmr));
   }
 
 
@@ -656,11 +671,12 @@ export class RdDTMRDialog extends Dialog {
 
     let sortReserveList = TMRUtility.getSortReserveList(this.sortsReserves, coord);
     if (sortReserveList.length > 0) {
-      if (EffetsDraconiques.isSortImpossible(this.actor)) {
+      if (EffetsDraconiques.isSortReserveImpossible(this.actor)) {
         ui.notifications.error("Une queue ou un souffle vous empèche de déclencher de sort!");
         return;
       }
-      if (EffetsDraconiques.isReserveEnSecurite(this.actor) || this.isReserveExtensible(coord)) {
+      if (!EffetsDraconiques.isUrgenceDraconique(this.actor) &&
+        (EffetsDraconiques.isReserveEnSecurite(this.actor) || this.isReserveExtensible(coord))) {
         let msg = "Vous êtes sur une case avec un Sort en Réserve. Grâce à votre Tête Reserve en Sécurité ou Réserve Exensible, vous pouvez contrôler le déclenchement. Cliquez si vous souhaitez le déclencher : ";
         for (let sortReserve of sortReserveList) {
           msg += "- " + sortReserve.sort.name + "
 ";
@@ -670,9 +686,9 @@ export class RdDTMRDialog extends Dialog {
           content: msg,
           whisper: ChatMessage.getWhisperRecipients(game.user.name)
         });
-      } else {
-        await this.processSortReserve(sortReserveList[0]);
+        return;
       }
+      await this.processSortReserve(sortReserveList[0]);
     }
   }
 
@@ -842,6 +858,7 @@ export class RdDTMRDialog extends Dialog {
     if (!(this.viewOnly || this.currentRencontre)) {
       await this.manageCaseHumide(tmr);
       await this.conquerirCiteFermee(tmr);
+      await this.purifierPeriple(tmr);
       await this.conquerirTMR(tmr);
       await this.validerVisite(tmr);
       await this.declencheSortEnReserve(tmr.coord);
diff --git a/module/tmr-utility.js b/module/tmr-utility.js
index aa0358ef..74863674 100644
--- a/module/tmr-utility.js
+++ b/module/tmr-utility.js
@@ -210,8 +210,8 @@ const TMRMapping = {
 
 export const TMRType = {
   cite: { name: "cité", genre: "f" },
-  sanctuaire: { name: "sanctuaire" },
-  plaines: { name: "plaines", genre: "p" },
+  sanctuaire: { name: "sanctuaire", genre: 'm' },
+  plaines: { name: "plaines", genre: "fp" },
   pont: { name: "pont", genre: "m" },
   collines: { name: "collines", genre: "p" },
   foret: { name: "forêt", genre: "f" },
@@ -332,7 +332,12 @@ export class TMRUtility {
   }
 
   static getTMRLabel(coord) {
-    return TMRMapping[coord]?.label ?? (coord+": case inconnue");
+    return TMRMapping[coord]?.label ?? (coord + ": case inconnue");
+  }
+
+  static getTMRDescr(coord) {
+    const tmr = TMRMapping[coord];
+    return Grammar.articleDetermine(tmr.genre) + ' ' + tmr.label;
   }
 
   static isCaseHumide(tmr) {
@@ -384,7 +389,7 @@ export class TMRUtility {
       currentPos.x = currentPos.x + direction.x;
       currentPos.y = currentPos.y + direction.y;
       if (this._checkTMRCoord(currentPos.x, currentPos.y)) { // Sortie de carte ! Ré-insertion aléatoire
-        coord  = TMRUtility.getTMR(TMRUtility.convertToTMRCoord(currentPos));
+        coord = TMRUtility.getTMR(TMRUtility.convertToTMRCoord(currentPos));
       } else {
         coord = await actor.reinsertionAleatoire('Sortie de carte');
       }
@@ -435,7 +440,7 @@ export class TMRUtility {
       return reserveList.filter(it => TMRUtility.getTMR(it.coord).type == 'fleuve');
     }
     // Reserve sur un case "normale"
-    return  reserveList.filter(it => it.coord == coord);
+    return reserveList.filter(it => it.coord == coord);
   }
 
   /* -------------------------------------------- */
@@ -450,9 +455,8 @@ export class TMRUtility {
       for (let dy = -portee; dy <= portee; dy++) { // Loop thru lines
         const currentPos = { x: centerPos.x + dx, y: centerPos.y + dy };
         if (this._checkTMRCoord(currentPos.x, currentPos.y)) { // Coordinate is valie
-          let posPicNow = this.computeRealPictureCoordinates(currentPos, tmrConstants);
-          let dist = Math.sqrt(Math.pow(posPicNow.x - posPic.x, 2) + Math.pow(posPicNow.y - posPic.y, 2)) / tmrConstants.cellw;
-          if (dist < portee + 0.5) {
+          let dist = this.distancePosTMR(centerPos, currentPos);
+          if (dist <= portee) {
             caseList.push(this.convertToTMRCoord(currentPos)); // Inside the area
           }
         }
@@ -460,5 +464,21 @@ export class TMRUtility {
     }
     return caseList;
   }
+
+  static distanceTMR(coord1, coord2) {
+    let pos1 = this.convertToCellPos(coord1);
+    let pos2 = this.convertToCellPos(coord2);
+    return this.distancePosTMR(pos1, pos2);
+  }
+
+  static distancePosTMR(pos1, pos2) {
+    const dx = pos2.x - pos1.x;
+    const dy = pos2.y - pos1.y;
+    const abs_dx = Math.abs(dx);
+    const abs_dy = Math.abs(dy);
+    const distance = Math.sign(dx) == Math.sign(dy) ? Math.max(abs_dx, abs_dy) : (abs_dx + abs_dy);
+    return distance;
+  }
+
 }
 
diff --git a/module/tmr/effets-draconiques.js b/module/tmr/effets-draconiques.js
index ab8bdc3d..6eefe7f3 100644
--- a/module/tmr/effets-draconiques.js
+++ b/module/tmr/effets-draconiques.js
@@ -14,6 +14,8 @@ import { PresentCites } from "./present-cites.js";
 import { Desorientation } from "./desorientation.js";
 import { Conquete } from "./conquete.js";
 import { Pelerinage } from "./pelerinage.js";
+import { Periple } from "./periple.js";
+import { UrgenceDraconique } from "./urgence-draconique.js";
 
 
 export class EffetsDraconiques {
@@ -32,6 +34,8 @@ export class EffetsDraconiques {
   static desorientation = new Desorientation();
   static conquete = new Conquete();
   static pelerinage = new Pelerinage();
+  static periple = new Periple();
+  static urgenceDraconique = new UrgenceDraconique();
 
   static init() {
     Draconique.register(EffetsDraconiques.carteTmr);
@@ -49,6 +53,8 @@ export class EffetsDraconiques {
     Draconique.register(EffetsDraconiques.desorientation);
     Draconique.register(EffetsDraconiques.conquete);
     Draconique.register(EffetsDraconiques.pelerinage);
+    Draconique.register(EffetsDraconiques.periple);
+    Draconique.register(EffetsDraconiques.urgenceDraconique);
   }
 
   /* -------------------------------------------- */
@@ -112,8 +118,7 @@ export class EffetsDraconiques {
   }
 
   static isPeriple(element) {
-    // TODO
-    return EffetsDraconiques.isMatching(element, it => Draconique.isSouffleDragon(it) && ir.name.toLowerCase() == 'périple');
+    return EffetsDraconiques.isMatching(element, it => EffetsDraconiques.periple.match(it));
   }
 
   static isDesorientation(element) {
@@ -122,7 +127,19 @@ export class EffetsDraconiques {
 
   /* -------------------------------------------- */
   static isSortImpossible(element) {
-    return EffetsDraconiques.isMatching(element, it => EffetsDraconiques.conquete.match(it) || EffetsDraconiques.pelerinage.match(it));
+    return EffetsDraconiques.isMatching(element, it =>
+      EffetsDraconiques.conquete.match(it) ||
+      EffetsDraconiques.periple.match(it) ||
+      EffetsDraconiques.urgenceDraconique.match(it) ||
+      EffetsDraconiques.pelerinage.match(it)
+    );
+  }
+  static isSortReserveImpossible(element) {
+    return EffetsDraconiques.isMatching(element, it =>
+      EffetsDraconiques.conquete.match(it) ||
+      EffetsDraconiques.periple.match(it) ||
+      EffetsDraconiques.pelerinage.match(it)
+    );
   }
 
   static isConquete(element) {
@@ -138,7 +155,7 @@ export class EffetsDraconiques {
   }
 
   static isUrgenceDraconique(element) {
-    return EffetsDraconiques.isMatching(element, it => Draconique.isQueueDragon(it) && it.name.toLowerCase() == 'urgence draconique');
+    return EffetsDraconiques.isMatching(element, it => EffetsDraconiques.urgenceDraconique.match(it));
   }
 
   /* -------------------------------------------- */
diff --git a/module/tmr/periple.js b/module/tmr/periple.js
new file mode 100644
index 00000000..feba1a2b
--- /dev/null
+++ b/module/tmr/periple.js
@@ -0,0 +1,44 @@
+import { Grammar } from "../grammar.js";
+import { tmrColors, tmrConstants, tmrTokenZIndex, TMRUtility } from "../tmr-utility.js";
+import { Draconique } from "./draconique.js";
+
+export class Periple extends Draconique {
+
+  constructor() {
+    super();
+  }
+
+  type() { return 'souffle' }
+  match(item) { return Draconique.isSouffleDragon(item) && Grammar.toLowerCaseNoAccent(item.name).includes('periple'); }
+  manualMessage() { return false }
+
+  async onActorCreateOwned(actor, souffle) {
+    let terrain = new Roll("1d2").evaluate().total == 1 ? 'sanctuaire' : 'necropole';
+    let tmrs = TMRUtility.getListTMR(terrain);
+    for (let tmr of tmrs) {
+      await this.createCaseTmr(actor, 'Périple: ' + tmr.label, tmr, souffle._id);
+    }
+  }
+
+
+  code() { return 'periple' }
+  tooltip(linkData) { return `Votre Périple passe par ${this.tmrDescr(linkData)}` }
+  img() { return 'icons/svg/acid.svg' }
+
+  createSprite(pixiTMR) {
+    return pixiTMR.sprite(this.code(), {
+      zIndex: tmrTokenZIndex.conquete,
+      alpha: 1,
+      color: tmrColors.souffle,
+      taille: tmrConstants.twoThird,
+      decallage: tmrConstants.right
+    });
+  }
+  getDifficulte(tmr) {
+    switch (tmr.type) {
+      case 'sanctuaire': return -3;
+      case 'necropole': return -5;
+    }
+    return 0;
+  }
+}
\ No newline at end of file
diff --git a/module/tmr/urgence-draconique.js b/module/tmr/urgence-draconique.js
new file mode 100644
index 00000000..8af5c992
--- /dev/null
+++ b/module/tmr/urgence-draconique.js
@@ -0,0 +1,55 @@
+import { ChatUtility } from "../chat-utility.js";
+import { Grammar } from "../grammar.js";
+import { Misc } from "../misc.js";
+import { RdDRollTables } from "../rdd-rolltables.js";
+import { tmrColors, tmrConstants, tmrTokenZIndex, TMRUtility } from "../tmr-utility.js";
+import { Draconique } from "./draconique.js";
+
+export class UrgenceDraconique extends Draconique {
+
+  constructor() {
+    super();
+  }
+
+  type() { return 'queue' }
+  match(item) { return Draconique.isQueueDragon(item) && Grammar.toLowerCaseNoAccent(item.name).includes('urgence draconique'); }
+  manualMessage() { return false }
+  async onActorCreateOwned(actor, queue) {
+    let coordSortsReserve = (actor.data.data.reve.reserve?.list.map(it => it.coord)) ?? [];
+    if (coordSortsReserve.length == 0) {
+      // La queue se transforme en idée fixe
+      let ideeFixe = await RdDRollTables.getIdeeFixe();
+      ChatMessage.create({
+        whisper: ChatUtility.getWhisperRecipientsAndGMs(game.user.name),
+        content: `En l'absence de sorts en réserve, l'urgence draconique de ${actor.name} se transforme en ${queue.name}`
+      });
+      await actor.createOwnedItem(ideeFixe);
+      await actor.deleteOwnedItem(queue._id);
+      return;
+    }
+    else {
+      let demiReve = actor.getDemiReve();
+      coordSortsReserve.sort((a, b) => TMRUtility.distanceTMR(a, demiReve) - TMRUtility.distanceTMR(b, demiReve));
+      let tmr = TMRUtility.getTMR(coordSortsReserve[0]);
+      await this.createCaseTmr(actor, 'Urgence draconique: ' + tmr.label, tmr, queue._id);
+    }
+  }
+
+  async onActorDeleteCaseTmr(actor, casetmr) {
+    await actor.deleteOwnedItem(casetmr.data.sourceid);
+  }
+
+  code() { return 'urgence' }
+  tooltip(linkData) { return `Urgence draconique!` }
+  img() { return 'icons/svg/hazard.svg' }
+
+  createSprite(pixiTMR) {
+    return pixiTMR.sprite(this.code(),
+      {
+        zIndex: tmrTokenZIndex.conquete,
+        color: tmrColors.queues,
+        taille: tmrConstants.full,
+        decallage: { x: 2, y: 0 }
+      });
+  }
+}
diff --git a/templates/casetmr-specific-list.html b/templates/casetmr-specific-list.html
index 48be5d5b..136f1f6d 100644
--- a/templates/casetmr-specific-list.html
+++ b/templates/casetmr-specific-list.html
@@ -1,12 +1,13 @@
+
+
+
+
+
+
+
+
+
+
 
 
-
-
-
-
-
-
-
-
-
-
+