{"id":23596,"date":"2026-07-12T06:33:55","date_gmt":"2026-07-12T06:33:55","guid":{"rendered":"https:\/\/www.transports-express-caraibes.fr\/blog\/bateau-inter-iles-antilles\/"},"modified":"2026-07-12T06:33:55","modified_gmt":"2026-07-12T06:33:55","slug":"bateau-inter-iles-antilles","status":"publish","type":"post","link":"https:\/\/www.transports-express-caraibes.fr\/blog\/bateau-inter-iles-antilles\/","title":{"rendered":"Bateau inter-\u00eeles aux Antilles fran\u00e7aises : guide complet pour voyager facilement"},"content":{"rendered":"<ul class=\"wp-block-list\"><li><strong>Bateau inter-\u00eeles<\/strong> : travers\u00e9es r\u00e9guli\u00e8res entre Martinique et Guadeloupe, 4\u20135 heures en moyenne.<\/li><li><strong>R\u00e9servation ferry<\/strong> recommand\u00e9e \u00e0 l\u2019avance pour avoir les meilleurs horaires et tarifs.<\/li><li><strong>Transport maritime<\/strong> : confort variable selon la compagnie, bagage standard souvent inclus (\u224825 kg).<\/li><li><strong>Alternatives<\/strong> : vol inter-\u00eeles (\u224845 min) ou location de bateau priv\u00e9 pour plus de flexibilit\u00e9.<\/li><li><strong>Conseil pratique<\/strong> : arriver au port 60 minutes avant l\u2019embarquement et v\u00e9rifier les horaires bateaux la veille.<\/li><\/ul>\n\n<p class=\"wp-block-paragraph\"><strong>Envie d\u2019un voyage facile entre les \u00eeles des Antilles ?<\/strong> Traverser la mer des Cara\u00efbes entre la Martinique et la Guadeloupe reste une exp\u00e9rience \u00e0 la fois pratique et pittoresque pour qui s\u2019organise correctement. Ce guide rassemble les informations concr\u00e8tes pour r\u00e9server et r\u00e9ussir votre travers\u00e9e inter-\u00eeles : quelles compagnies desservent la liaison, combien co\u00fbte un billet, combien de temps dure la travers\u00e9e, quels documents et bagages pr\u00e9voir, et quelles alternatives consid\u00e9rer si le temps presse. Des astuces terrain, des erreurs \u00e0 \u00e9viter et des exemples chiffr\u00e9s permettront de pr\u00e9parer un trajet serein, que vous voyagiez en famille, en groupe ou seul. Les conseils sont centr\u00e9s sur le transport maritime local, avec des r\u00e9f\u00e9rences vers les plateformes de r\u00e9servation et des retours d\u2019exp\u00e9rience r\u00e9alistes pour que votre prochain d\u00e9placement aux Antilles fran\u00e7aises se transforme en un vrai moment de plaisir plut\u00f4t qu\u2019en une source de stress logistique.<\/p>\n\n<h2 class=\"wp-block-heading\">Comment fonctionne le bateau inter-\u00eeles entre Martinique et Guadeloupe<\/h2>\n\n<p class=\"wp-block-paragraph\">Le transport maritime entre Fort\u2011de\u2011France et Pointe\u2011\u00e0\u2011Pitre est assur\u00e9 par plusieurs op\u00e9rateurs. Les navires combinent si\u00e8ges int\u00e9rieurs climatis\u00e9s et ponts ext\u00e9rieurs pour profiter du paysage. <strong>La dur\u00e9e type<\/strong> se situe entre <strong>4 et 5 heures<\/strong>, variable selon la m\u00e9t\u00e9o et les escales.<\/p>\n\n<p class=\"wp-block-paragraph\">Les compagnies proposent des classes de service diff\u00e9rentes : standard, premium (salon), et parfois des options de bagages incluses. Pour comparer les offres et r\u00e9server rapidement, utiliser une plateforme de r\u00e9servation en ligne facilite grandement l\u2019organisation.<\/p>\n\n<p class=\"wp-block-paragraph\">Cl\u00e9 pratique : choisir la compagnie en fonction de l\u2019horaire qui convient le mieux \u00e0 votre planning, pas seulement sur le prix. C\u2019est souvent ce choix qui garantit un <strong>voyage facile<\/strong>.<\/p>\n\n<h2 class=\"wp-block-heading\">Horaires bateaux, dur\u00e9e et r\u00e9servation ferry<\/h2>\n\n<p class=\"wp-block-paragraph\">Les horaires bateaux varient selon la saison et la compagnie. En haute saison, il y a des d\u00e9parts quotidiens le matin et des retours en fin d\u2019apr\u00e8s\u2011midi. V\u00e9rifiez les cr\u00e9neaux la veille et surveillez les changements m\u00e9t\u00e9o qui peuvent impacter les travers\u00e9es.<\/p>\n\n<p class=\"wp-block-paragraph\">R\u00e9server t\u00f4t permet d\u2019acc\u00e9der \u00e0 des prix plus bas et \u00e0 des places mieux situ\u00e9es. Les plateformes sp\u00e9cialis\u00e9es listent les d\u00e9parts et comparent les services offerts.<\/p>\n\n<p class=\"wp-block-paragraph\">O\u00f9 consulter et r\u00e9server :<\/p>\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/www.frs-express.com\/\" target=\"_blank\" rel=\"noopener\">Site officiel de FRS Express<\/a> pour les liaisons r\u00e9guli\u00e8res et offres sp\u00e9ciales.<\/li><li><a href=\"https:\/\/www.karibnav.com\/\" target=\"_blank\" rel=\"noopener\">Karib&rsquo;Nav<\/a> pour comparer plusieurs ferries et r\u00e9server en ligne.<\/li><li><a href=\"https:\/\/www.antillesevasion.com\/fr\/guide\/comment-se-deplacer-aux-antilles-francaises-ferries-vols-conseils\" target=\"_blank\" rel=\"noopener\">Guide pratique Antilles \u00c9vasion<\/a> pour conseils et alternatives.<\/li><\/ul>\n\n<figure class=\"wp-block-table\"><table>\n<thead>\n<tr>\n<th>Compagnie<\/th>\n<th>Dur\u00e9e estim\u00e9e<\/th>\n<th>Prix indicatif aller simple<\/th>\n<th>Services inclus<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><strong>FRS Express<\/strong><\/td>\n<td><strong>4\u20135 h<\/strong><\/td>\n<td><strong>\u224850\u201399 \u20ac<\/strong><\/td>\n<td>Bagage 25 kg, salon climatis\u00e9<\/td>\n<\/tr>\n<tr>\n<td>Op\u00e9rateur alternatif<\/td>\n<td>4\u20135 h<\/td>\n<td>\u224840\u201379 \u20ac<\/td>\n<td>Espace ext\u00e9rieur, snack \u00e0 bord<\/td>\n<\/tr>\n<tr>\n<td>Vol inter-\u00eeles (comparatif)<\/td>\n<td><strong>\u224845 min<\/strong><\/td>\n<td><strong>\u2248120\u2013150 \u20ac A\/R<\/strong><\/td>\n<td>Rapide, moins panoramique<\/td>\n<\/tr>\n<\/tbody>\n<\/table><\/figure>\n\n<p class=\"wp-block-paragraph\">\u00c9tapes concr\u00e8tes pour r\u00e9server :<\/p>\n\n<ol class=\"wp-block-list\"><li>Comparer horaires et tarifs sur une plateforme de r\u00e9servation ou directement sur le site de la compagnie.<\/li><li>Choisir l\u2019horaire qui laisse une marge en cas de retard (pr\u00e9f\u00e9rer matin\u00e9es pour l\u2019arriv\u00e9e le m\u00eame jour).<\/li><li>R\u00e9server et imprimer ou conserver le billet sur smartphone.<\/li><li>Arriver au port <strong>60 minutes<\/strong> avant l\u2019embarquement avec pi\u00e8ce d\u2019identit\u00e9 et bagages pr\u00eats.<\/li><\/ol>\n\n<p class=\"wp-block-paragraph\">Une bonne pr\u00e9paration r\u00e9duit le stress et garantit une travers\u00e9e plus agr\u00e9able.<\/p>\n\n<h2 class=\"wp-block-heading\">Tarifs, services \u00e0 bord et alternatives au ferry<\/h2>\n\n<p class=\"wp-block-paragraph\">Les tarifs d\u00e9pendent de la compagnie, de la saison et des options choisies. En g\u00e9n\u00e9ral, les billets aller simple se situent entre <strong>40 \u20ac et 100 \u20ac<\/strong>. Pour un aller\u2011retour, pr\u00e9voyez souvent une remise si r\u00e9serv\u00e9 en pack.<\/p>\n\n<p class=\"wp-block-paragraph\">\u00c0 bord, on trouve fr\u00e9quemment un snack, des toilettes, des zones assises climatis\u00e9es et des ponts ext\u00e9rieurs. Certaines travers\u00e9es proposent aussi divertissements l\u00e9gers (musique, \u00e9cran).<\/p>\n\n<p class=\"wp-block-paragraph\">Alternatives :<\/p>\n\n<ul class=\"wp-block-list\"><li><strong>Avion<\/strong> : plus rapide (\u224845 minutes), co\u00fbte g\u00e9n\u00e9ralement 120\u2013150 \u20ac A\/R.<\/li><li><strong>Location de bateau priv\u00e9<\/strong> : \u00e0 partir de 500 \u20ac la journ\u00e9e selon le type d\u2019embarcation.<\/li><li><strong>Combinaisons<\/strong> : ferry + vol pour optimisation d\u2019itin\u00e9raire selon escales.<\/li><\/ul>\n\n<p class=\"wp-block-paragraph\">Choix cl\u00e9 : privil\u00e9gier le ferry pour le panorama et le co\u00fbt, l\u2019avion pour la rapidit\u00e9. Cette clart\u00e9 facilite la d\u00e9cision.<\/p>\n\n<h2 class=\"wp-block-heading\">Erreurs fr\u00e9quentes \u00e0 \u00e9viter et conseils terrain pour un voyage facile<\/h2>\n\n<p class=\"wp-block-paragraph\">Plusieurs erreurs reviennent souvent chez les voyageurs qui prennent le bateau inter-\u00eeles. Les \u00e9viter rend l\u2019exp\u00e9rience plus fluide.<\/p>\n\n<ul class=\"wp-block-list\"><li>R\u00e9server au dernier moment pendant la haute saison et se retrouver sans place.<\/li><li>Ignorer les conditions m\u00e9t\u00e9o : la mer peut \u00eatre agit\u00e9e, ce qui rallonge la travers\u00e9e.<\/li><li>Arriver tard au port : proc\u00e9dures d\u2019embarquement et contr\u00f4le des billets prennent du temps.<\/li><li>Ne pas v\u00e9rifier la politique bagages : au-del\u00e0 de 25 kg, des frais s\u2019ajoutent.<\/li><li>Penser pouvoir embarquer un v\u00e9hicule : la plupart des liaisons ne transportent pas de voitures.<\/li><\/ul>\n\n<p class=\"wp-block-paragraph\">Conseils terrain :<\/p>\n\n<ol class=\"wp-block-list\"><li>Pr\u00e9voir un anti\u2011naus\u00e9e si vous \u00eates sensible, et choisir un si\u00e8ge central si possible.<\/li><li>R\u00e9server les premi\u00e8res places ext\u00e9rieures pour profiter de la lumi\u00e8re et \u00e9viter la promiscuit\u00e9 int\u00e9rieure.<\/li><li>Informer la compagnie en cas de mobilit\u00e9 r\u00e9duite pour une assistance d\u00e9di\u00e9e.<\/li><\/ol>\n\n<script src=\"https:\/\/cdn.jsdelivr.net\/npm\/@tailwindcss\/browser@4\"><\/script>\n\n<!--\n  Outil : Tableau comparateur interactif (fran\u00e7ais) pour \"Bateau inter-\u00eeles aux Antilles fran\u00e7aises : guide complet pour voyager facilement\"\n  - \u00c0 coller tel quel dans votre page.\n  - Hauteur maximale du composant limit\u00e9e via CSS (max-height).\n  - Toutes les cha\u00eenes en fran\u00e7ais et facilement \u00e9ditables ci-dessous.\n  - Utilise l'API gratuite exchangerate.host pour conversion de devises (optionnelle).\n    URL exemple : https:\/\/api.exchangerate.host\/latest?base=EUR&symbols=USD,GBP\n    Exemple de r\u00e9ponse JSON :\n    {\n      \"motd\": {\"msg\":\"If you or your company use this project, please consider supporting us\", \"url\":\"https:\/\/exchangerate.host\/#\/donate\"},\n      \"success\": true,\n      \"base\": \"EUR\",\n      \"date\": \"2024-01-01\",\n      \"rates\": {\"USD\": 1.10, \"GBP\": 0.87}\n    }\n-->\n\n<style>\n  \/* Conteneur principal : hauteur contr\u00f4l\u00e9e pour respecter la contrainte *\/\n  .comparateur-container { max-height: 900px; }\n  \/* Petite mise en page pour le tableau *\/\n  .sticky-header thead th { position: sticky; top: 0; backdrop-filter: blur(6px); background: rgba(255,255,255,0.85); z-index: 2; }\n  \/* Focus visible pour l'accessibilit\u00e9 *\/\n  .focus-ring:focus { outline: 3px solid #60a5fa; outline-offset: 2px; }\n  \/* Texte monospaced pour co\u00fbts convertis *\/\n  .cost-small { font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, \"Roboto Mono\", monospace; font-size: 0.95rem; }\n  \/* Table responsive container *\/\n  .table-scroll { overflow: auto; max-height: 560px; }\n<\/style>\n\n<div id=\"comparateur\" class=\"comparateur-container p-4 rounded-lg shadow-lg bg-white dark:bg-slate-800 text-slate-800 dark:text-slate-100\">\n  <!-- En-t\u00eate et contr\u00f4les -->\n  <div class=\"flex flex-col md:flex-row md:items-center md:justify-between gap-3 mb-4\">\n    <div>\n      <h2 class=\"text-2xl font-bold\">Comparateur de moyens inter-\u00eeles<\/h2>\n      <p class=\"text-sm text-slate-600 dark:text-slate-300\">Comparez ferry, avion et bateau priv\u00e9 pour voyager facilement aux Antilles fran\u00e7aises.<\/p>\n    <\/div>\n\n    <div class=\"flex flex-col sm:flex-row gap-2 items-stretch\">\n      <label class=\"sr-only\" for=\"searchInput\">Recherche<\/label>\n      <input id=\"searchInput\" type=\"search\" placeholder=\"Rechercher (ex. Ferry, Rapide, \u00e9conomique)\" class=\"focus-ring px-3 py-2 rounded border dark:bg-slate-700 dark:border-slate-600\" \/>\n\n      <select id=\"sortSelect\" class=\"focus-ring px-3 py-2 rounded border dark:bg-slate-700 dark:border-slate-600\" aria-label=\"Trier\">\n        <option value=\"default\">Trier : par d\u00e9faut<\/option>\n        <option value=\"option-asc\">Trier : option A\u2192Z<\/option>\n        <option value=\"option-desc\">Trier : option Z\u2192A<\/option>\n        <option value=\"cost-asc\">Trier : co\u00fbt croissant<\/option>\n        <option value=\"cost-desc\">Trier : co\u00fbt d\u00e9croissant<\/option>\n      <\/select>\n\n      <select id=\"currencySelect\" class=\"focus-ring px-3 py-2 rounded border dark:bg-slate-700 dark:border-slate-600\" aria-label=\"Devise\">\n        <option value=\"EUR\">EUR (\u20ac)<\/option>\n        <option value=\"USD\">USD ($)<\/option>\n        <option value=\"GBP\">GBP (\u00a3)<\/option>\n      <\/select>\n    <\/div>\n  <\/div>\n\n  <!-- Panneau de filtres -->\n  <div class=\"grid grid-cols-1 sm:grid-cols-3 gap-3 mb-4\">\n    <div class=\"flex items-center gap-2\">\n      <label for=\"durationFilter\" class=\"w-36\">Dur\u00e9e maximale :<\/label>\n      <select id=\"durationFilter\" class=\"focus-ring px-3 py-2 rounded border dark:bg-slate-700 dark:border-slate-600\">\n        <option value=\"any\">Toutes<\/option>\n        <option value=\"short\">Courte (&lt; 1h)<\/option>\n        <option value=\"medium\">Moyenne (1\u20133h)<\/option>\n        <option value=\"long\">Longue (&gt; 3h)<\/option>\n      <\/select>\n    <\/div>\n\n    <div class=\"flex items-center gap-2\">\n      <label for=\"maxCost\" class=\"w-36\">Co\u00fbt maximum (\u20ac) :<\/label>\n      <input id=\"maxCost\" type=\"number\" min=\"0\" placeholder=\"ex. 150\" class=\"focus-ring px-3 py-2 rounded border dark:bg-slate-700 dark:border-slate-600\" \/>\n    <\/div>\n\n    <div class=\"flex items-center gap-2\">\n      <button id=\"resetFilters\" class=\"focus-ring px-3 py-2 rounded bg-sky-500 text-white hover:bg-sky-600\">R\u00e9initialiser filtres<\/button>\n      <button id=\"downloadCsv\" class=\"focus-ring px-3 py-2 rounded border bg-white dark:bg-slate-700\">T\u00e9l\u00e9charger CSV<\/button>\n    <\/div>\n  <\/div>\n\n  <!-- Tableau -->\n  <div class=\"table-scroll border rounded\">\n    <table id=\"compareTable\" class=\"min-w-full text-left sticky-header\">\n      <thead class=\"bg-slate-50 dark:bg-slate-700\">\n        <tr>\n          <th class=\"px-3 py-2\">S\u00e9lection<\/th>\n          <th class=\"px-3 py-2\">Option<\/th>\n          <th class=\"px-3 py-2\">Dur\u00e9e<\/th>\n          <th class=\"px-3 py-2\">Co\u00fbt indicatif<\/th>\n          <th class=\"px-3 py-2\">Avantage<\/th>\n          <th class=\"px-3 py-2\">Inconv\u00e9nient<\/th>\n        <\/tr>\n      <\/thead>\n      <tbody id=\"tableBody\" class=\"divide-y\"><\/tbody>\n    <\/table>\n  <\/div>\n\n  <!-- R\u00e9sum\u00e9 & actions -->\n  <div class=\"mt-4 flex flex-col md:flex-row md:items-center md:justify-between gap-3\">\n    <div>\n      <p id=\"selectionSummary\" class=\"text-sm\">Aucune option s\u00e9lectionn\u00e9e.<\/p>\n      <p id=\"convertedNote\" class=\"text-xs text-slate-500\">Les co\u00fbts sont indicatifs. Conversion effectu\u00e9e via exchangerate.host (si s\u00e9lectionn\u00e9e).<\/p>\n    <\/div>\n\n    <div class=\"flex gap-2\">\n      <button id=\"copyBtn\" class=\"focus-ring px-3 py-2 rounded border bg-white dark:bg-slate-700\">Copier s\u00e9lection<\/button>\n      <button id=\"compareBtn\" class=\"focus-ring px-3 py-2 rounded bg-emerald-500 text-white hover:bg-emerald-600\">Comparer s\u00e9lectionn\u00e9es<\/button>\n    <\/div>\n  <\/div>\n<\/div>\n\n<script>\n\/*\n  Script JavaScript (comment\u00e9) :\n  - Contient les donn\u00e9es initiales fournies (en fran\u00e7ais).\n  - Offre recherche, tri, filtres, conversion de devises via API gratuite exchangerate.host,\n    export CSV, copie, et affichage r\u00e9sum\u00e9.\n  - Accessible (ARIA labels, focus visible).\n*\/\n\n\/* ==========================\n   Configuration & donn\u00e9es\n   Toutes les cha\u00eenes en fran\u00e7ais et faciles \u00e0 \u00e9diter ici.\n   ========================== *\/\nconst CONFIG = {\n  locale: 'fr-FR',\n  defaultCurrency: 'EUR',\n  maxHeightPx: 900,\n  texts: {\n    noSelection: 'Aucune option s\u00e9lectionn\u00e9e.',\n    selectedCount: (n) => `${n} option(s) s\u00e9lectionn\u00e9e(s).`,\n    compareTitle: (items) => `Comparaison : ${items.join(' \/ ')}`,\n    copied: 'S\u00e9lection copi\u00e9e dans le presse-papiers.',\n    csvDownloaded: 'CSV g\u00e9n\u00e9r\u00e9.',\n  },\n  \/\/ API de conversion de devises (gratuite) - exchangerate.host\n  exchangeApi: 'https:\/\/api.exchangerate.host\/latest?base=EUR&symbols=USD,GBP',\n};\n\n\/* Donn\u00e9es initiales (provenant du fragment fourni). Toutes en fran\u00e7ais. *\/\nconst rawData = [\n  { Option: 'Ferry', Dur\u00e9e: '4\u20135 h', 'Co\u00fbt indicatif': '40\u2013100 \u20ac', Avantage: 'Panorama, \u00e9conomique', Inconv\u00e9nient: 'Temps de trajet long' },\n  { Option: 'Avion', Dur\u00e9e: '45 min', 'Co\u00fbt indicatif': '120\u2013150 \u20ac', Avantage: 'Rapide', Inconv\u00e9nient: 'Co\u00fbt plus \u00e9lev\u00e9' },\n  { Option: 'Bateau priv\u00e9', Dur\u00e9e: 'variable', 'Co\u00fbt indicatif': '500\u20131000 \u20ac', Avantage: 'Flexibilit\u00e9 totale', Inconv\u00e9nient: 'Co\u00fbt \u00e9lev\u00e9' },\n];\n\n\/* Etat applicatif *\/\nlet state = {\n  data: [...rawData],           \/\/ donn\u00e9es originales\n  displayed: [...rawData],      \/\/ donn\u00e9es actuellement affich\u00e9es apr\u00e8s filtres\n  currency: CONFIG.defaultCurrency,\n  rates: { EUR: 1, USD: 1, GBP: 1 }, \/\/ taux (EUR par d\u00e9faut)\n  selected: new Set(),           \/\/ indices s\u00e9lectionn\u00e9s\n};\n\n\/* =============\n   Utilitaires\n   ============= *\/\n\n\/**\n * Convertit une cha\u00eene de co\u00fbt (ex: \"40\u2013100 \u20ac\", \"120\u2013150 \u20ac\", \"500\u20131000 \u20ac\", \"120 \u20ac\", \"40\u2013100\u20ac\")\n * en version convertie vers la devise cible, en pr\u00e9servant les plages.\n * Retour: cha\u00eene lisible, ex: \"44\u2013110 $\"\n *\/\nfunction convertCostString(costStr, toCurrency) {\n  \/\/ Extraire tous les nombres (entiers ou d\u00e9cimaux)\n  const numbers = Array.from(costStr.matchAll(\/[d]+(?:[.,]d+)?\/g)).map(m => m[0].replace(',', '.'));\n  if (numbers.length === 0) return costStr; \/\/ rien \u00e0 convertir\n\n  \/\/ Convertir chaque nombre en float, appliquer taux (EUR -> target)\n  const convertNumber = n => {\n    const eurValue = parseFloat(n);\n    const rate = state.rates[toCurrency] ?? 1;\n    const converted = eurValue * rate;\n    \/\/ Formater selon locale\n    return new Intl.NumberFormat(CONFIG.locale, { maximumFractionDigits: 0 }).format(Math.round(converted));\n  };\n\n  if (numbers.length === 1) {\n    const formatted = convertNumber(numbers[0]);\n    return `${formatted} ${currencySymbol(toCurrency)}`;\n  } else {\n    const formatted = numbers.map(convertNumber).join('\u2013');\n    return `${formatted} ${currencySymbol(toCurrency)}`;\n  }\n}\n\nfunction currencySymbol(cur) {\n  return cur === 'EUR' ? '\u20ac' : cur === 'USD' ? '$' : cur === 'GBP' ? '\u00a3' : cur;\n}\n\n\/* Parse dur\u00e9e pour filtrage :\n   Retourne 'short' (<1h), 'medium' (1-3h), 'long' (>3h), 'variable' or 'unknown' *\/\nfunction classifyDuration(dStr) {\n  if (!dStr) return 'unknown';\n  if (dStr.includes('variable')) return 'variable';\n  \/\/ Cherche pattern heures\/minutes\n  const hoursMatch = dStr.match(\/(d+(?:[.,]d+)?)s*h\/);\n  const minMatch = dStr.match(\/(d+)s*min\/);\n  if (minMatch && !hoursMatch) {\n    const mins = parseInt(minMatch[1], 10);\n    return mins < 60 ? 'short' : mins <= 180 ? 'medium' : 'long';\n  }\n  if (hoursMatch) {\n    const hours = parseFloat(hoursMatch[1].replace(',', '.'));\n    if (hours < 1) return 'short';\n    if (hours <= 3) return 'medium';\n    return 'long';\n  }\n  \/\/ Range like \"4\u20135 h\"\n  const rangeMatch = dStr.match(\/(d+)[^d]+(d+)s*h\/);\n  if (rangeMatch) {\n    const h1 = parseInt(rangeMatch[1],10), h2 = parseInt(rangeMatch[2],10);\n    const avg = (h1+h2)\/2;\n    if (avg < 1) return 'short';\n    if (avg <= 3) return 'medium';\n    return 'long';\n  }\n  return 'unknown';\n}\n\n\/* Extraire une valeur num\u00e9rique indicative du champ \"Co\u00fbt indicatif\" pour filtrage (en EUR) :\n   - si plage \"40\u2013100 \u20ac\" -> prend la valeur max (100)\n   - si \"120 \u20ac\" -> 120\n   - renvoie null si non trouv\u00e9 *\/\nfunction extractMaxCostEUR(costStr) {\n  if (!costStr) return null;\n  const nums = Array.from(costStr.matchAll(\/[d]+(?:[.,]d+)?\/g)).map(m => parseFloat(m[0].replace(',', '.')));\n  if (nums.length === 0) return null;\n  \/\/ si plusieurs valeurs, retourner la valeur maximale\n  return Math.max(...nums);\n}\n\n\/* ===========================\n   Rendu du tableau & interactions\n   =========================== *\/\n\nconst tableBody = document.getElementById('tableBody');\nconst searchInput = document.getElementById('searchInput');\nconst sortSelect = document.getElementById('sortSelect');\nconst durationFilter = document.getElementById('durationFilter');\nconst maxCostInput = document.getElementById('maxCost');\nconst resetFilters = document.getElementById('resetFilters');\nconst currencySelect = document.getElementById('currencySelect');\nconst selectionSummary = document.getElementById('selectionSummary');\nconst convertedNote = document.getElementById('convertedNote');\nconst copyBtn = document.getElementById('copyBtn');\nconst compareBtn = document.getElementById('compareBtn');\nconst downloadCsv = document.getElementById('downloadCsv');\n\n\/* Construire la ligne de tableau pour une entr\u00e9e donn\u00e9e *\/\nfunction renderRow(item, index) {\n  const tr = document.createElement('tr');\n  tr.setAttribute('tabindex', '-1');\n\n  \/\/ S\u00e9lection checkbox\n  const tdSelect = document.createElement('td');\n  tdSelect.className = 'px-3 py-2';\n  const checkbox = document.createElement('input');\n  checkbox.type = 'checkbox';\n  checkbox.className = 'focus-ring';\n  checkbox.setAttribute('aria-label', `S\u00e9lectionner ${item.Option}`);\n  checkbox.checked = state.selected.has(index);\n  checkbox.addEventListener('change', (e) => {\n    if (e.target.checked) state.selected.add(index);\n    else state.selected.delete(index);\n    updateSelectionSummary();\n  });\n  tdSelect.appendChild(checkbox);\n  tr.appendChild(tdSelect);\n\n  \/\/ Option\n  const tdOption = document.createElement('td');\n  tdOption.className = 'px-3 py-2 font-semibold';\n  tdOption.textContent = item.Option;\n  tr.appendChild(tdOption);\n\n  \/\/ Dur\u00e9e\n  const tdDuration = document.createElement('td');\n  tdDuration.className = 'px-3 py-2';\n  tdDuration.textContent = item.Dur\u00e9e;\n  tdDuration.setAttribute('title', `Dur\u00e9e : ${item.Dur\u00e9e}`);\n  tr.appendChild(tdDuration);\n\n  \/\/ Co\u00fbt indicatif (afficher conversion si diff\u00e9rent de EUR)\n  const tdCost = document.createElement('td');\n  tdCost.className = 'px-3 py-2 cost-small';\n  const base = item['Co\u00fbt indicatif'];\n  const converted = state.currency === 'EUR' ? base : convertCostString(base, state.currency);\n  \/\/ Afficher les deux lignes : original (EUR) + converti\n  const spanConverted = document.createElement('div');\n  spanConverted.textContent = converted;\n  const spanBase = document.createElement('div');\n  spanBase.textContent = `(${base.trim()})`;\n  spanBase.className = 'text-xs text-slate-500 dark:text-slate-400';\n  tdCost.appendChild(spanConverted);\n  tdCost.appendChild(spanBase);\n  tr.appendChild(tdCost);\n\n  \/\/ Avantage\n  const tdPros = document.createElement('td');\n  tdPros.className = 'px-3 py-2';\n  tdPros.textContent = item.Avantage;\n  tr.appendChild(tdPros);\n\n  \/\/ Inconv\u00e9nient\n  const tdCons = document.createElement('td');\n  tdCons.className = 'px-3 py-2 text-slate-600 dark:text-slate-300';\n  tdCons.textContent = item.Inconv\u00e9nient;\n  tr.appendChild(tdCons);\n\n  return tr;\n}\n\n\/* Rendre tout le tableau selon state.displayed *\/\nfunction renderTable() {\n  tableBody.innerHTML = '';\n  state.displayed.forEach((item, idx) => {\n    \/\/ idx est l'indice dans displayed ; nous avons besoin d'un identifiant stable pour la s\u00e9lection.\n    \/\/ Pour simplicit\u00e9, on lie la s\u00e9lection \u00e0 l'indice dans l'array d'origine.\n    const originalIndex = state.data.findIndex(d => d.Option === item.Option && d['Co\u00fbt indicatif'] === item['Co\u00fbt indicatif']);\n    const row = renderRow(item, originalIndex);\n    tableBody.appendChild(row);\n  });\n  updateSelectionSummary();\n}\n\n\/* ==============\n   Filtres & recherche\n   ============== *\/\n\n\/* Applique les filtres et la recherche, puis tri *\/\nfunction applyFiltersAndSort() {\n  let list = [...state.data];\n\n  \/\/ Recherche texte (sur toutes les colonnes)\n  const q = searchInput.value.trim().toLowerCase();\n  if (q) {\n    list = list.filter(item => {\n      return Object.values(item).some(v => String(v).toLowerCase().includes(q));\n    });\n  }\n\n  \/\/ Dur\u00e9e filtre\n  const durationChoice = durationFilter.value;\n  if (durationChoice && durationChoice !== 'any') {\n    list = list.filter(item => {\n      const cls = classifyDuration(item.Dur\u00e9e);\n      if (durationChoice === 'short') return cls === 'short';\n      if (durationChoice === 'medium') return cls === 'medium';\n      if (durationChoice === 'long') return cls === 'long';\n      return false;\n    });\n  }\n\n  \/\/ Co\u00fbt max (en EUR) : on compare via valeur max extraite\n  const maxCostVal = parseFloat(maxCostInput.value);\n  if (!isNaN(maxCostVal)) {\n    list = list.filter(item => {\n      const maxCost = extractMaxCostEUR(item['Co\u00fbt indicatif']);\n      return maxCost === null ? true : maxCost <= maxCostVal;\n    });\n  }\n\n  \/\/ Tri\n  const sortVal = sortSelect.value;\n  if (sortVal === 'option-asc') list.sort((a,b) => a.Option.localeCompare(b.Option, CONFIG.locale));\n  else if (sortVal === 'option-desc') list.sort((a,b) => b.Option.localeCompare(a.Option, CONFIG.locale));\n  else if (sortVal === 'cost-asc') list.sort((a,b) => (extractMaxCostEUR(a['Co\u00fbt indicatif'])||0) - (extractMaxCostEUR(b['Co\u00fbt indicatif'])||0));\n  else if (sortVal === 'cost-desc') list.sort((a,b) => (extractMaxCostEUR(b['Co\u00fbt indicatif'])||0) - (extractMaxCostEUR(a['Co\u00fbt indicatif'])||0));\n  \/\/ default: keep original order\n\n  state.displayed = list;\n  renderTable();\n}\n\n\/* ==============\n   S\u00e9lection & actions\n   ============== *\/\n\nfunction updateSelectionSummary() {\n  const n = state.selected.size;\n  if (n === 0) selectionSummary.textContent = CONFIG.texts.noSelection;\n  else selectionSummary.textContent = CONFIG.texts.selectedCount(n);\n}\n\n\/* Copier la s\u00e9lection au presse-papiers (format lisible) *\/\nasync function copySelectionToClipboard() {\n  if (state.selected.size === 0) return alert(CONFIG.texts.noSelection);\n  const rows = Array.from(state.selected).map(i => state.data[i]);\n  const lines = rows.map(r => `${r.Option} \u2014 Dur\u00e9e : ${r.Dur\u00e9e} \u2014 Co\u00fbt : ${state.currency === 'EUR' ? r['Co\u00fbt indicatif'] : convertCostString(r['Co\u00fbt indicatif'], state.currency)} \u2014 Avantage : ${r.Avantage} \u2014 Inconv\u00e9nient : ${r.Inconv\u00e9nient}`);\n  const text = lines.join('n');\n  try {\n    await navigator.clipboard.writeText(text);\n    alert(CONFIG.texts.copied);\n  } catch (e) {\n    \/\/ fallback\n    const ta = document.createElement('textarea');\n    ta.value = text;\n    document.body.appendChild(ta);\n    ta.select();\n    document.execCommand('copy');\n    document.body.removeChild(ta);\n    alert(CONFIG.texts.copied);\n  }\n}\n\n\/* T\u00e9l\u00e9charger CSV des lignes affich\u00e9es ou s\u00e9lectionn\u00e9es *\/\nfunction downloadCSV() {\n  const rows = state.selected.size ? Array.from(state.selected).map(i => state.data[i]) : state.displayed;\n  if (rows.length === 0) { alert('Aucune ligne \u00e0 exporter.'); return; }\n\n  const header = ['Option','Dur\u00e9e','Co\u00fbt indicatif','Avantage','Inconv\u00e9nient'];\n  const csv = [\n    header.join(','),\n    ...rows.map(r => [\n      csvEscape(r.Option),\n      csvEscape(r.Dur\u00e9e),\n      csvEscape(state.currency === 'EUR' ? r['Co\u00fbt indicatif'] : convertCostString(r['Co\u00fbt indicatif'], state.currency)),\n      csvEscape(r.Avantage),\n      csvEscape(r.Inconv\u00e9nient)\n    ].join(','))\n  ].join('n');\n\n  const blob = new Blob([csv], { type: 'text\/csv;charset=utf-8;' });\n  const url = URL.createObjectURL(blob);\n  const a = document.createElement('a');\n  a.href = url;\n  a.download = 'comparateur_inter_iles.csv';\n  document.body.appendChild(a);\n  a.click();\n  document.body.removeChild(a);\n  URL.revokeObjectURL(url);\n  alert(CONFIG.texts.csvDownloaded);\n}\n\nfunction csvEscape(text) {\n  if (typeof text !== 'string') return '';\n  if (text.includes(',') || text.includes('\"') || text.includes('n')) {\n    return `\"${text.replace(\/\"\/g, '\"\"')}\"`;\n  }\n  return text;\n}\n\n\/* Affiche une modale simple (alerte) de comparaison des \u00e9l\u00e9ments s\u00e9lectionn\u00e9s *\/\nfunction compareSelected() {\n  if (state.selected.size === 0) return alert(CONFIG.texts.noSelection);\n  const selectedItems = Array.from(state.selected).map(i => state.data[i]);\n  const title = CONFIG.texts.compareTitle(selectedItems.map(i => i.Option));\n  const lines = selectedItems.map(it => `${it.Option} \u2014 Dur\u00e9e: ${it.Dur\u00e9e} \u2014 Co\u00fbt: ${state.currency === 'EUR' ? it['Co\u00fbt indicatif'] : convertCostString(it['Co\u00fbt indicatif'], state.currency)} \u2014 +${it.Avantage} \/ -${it.Inconv\u00e9nient}`);\n  alert(`${title}nn${lines.join('n')}`);\n}\n\n\/* ==================\n   Conversion devises (API libre)\n   ================== *\/\n\n\/* R\u00e9cup\u00e8re les taux depuis exchangerate.host et met \u00e0 jour state.rates\n   - API gratuite, pas de cl\u00e9 requise.\n   - Exemple : https:\/\/api.exchangerate.host\/latest?base=EUR&symbols=USD,GBP\n*\/\nasync function fetchExchangeRates() {\n  try {\n    const resp = await fetch(CONFIG.exchangeApi);\n    if (!resp.ok) throw new Error('Impossible de r\u00e9cup\u00e9rer les taux.');\n    const data = await resp.json();\n    \/\/ structure attendue : { base: 'EUR', rates: { USD: 1.1, GBP: 0.87 }, ... }\n    if (data && data.rates) {\n      state.rates.EUR = 1;\n      state.rates.USD = data.rates.USD ?? state.rates.USD;\n      state.rates.GBP = data.rates.GBP ?? state.rates.GBP;\n    }\n  } catch (e) {\n    \/\/ en cas d'erreur, on laisse les taux par d\u00e9faut (1:1) et on notifie discr\u00e8tement\n    console.warn('Erreur r\u00e9cup\u00e9ration taux de change (API gratuite).', e);\n  }\n}\n\n\/* ====================\n   \u00c9v\u00e9nements & initialisation\n   ==================== *\/\n\nsearchInput.addEventListener('input', () => {\n  applyFiltersAndSort();\n});\n\nsortSelect.addEventListener('change', () => {\n  applyFiltersAndSort();\n});\n\ndurationFilter.addEventListener('change', () => {\n  applyFiltersAndSort();\n});\n\nmaxCostInput.addEventListener('input', () => {\n  applyFiltersAndSort();\n});\n\nresetFilters.addEventListener('click', () => {\n  searchInput.value = '';\n  sortSelect.value = 'default';\n  durationFilter.value = 'any';\n  maxCostInput.value = '';\n  currencySelect.value = CONFIG.defaultCurrency;\n  state.currency = CONFIG.defaultCurrency;\n  applyFiltersAndSort();\n});\n\ncurrencySelect.addEventListener('change', async (e) => {\n  const newCur = e.target.value;\n  state.currency = newCur;\n  \/\/ Si conversion demand\u00e9e autre que EUR, on tente de r\u00e9cup\u00e9rer les taux\n  if (newCur !== 'EUR') {\n    await fetchExchangeRates();\n  }\n  renderTable();\n});\n\ncopyBtn.addEventListener('click', copySelectionToClipboard);\ncompareBtn.addEventListener('click', compareSelected);\ndownloadCsv.addEventListener('click', downloadCSV);\n\n\/* Initialisation : r\u00e9cup\u00e9rer taux et afficher tableau *\/\n(async function init() {\n  \/\/ Essayer de r\u00e9cup\u00e9rer les taux (silencieux)\n  await fetchExchangeRates();\n  applyFiltersAndSort();\n\n  \/\/ contraintes d'accessibilit\u00e9 : focus ring visibles sur tab\n  document.querySelectorAll('.focus-ring').forEach(el => {\n    el.addEventListener('keyup', (ev) => {\n      if (ev.key === 'Enter') el.click && el.click();\n    });\n  });\n\n  \/\/ Info utilisateur sur l'utilisation des conversions\n  convertedNote.textContent = 'Les co\u00fbts affich\u00e9s entre parenth\u00e8ses sont en EUR ; la conversion utilise exchangerate.host (gratuite).';\n})();\n<\/script>\n\n<p class=\"wp-block-paragraph\">Un dernier point : pr\u00e9voir une marge sur votre planning \u00e9vite d\u2019encha\u00eener les impr\u00e9vus.<\/p>\n\n<h2 class=\"wp-block-heading\">Variantes selon le profil : familles, voyageurs press\u00e9s et groupes<\/h2>\n\n<p class=\"wp-block-paragraph\">Chaque profil de voyageur a des besoins diff\u00e9rents. Adapter la r\u00e9servation et le choix du service garantit un voyage plus confortable.<\/p>\n\n<h3 class=\"wp-block-heading\">Familles<\/h3>\n\n<p class=\"wp-block-paragraph\">Privil\u00e9gier les travers\u00e9es avec services \u00e0 bord (snack, toilettes propres) et choisir des horaires qui \u00e9vitent les heures de sieste des enfants. Emporter jeux l\u00e9gers et en-cas.<\/p>\n\n<h3 class=\"wp-block-heading\">Voyageurs press\u00e9s<\/h3>\n\n<p class=\"wp-block-paragraph\">Pour gagner du temps, pr\u00e9f\u00e9rer le vol inter-\u00eeles ou r\u00e9server le premier ferry du matin. Anticiper les transferts entre a\u00e9roport\/port pour limiter les retards.<\/p>\n\n<h3 class=\"wp-block-heading\">Groupes et associations<\/h3>\n\n<p class=\"wp-block-paragraph\">Demander les tarifs groupe et v\u00e9rifier les conditions de bagages pour \u00e9viter des frais suppl\u00e9mentaires. Certaines compagnies offrent des r\u00e9ductions ou des cabines r\u00e9servables.<\/p>\n\n<p class=\"wp-block-paragraph\">Adapter le trajet \u00e0 votre profil vous fait gagner en confort et en s\u00e9r\u00e9nit\u00e9.<\/p>\n\n<p class=\"wp-block-paragraph\"><strong>Action imm\u00e9diate<\/strong> : comparer horaires et r\u00e9server votre billet d\u00e8s que les dates sont choisies pour s\u00e9curiser le meilleur horaire et le prix adapt\u00e9 \u00e0 votre profil.<\/p>\n\n<script type=\"application\/ld+json\">\n{\"@context\":\"https:\/\/schema.org\",\"@type\":\"FAQPage\",\"mainEntity\":[{\"@type\":\"Question\",\"name\":\"Peut-on embarquer une voiture sur les ferries entre Martinique et Guadeloupe ?\",\"acceptedAnswer\":{\"@type\":\"Answer\",\"text\":\"Non, la plupart des traversu00e9es inter-u00eeles ne transportent pas de vu00e9hicules. Il est conseillu00e9 de louer une voiture sur place si nu00e9cessaire.\"}},{\"@type\":\"Question\",\"name\":\"Quels documents fautu2011il pru00e9senter u00e0 lu2019embarquement ?\",\"acceptedAnswer\":{\"@type\":\"Answer\",\"text\":\"Une piu00e8ce du2019identitu00e9 valide (carte nationale du2019identitu00e9) suffit pour les du00e9placements entre territoires franu00e7ais. Conserver le billet imprimu00e9 ou numu00e9rique.\"}},{\"@type\":\"Question\",\"name\":\"Comment se comportent les politiques de bagages ?\",\"acceptedAnswer\":{\"@type\":\"Answer\",\"text\":\"Un bagage de 25 kg est souvent inclus. Des frais peuvent su2019appliquer pour les excu00e9dents : vu00e9rifier la politique de la compagnie avant la ru00e9servation.\"}},{\"@type\":\"Question\",\"name\":\"Existe-t-il des services pour les personnes u00e0 mobilitu00e9 ru00e9duite ?\",\"acceptedAnswer\":{\"@type\":\"Answer\",\"text\":\"Oui, la plupart des opu00e9rateurs disposent du2019installations adaptu00e9es. Informer la compagnie lors de la ru00e9servation pour organiser lu2019assistance.\"}}]}\n<\/script>\n<h3>Peut-on embarquer une voiture sur les ferries entre Martinique et Guadeloupe ?<\/h3>\n<p>Non, la plupart des travers\u00e9es inter-\u00eeles ne transportent pas de v\u00e9hicules. Il est conseill\u00e9 de louer une voiture sur place si n\u00e9cessaire.<\/p>\n<h3>Quels documents faut\u2011il pr\u00e9senter \u00e0 l\u2019embarquement ?<\/h3>\n<p>Une pi\u00e8ce d\u2019identit\u00e9 valide (carte nationale d\u2019identit\u00e9) suffit pour les d\u00e9placements entre territoires fran\u00e7ais. Conserver le billet imprim\u00e9 ou num\u00e9rique.<\/p>\n<h3>Comment se comportent les politiques de bagages ?<\/h3>\n<p>Un bagage de 25 kg est souvent inclus. Des frais peuvent s\u2019appliquer pour les exc\u00e9dents : v\u00e9rifier la politique de la compagnie avant la r\u00e9servation.<\/p>\n<h3>Existe-t-il des services pour les personnes \u00e0 mobilit\u00e9 r\u00e9duite ?<\/h3>\n<p>Oui, la plupart des op\u00e9rateurs disposent d\u2019installations adapt\u00e9es. Informer la compagnie lors de la r\u00e9servation pour organiser l\u2019assistance.<\/p>\n\n<p class=\"wp-block-paragraph\">Ressources utiles et lectures compl\u00e9mentaires : <a href=\"https:\/\/voy12.com\/\" target=\"_blank\" rel=\"noopener\">informations locales sur les liaisons<\/a> et un guide pratique compl\u00e9mentaire sur les travers\u00e9es publi\u00e9 par un sp\u00e9cialiste r\u00e9gional : <a href=\"https:\/\/www.transports-express-caraibes.fr\/blog\/bateau-martinique-guadeloupe\/\">guide bateau Martinique\u2013Guadeloupe<\/a>.<\/p>\n\n","protected":false},"excerpt":{"rendered":"<p>Envie d\u2019un voyage facile entre les \u00eeles des Antilles ? Traverser la mer des Cara\u00efbes entre la Martinique et la Guadeloupe reste une exp\u00e9rience \u00e0 la fois pratique et pittoresque pour qui s\u2019organise correctement. Ce guide rassemble les informations concr\u00e8tes pour r\u00e9server et r\u00e9ussir votre travers\u00e9e inter-\u00eeles : quelles compagnies desservent la liaison, combien co\u00fbte &#8230; <a title=\"Bateau inter-\u00eeles aux Antilles fran\u00e7aises : guide complet pour voyager facilement\" class=\"read-more\" href=\"https:\/\/www.transports-express-caraibes.fr\/blog\/bateau-inter-iles-antilles\/\" aria-label=\"En savoir plus sur Bateau inter-\u00eeles aux Antilles fran\u00e7aises : guide complet pour voyager facilement\">Lire plus<\/a><\/p>\n","protected":false},"author":3,"featured_media":23595,"comment_status":"","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[82],"tags":[],"class_list":["post-23596","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-transport"],"views":17,"_links":{"self":[{"href":"https:\/\/www.transports-express-caraibes.fr\/blog\/wp-json\/wp\/v2\/posts\/23596","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.transports-express-caraibes.fr\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.transports-express-caraibes.fr\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.transports-express-caraibes.fr\/blog\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/www.transports-express-caraibes.fr\/blog\/wp-json\/wp\/v2\/comments?post=23596"}],"version-history":[{"count":0,"href":"https:\/\/www.transports-express-caraibes.fr\/blog\/wp-json\/wp\/v2\/posts\/23596\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.transports-express-caraibes.fr\/blog\/wp-json\/wp\/v2\/media\/23595"}],"wp:attachment":[{"href":"https:\/\/www.transports-express-caraibes.fr\/blog\/wp-json\/wp\/v2\/media?parent=23596"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.transports-express-caraibes.fr\/blog\/wp-json\/wp\/v2\/categories?post=23596"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.transports-express-caraibes.fr\/blog\/wp-json\/wp\/v2\/tags?post=23596"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}