{"title":"MEILLEURS VENDEURS","description":null,"products":[{"product_id":"colombie-huila-decafeine","title":"DÉCAFÉINÉ - COLOMBIE","description":"\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 1 : NOTES DE DÉGUSTATION\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto; border: 2px solid var(--product-box-background, #000); border-radius: 12px; overflow: hidden;\"\u003e\n\u003cdiv style=\"padding: 10px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center;\"\u003eNotes de dégustation\u003c\/div\u003e\n\u003cdiv style=\"padding: 16px 14px; font-weight: 900; text-transform: uppercase; font-size: 28px; letter-spacing: .05em; text-align: center; background: transparent;\"\u003eTOFFEE + ABRICOT + SIROP DE COLA\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 1 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 2 : APPROVISIONNEMENT\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto;\"\u003e\n\u003cdiv style=\"padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center; border-radius: 12px 12px 0 0;\"\u003eApprovisionnement\u003c\/div\u003e\n\u003ctable border=\"3\" cellpadding=\"1\" cellspacing=\"1\" style=\"width: 100%; border-collapse: collapse; background: transparent;\"\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd style=\"width: 20%;\"\u003eORIGINE\u003c\/td\u003e\n\u003ctd\u003eMunicipalité de Buesaco, département de Nariño, Colombie\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePRODUCTEURS\u003c\/td\u003e\n\u003ctd\u003ePlusieurs petit·es producteur·rices\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eVARIÉTÉ\u003c\/td\u003e\n\u003ctd\u003eVariées\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePROCÉDÉ\u003c\/td\u003e\n\u003ctd\u003eLavé et décaféiné à l’acétate d’éthyle\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eALTITUDE\u003c\/td\u003e\n\u003ctd\u003e2100 à 2400 m\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePARTENAIRES\u003c\/td\u003e\n\u003ctd\u003eApex Coffee Imports\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eVOLUME ACHETÉ\u003c\/td\u003e\n\u003ctd\u003e5600 kg\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eFAB\u003c\/td\u003e\n\u003ctd\u003e4,20 $ US\/lb\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePRIX LIVRÉ\u003c\/td\u003e\n\u003ctd\u003e8,30 $ CAD\/LB\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eRELATION\u003c\/td\u003e\n\u003ctd\u003e1 an\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003c\/tbody\u003e\n\u003c\/table\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 2 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 3 : INFORMATIONS SUR LE CAFÉ\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto;\"\u003e\n\u003cdiv style=\"padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center; border-radius: 12px 12px 0 0;\"\u003eInformations sur le café\u003c\/div\u003e\n\u003cdiv style=\"border: 2px solid var(--product-box-background, #000); border-top: none; border-radius: 0 0 12px 12px; padding: 16px 14px; background: transparent;\"\u003e\n\u003cp style=\"margin: 0 0 12px 0;\"\u003eCe café offre un profil classique, aux arômes de chocolat, de sirop de cola et de toffee, avec une belle acidité qui rappelle l’abricot, qui s’apprécie aussi bien en espresso qu’en infusion filtre. Il a été décaféiné à l’acétate d’éthyle, un solvant pouvant être obtenu à partir de la canne à sucre. Le procédé consiste à humidifier les grains de café vert, à les mettre en contact avec le solvant, puis à les rincer à la vapeur et à les sécher. Cette méthode permet d’extraire la caféine tout en préservant une bonne partie des arômes du café.\u003c\/p\u003e\n\u003cp style=\"margin: 0 0 12px 0;\"\u003eLe nom de ce café, Buesaco Jardines, signifie « Jardins de Buesaco », un clin d’œil aux jardins verdoyants qui entourent les petites fermes caféières de cette municipalité perchée dans la cordillère des Andes. Le projet Jardines est né d’une volonté collective : regrouper de petites récoltes afin de créer des lots plus cohérents, plus simples à gérer et capables de mettre pleinement en valeur la personnalité du terroir.\u003c\/p\u003e\n\u003cp style=\"margin: 0;\"\u003eCe lot réunit plusieurs producteur·rices, dont Aura Montánchez, deuxième génération de cultivateur·rices, Yovanny Pinchao de la ferme La Esperanza, premier de sa famille à se lancer dans le café en 2019, ainsi que Javier Martínez, producteur de Villa Moreno établi au village d’El Cortijo.\u003c\/p\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 3 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 4 : PARAMÈTRES D'EXTRACTION — ESPRESSO\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto;\"\u003e\n\u003cdetails open=\"\" style=\"border: 2px solid var(--product-box-background, #000); border-radius: 12px; overflow: hidden; margin: 0 0 12px 0; background: rgba(255,255,255,0.5);\"\u003e\n\u003csummary style=\"cursor: pointer; list-style: none; padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center;\"\u003eEspresso — paramètres recommandés\u003c\/summary\u003e\n\u003cdiv style=\"padding: 12px 14px;\"\u003e\n\u003ctable style=\"width: 100%; border-collapse: collapse; background: transparent;\"\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd style=\"padding: 10px 0; font-weight: 800; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003eCafé moulu\u003c\/td\u003e\n\u003ctd style=\"padding: 10px 0; text-align: right; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003e17,7 g\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd style=\"padding: 10px 0; font-weight: 800; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003eCafé dans la tasse\u003c\/td\u003e\n\u003ctd style=\"padding: 10px 0; text-align: right; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003e34 g\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd style=\"padding: 10px 0; font-weight: 800;\"\u003eTemps d'extraction\u003c\/td\u003e\n\u003ctd style=\"padding: 10px 0; text-align: right;\"\u003e28 sec\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003c\/tbody\u003e\n\u003c\/table\u003e\n\u003cdiv style=\"margin-top: 10px; padding: 8px 10px; border-radius: 8px; background: rgba(0,0,0,.04); border: 1px dashed rgba(0,0,0,.2); font-size: 12px; opacity: .7; line-height: 1.4;\"\u003e\n\u003cstrong\u003eÀ noter —\u003c\/strong\u003e Recette optimisée pour un panier de \u003cstrong\u003e18 g\u003c\/strong\u003e. Consulte le manuel de ta machine pour connaître la capacité de ton panier.\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/details\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 4 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 5 : V60\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto;\"\u003e\n\u003cdetails id=\"v60Details-decafbuesaco\" open=\"\" style=\"border: 2px solid var(--product-box-background, #000); border-radius: 12px; overflow: hidden; margin: 0 0 12px 0; background: rgba(255,255,255,0.5);\"\u003e\n\u003csummary style=\"cursor: pointer; list-style: none; padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center;\"\u003eV60 – Recette\u003c\/summary\u003e\n\u003cdiv style=\"padding: 12px 14px;\"\u003e\n\u003cdiv style=\"padding: 10px 0 10px; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003e\n\u003cdiv style=\"font-weight: 900; font-size: 16px;\"\u003eRatio 1:16\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 4px; opacity: .7; font-size: 13px;\"\u003e15 g in – 240 g out\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 6px; font-size: 13px;\"\u003e\n\u003cstrong\u003eTempérature de l'eau :\u003c\/strong\u003e 91 °C\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; padding: 10px 0 8px;\"\u003e\n\u003cdiv style=\"display: flex; gap: 8px; align-items: center; flex-wrap: wrap;\"\u003e\n\u003cbutton style=\"cursor: pointer; border: 2px solid var(--product-box-background, #000); background: var(--product-box-background, #000); color: var(--product-box-text, #fff); font-weight: 900; padding: 8px 10px; border-radius: 10px; text-transform: uppercase; letter-spacing: .02em; font-size: 12px;\" type=\"button\" id=\"v60StartBtn-decafbuesaco\"\u003eDémarrer\u003c\/button\u003e \u003cbutton style=\"cursor: pointer; border: 2px solid var(--product-box-background, #000); background: var(--product-box-text, #fff); color: var(--product-box-background, #000); font-weight: 900; padding: 8px 10px; border-radius: 10px; text-transform: uppercase; letter-spacing: .02em; font-size: 12px; opacity: .5;\" disabled type=\"button\" id=\"v60StopBtn-decafbuesaco\"\u003eStop\u003c\/button\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; line-height: 1;\"\u003e\n\u003cspan style=\"opacity: .70; font-size: 12px; font-weight: 800; text-transform: uppercase; letter-spacing: .04em;\"\u003eTimer\u003c\/span\u003e \u003cspan style=\"font-weight: 950; font-size: 28px; letter-spacing: .01em;\" id=\"v60Timer-decafbuesaco\"\u003e0:00\u003c\/span\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"flex-basis: 100%; opacity: .6; font-size: 12px; line-height: 1.3; margin-top: 2px;\" id=\"v60WakeStatus-decafbuesaco\"\u003eℹ️ Appuie sur \"Démarrer\" pour garder l'écran allumé.\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 8px; display: grid; gap: 10px;\"\u003e\n\u003cdiv style=\"border: 1px solid rgba(0,0,0,.18); border-radius: 12px; padding: 10px 12px;\" id=\"v60-card-1-decafbuesaco\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; margin-bottom: 6px;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e0:00\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003ePhase 1 — Bloom\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 8px; flex-wrap: wrap; font-size: 12.5px; font-weight: 800;\"\u003e\n\u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\" id=\"v60-pill-1-decafbuesaco\"\u003eVerser pendant 0:10s\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\"\u003eTotal 50 g\u003c\/span\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"border: 1px solid rgba(0,0,0,.18); border-radius: 12px; padding: 10px 12px;\" id=\"v60-card-2-decafbuesaco\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; margin-bottom: 6px;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e0:40\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003ePhase 2\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 8px; flex-wrap: wrap; font-size: 12.5px; font-weight: 800;\"\u003e\n\u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\" id=\"v60-pill-2-decafbuesaco\"\u003eVerser pendant 0:30s\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\"\u003eTotal 150 g\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12); opacity: .6;\"\u003e+100 g\u003c\/span\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"border: 1px solid rgba(0,0,0,.18); border-radius: 12px; padding: 10px 12px;\" id=\"v60-card-3-decafbuesaco\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; margin-bottom: 6px;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e1:20\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003ePhase 3\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 8px; flex-wrap: wrap; font-size: 12.5px; font-weight: 800;\"\u003e\n\u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\" id=\"v60-pill-3-decafbuesaco\"\u003eVerser pendant 0:25s\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\"\u003eTotal 240 g\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12); opacity: .6;\"\u003e+90 g\u003c\/span\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 12px; border-top: 1px solid rgba(0,0,0,.2); padding-top: 10px;\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e2:15\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003eTemps final écoulement complet\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 8px; padding: 8px 10px; border-radius: 8px; background: rgba(0,0,0,.04); border: 1px dashed rgba(0,0,0,.2); font-size: 12px; opacity: .6; line-height: 1.4;\"\u003e\n\u003cstrong\u003eℹ️ Astuce —\u003c\/strong\u003e Si le temps total est plus court, la mouture est probablement trop grosse. S'il est plus long, la mouture est probablement trop fine.\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/details\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 5 ========= --\u003e\u003csvg style=\"display: none;\"\u003e\n\u003cstyle\u003e\n  @keyframes v60PulsePhase {\n    0%   { transform: scale(1);    box-shadow: 0 0 0 0 rgba(200,169,126,.35); }\n    50%  { transform: scale(1.06); box-shadow: 0 0 0 10px rgba(200,169,126,0); }\n    100% { transform: scale(1);    box-shadow: 0 0 0 0 rgba(200,169,126,0); }\n  }\n  .v60-pulse {\n    animation: v60PulsePhase 700ms ease-out 1;\n    transform-origin: center;\n    will-change: transform;\n  }\n  @keyframes v60BlinkPill {\n    0%, 100% { opacity: 1; transform: scale(1); }\n    50%      { opacity: .22; transform: scale(1.03); }\n  }\n  .v60-pill-pour-active {\n    background: #ffe7b7 !important;\n    border: 2px solid #d2a44a !important;\n    color: #3b2a12 !important;\n    font-weight: 900 !important;\n    letter-spacing: .02em;\n    animation: v60BlinkPill 2500ms ease-in-out infinite;\n    box-shadow:\n      0 0 0 2px rgba(210,164,74,.18) inset,\n      0 10px 22px rgba(0,0,0,.12),\n      0 0 0 6px rgba(210,164,74,.10);\n  }\n  @media (prefers-reduced-motion: reduce) {\n    .v60-pill-pour-active { animation: none; }\n    .v60-pulse { animation: none; }\n  }\n\u003c\/style\u003e\n\u003cscript\u003e\n(function() {\n  var SUFFIX = '-decafbuesaco';\n  var END_AT = 135;\n  var phases = [\n    { key: 1, t: 0,  pourLen: 10 },\n    { key: 2, t: 40, pourLen: 30 },\n    { key: 3, t: 80, pourLen: 25 }\n  ];\n  var latte = {\n    cardBg:     '#f6f1ea',\n    cardBorder: '#c8a97e',\n    pillBg:     '#eadfce'\n  };\n  var details  = document.getElementById('v60Details'    + SUFFIX);\n  var startBtn = document.getElementById('v60StartBtn'   + SUFFIX);\n  var stopBtn  = document.getElementById('v60StopBtn'    + SUFFIX);\n  var timerEl  = document.getElementById('v60Timer'      + SUFFIX);\n  var statusEl = document.getElementById('v60WakeStatus' + SUFFIX);\n  var pills = {\n    1: document.getElementById('v60-pill-1' + SUFFIX),\n    2: document.getElementById('v60-pill-2' + SUFFIX),\n    3: document.getElementById('v60-pill-3' + SUFFIX)\n  };\n  var cards = {\n    1: document.getElementById('v60-card-1' + SUFFIX),\n    2: document.getElementById('v60-card-2' + SUFFIX),\n    3: document.getElementById('v60-card-3' + SUFFIX)\n  };\n  function setCardActive(key) {\n    Object.keys(cards).forEach(function(k) {\n      var c = cards[k];\n      if (!c) return;\n      if (parseInt(k) === key) {\n        c.style.borderColor = latte.cardBorder;\n        c.style.background  = latte.cardBg;\n        c.style.boxShadow   = '0 0 0 2px rgba(200,169,126,.25) inset, 0 8px 22px rgba(200,169,126,.28)';\n      } else {\n        c.style.borderColor = 'rgba(0,0,0,.18)';\n        c.style.background  = 'transparent';\n        c.style.boxShadow   = 'none';\n      }\n    });\n  }\n  function setPillPhaseActive(key, doPulse) {\n    Object.keys(pills).forEach(function(k) {\n      var p = pills[k];\n      if (!p) return;\n      p.style.background  = 'rgba(0,0,0,.05)';\n      p.style.borderColor = 'rgba(0,0,0,.12)';\n      p.style.boxShadow   = 'none';\n      p.classList.remove('v60-pulse');\n    });\n    var pill = pills[key];\n    if (pill) {\n      pill.style.background  = latte.pillBg;\n      pill.style.borderColor = latte.cardBorder;\n      pill.style.boxShadow   = '0 0 0 2px rgba(200,169,126,.25) inset';\n      if (doPulse) {\n        pill.classList.remove('v60-pulse');\n        void pill.offsetWidth;\n        pill.classList.add('v60-pulse');\n      }\n    }\n  }\n  function resetPourPills() {\n    Object.values(pills).forEach(function(p) {\n      if (!p) return;\n      p.classList.remove('v60-pill-pour-active');\n    });\n  }\n  function setPourPillActive(key) {\n    resetPourPills();\n    if (!key) return;\n    var pill = pills[key];\n    if (pill) pill.classList.add('v60-pill-pour-active');\n  }\n  function clearAll() {\n    Object.values(cards).forEach(function(c) {\n      if (!c) return;\n      c.style.borderColor = 'rgba(0,0,0,.18)';\n      c.style.background  = 'transparent';\n      c.style.boxShadow   = 'none';\n    });\n    Object.values(pills).forEach(function(p) {\n      if (!p) return;\n      p.style.background  = 'rgba(0,0,0,.05)';\n      p.style.borderColor = 'rgba(0,0,0,.12)';\n      p.style.boxShadow   = 'none';\n      p.classList.remove('v60-pulse');\n      p.classList.remove('v60-pill-pour-active');\n    });\n  }\n  var wakeLock  = null;\n  var startTime = null;\n  var rafId     = null;\n  var lastPhaseKey = null;\n  var lastPourKey  = null;\n  function fmt(sec) {\n    sec = Math.max(0, Math.floor(sec));\n    var m = Math.floor(sec \/ 60);\n    var s = sec % 60;\n    return m + ':' + (s \u0026lt; 10 ? '0' : '') + s;\n  }\n  function getCurrentPhaseKey(elapsed) {\n    var current = phases[0].key;\n    for (var i = 0; i \u0026lt; phases.length; i++) if (elapsed \u0026gt;= phases[i].t) current = phases[i].key;\n    return current;\n  }\n  function getPourKey(elapsed) {\n    for (var i = phases.length - 1; i \u0026gt;= 0; i--) {\n      var p = phases[i];\n      if (elapsed \u0026gt;= p.t \u0026amp;\u0026amp; elapsed \u0026lt; (p.t + p.pourLen)) return p.key;\n    }\n    return null;\n  }\n  function enableWakeLock() {\n    if (!('wakeLock' in navigator)) {\n      statusEl.textContent = '⚠️ Ton navigateur ne supporte pas le mode écran allumé.';\n      return Promise.resolve();\n    }\n    return navigator.wakeLock.request('screen').then(function(wl) {\n      wakeLock = wl;\n      statusEl.textContent = '✅ Écran maintenu allumé pendant la recette.';\n      wakeLock.addEventListener('release', function() {\n        statusEl.textContent = 'ℹ️ Mode écran allumé relâché.';\n      });\n    }).catch(function() {\n      statusEl.textContent = '⚠️ Impossible d\\'activer le mode écran allumé.';\n      wakeLock = null;\n    });\n  }\n  function disableWakeLock() {\n    if (wakeLock) { wakeLock.release(); wakeLock = null; }\n  }\n  function setButtons(running) {\n    startBtn.disabled = running;\n    stopBtn.disabled  = !running;\n    stopBtn.style.opacity = running ? '1' : '.5';\n  }\n  function tick() {\n    var elapsed = (Date.now() - startTime) \/ 1000;\n    timerEl.textContent = fmt(elapsed);\n    var phaseKey = getCurrentPhaseKey(elapsed);\n    if (phaseKey !== lastPhaseKey) {\n      setCardActive(phaseKey);\n      setPillPhaseActive(phaseKey, lastPhaseKey !== null);\n      lastPhaseKey = phaseKey;\n    }\n    var pourKey = getPourKey(elapsed);\n    if (pourKey !== lastPourKey) {\n      setPourPillActive(pourKey);\n      lastPourKey = pourKey;\n    }\n    if (elapsed \u0026gt;= END_AT) { stopRecipe(true); return; }\n    rafId = requestAnimationFrame(tick);\n  }\n  function startRecipe() {\n    setButtons(true);\n    timerEl.textContent = '0:00';\n    lastPhaseKey = null;\n    lastPourKey  = null;\n    enableWakeLock().then(function() {\n      setCardActive(1);\n      setPillPhaseActive(1, false);\n      setPourPillActive(1);\n      lastPhaseKey = 1;\n      lastPourKey  = 1;\n      startTime = Date.now();\n      if (rafId) cancelAnimationFrame(rafId);\n      rafId = requestAnimationFrame(tick);\n    });\n  }\n  function stopRecipe(autoEnded) {\n    if (rafId) cancelAnimationFrame(rafId);\n    rafId     = null;\n    startTime = null;\n    disableWakeLock();\n    setButtons(false);\n    clearAll();\n    lastPhaseKey = null;\n    lastPourKey  = null;\n    if (autoEnded) {\n      statusEl.textContent = '✅ Recette terminée — écran libéré.';\n      timerEl.textContent  = fmt(END_AT);\n    } else {\n      statusEl.textContent = 'ℹ️ Recette arrêtée — écran libéré.';\n    }\n  }\n  startBtn.addEventListener('click', startRecipe);\n  stopBtn.addEventListener('click', function() { stopRecipe(false); });\n  details.addEventListener('toggle', function() { if (!details.open) stopRecipe(false); });\n  document.addEventListener('visibilitychange', function() {\n    if (document.visibilityState === 'visible' \u0026amp;\u0026amp; startTime \u0026amp;\u0026amp; !wakeLock) enableWakeLock();\n  });\n})();\n\u003c\/script\u003e\n\u003c\/svg\u003e","brand":"ZAB","offers":[{"title":"300g","offer_id":10369779662891,"sku":"CAF-SIN-DECA-300","price":26.5,"currency_code":"CAD","in_stock":true},{"title":"808g","offer_id":32797185572939,"sku":"CAF-SIN-DECA-808","price":64.5,"currency_code":"CAD","in_stock":true},{"title":"2268g (5lbs)","offer_id":32797183901771,"sku":"CAF-SIN-DECA-2268","price":165.0,"currency_code":"CAD","in_stock":true},{"title":"100g","offer_id":51434155704629,"sku":"CAF-SIN-DECA-100","price":13.75,"currency_code":"CAD","in_stock":true},{"title":"Bucket - 5lbs (Livraison locale seulement)","offer_id":52564443463989,"sku":"CAF-SIN-DECA-BUCK-5","price":190.0,"currency_code":"CAD","in_stock":true},{"title":"Bucket - 15lbs (Livraison locale seulement)","offer_id":52478907842869,"sku":"CAF-SIN-DECA-BUCK-15","price":520.0,"currency_code":"CAD","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/2716\/1842\/files\/decaf-buesaco-300g.jpg?v=1793313023"},{"product_id":"joyeux-roger","title":"BRÉSIL - JOYEUX ROGER","description":"\u003c!-- =========================================================\n  SECTION 1 : NOTES DE DÉGUSTATION\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto; border: 2px solid var(--product-box-background, #000); border-radius: 12px; overflow: hidden;\"\u003e\n\u003cdiv style=\"padding: 10px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center;\"\u003eNotes de dégustation\u003c\/div\u003e\n\u003cdiv style=\"padding: 16px 14px; font-weight: 900; text-transform: uppercase; font-size: 28px; letter-spacing: .05em; text-align: center; background: transparent;\"\u003eBROWNIE + NOISETTE + CRÉMEUX\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 1 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION CAROUSEL : IMAGES\n========================================================= --\u003e\n\u003cdiv id=\"carousel-sancoffee\" style=\"position: relative; width: 100%; padding-bottom: 33.33%; height: 0; overflow: hidden; border-radius: 8px;\"\u003e\n\u003cimg class=\"carousel-img-sancoffee\" src=\"https:\/\/cdn.shopify.com\/s\/files\/1\/2716\/1842\/files\/San-Coffee-image-groupe.jpg?v=1781785600\" alt=\"Sancoffee - groupe\" style=\"position: absolute; top: 0; left: 0; width: 100%; height: 100%; object-fit: cover; border-radius: 8px; opacity: 1; transition: opacity .6s ease;\"\u003e \u003cimg class=\"carousel-img-sancoffee\" src=\"https:\/\/cdn.shopify.com\/s\/files\/1\/2716\/1842\/files\/San-Coffee-image-warehouse.jpg?v=1781785600\" alt=\"Sancoffee - entrepôt\" style=\"position: absolute; top: 0; left: 0; width: 100%; height: 100%; object-fit: cover; border-radius: 8px; opacity: 0; transition: opacity .6s ease;\"\u003e \u003cimg class=\"carousel-img-sancoffee\" src=\"https:\/\/cdn.shopify.com\/s\/files\/1\/2716\/1842\/files\/San-Coffee-image-ferme.jpg?v=1781785600\" alt=\"Sancoffee - ferme\" style=\"position: absolute; top: 0; left: 0; width: 100%; height: 100%; object-fit: cover; border-radius: 8px; opacity: 0; transition: opacity .6s ease;\"\u003e \u003cbutton type=\"button\" id=\"carousel-prev-sancoffee\" style=\"position: absolute; top: 50%; left: 8px; transform: translateY(-50%); z-index: 3; cursor: pointer; border: none; background: rgba(0,0,0,.25); color: #fff; font-weight: 400; width: 28px; height: 28px; border-radius: 999px; font-size: 15px; line-height: 1; display: flex; align-items: center; justify-content: center; opacity: .55;\"\u003e‹\u003c\/button\u003e \u003cbutton type=\"button\" id=\"carousel-next-sancoffee\" style=\"position: absolute; top: 50%; right: 8px; transform: translateY(-50%); z-index: 3; cursor: pointer; border: none; background: rgba(0,0,0,.25); color: #fff; font-weight: 400; width: 28px; height: 28px; border-radius: 999px; font-size: 15px; line-height: 1; display: flex; align-items: center; justify-content: center; opacity: .55;\"\u003e›\u003c\/button\u003e\n\u003cdiv id=\"carousel-dots-sancoffee\" style=\"position: absolute; bottom: 10px; left: 0; right: 0; z-index: 3; display: flex; gap: 8px; align-items: center; justify-content: center;\"\u003e\n\u003cspan class=\"carousel-dot-sancoffee\" data-i=\"0\" style=\"cursor: pointer; width: 10px; height: 10px; border-radius: 999px; background: #fff; border: 1px solid rgba(0,0,0,.4); opacity: 1;\"\u003e\u003c\/span\u003e \u003cspan class=\"carousel-dot-sancoffee\" data-i=\"1\" style=\"cursor: pointer; width: 10px; height: 10px; border-radius: 999px; background: #fff; border: 1px solid rgba(0,0,0,.4); opacity: .5;\"\u003e\u003c\/span\u003e \u003cspan class=\"carousel-dot-sancoffee\" data-i=\"2\" style=\"cursor: pointer; width: 10px; height: 10px; border-radius: 999px; background: #fff; border: 1px solid rgba(0,0,0,.4); opacity: .5;\"\u003e\u003c\/span\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION CAROUSEL ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 2 : APPROVISIONNEMENT\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto;\"\u003e\n\u003cdiv style=\"padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center; border-radius: 12px 12px 0 0;\"\u003eApprovisionnement\u003c\/div\u003e\n\u003ctable style=\"width: 100%; border-collapse: collapse; background: transparent;\" cellspacing=\"1\" cellpadding=\"1\" border=\"3\"\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd style=\"width: 20%;\"\u003eORIGINE\u003c\/td\u003e\n\u003ctd\u003eCampo das Vertentes, Minas Gerais, Brésil\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePRODUCTEUR.RICE\u003c\/td\u003e\n\u003ctd\u003ePlusieurs producteur.rices de Sancoffee\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eVARIÉTÉS\u003c\/td\u003e\n\u003ctd\u003eCatucai jaune, Mundo Novo, Catuai rouge, Topázio\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePROCÉDÉ\u003c\/td\u003e\n\u003ctd\u003eNaturel\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eALTITUDE\u003c\/td\u003e\n\u003ctd\u003e900 – 1200 m\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePARTENAIRES\u003c\/td\u003e\n\u003ctd\u003eCrop to Cup\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eVOLUME ACHETÉ\u003c\/td\u003e\n\u003ctd\u003e96 600 kg\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eFAB\u003c\/td\u003e\n\u003ctd\u003e2,40 $ US\/LB\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePRIX LIVRÉ\u003c\/td\u003e\n\u003ctd\u003e4,55 $ CAD\/LB\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eRELATION\u003c\/td\u003e\n\u003ctd\u003e2 ans\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003c\/tbody\u003e\n\u003c\/table\u003e\n\u003cp style=\"margin: 6px 0 0 0; font-size: 13px;\"\u003e \u003c\/p\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 2 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 3 : INFORMATIONS SUR LE CAFÉ\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto;\"\u003e\n\u003cdiv style=\"padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center; border-radius: 12px 12px 0 0;\"\u003eInformations sur le café\u003c\/div\u003e\n\u003cdiv style=\"border: 2px solid var(--product-box-background, #000); border-top: none; border-radius: 0 0 12px 12px; padding: 16px 14px; background: transparent;\"\u003e\n\u003cp style=\"margin: 0 0 12px 0; text-align: justify;\"\u003eSancoffee est une coopérative indépendante certifiée B-Corp, originaire de la région de Campo das Vertentes, dans l'État de Minas Gerais, au Brésil. Sancoffee regroupe 20 fermes membres et soutient 600 petit.tes producteur.rices, partageant une vision collective axée sur la durabilité, la qualité et l'impact communautaire. La coopérative allie fièrement sa riche tradition caféière, remontant à 1860, à des initiatives modernes favorisant la préservation de l'environnement et le progrès social. Pour en apprendre plus, visite leur \u003ca rel=\"noopener\" href=\"https:\/\/sancoffee.com\/\" target=\"_blank\"\u003e\u003cstrong\u003esite web\u003c\/strong\u003e\u003c\/a\u003e.\u003c\/p\u003e\n\u003cp style=\"margin: 0 0 12px 0; text-align: justify;\"\u003eDes programmes de la coopérative comme Beyond Borders offrent aux petit.tes producteur.rices des outils et un soutien technique, leur permettant de gagner en reconnaissance et de valoriser leur travail. Grâce à des ateliers éducatifs et des formations pour la jeunesse, Sancoffee investit dans l'avenir de ses communautés, favorisant une croissance durable et des opportunités pour tous.\u003c\/p\u003e\n\u003cp style=\"margin: 0 0 16px 0; text-align: justify;\"\u003eSancoffee a atteint la neutralité carbone en 2020, devenant un pionnier de la production de café respectueuse de l'environnement. Ses efforts incluent la restauration de la biodiversité, la plantation d'arbres indigènes et la recherche pour réduire l'empreinte carbone au niveau des exploitations agricoles.\u003c\/p\u003e\n\u003cdiv class=\"logos-sancoffee\" style=\"display: flex; gap: 20px; align-items: center; justify-content: space-between; flex-wrap: wrap; padding-top: 16px; border-top: 1px solid rgba(0,0,0,.12);\"\u003e\n\u003ca rel=\"noopener\" href=\"https:\/\/sancoffee.com\/\" style=\"display: inline-block;\" target=\"_blank\"\u003e \u003cimg src=\"https:\/\/cdn.shopify.com\/s\/files\/1\/2716\/1842\/files\/san_coffee_logo.svg?v=1781786545\" alt=\"Sancoffee\" style=\"height: 80px; width: auto;\"\u003e \u003c\/a\u003e\n\u003cdiv class=\"logos-certs-sancoffee\" style=\"display: flex; gap: 20px; align-items: center; flex-wrap: wrap;\"\u003e\n\u003cimg src=\"https:\/\/cdn.shopify.com\/s\/files\/1\/2716\/1842\/files\/bcorp-logo.webp?v=1781785759\" alt=\"Certification B-Corp\" style=\"height: 80px; width: auto;\"\u003e \u003cimg src=\"https:\/\/cdn.shopify.com\/s\/files\/1\/2716\/1842\/files\/For-Profit-Sus-2024-Stone_white.webp?v=1781785759\" alt=\"Sustainability Award 2024\" style=\"height: 80px; width: auto;\"\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 3 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 5 : EN GROS\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto;\"\u003e\n\u003cdiv style=\"border: 2px solid var(--product-box-background, #000); border-radius: 12px; overflow: hidden;\"\u003e\n\u003cdiv style=\"padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center;\"\u003eEn gros\u003c\/div\u003e\n\u003cdiv style=\"padding: 16px 14px; background: transparent;\"\u003e\n\u003cp style=\"margin: 0;\"\u003eTu veux commander deux sacs de 5 lbs ou plus? Visite notre section \u003ca rel=\"noopener\" href=\"https:\/\/zabcafe.com\/products\/bresil-joyeux-roger-en-gros\" target=\"_blank\"\u003e\u003cstrong\u003eEN GROS\u003c\/strong\u003e\u003c\/a\u003e pour profiter d'un rabais de volume!\u003c\/p\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 5 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 4 : PARAMÈTRES D'EXTRACTION — ESPRESSO\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto;\"\u003e\n\u003cdetails open=\"\" style=\"border: 2px solid var(--product-box-background, #000); border-radius: 12px; overflow: hidden; margin: 0 0 12px 0; background: transparent;\"\u003e\n\u003csummary style=\"cursor: pointer; list-style: none; padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center;\"\u003eEspresso — paramètres recommandés\u003c\/summary\u003e\n\u003cdiv style=\"padding: 12px 14px; background: transparent;\"\u003e\n\u003ctable style=\"width: 100%; border-collapse: collapse; background: transparent;\"\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd style=\"padding: 10px 0; font-weight: 800; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003eCafé moulu\u003c\/td\u003e\n\u003ctd style=\"padding: 10px 0; text-align: right; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003e18,5 g\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd style=\"padding: 10px 0; font-weight: 800; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003eCafé dans la tasse\u003c\/td\u003e\n\u003ctd style=\"padding: 10px 0; text-align: right; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003e30 g\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd style=\"padding: 10px 0; font-weight: 800;\"\u003eTemps d'extraction\u003c\/td\u003e\n\u003ctd style=\"padding: 10px 0; text-align: right;\"\u003e32 sec\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003c\/tbody\u003e\n\u003c\/table\u003e\n\u003cdiv style=\"margin-top: 10px; padding: 8px 10px; border-radius: 8px; background: rgba(0,0,0,.04); border: 1px dashed rgba(0,0,0,.2); font-size: 12px; opacity: .7; line-height: 1.4;\"\u003e\n\u003cstrong\u003eÀ noter —\u003c\/strong\u003e\u003cspan\u003e Recette optimisée pour un panier de \u003c\/span\u003e\u003cstrong\u003e18 g\u003c\/strong\u003e\u003cspan\u003e. Ajuster légèrement la mouture pour atteindre 32 secondes d'extraction.\u003c\/span\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/details\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 4 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 6 : PARAMÈTRES FELLOW AIDEN\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto;\"\u003e\n\u003cdiv style=\"border: 2px solid var(--product-box-background, #000); border-radius: 12px; overflow: hidden;\"\u003e\n\u003cdiv style=\"padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center;\"\u003eParamètres pour la Fellow Aiden\u003c\/div\u003e\n\u003cdiv style=\"padding: 16px 14px; background: transparent;\"\u003e\n\u003cp style=\"margin: 0;\"\u003e\u003ca rel=\"noopener\" href=\"https:\/\/brew.link\/p\/lYvn\" target=\"_blank\"\u003eTélécharge le profil Joyeux Roger pour la machine Aiden de Fellow!\u003c\/a\u003e\u003c\/p\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 6 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 7 : V60\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto;\"\u003e\n\u003cdetails id=\"v60Details-joyeuxroger\" open=\"\" style=\"border: 2px solid var(--product-box-background, #000); border-radius: 12px; overflow: hidden; margin: 0 0 12px 0; background: rgba(255,255,255,0.5);\"\u003e\n\u003csummary style=\"cursor: pointer; list-style: none; padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center;\"\u003eV60 – Recette\u003c\/summary\u003e\n\u003cdiv style=\"padding: 12px 14px;\"\u003e\n\u003cdiv style=\"padding: 10px 0 10px; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003e\n\u003cdiv style=\"font-weight: 900; font-size: 16px;\"\u003eRatio 1:15\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 4px; opacity: .7; font-size: 13px;\"\u003e15 g in – 225 g out\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 6px; font-size: 13px;\"\u003e\n\u003cstrong\u003eTempérature de l'eau :\u003c\/strong\u003e 85 °C\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; padding: 10px 0 8px;\"\u003e\n\u003cdiv style=\"display: flex; gap: 8px; align-items: center; flex-wrap: wrap;\"\u003e\n\u003cbutton style=\"cursor: pointer; border: 2px solid var(--product-box-background, #000); background: var(--product-box-background, #000); color: var(--product-box-text, #fff); font-weight: 900; padding: 8px 10px; border-radius: 10px; text-transform: uppercase; letter-spacing: .02em; font-size: 12px;\" type=\"button\" id=\"v60StartBtn-joyeuxroger\"\u003eDémarrer\u003c\/button\u003e \u003cbutton style=\"cursor: pointer; border: 2px solid var(--product-box-background, #000); background: var(--product-box-text, #fff); color: var(--product-box-background, #000); font-weight: 900; padding: 8px 10px; border-radius: 10px; text-transform: uppercase; letter-spacing: .02em; font-size: 12px; opacity: .5;\" disabled type=\"button\" id=\"v60StopBtn-joyeuxroger\"\u003eStop\u003c\/button\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; line-height: 1;\"\u003e\n\u003cspan style=\"opacity: .70; font-size: 12px; font-weight: 800; text-transform: uppercase; letter-spacing: .04em;\"\u003eTimer\u003c\/span\u003e \u003cspan style=\"font-weight: 950; font-size: 28px; letter-spacing: .01em;\" id=\"v60Timer-joyeuxroger\"\u003e0:00\u003c\/span\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"flex-basis: 100%; opacity: .6; font-size: 12px; line-height: 1.3; margin-top: 2px;\" id=\"v60WakeStatus-joyeuxroger\"\u003eℹ️ Appuie sur \"Démarrer\" pour garder l'écran allumé.\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 8px; display: grid; gap: 10px;\"\u003e\n\u003cdiv style=\"border: 1px solid rgba(0,0,0,.18); border-radius: 12px; padding: 10px 12px;\" id=\"v60-card-1-joyeuxroger\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; margin-bottom: 6px;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e0:00\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003ePhase 1 — Bloom\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 8px; flex-wrap: wrap; font-size: 12.5px; font-weight: 800;\"\u003e\n\u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\" id=\"v60-pill-1-joyeuxroger\"\u003eVerser pendant 0:10s\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\"\u003eTotal 35 g\u003c\/span\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"border: 1px solid rgba(0,0,0,.18); border-radius: 12px; padding: 10px 12px;\" id=\"v60-card-2-joyeuxroger\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; margin-bottom: 6px;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e0:30\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003ePhase 2\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 8px; flex-wrap: wrap; font-size: 12.5px; font-weight: 800;\"\u003e\n\u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\" id=\"v60-pill-2-joyeuxroger\"\u003eVerser pendant 0:30s\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\"\u003eTotal 170 g\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12); opacity: .6;\"\u003e+135 g\u003c\/span\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"border: 1px solid rgba(0,0,0,.18); border-radius: 12px; padding: 10px 12px;\" id=\"v60-card-3-joyeuxroger\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; margin-bottom: 6px;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e1:30\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003ePhase 3\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 8px; flex-wrap: wrap; font-size: 12.5px; font-weight: 800;\"\u003e\n\u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\" id=\"v60-pill-3-joyeuxroger\"\u003eVerser pendant 0:15s\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\"\u003eTotal 225 g\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12); opacity: .6;\"\u003e+55 g\u003c\/span\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 12px; border-top: 1px solid rgba(0,0,0,.2); padding-top: 10px;\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e3:00\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003eTemps final écoulement complet\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 8px; padding: 8px 10px; border-radius: 8px; background: rgba(0,0,0,.04); border: 1px dashed rgba(0,0,0,.2); font-size: 12px; opacity: .6; line-height: 1.4;\"\u003e\n\u003cstrong\u003eℹ️ Astuce —\u003c\/strong\u003e Si le temps total est plus court, la mouture est probablement trop grosse. S'il est plus long, la mouture est probablement trop fine.\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/details\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 7 ========= --\u003e\u003csvg style=\"display: none;\"\u003e\n\u003cstyle\u003e\n  @keyframes v60PulsePhase {\n    0%   { transform: scale(1);    box-shadow: 0 0 0 0 rgba(200,169,126,.35); }\n    50%  { transform: scale(1.06); box-shadow: 0 0 0 10px rgba(200,169,126,0); }\n    100% { transform: scale(1);    box-shadow: 0 0 0 0 rgba(200,169,126,0); }\n  }\n  .v60-pulse {\n    animation: v60PulsePhase 700ms ease-out 1;\n    transform-origin: center;\n    will-change: transform;\n  }\n  @keyframes v60BlinkPill {\n    0%, 100% { opacity: 1; transform: scale(1); }\n    50%      { opacity: .22; transform: scale(1.03); }\n  }\n  .v60-pill-pour-active {\n    background: #ffe7b7 !important;\n    border: 2px solid #d2a44a !important;\n    color: #3b2a12 !important;\n    font-weight: 900 !important;\n    letter-spacing: .02em;\n    animation: v60BlinkPill 2500ms ease-in-out infinite;\n    box-shadow:\n      0 0 0 2px rgba(210,164,74,.18) inset,\n      0 10px 22px rgba(0,0,0,.12),\n      0 0 0 6px rgba(210,164,74,.10);\n  }\n  @media (prefers-reduced-motion: reduce) {\n    .v60-pill-pour-active { animation: none; }\n    .v60-pulse { animation: none; }\n  }\n  @media (max-width: 600px) {\n    .logos-sancoffee { justify-content: center !important; gap: 16px !important; }\n    .logos-sancoffee \u0026gt; a { width: 100% !important; text-align: center !important; }\n    .logos-certs-sancoffee { width: 100% !important; justify-content: center !important; }\n  }\n\u003c\/style\u003e\n\u003cscript\u003e\n(function() {\n  \/* ===== CARROUSEL ===== *\/\n  var cSuffix = '-sancoffee';\n  var cImgs  = document.querySelectorAll('.carousel-img' + cSuffix);\n  var cDots  = document.querySelectorAll('.carousel-dot' + cSuffix);\n  var cPrev  = document.getElementById('carousel-prev' + cSuffix);\n  var cNext  = document.getElementById('carousel-next' + cSuffix);\n  var cIndex = 0;\n  var cTimer = null;\n  function cShow(i) {\n    cIndex = (i + cImgs.length) % cImgs.length;\n    for (var k = 0; k \u0026lt; cImgs.length; k++) cImgs[k].style.opacity = (k === cIndex) ? '1' : '0';\n    for (var d = 0; d \u0026lt; cDots.length; d++) cDots[d].style.opacity = (d === cIndex) ? '1' : '.5';\n  }\n  function cStart() { cStop(); cTimer = setInterval(function() { cShow(cIndex + 1); }, 5000); }\n  function cStop() { if (cTimer) { clearInterval(cTimer); cTimer = null; } }\n  if (cPrev) cPrev.addEventListener('click', function() { cShow(cIndex - 1); cStart(); });\n  if (cNext) cNext.addEventListener('click', function() { cShow(cIndex + 1); cStart(); });\n  for (var dd = 0; dd \u0026lt; cDots.length; dd++) {\n    (function(node) {\n      node.addEventListener('click', function() { cShow(parseInt(node.getAttribute('data-i'), 10)); cStart(); });\n    })(cDots[dd]);\n  }\n  cShow(0);\n  cStart();\n\n  \/* ===== TIMER V60 ===== *\/\n  var SUFFIX = '-joyeuxroger';\n  var END_AT = 180;\n  var phases = [\n    { key: 1, t: 0,  pourLen: 10 },\n    { key: 2, t: 30, pourLen: 30 },\n    { key: 3, t: 90, pourLen: 15 }\n  ];\n  var latte = {\n    cardBg:     '#f6f1ea',\n    cardBorder: '#c8a97e',\n    pillBg:     '#eadfce'\n  };\n  var details  = document.getElementById('v60Details'    + SUFFIX);\n  var startBtn = document.getElementById('v60StartBtn'   + SUFFIX);\n  var stopBtn  = document.getElementById('v60StopBtn'    + SUFFIX);\n  var timerEl  = document.getElementById('v60Timer'      + SUFFIX);\n  var statusEl = document.getElementById('v60WakeStatus' + SUFFIX);\n  var pills = {\n    1: document.getElementById('v60-pill-1' + SUFFIX),\n    2: document.getElementById('v60-pill-2' + SUFFIX),\n    3: document.getElementById('v60-pill-3' + SUFFIX)\n  };\n  var cards = {\n    1: document.getElementById('v60-card-1' + SUFFIX),\n    2: document.getElementById('v60-card-2' + SUFFIX),\n    3: document.getElementById('v60-card-3' + SUFFIX)\n  };\n  function setCardActive(key) {\n    Object.keys(cards).forEach(function(k) {\n      var c = cards[k];\n      if (!c) return;\n      if (parseInt(k) === key) {\n        c.style.borderColor = latte.cardBorder;\n        c.style.background  = latte.cardBg;\n        c.style.boxShadow   = '0 0 0 2px rgba(200,169,126,.25) inset, 0 8px 22px rgba(200,169,126,.28)';\n      } else {\n        c.style.borderColor = 'rgba(0,0,0,.18)';\n        c.style.background  = 'transparent';\n        c.style.boxShadow   = 'none';\n      }\n    });\n  }\n  function setPillPhaseActive(key, doPulse) {\n    Object.keys(pills).forEach(function(k) {\n      var p = pills[k];\n      if (!p) return;\n      p.style.background  = 'rgba(0,0,0,.05)';\n      p.style.borderColor = 'rgba(0,0,0,.12)';\n      p.style.boxShadow   = 'none';\n      p.classList.remove('v60-pulse');\n    });\n    var pill = pills[key];\n    if (pill) {\n      pill.style.background  = latte.pillBg;\n      pill.style.borderColor = latte.cardBorder;\n      pill.style.boxShadow   = '0 0 0 2px rgba(200,169,126,.25) inset';\n      if (doPulse) {\n        pill.classList.remove('v60-pulse');\n        void pill.offsetWidth;\n        pill.classList.add('v60-pulse');\n      }\n    }\n  }\n  function resetPourPills() {\n    Object.values(pills).forEach(function(p) {\n      if (!p) return;\n      p.classList.remove('v60-pill-pour-active');\n    });\n  }\n  function setPourPillActive(key) {\n    resetPourPills();\n    if (!key) return;\n    var pill = pills[key];\n    if (pill) pill.classList.add('v60-pill-pour-active');\n  }\n  function clearAll() {\n    Object.values(cards).forEach(function(c) {\n      if (!c) return;\n      c.style.borderColor = 'rgba(0,0,0,.18)';\n      c.style.background  = 'transparent';\n      c.style.boxShadow   = 'none';\n    });\n    Object.values(pills).forEach(function(p) {\n      if (!p) return;\n      p.style.background  = 'rgba(0,0,0,.05)';\n      p.style.borderColor = 'rgba(0,0,0,.12)';\n      p.style.boxShadow   = 'none';\n      p.classList.remove('v60-pulse');\n      p.classList.remove('v60-pill-pour-active');\n    });\n  }\n  var wakeLock  = null;\n  var startTime = null;\n  var rafId     = null;\n  var lastPhaseKey = null;\n  var lastPourKey  = null;\n  function fmt(sec) {\n    sec = Math.max(0, Math.floor(sec));\n    var m = Math.floor(sec \/ 60);\n    var s = sec % 60;\n    return m + ':' + (s \u0026lt; 10 ? '0' : '') + s;\n  }\n  function getCurrentPhaseKey(elapsed) {\n    var current = phases[0].key;\n    for (var i = 0; i \u0026lt; phases.length; i++) if (elapsed \u0026gt;= phases[i].t) current = phases[i].key;\n    return current;\n  }\n  function getPourKey(elapsed) {\n    for (var i = phases.length - 1; i \u0026gt;= 0; i--) {\n      var p = phases[i];\n      if (elapsed \u0026gt;= p.t \u0026amp;\u0026amp; elapsed \u0026lt; (p.t + p.pourLen)) return p.key;\n    }\n    return null;\n  }\n  function enableWakeLock() {\n    if (!('wakeLock' in navigator)) {\n      statusEl.textContent = '⚠️ Ton navigateur ne supporte pas le mode \\xe9cran allum\\xe9.';\n      return Promise.resolve();\n    }\n    return navigator.wakeLock.request('screen').then(function(wl) {\n      wakeLock = wl;\n      statusEl.textContent = '✅ \\xc9cran maintenu allum\\xe9 pendant la recette.';\n      wakeLock.addEventListener('release', function() {\n        statusEl.textContent = 'ℹ️ Mode \\xe9cran allum\\xe9 rel\\xe2ch\\xe9.';\n      });\n    }).catch(function() {\n      statusEl.textContent = '⚠️ Impossible d\\'activer le mode \\xe9cran allum\\xe9.';\n      wakeLock = null;\n    });\n  }\n  function disableWakeLock() {\n    if (wakeLock) { wakeLock.release(); wakeLock = null; }\n  }\n  function setButtons(running) {\n    startBtn.disabled = running;\n    stopBtn.disabled  = !running;\n    stopBtn.style.opacity = running ? '1' : '.5';\n  }\n  function tick() {\n    var elapsed = (Date.now() - startTime) \/ 1000;\n    timerEl.textContent = fmt(elapsed);\n    var phaseKey = getCurrentPhaseKey(elapsed);\n    if (phaseKey !== lastPhaseKey) {\n      setCardActive(phaseKey);\n      setPillPhaseActive(phaseKey, lastPhaseKey !== null);\n      lastPhaseKey = phaseKey;\n    }\n    var pourKey = getPourKey(elapsed);\n    if (pourKey !== lastPourKey) {\n      setPourPillActive(pourKey);\n      lastPourKey = pourKey;\n    }\n    if (elapsed \u0026gt;= END_AT) { stopRecipe(true); return; }\n    rafId = requestAnimationFrame(tick);\n  }\n  function startRecipe() {\n    setButtons(true);\n    timerEl.textContent = '0:00';\n    lastPhaseKey = null;\n    lastPourKey  = null;\n    enableWakeLock().then(function() {\n      setCardActive(1);\n      setPillPhaseActive(1, false);\n      setPourPillActive(1);\n      lastPhaseKey = 1;\n      lastPourKey  = 1;\n      startTime = Date.now();\n      if (rafId) cancelAnimationFrame(rafId);\n      rafId = requestAnimationFrame(tick);\n    });\n  }\n  function stopRecipe(autoEnded) {\n    if (rafId) cancelAnimationFrame(rafId);\n    rafId     = null;\n    startTime = null;\n    disableWakeLock();\n    setButtons(false);\n    clearAll();\n    lastPhaseKey = null;\n    lastPourKey  = null;\n    if (autoEnded) {\n      statusEl.textContent = '✅ Recette termin\\xe9e — \\xe9cran lib\\xe9r\\xe9.';\n      timerEl.textContent  = fmt(END_AT);\n    } else {\n      statusEl.textContent = 'ℹ️ Recette arr\\xeat\\xe9e — \\xe9cran lib\\xe9r\\xe9.';\n    }\n  }\n  startBtn.addEventListener('click', startRecipe);\n  stopBtn.addEventListener('click', function() { stopRecipe(false); });\n  details.addEventListener('toggle', function() { if (!details.open) stopRecipe(false); });\n  document.addEventListener('visibilitychange', function() {\n    if (document.visibilityState === 'visible' \u0026amp;\u0026amp; startTime \u0026amp;\u0026amp; !wakeLock) enableWakeLock();\n  });\n})();\n\u003c\/script\u003e\n\u003c\/svg\u003e","brand":"ZAB","offers":[{"title":"300g","offer_id":15744685244459,"sku":"CAF-SIN-JOYE-300","price":22.0,"currency_code":"CAD","in_stock":true},{"title":"808g","offer_id":32176690364491,"sku":"CAF-SIN-JOYE-808","price":50.0,"currency_code":"CAD","in_stock":true},{"title":"2268g (5lbs)","offer_id":15853630717995,"sku":"CAF-SIN-JOYE-2268","price":123.0,"currency_code":"CAD","in_stock":true},{"title":"100g","offer_id":51434079519029,"sku":"CAF-SIN-JOYE-100","price":10.75,"currency_code":"CAD","in_stock":true},{"title":"Bucket - 5lbs (Livraison locale seulement)","offer_id":52569460638005,"sku":"CAF-SIN-JOYE-BUCK-5","price":148.0,"currency_code":"CAD","in_stock":true},{"title":"Bucket - 15lbs (Livraison locale seulement)","offer_id":52569460670773,"sku":"CAF-SIN-JOYE-BUCK-15","price":394.0,"currency_code":"CAD","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/2716\/1842\/files\/joyeux-roger-300g.jpg?v=1762137534"},{"product_id":"choix-du-torrefacteur-roasters-choice","title":"Choix du torréfacteur - Roaster's choice - Abonnement seulement","description":"\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 1 : CHOIX DU TORRÉFACTEUR\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto; border: 2px solid var(--product-box-background, #000); border-radius: 12px; overflow: hidden;\"\u003e\n\u003cdiv style=\"padding: 10px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center;\"\u003e✦ Choix du torréfacteur ✦\u003c\/div\u003e\n\u003cdiv style=\"padding: 20px 16px; background: transparent;\"\u003e\n\n\u003cp style=\"margin: 0 0 16px 0; font-size: 16px; font-weight: 700; text-align: center; text-transform: uppercase; letter-spacing: .04em;\"\u003eLaisse notre torréfacteur choisir lui-même ce qu'il veut te faire découvrir!\u003c\/p\u003e\n\n\u003cdiv style=\"border-top: 2px solid var(--product-box-background, #000); margin: 0 0 16px 0;\"\u003e\u003c\/div\u003e\n\n\u003cul style=\"margin: 0; padding: 0 0 0 20px; line-height: 2;\"\u003e\n\u003cli\u003e\u003cstrong\u003eDisponible en abonnement mensuel seulement.\u003c\/strong\u003e\u003c\/li\u003e\n\u003cli\u003e\u003cstrong\u003eLa sélection change une fois par mois.\u003c\/strong\u003e\u003c\/li\u003e\n\u003cli\u003e\u003cstrong\u003eSi tu commandes plusieurs \"Choix du torréfacteur\" par mois, les sacs seront différents.\u003c\/strong\u003e\u003c\/li\u003e\n\u003c\/ul\u003e\n\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 1 ========= --\u003e","brand":"ZAB","offers":[{"title":"300g","offer_id":30229889155115,"sku":"CAF-340-0013","price":24.5,"currency_code":"CAD","in_stock":true},{"title":"808g","offer_id":30229889220651,"sku":"CAF-2LB-0013","price":61.0,"currency_code":"CAD","in_stock":true},{"title":"2268g (5lbs)","offer_id":30229889187883,"sku":"CAF-5LB-0013","price":152.0,"currency_code":"CAD","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/2716\/1842\/files\/choix-300g_d5b1aa91-74db-40e5-8f84-ae76312e2b31.jpg?v=1756920101"},{"product_id":"brewmance-1","title":"BREWMANCE","description":"\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 1 : NOTES DE DÉGUSTATION\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto; border: 2px solid var(--product-box-background, #000); border-radius: 12px; overflow: hidden;\"\u003e\n\u003cdiv style=\"padding: 10px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center;\"\u003eNotes de dégustation\u003c\/div\u003e\n\u003cdiv style=\"padding: 16px 14px; font-weight: 900; text-transform: uppercase; font-size: 28px; letter-spacing: .05em; text-align: center; background: transparent;\"\u003eFRUITÉ + CHOCOLATÉ + CRÉMEUX\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 1 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 2 : APPROVISIONNEMENT (mélange 80\/20)\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto;\"\u003e\n\u003cdiv style=\"padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center; border-radius: 12px 12px 0 0;\"\u003eApprovisionnement — Joyeux Roger (80 %)\u003c\/div\u003e\n\u003ctable style=\"width: 100%; border-collapse: collapse; background: transparent;\" cellspacing=\"1\" cellpadding=\"1\" border=\"3\"\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd style=\"width: 20%;\"\u003eORIGINE\u003c\/td\u003e\n\u003ctd\u003eCampo das Vertentes, Minas Gerais, Brésil\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePRODUCTEUR.RICE\u003c\/td\u003e\n\u003ctd\u003ePlusieurs producteur.rices de Sancoffee\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eVARIÉTÉS\u003c\/td\u003e\n\u003ctd\u003eCatucai jaune, Mundo Novo, Catuai rouge, Topázio\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePROCÉDÉ\u003c\/td\u003e\n\u003ctd\u003eNaturel\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eALTITUDE\u003c\/td\u003e\n\u003ctd\u003e900 – 1200 m\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePARTENAIRES\u003c\/td\u003e\n\u003ctd\u003eCrop to Cup\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eVOLUME ACHETÉ\u003c\/td\u003e\n\u003ctd\u003e96 600 kg\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eFAB\u003c\/td\u003e\n\u003ctd\u003e2,40 $ US\/LB\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePRIX LIVRÉ\u003c\/td\u003e\n\u003ctd\u003e4,55 $ CAD\/LB\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eRELATION\u003c\/td\u003e\n\u003ctd\u003e2 ans\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003c\/tbody\u003e\n\u003c\/table\u003e\n\u003cp style=\"margin: 6px 0 0 0; font-size: 13px;\"\u003e \u003c\/p\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto;\"\u003e\n\u003cdiv style=\"padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center; border-radius: 12px 12px 0 0;\"\u003eApprovisionnement — Tariku (20 %)\u003c\/div\u003e\n\u003ctable style=\"width: 100%; border-collapse: collapse; background: transparent;\" cellspacing=\"1\" cellpadding=\"1\" border=\"3\"\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd style=\"width: 20%;\"\u003eORIGINE\u003c\/td\u003e\n\u003ctd\u003eRégion d'Oromia, Zone de West Arsi, District de Nensebo, Éthiopie\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePRODUCTEURS\u003c\/td\u003e\n\u003ctd\u003e593 petit.es producteur.rices\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eGESTIONNAIRE DU LOT\u003c\/td\u003e\n\u003ctd\u003eTariku Kare\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eSTATION DE LAVAGE\u003c\/td\u003e\n\u003ctd\u003eRafisa\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eVARIÉTÉ\u003c\/td\u003e\n\u003ctd\u003e74158, 74110, 74112\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePROCÉDÉ\u003c\/td\u003e\n\u003ctd\u003eNaturel\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eALTITUDE\u003c\/td\u003e\n\u003ctd\u003e2000–2200 m\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePARTENAIRES\u003c\/td\u003e\n\u003ctd\u003eCrop to Cup\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eVOLUME ACHETÉ\u003c\/td\u003e\n\u003ctd\u003e5 400 kg\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eFAB\u003c\/td\u003e\n\u003ctd\u003e4,35 $ US\/lb\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePRIX LIVRÉ\u003c\/td\u003e\n\u003ctd\u003e9,16 $ CAD\/lb\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eRELATION\u003c\/td\u003e\n\u003ctd\u003e1 an\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003c\/tbody\u003e\n\u003c\/table\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 2 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\n\u003c!-- =========================================================\n  SECTION 3 : INFORMATIONS SUR LE CAFÉ\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto;\"\u003e\n\u003cdiv style=\"padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center; border-radius: 12px 12px 0 0;\"\u003eInformations sur le café\u003c\/div\u003e\n\u003cdiv style=\"border: 2px solid var(--product-box-background, #000); border-top: none; border-radius: 0 0 12px 12px; padding: 16px 14px; background: transparent;\"\u003e\n\u003cp style=\"margin: 0;\"\u003eLe \u003cem\u003eBREWMANCE\u003c\/em\u003e (\u003ca href=\"https:\/\/zabcafe.com\/products\/joyeux-roger\" target=\"_blank\"\u003eJoyeux Roger\u003c\/a\u003e + \u003ca href=\"https:\/\/zabcafe.com\/collections\/cafes\" target=\"_blank\" rel=\"noopener\"\u003eTariku\u003c\/a\u003e) est notre mélange qui allie le réconfort du chocolat et des noix à la touche funky de fruits bien mûrs. C'est un café du quotidien, mais avec juste assez de notes fruitées pour éveiller la curiosité.\u003c\/p\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 3 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 5 : EN GROS\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto;\"\u003e\n\u003cdiv style=\"border: 2px solid var(--product-box-background, #000); border-radius: 12px; overflow: hidden;\"\u003e\n\u003cdiv style=\"padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center;\"\u003eEn gros\u003c\/div\u003e\n\u003cdiv style=\"padding: 16px 14px; background: transparent;\"\u003e\n\u003cp style=\"margin: 0;\"\u003eTu veux commander deux sacs de 5 lbs ou plus? Visite notre section \u003ca href=\"https:\/\/zabcafe.com\/products\/brewmance-en-gros\" rel=\"noopener\" target=\"_blank\"\u003e\u003cstrong\u003eEN GROS\u003c\/strong\u003e\u003c\/a\u003e pour profiter d'un rabais de volume!\u003c\/p\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 5 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 4 : PARAMÈTRES D'EXTRACTION — ESPRESSO\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto;\"\u003e\n\u003cdetails open=\"\" style=\"border: 2px solid var(--product-box-background, #000); border-radius: 12px; overflow: hidden; margin: 0 0 12px 0; background: transparent;\"\u003e\n\u003csummary style=\"cursor: pointer; list-style: none; padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center;\"\u003eEspresso — paramètres recommandés\u003c\/summary\u003e\n\u003cdiv style=\"padding: 12px 14px; background: transparent;\"\u003e\n\u003ctable style=\"width: 100%; border-collapse: collapse; background: transparent;\"\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd style=\"padding: 10px 0; font-weight: 800; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003eCafé moulu\u003c\/td\u003e\n\u003ctd style=\"padding: 10px 0; text-align: right; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003e18,5 g\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd style=\"padding: 10px 0; font-weight: 800; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003eCafé dans la tasse\u003c\/td\u003e\n\u003ctd style=\"padding: 10px 0; text-align: right; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003e31 g\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd style=\"padding: 10px 0; font-weight: 800;\"\u003eTemps d'extraction\u003c\/td\u003e\n\u003ctd style=\"padding: 10px 0; text-align: right;\"\u003e33 sec\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003c\/tbody\u003e\n\u003c\/table\u003e\n\u003cdiv style=\"margin-top: 10px; padding: 8px 10px; border-radius: 8px; background: rgba(0,0,0,.04); border: 1px dashed rgba(0,0,0,.2); font-size: 12px; opacity: .7; line-height: 1.4;\"\u003e\n\u003cstrong\u003eÀ noter —\u003c\/strong\u003e\u003cspan\u003e Recette optimisée pour un panier de \u003c\/span\u003e\u003cstrong\u003e18 g\u003c\/strong\u003e\u003cspan\u003e. Ajuster légèrement la mouture pour atteindre 32 secondes d'extraction.\u003c\/span\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/details\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 4 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 6 : PARAMÈTRES FELLOW AIDEN\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto;\"\u003e\n\u003cdiv style=\"border: 2px solid var(--product-box-background, #000); border-radius: 12px; overflow: hidden;\"\u003e\n\u003cdiv style=\"padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center;\"\u003eParamètres pour la Fellow Aiden\u003c\/div\u003e\n\u003cdiv style=\"padding: 16px 14px; background: transparent;\"\u003e\n\u003cp style=\"margin: 0;\"\u003e\u003ca href=\"https:\/\/brew.link\/p\/2Cpn\" rel=\"noopener\" target=\"_blank\"\u003eTélécharge le profil Brewmance pour la machine Aiden de Fellow!\u003c\/a\u003e\u003c\/p\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 6 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 7 : V60\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto;\"\u003e\n\u003cdetails id=\"v60Details-brewmance\" open=\"\" style=\"border: 2px solid var(--product-box-background, #000); border-radius: 12px; overflow: hidden; margin: 0 0 12px 0; background: rgba(255,255,255,0.5);\"\u003e\n\u003csummary style=\"cursor: pointer; list-style: none; padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center;\"\u003eV60 – Recette\u003c\/summary\u003e\n\u003cdiv style=\"padding: 12px 14px;\"\u003e\n\u003cdiv style=\"padding: 10px 0 10px; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003e\n\u003cdiv style=\"font-weight: 900; font-size: 16px;\"\u003eRatio 1:15\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 4px; opacity: .7; font-size: 13px;\"\u003e15 g in – 225 g out\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 6px; font-size: 13px;\"\u003e\n\u003cstrong\u003eTempérature de l'eau :\u003c\/strong\u003e 88 °C\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; padding: 10px 0 8px;\"\u003e\n\u003cdiv style=\"display: flex; gap: 8px; align-items: center; flex-wrap: wrap;\"\u003e\n\u003cbutton style=\"cursor: pointer; border: 2px solid var(--product-box-background, #000); background: var(--product-box-background, #000); color: var(--product-box-text, #fff); font-weight: 900; padding: 8px 10px; border-radius: 10px; text-transform: uppercase; letter-spacing: .02em; font-size: 12px;\" type=\"button\" id=\"v60StartBtn-brewmance\"\u003eDémarrer\u003c\/button\u003e \u003cbutton style=\"cursor: pointer; border: 2px solid var(--product-box-background, #000); background: var(--product-box-text, #fff); color: var(--product-box-background, #000); font-weight: 900; padding: 8px 10px; border-radius: 10px; text-transform: uppercase; letter-spacing: .02em; font-size: 12px; opacity: .5;\" disabled type=\"button\" id=\"v60StopBtn-brewmance\"\u003eStop\u003c\/button\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; line-height: 1;\"\u003e\n\u003cspan style=\"opacity: .70; font-size: 12px; font-weight: 800; text-transform: uppercase; letter-spacing: .04em;\"\u003eTimer\u003c\/span\u003e \u003cspan style=\"font-weight: 950; font-size: 28px; letter-spacing: .01em;\" id=\"v60Timer-brewmance\"\u003e0:00\u003c\/span\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"flex-basis: 100%; opacity: .6; font-size: 12px; line-height: 1.3; margin-top: 2px;\" id=\"v60WakeStatus-brewmance\"\u003eℹ️ Appuie sur \"Démarrer\" pour garder l'écran allumé.\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 8px; display: grid; gap: 10px;\"\u003e\n\u003cdiv style=\"border: 1px solid rgba(0,0,0,.18); border-radius: 12px; padding: 10px 12px;\" id=\"v60-card-1-brewmance\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; margin-bottom: 6px;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e0:00\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003ePhase 1 — Bloom\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 8px; flex-wrap: wrap; font-size: 12.5px; font-weight: 800;\"\u003e\n\u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\" id=\"v60-pill-1-brewmance\"\u003eVerser pendant 0:10s\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\"\u003eTotal 35 g\u003c\/span\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"border: 1px solid rgba(0,0,0,.18); border-radius: 12px; padding: 10px 12px;\" id=\"v60-card-2-brewmance\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; margin-bottom: 6px;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e0:30\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003ePhase 2\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 8px; flex-wrap: wrap; font-size: 12.5px; font-weight: 800;\"\u003e\n\u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\" id=\"v60-pill-2-brewmance\"\u003eVerser pendant 0:30s\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\"\u003eTotal 170 g\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12); opacity: .6;\"\u003e+135 g\u003c\/span\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"border: 1px solid rgba(0,0,0,.18); border-radius: 12px; padding: 10px 12px;\" id=\"v60-card-3-brewmance\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; margin-bottom: 6px;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e1:30\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003ePhase 3\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 8px; flex-wrap: wrap; font-size: 12.5px; font-weight: 800;\"\u003e\n\u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\" id=\"v60-pill-3-brewmance\"\u003eVerser pendant 0:15s\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\"\u003eTotal 225 g\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12); opacity: .6;\"\u003e+55 g\u003c\/span\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 12px; border-top: 1px solid rgba(0,0,0,.2); padding-top: 10px;\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e3:00\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003eTemps final écoulement complet\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 8px; padding: 8px 10px; border-radius: 8px; background: rgba(0,0,0,.04); border: 1px dashed rgba(0,0,0,.2); font-size: 12px; opacity: .6; line-height: 1.4;\"\u003e\n\u003cstrong\u003eℹ️ Astuce —\u003c\/strong\u003e Si le temps total est plus court, la mouture est probablement trop grosse. S'il est plus long, la mouture est probablement trop fine.\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/details\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 7 ========= --\u003e\u003csvg style=\"display: none;\"\u003e\n\u003cstyle\u003e\n  @keyframes v60PulsePhase {\n    0%   { transform: scale(1);    box-shadow: 0 0 0 0 rgba(200,169,126,.35); }\n    50%  { transform: scale(1.06); box-shadow: 0 0 0 10px rgba(200,169,126,0); }\n    100% { transform: scale(1);    box-shadow: 0 0 0 0 rgba(200,169,126,0); }\n  }\n  .v60-pulse {\n    animation: v60PulsePhase 700ms ease-out 1;\n    transform-origin: center;\n    will-change: transform;\n  }\n  @keyframes v60BlinkPill {\n    0%, 100% { opacity: 1; transform: scale(1); }\n    50%      { opacity: .22; transform: scale(1.03); }\n  }\n  .v60-pill-pour-active {\n    background: #ffe7b7 !important;\n    border: 2px solid #d2a44a !important;\n    color: #3b2a12 !important;\n    font-weight: 900 !important;\n    letter-spacing: .02em;\n    animation: v60BlinkPill 2500ms ease-in-out infinite;\n    box-shadow:\n      0 0 0 2px rgba(210,164,74,.18) inset,\n      0 10px 22px rgba(0,0,0,.12),\n      0 0 0 6px rgba(210,164,74,.10);\n  }\n  @media (prefers-reduced-motion: reduce) {\n    .v60-pill-pour-active { animation: none; }\n    .v60-pulse { animation: none; }\n  }\n\u003c\/style\u003e\n\u003cscript\u003e\n(function() {\n  var SUFFIX = '-brewmance';\n  var END_AT = 180;\n  var phases = [\n    { key: 1, t: 0,  pourLen: 10 },\n    { key: 2, t: 30, pourLen: 30 },\n    { key: 3, t: 90, pourLen: 15 }\n  ];\n  var latte = {\n    cardBg:     '#f6f1ea',\n    cardBorder: '#c8a97e',\n    pillBg:     '#eadfce'\n  };\n  var details  = document.getElementById('v60Details'    + SUFFIX);\n  var startBtn = document.getElementById('v60StartBtn'   + SUFFIX);\n  var stopBtn  = document.getElementById('v60StopBtn'    + SUFFIX);\n  var timerEl  = document.getElementById('v60Timer'      + SUFFIX);\n  var statusEl = document.getElementById('v60WakeStatus' + SUFFIX);\n  var pills = {\n    1: document.getElementById('v60-pill-1' + SUFFIX),\n    2: document.getElementById('v60-pill-2' + SUFFIX),\n    3: document.getElementById('v60-pill-3' + SUFFIX)\n  };\n  var cards = {\n    1: document.getElementById('v60-card-1' + SUFFIX),\n    2: document.getElementById('v60-card-2' + SUFFIX),\n    3: document.getElementById('v60-card-3' + SUFFIX)\n  };\n  function setCardActive(key) {\n    Object.keys(cards).forEach(function(k) {\n      var c = cards[k];\n      if (!c) return;\n      if (parseInt(k) === key) {\n        c.style.borderColor = latte.cardBorder;\n        c.style.background  = latte.cardBg;\n        c.style.boxShadow   = '0 0 0 2px rgba(200,169,126,.25) inset, 0 8px 22px rgba(200,169,126,.28)';\n      } else {\n        c.style.borderColor = 'rgba(0,0,0,.18)';\n        c.style.background  = 'transparent';\n        c.style.boxShadow   = 'none';\n      }\n    });\n  }\n  function setPillPhaseActive(key, doPulse) {\n    Object.keys(pills).forEach(function(k) {\n      var p = pills[k];\n      if (!p) return;\n      p.style.background  = 'rgba(0,0,0,.05)';\n      p.style.borderColor = 'rgba(0,0,0,.12)';\n      p.style.boxShadow   = 'none';\n      p.classList.remove('v60-pulse');\n    });\n    var pill = pills[key];\n    if (pill) {\n      pill.style.background  = latte.pillBg;\n      pill.style.borderColor = latte.cardBorder;\n      pill.style.boxShadow   = '0 0 0 2px rgba(200,169,126,.25) inset';\n      if (doPulse) {\n        pill.classList.remove('v60-pulse');\n        void pill.offsetWidth;\n        pill.classList.add('v60-pulse');\n      }\n    }\n  }\n  function resetPourPills() {\n    Object.values(pills).forEach(function(p) {\n      if (!p) return;\n      p.classList.remove('v60-pill-pour-active');\n    });\n  }\n  function setPourPillActive(key) {\n    resetPourPills();\n    if (!key) return;\n    var pill = pills[key];\n    if (pill) pill.classList.add('v60-pill-pour-active');\n  }\n  function clearAll() {\n    Object.values(cards).forEach(function(c) {\n      if (!c) return;\n      c.style.borderColor = 'rgba(0,0,0,.18)';\n      c.style.background  = 'transparent';\n      c.style.boxShadow   = 'none';\n    });\n    Object.values(pills).forEach(function(p) {\n      if (!p) return;\n      p.style.background  = 'rgba(0,0,0,.05)';\n      p.style.borderColor = 'rgba(0,0,0,.12)';\n      p.style.boxShadow   = 'none';\n      p.classList.remove('v60-pulse');\n      p.classList.remove('v60-pill-pour-active');\n    });\n  }\n  var wakeLock  = null;\n  var startTime = null;\n  var rafId     = null;\n  var lastPhaseKey = null;\n  var lastPourKey  = null;\n  function fmt(sec) {\n    sec = Math.max(0, Math.floor(sec));\n    var m = Math.floor(sec \/ 60);\n    var s = sec % 60;\n    return m + ':' + (s \u0026lt; 10 ? '0' : '') + s;\n  }\n  function getCurrentPhaseKey(elapsed) {\n    var current = phases[0].key;\n    for (var i = 0; i \u0026lt; phases.length; i++) if (elapsed \u0026gt;= phases[i].t) current = phases[i].key;\n    return current;\n  }\n  function getPourKey(elapsed) {\n    for (var i = phases.length - 1; i \u0026gt;= 0; i--) {\n      var p = phases[i];\n      if (elapsed \u0026gt;= p.t \u0026amp;\u0026amp; elapsed \u0026lt; (p.t + p.pourLen)) return p.key;\n    }\n    return null;\n  }\n  function enableWakeLock() {\n    if (!('wakeLock' in navigator)) {\n      statusEl.textContent = '⚠️ Ton navigateur ne supporte pas le mode écran allumé.';\n      return Promise.resolve();\n    }\n    return navigator.wakeLock.request('screen').then(function(wl) {\n      wakeLock = wl;\n      statusEl.textContent = '✅ Écran maintenu allumé pendant la recette.';\n      wakeLock.addEventListener('release', function() {\n        statusEl.textContent = 'ℹ️ Mode écran allumé relâché.';\n      });\n    }).catch(function() {\n      statusEl.textContent = '⚠️ Impossible d\\'activer le mode écran allumé.';\n      wakeLock = null;\n    });\n  }\n  function disableWakeLock() {\n    if (wakeLock) { wakeLock.release(); wakeLock = null; }\n  }\n  function setButtons(running) {\n    startBtn.disabled = running;\n    stopBtn.disabled  = !running;\n    stopBtn.style.opacity = running ? '1' : '.5';\n  }\n  function tick() {\n    var elapsed = (Date.now() - startTime) \/ 1000;\n    timerEl.textContent = fmt(elapsed);\n    var phaseKey = getCurrentPhaseKey(elapsed);\n    if (phaseKey !== lastPhaseKey) {\n      setCardActive(phaseKey);\n      setPillPhaseActive(phaseKey, lastPhaseKey !== null);\n      lastPhaseKey = phaseKey;\n    }\n    var pourKey = getPourKey(elapsed);\n    if (pourKey !== lastPourKey) {\n      setPourPillActive(pourKey);\n      lastPourKey = pourKey;\n    }\n    if (elapsed \u0026gt;= END_AT) { stopRecipe(true); return; }\n    rafId = requestAnimationFrame(tick);\n  }\n  function startRecipe() {\n    setButtons(true);\n    timerEl.textContent = '0:00';\n    lastPhaseKey = null;\n    lastPourKey  = null;\n    enableWakeLock().then(function() {\n      setCardActive(1);\n      setPillPhaseActive(1, false);\n      setPourPillActive(1);\n      lastPhaseKey = 1;\n      lastPourKey  = 1;\n      startTime = Date.now();\n      if (rafId) cancelAnimationFrame(rafId);\n      rafId = requestAnimationFrame(tick);\n    });\n  }\n  function stopRecipe(autoEnded) {\n    if (rafId) cancelAnimationFrame(rafId);\n    rafId     = null;\n    startTime = null;\n    disableWakeLock();\n    setButtons(false);\n    clearAll();\n    lastPhaseKey = null;\n    lastPourKey  = null;\n    if (autoEnded) {\n      statusEl.textContent = '✅ Recette terminée — écran libéré.';\n      timerEl.textContent  = fmt(END_AT);\n    } else {\n      statusEl.textContent = 'ℹ️ Recette arrêtée — écran libéré.';\n    }\n  }\n  startBtn.addEventListener('click', startRecipe);\n  stopBtn.addEventListener('click', function() { stopRecipe(false); });\n  details.addEventListener('toggle', function() { if (!details.open) stopRecipe(false); });\n  document.addEventListener('visibilitychange', function() {\n    if (document.visibilityState === 'visible' \u0026amp;\u0026amp; startTime \u0026amp;\u0026amp; !wakeLock) enableWakeLock();\n  });\n})();\n\u003c\/script\u003e\n\u003c\/svg\u003e","brand":"ZAB","offers":[{"title":"300g","offer_id":31773916430411,"sku":"CAF-BLE-BREW-300","price":23.0,"currency_code":"CAD","in_stock":true},{"title":"808g","offer_id":32176694984779,"sku":"CAF-BLE-BREW-808","price":56.0,"currency_code":"CAD","in_stock":true},{"title":"2268g (5lbs)","offer_id":31773916463179,"sku":"CAF-BLE-BREW-2268","price":135.0,"currency_code":"CAD","in_stock":true},{"title":"100g","offer_id":51434082009397,"sku":"CAF-BLE-BREW-100","price":13.0,"currency_code":"CAD","in_stock":true},{"title":"Bucket - 5lbs (Livraison locale seulement)","offer_id":52569815941429,"sku":"CAF-BLE-BREW-BUCK-5","price":160.0,"currency_code":"CAD","in_stock":true},{"title":"Bucket - 15lbs (Livraison locale seulement)","offer_id":52569815974197,"sku":"CAF-BLE-BREW-BUCK-15","price":430.0,"currency_code":"CAD","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/2716\/1842\/files\/brewmance-300g.jpg?v=1756855352"},{"product_id":"boite-cafe-introduction-zab","title":"Boîte Café - Introduction Zab","description":"\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 1 : EN-TÊTE BOÎTE\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto; border: 2px solid var(--product-box-background, #000); border-radius: 12px; overflow: hidden;\"\u003e\n\u003cdiv style=\"padding: 10px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center;\"\u003eBoîte Introduction — 3 × 300 g\u003c\/div\u003e\n\u003cdiv style=\"padding: 16px 14px; font-size: 14px; line-height: 1.6; text-align: center; background: transparent;\"\u003e\n\u003cp style=\"margin: 0 0 10px 0;\"\u003eCette boîte te permet de découvrir nos cafés les plus vendus. Que ce soit pour tes breuvages à base de lait ou pour ton café filtre, cette boîte t’invite à entrer dans l'univers Zab avec nos classiques.\u003c\/p\u003e\n\u003cp style=\"margin: 0;\"\u003eEt pour pimenter ton quotidien, on te lance le défi de diminuer la quantité de lait que tu utilises habituellement dans tes cafés. Tu pourrais ainsi découvrir des arômes surprenants qui pourraient changer tes habitudes à tout jamais!\u003c\/p\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 1 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 2 : CAFÉS INCLUS\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto;\"\u003e\n\u003cdiv style=\"padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center; border-radius: 12px 12px 0 0;\"\u003eCafés inclus\u003c\/div\u003e\n\u003cdiv style=\"border: 2px solid var(--product-box-background, #000); border-top: none; border-radius: 0 0 12px 12px; background: transparent; overflow: hidden;\"\u003e\n\u003c!-- Joyeux Roger --\u003e\n\u003cdiv style=\"padding: 14px 16px; border-bottom: 1px solid rgba(0,0,0,.12);\"\u003e\n\u003cdiv style=\"font-weight: 900; font-size: 20px; margin-bottom: 6px;\"\u003e\n\u003ca href=\"https:\/\/zabcafe.com\/collections\/cafes\/products\/joyeux-roger\" title=\"Joyeux Roger\" rel=\"noopener\" style=\"color: #000; text-decoration: underline;\" target=\"_blank\"\u003eJoyeux Roger\u003c\/a\u003e\u003cspan style=\"font-weight: 400; opacity: .45; font-size: 14px;\"\u003e | 300g\u003c\/span\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"font-size: 11px; font-weight: bold; text-transform: uppercase; letter-spacing: .08em; opacity: .5; margin-bottom: 4px;\"\u003eNotes de dégustation\u003c\/div\u003e\n\u003cdiv style=\"font-size: 13px; font-weight: 800; text-transform: uppercase; letter-spacing: .04em; margin-bottom: 10px;\"\u003eBROWNIE + NOISETTE + CRÉMEUX\u003c\/div\u003e\n\u003cdiv style=\"font-size: 13px; line-height: 1.6; opacity: .8;\"\u003eNotre café brésilien classique et indétrônable offre une tasse équilibrée, sucrée, réconfortante et accessible. Le résultat d'un partenariat à l'origine de longue date et le café préféré de tous.tes.\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c!-- Bon Matin --\u003e\n\u003cdiv style=\"padding: 14px 16px; border-bottom: 1px solid rgba(0,0,0,.12);\"\u003e\n\u003cdiv style=\"font-weight: 900; font-size: 20px; margin-bottom: 6px;\"\u003e\n\u003ca href=\"https:\/\/zabcafe.com\/collections\/cafes\/products\/bon-matin\" title=\"Bon Matin\" rel=\"noopener\" style=\"color: #000; text-decoration: underline;\" target=\"_blank\"\u003eBon Matin\u003c\/a\u003e\u003cspan style=\"font-weight: 400; opacity: .45; font-size: 14px;\"\u003e | 300g\u003c\/span\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"font-size: 11px; font-weight: bold; text-transform: uppercase; letter-spacing: .08em; opacity: .5; margin-bottom: 4px;\"\u003eNotes de dégustation\u003c\/div\u003e\n\u003cdiv style=\"font-size: 13px; font-weight: 800; text-transform: uppercase; letter-spacing: .04em; margin-bottom: 10px;\"\u003ePACANE GRILLÉE + CHOCOLAT NOIR + CARAMEL ÉCOSSAIS\u003c\/div\u003e\n\u003cdiv style=\"font-size: 13px; line-height: 1.6; opacity: .8;\"\u003eNotre interprétation d'une torréfaction foncée (brésilien Joyeux Roger), mettant en valeur une texture crémeuse et un goût intense, idéale pour accompagner le lait. C'est notre café nostalgique qui offre une belle amertume et une acidité modérée. Un vrai réveille-matin dans ta tasse!\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c!-- Brewmance --\u003e\n\u003cdiv style=\"padding: 14px 16px;\"\u003e\n\u003cdiv style=\"font-weight: 900; font-size: 20px; margin-bottom: 6px;\"\u003e\n\u003ca href=\"https:\/\/zabcafe.com\/collections\/cafes\/products\/brewmance-1\" title=\"Brewmance\" rel=\"noopener\" style=\"color: #000; text-decoration: underline;\" target=\"_blank\"\u003eBrewmance\u003c\/a\u003e\u003cspan style=\"font-weight: 400; opacity: .45; font-size: 14px;\"\u003e | 300g\u003c\/span\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"font-size: 11px; font-weight: bold; text-transform: uppercase; letter-spacing: .08em; opacity: .5; margin-bottom: 4px;\"\u003eNotes de dégustation\u003c\/div\u003e\n\u003cdiv style=\"font-size: 13px; font-weight: 800; text-transform: uppercase; letter-spacing: .04em; margin-bottom: 10px;\"\u003eFRUITÉ + CHOCOLATÉ + CRÉMEUX\u003c\/div\u003e\n\u003cdiv style=\"font-size: 13px; line-height: 1.6; opacity: .8;\"\u003eLe Brewmance (brésilien Joyeux Roger + éthiopien Tariku) est notre mélange qui allie le réconfort du chocolat et des noix à la touche funky de fruits bien mûrs. C'est un café du quotidien, mais avec juste assez de notes fruitées pour éveiller la curiosité.\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 2 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e","brand":"ZAB","offers":[{"title":"Default Title","offer_id":32018737102923,"sku":"CAF-BOI-TORR-INTR","price":63.25,"currency_code":"CAD","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/2716\/1842\/files\/boites-classique-fermee_53343e76-9ff0-4122-9927-234ca5918156.jpg?v=1756855653"},{"product_id":"boite-decouvertre-filtre-pour-over-chemex","title":"Boîte Café - Choix du Torréfacteur","description":"\u003cp\u003e \u003c\/p\u003e\n\n\u003c!-- =========================================================\n  SECTION 1 : EN-TÊTE BOÎTE\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto; border: 2px solid var(--product-box-background, #000); border-radius: 12px; overflow: hidden;\"\u003e\n  \u003cdiv style=\"padding: 10px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center;\"\u003eBoîte Choix du torréfacteur — 3 × 300 g\u003c\/div\u003e\n  \u003cdiv style=\"padding: 16px 14px; font-size: 14px; line-height: 1.6; text-align: center; background: transparent;\"\u003e\n    \u003cp style=\"margin: 0 0 10px 0;\"\u003eCette boîte te permet de découvrir nos cafés « coups de cœur » du moment. On doit l'avouer : on trippe sur le café. Que ce soit en filtre, en extraction manuelle ou dans ton breuvage à base de lait, tu découvriras tout le caractère propre à chaque terroir!\u003c\/p\u003e\n    \u003cp style=\"margin: 0;\"\u003eNote : Certains cafés dans cette boîte pourraient te faire vivre une expérience différente avec le lait. Si tu préfères des breuvages plus classiques, cette boîte n'est peut-être pas la bonne pour toi.\u003c\/p\u003e\n  \u003c\/div\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 1 ========= --\u003e\n\n\u003cp\u003e \u003c\/p\u003e\n\n\u003c!-- =========================================================\n  NOTE DE BAS DE PAGE\n========================================================= --\u003e\n\u003cdiv style=\"padding: 10px 14px; border-radius: 8px; background: rgba(0,0,0,.04); border: 1px dashed rgba(0,0,0,.2); font-size: 12px; opacity: .7; line-height: 1.5;\"\u003e\n  \u003cstrong\u003eÀ noter —\u003c\/strong\u003e La boîte contient 3 sacs (300g) au choix du torréfacteur. La boîte ne contient pas de café décaféiné et il est impossible de demander un café en particulier. Pour choisir tes cafés, commande-les à l'unité.\n\u003c\/div\u003e\n\n\u003cp\u003e \u003c\/p\u003e","brand":"ZAB","offers":[{"title":"Default Title","offer_id":32018737856587,"sku":"CAF-BOI-TORR-CHOI","price":73.25,"currency_code":"CAD","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/2716\/1842\/files\/boites-choix-du-torrefacteur-fermee.jpg?v=1756855415"},{"product_id":"bon-matin","title":"BON MATIN","description":"\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 1 : NOTES DE DÉGUSTATION\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto; border: 2px solid var(--product-box-background, #000); border-radius: 12px; overflow: hidden;\"\u003e\n\u003cdiv style=\"padding: 10px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center;\"\u003eNotes de dégustation\u003c\/div\u003e\n\u003cdiv style=\"padding: 16px 14px; font-weight: 900; text-transform: uppercase; font-size: 28px; letter-spacing: .05em; text-align: center; background: transparent;\"\u003ePACANE GRILLÉE + CHOCOLAT NOIR + CARAMEL ÉCOSSAIS\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 1 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION CAROUSEL : IMAGES\n========================================================= --\u003e\n\u003cdiv id=\"carousel-sancoffee\" style=\"position: relative; width: 100%; padding-bottom: 33.33%; height: 0; overflow: hidden; border-radius: 8px;\"\u003e\n\u003cimg class=\"carousel-img-sancoffee\" src=\"https:\/\/cdn.shopify.com\/s\/files\/1\/2716\/1842\/files\/San-Coffee-image-groupe.jpg?v=1781785600\" alt=\"Sancoffee - groupe\" style=\"position: absolute; top: 0; left: 0; width: 100%; height: 100%; object-fit: cover; border-radius: 8px; opacity: 1; transition: opacity .6s ease;\"\u003e\n\u003cimg class=\"carousel-img-sancoffee\" src=\"https:\/\/cdn.shopify.com\/s\/files\/1\/2716\/1842\/files\/San-Coffee-image-warehouse.jpg?v=1781785600\" alt=\"Sancoffee - entrepôt\" style=\"position: absolute; top: 0; left: 0; width: 100%; height: 100%; object-fit: cover; border-radius: 8px; opacity: 0; transition: opacity .6s ease;\"\u003e\n\u003cimg class=\"carousel-img-sancoffee\" src=\"https:\/\/cdn.shopify.com\/s\/files\/1\/2716\/1842\/files\/San-Coffee-image-ferme.jpg?v=1781785600\" alt=\"Sancoffee - ferme\" style=\"position: absolute; top: 0; left: 0; width: 100%; height: 100%; object-fit: cover; border-radius: 8px; opacity: 0; transition: opacity .6s ease;\"\u003e\n\n\u003cbutton type=\"button\" id=\"carousel-prev-sancoffee\" aria-label=\"Image précédente\" style=\"position: absolute; top: 50%; left: 8px; transform: translateY(-50%); z-index: 3; cursor: pointer; border: none; background: rgba(0,0,0,.25); color: #fff; font-weight: 400; width: 28px; height: 28px; border-radius: 999px; font-size: 15px; line-height: 1; display: flex; align-items: center; justify-content: center; opacity: .55;\"\u003e‹\u003c\/button\u003e\n\u003cbutton type=\"button\" id=\"carousel-next-sancoffee\" aria-label=\"Image suivante\" style=\"position: absolute; top: 50%; right: 8px; transform: translateY(-50%); z-index: 3; cursor: pointer; border: none; background: rgba(0,0,0,.25); color: #fff; font-weight: 400; width: 28px; height: 28px; border-radius: 999px; font-size: 15px; line-height: 1; display: flex; align-items: center; justify-content: center; opacity: .55;\"\u003e›\u003c\/button\u003e\n\n\u003cdiv id=\"carousel-dots-sancoffee\" style=\"position: absolute; bottom: 10px; left: 0; right: 0; z-index: 3; display: flex; gap: 8px; align-items: center; justify-content: center;\"\u003e\n\u003cspan class=\"carousel-dot-sancoffee\" data-i=\"0\" style=\"cursor: pointer; width: 10px; height: 10px; border-radius: 999px; background: #fff; border: 1px solid rgba(0,0,0,.4); opacity: 1;\"\u003e\u003c\/span\u003e\n\u003cspan class=\"carousel-dot-sancoffee\" data-i=\"1\" style=\"cursor: pointer; width: 10px; height: 10px; border-radius: 999px; background: #fff; border: 1px solid rgba(0,0,0,.4); opacity: .5;\"\u003e\u003c\/span\u003e\n\u003cspan class=\"carousel-dot-sancoffee\" data-i=\"2\" style=\"cursor: pointer; width: 10px; height: 10px; border-radius: 999px; background: #fff; border: 1px solid rgba(0,0,0,.4); opacity: .5;\"\u003e\u003c\/span\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION CAROUSEL ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 2 : APPROVISIONNEMENT\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto;\"\u003e\n\u003cdiv style=\"padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center; border-radius: 12px 12px 0 0;\"\u003eApprovisionnement\u003c\/div\u003e\n\u003ctable style=\"width: 100%; border-collapse: collapse; background: transparent;\" cellspacing=\"1\" cellpadding=\"1\" border=\"3\"\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd style=\"width: 20%;\"\u003eORIGINE\u003c\/td\u003e\n\u003ctd\u003eCampo das Vertentes, Minas Gerais, Brésil\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePRODUCTEUR.RICE\u003c\/td\u003e\n\u003ctd\u003ePlusieurs producteur.rices de Sancoffee\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eVARIÉTÉS\u003c\/td\u003e\n\u003ctd\u003eCatucai jaune, Mundo Novo, Catuai rouge, Topázio\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePROCÉDÉ\u003c\/td\u003e\n\u003ctd\u003eNaturel\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eALTITUDE\u003c\/td\u003e\n\u003ctd\u003e900 – 1200 m\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePARTENAIRES\u003c\/td\u003e\n\u003ctd\u003eCrop to Cup\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eVOLUME ACHETÉ\u003c\/td\u003e\n\u003ctd\u003e96 600 kg\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eFAB\u003c\/td\u003e\n\u003ctd\u003e2,40 $ US\/LB\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePRIX LIVRÉ\u003c\/td\u003e\n\u003ctd\u003e4,55 $ CAD\/LB\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eRELATION\u003c\/td\u003e\n\u003ctd\u003e2 ans\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003c\/tbody\u003e\n\u003c\/table\u003e\n\u003cp style=\"margin: 6px 0 0 0; font-size: 13px;\"\u003e \u003c\/p\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 2 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 3 : INFORMATIONS SUR LE CAFÉ\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto;\"\u003e\n\u003cdiv style=\"padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center; border-radius: 12px 12px 0 0;\"\u003eInformations sur le café\u003c\/div\u003e\n\u003cdiv style=\"border: 2px solid var(--product-box-background, #000); border-top: none; border-radius: 0 0 12px 12px; padding: 16px 14px; background: transparent;\"\u003e\n\u003cp style=\"margin: 0 0 12px 0; text-align: justify;\"\u003eLe Bon Matin, c'est notre Joyeux Roger mais avec une torréfaction un peu plus poussée. La caramélisation des sucres est accentuée pour lui donner un goût plus grillé.\u003c\/p\u003e\n\u003cp style=\"margin: 0 0 12px 0; text-align: justify;\"\u003eSancoffee est une coopérative indépendante certifiée B-Corp, originaire de la région de Campo das Vertentes, dans l'État de Minas Gerais, au Brésil. Sancoffee regroupe 20 fermes membres et soutient 600 petit.tes producteur.rices, partageant une vision collective axée sur la durabilité, la qualité et l'impact communautaire. La coopérative allie fièrement sa riche tradition caféière, remontant à 1860, à des initiatives modernes favorisant la préservation de l'environnement et le progrès social. Pour en apprendre plus, visite leur \u003ca rel=\"noopener\" href=\"https:\/\/sancoffee.com\/\" target=\"_blank\"\u003e\u003cstrong\u003esite web\u003c\/strong\u003e\u003c\/a\u003e.\u003c\/p\u003e\n\u003cp style=\"margin: 0 0 12px 0; text-align: justify;\"\u003eDes programmes de la coopérative comme Beyond Borders offrent aux petit.tes producteur.rices des outils et un soutien technique, leur permettant de gagner en reconnaissance et de valoriser leur travail. Grâce à des ateliers éducatifs et des formations pour la jeunesse, Sancoffee investit dans l'avenir de ses communautés, favorisant une croissance durable et des opportunités pour tous.\u003c\/p\u003e\n\u003cp style=\"margin: 0 0 16px 0; text-align: justify;\"\u003eSancoffee a atteint la neutralité carbone en 2020, devenant un pionnier de la production de café respectueuse de l'environnement. Ses efforts incluent la restauration de la biodiversité, la plantation d'arbres indigènes et la recherche pour réduire l'empreinte carbone au niveau des exploitations agricoles.\u003c\/p\u003e\n\u003cdiv class=\"logos-sancoffee\" style=\"display: flex; gap: 20px; align-items: center; justify-content: space-between; flex-wrap: wrap; padding-top: 16px; border-top: 1px solid rgba(0,0,0,.12);\"\u003e\n\u003ca rel=\"noopener\" href=\"https:\/\/sancoffee.com\/\" target=\"_blank\" style=\"display: inline-block;\"\u003e\n\u003cimg src=\"https:\/\/cdn.shopify.com\/s\/files\/1\/2716\/1842\/files\/san_coffee_logo.svg?v=1781786545\" alt=\"Sancoffee\" style=\"height: 80px; width: auto;\"\u003e\n\u003c\/a\u003e\n\u003cdiv class=\"logos-certs-sancoffee\" style=\"display: flex; gap: 20px; align-items: center; flex-wrap: wrap;\"\u003e\n\u003cimg src=\"https:\/\/cdn.shopify.com\/s\/files\/1\/2716\/1842\/files\/bcorp-logo.webp?v=1781785759\" alt=\"Certification B-Corp\" style=\"height: 80px; width: auto;\"\u003e\n\u003cimg src=\"https:\/\/cdn.shopify.com\/s\/files\/1\/2716\/1842\/files\/For-Profit-Sus-2024-Stone_white.webp?v=1781785759\" alt=\"Sustainability Award 2024\" style=\"height: 80px; width: auto;\"\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 3 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 5 : EN GROS\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto;\"\u003e\n\u003cdiv style=\"border: 2px solid var(--product-box-background, #000); border-radius: 12px; overflow: hidden;\"\u003e\n\u003cdiv style=\"padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center;\"\u003eEn gros\u003c\/div\u003e\n\u003cdiv style=\"padding: 16px 14px; background: transparent;\"\u003e\n\u003cp style=\"margin: 0;\"\u003eTu veux commander deux sacs de 5 lbs ou plus? Visite notre section \u003ca rel=\"noopener\" href=\"https:\/\/zabcafe.com\/products\/bon-matin-en-gros\" target=\"_blank\"\u003e\u003cstrong\u003eEN GROS\u003c\/strong\u003e\u003c\/a\u003e pour profiter d'un rabais de volume!\u003c\/p\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 5 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 4 : PARAMÈTRES D'EXTRACTION — ESPRESSO\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto;\"\u003e\n\u003cdetails open=\"\" style=\"border: 2px solid var(--product-box-background, #000); border-radius: 12px; overflow: hidden; margin: 0 0 12px 0; background: transparent;\"\u003e\n\u003csummary style=\"cursor: pointer; list-style: none; padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center;\"\u003eEspresso — paramètres recommandés\u003c\/summary\u003e\n\u003cdiv style=\"padding: 12px 14px; background: transparent;\"\u003e\n\u003ctable style=\"width: 100%; border-collapse: collapse; background: transparent;\"\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd style=\"padding: 10px 0; font-weight: 800; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003eCafé moulu\u003c\/td\u003e\n\u003ctd style=\"padding: 10px 0; text-align: right; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003e17,5 g\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd style=\"padding: 10px 0; font-weight: 800; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003eCafé dans la tasse\u003c\/td\u003e\n\u003ctd style=\"padding: 10px 0; text-align: right; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003e32 g\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd style=\"padding: 10px 0; font-weight: 800;\"\u003eTemps d'extraction\u003c\/td\u003e\n\u003ctd style=\"padding: 10px 0; text-align: right;\"\u003e30 sec\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003c\/tbody\u003e\n\u003c\/table\u003e\n\u003cdiv style=\"margin-top: 10px; padding: 8px 10px; border-radius: 8px; background: rgba(0,0,0,.04); border: 1px dashed rgba(0,0,0,.2); font-size: 12px; opacity: .7; line-height: 1.4;\"\u003e\n\u003cstrong\u003eÀ noter —\u003c\/strong\u003e\u003cspan\u003e Recette optimisée pour un panier de \u003c\/span\u003e\u003cstrong\u003e18 g\u003c\/strong\u003e\u003cspan\u003e. Ajuster légèrement la mouture pour atteindre 32 secondes d'extraction.\u003c\/span\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/details\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 4 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 6 : PARAMÈTRES FELLOW AIDEN\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto;\"\u003e\n\u003cdiv style=\"border: 2px solid var(--product-box-background, #000); border-radius: 12px; overflow: hidden;\"\u003e\n\u003cdiv style=\"padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center;\"\u003eParamètres pour la Fellow Aiden\u003c\/div\u003e\n\u003cdiv style=\"padding: 16px 14px; background: transparent;\"\u003e\n\u003cp style=\"margin: 0;\"\u003e\u003ca rel=\"noopener\" href=\"https:\/\/brew.link\/p\/seW0\" target=\"_blank\"\u003eTélécharge le profil Bon Matin pour la machine Aiden de Fellow!\u003c\/a\u003e\u003c\/p\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 6 ========= --\u003e\n\n\u003cp\u003e \u003c\/p\u003e\n\n\u003c!-- =========================================================\n  SECTION 7 : V60\n========================================================= --\u003e\n\n\u003cdiv style=\"width: 100%; margin: 0 auto;\"\u003e\n  \u003cdetails id=\"v60Details-bonmatin\" open=\"\" style=\"border: 2px solid var(--product-box-background, #000); border-radius: 12px; overflow: hidden; margin: 0 0 12px 0; background: rgba(255,255,255,0.5);\"\u003e\n    \u003csummary style=\"cursor: pointer; list-style: none; padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center;\"\u003eV60 – Recette\u003c\/summary\u003e\n\n    \u003cdiv style=\"padding: 12px 14px;\"\u003e\n      \u003cdiv style=\"padding: 10px 0 10px; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003e\n        \u003cdiv style=\"font-weight: 900; font-size: 16px;\"\u003eRatio 1:15\u003c\/div\u003e\n        \u003cdiv style=\"margin-top: 4px; opacity: .7; font-size: 13px;\"\u003e15 g in – 225 g out\u003c\/div\u003e\n        \u003cdiv style=\"margin-top: 6px; font-size: 13px;\"\u003e\n\u003cstrong\u003eTempérature de l'eau :\u003c\/strong\u003e 85 °C\u003c\/div\u003e\n      \u003c\/div\u003e\n\n      \u003cdiv style=\"display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; padding: 10px 0 8px;\"\u003e\n        \u003cdiv style=\"display: flex; gap: 8px; align-items: center; flex-wrap: wrap;\"\u003e\n          \u003cbutton style=\"cursor: pointer; border: 2px solid var(--product-box-background, #000); background: var(--product-box-background, #000); color: var(--product-box-text, #fff); font-weight: 900; padding: 8px 10px; border-radius: 10px; text-transform: uppercase; letter-spacing: .02em; font-size: 12px;\" type=\"button\" id=\"v60StartBtn-bonmatin\"\u003eDémarrer\u003c\/button\u003e\n          \u003cbutton style=\"cursor: pointer; border: 2px solid var(--product-box-background, #000); background: var(--product-box-text, #fff); color: var(--product-box-background, #000); font-weight: 900; padding: 8px 10px; border-radius: 10px; text-transform: uppercase; letter-spacing: .02em; font-size: 12px; opacity: .5;\" disabled type=\"button\" id=\"v60StopBtn-bonmatin\"\u003eStop\u003c\/button\u003e\n        \u003c\/div\u003e\n        \u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; line-height: 1;\"\u003e\n          \u003cspan style=\"opacity: .70; font-size: 12px; font-weight: 800; text-transform: uppercase; letter-spacing: .04em;\"\u003eTimer\u003c\/span\u003e\n          \u003cspan style=\"font-weight: 950; font-size: 28px; letter-spacing: .01em;\" id=\"v60Timer-bonmatin\"\u003e0:00\u003c\/span\u003e\n        \u003c\/div\u003e\n        \u003cdiv style=\"flex-basis: 100%; opacity: .6; font-size: 12px; line-height: 1.3; margin-top: 2px;\" id=\"v60WakeStatus-bonmatin\"\u003eℹ️ Appuie sur \"Démarrer\" pour garder l'écran allumé.\u003c\/div\u003e\n      \u003c\/div\u003e\n\n      \u003cdiv style=\"margin-top: 8px; display: grid; gap: 10px;\"\u003e\n\n        \u003cdiv style=\"border: 1px solid rgba(0,0,0,.18); border-radius: 12px; padding: 10px 12px;\" id=\"v60-card-1-bonmatin\"\u003e\n          \u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; margin-bottom: 6px;\"\u003e\n            \u003cdiv style=\"font-weight: 900;\"\u003e0:00\u003c\/div\u003e\n            \u003cdiv style=\"font-weight: 900;\"\u003ePhase 1 — Bloom\u003c\/div\u003e\n          \u003c\/div\u003e\n          \u003cdiv style=\"display: flex; gap: 8px; flex-wrap: wrap; font-size: 12.5px; font-weight: 800;\"\u003e\n            \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\" id=\"v60-pill-1-bonmatin\"\u003eVerser pendant 0:10s\u003c\/span\u003e\n            \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\"\u003eTotal 35 g\u003c\/span\u003e\n          \u003c\/div\u003e\n        \u003c\/div\u003e\n\n        \u003cdiv style=\"border: 1px solid rgba(0,0,0,.18); border-radius: 12px; padding: 10px 12px;\" id=\"v60-card-2-bonmatin\"\u003e\n          \u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; margin-bottom: 6px;\"\u003e\n            \u003cdiv style=\"font-weight: 900;\"\u003e0:30\u003c\/div\u003e\n            \u003cdiv style=\"font-weight: 900;\"\u003ePhase 2\u003c\/div\u003e\n          \u003c\/div\u003e\n          \u003cdiv style=\"display: flex; gap: 8px; flex-wrap: wrap; font-size: 12.5px; font-weight: 800;\"\u003e\n            \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\" id=\"v60-pill-2-bonmatin\"\u003eVerser pendant 0:50s\u003c\/span\u003e\n            \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\"\u003eTotal 225 g\u003c\/span\u003e\n            \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12); opacity: .6;\"\u003e+190 g\u003c\/span\u003e\n          \u003c\/div\u003e\n        \u003c\/div\u003e\n\n      \u003c\/div\u003e\n\n      \u003cdiv style=\"margin-top: 12px; border-top: 1px solid rgba(0,0,0,.2); padding-top: 10px;\"\u003e\n        \u003cdiv style=\"display: flex; gap: 10px; align-items: baseline;\"\u003e\n          \u003cdiv style=\"font-weight: 900;\"\u003e2:40\u003c\/div\u003e\n          \u003cdiv style=\"font-weight: 900;\"\u003eTemps final écoulement complet\u003c\/div\u003e\n        \u003c\/div\u003e\n        \u003cdiv style=\"margin-top: 8px; padding: 8px 10px; border-radius: 8px; background: rgba(0,0,0,.04); border: 1px dashed rgba(0,0,0,.2); font-size: 12px; opacity: .6; line-height: 1.4;\"\u003e\n          \u003cstrong\u003eℹ️ Astuce —\u003c\/strong\u003e Si le temps total est plus court, la mouture est probablement trop grosse. S'il est plus long, la mouture est probablement trop fine.\n        \u003c\/div\u003e\n      \u003c\/div\u003e\n    \u003c\/div\u003e\n  \u003c\/details\u003e\n\u003c\/div\u003e\n\n\u003c!-- ========= FIN SECTION 7 ========= --\u003e\n\n\u003csvg style=\"display: none;\"\u003e\n\u003cstyle\u003e\n  @keyframes v60PulsePhase {\n    0%   { transform: scale(1);    box-shadow: 0 0 0 0 rgba(200,169,126,.35); }\n    50%  { transform: scale(1.06); box-shadow: 0 0 0 10px rgba(200,169,126,0); }\n    100% { transform: scale(1);    box-shadow: 0 0 0 0 rgba(200,169,126,0); }\n  }\n  .v60-pulse {\n    animation: v60PulsePhase 700ms ease-out 1;\n    transform-origin: center;\n    will-change: transform;\n  }\n  @keyframes v60BlinkPill {\n    0%, 100% { opacity: 1; transform: scale(1); }\n    50%      { opacity: .22; transform: scale(1.03); }\n  }\n  .v60-pill-pour-active {\n    background: #ffe7b7 !important;\n    border: 2px solid #d2a44a !important;\n    color: #3b2a12 !important;\n    font-weight: 900 !important;\n    letter-spacing: .02em;\n    animation: v60BlinkPill 2500ms ease-in-out infinite;\n    box-shadow:\n      0 0 0 2px rgba(210,164,74,.18) inset,\n      0 10px 22px rgba(0,0,0,.12),\n      0 0 0 6px rgba(210,164,74,.10);\n  }\n  @media (prefers-reduced-motion: reduce) {\n    .v60-pill-pour-active { animation: none; }\n    .v60-pulse { animation: none; }\n  }\n  @media (max-width: 600px) {\n    .logos-sancoffee { justify-content: center !important; gap: 16px !important; }\n    .logos-sancoffee \u003e a { width: 100% !important; text-align: center !important; }\n    .logos-certs-sancoffee { width: 100% !important; justify-content: center !important; }\n  }\n\u003c\/style\u003e\n\u003cscript\u003e\n(function() {\n  \/* ===== CARROUSEL ===== *\/\n  var cSuffix = '-sancoffee';\n  var cImgs  = document.querySelectorAll('.carousel-img' + cSuffix);\n  var cDots  = document.querySelectorAll('.carousel-dot' + cSuffix);\n  var cPrev  = document.getElementById('carousel-prev' + cSuffix);\n  var cNext  = document.getElementById('carousel-next' + cSuffix);\n  var cIndex = 0;\n  var cTimer = null;\n  function cShow(i) {\n    cIndex = (i + cImgs.length) % cImgs.length;\n    for (var k = 0; k \u003c cImgs.length; k++) cImgs[k].style.opacity = (k === cIndex) ? '1' : '0';\n    for (var d = 0; d \u003c cDots.length; d++) cDots[d].style.opacity = (d === cIndex) ? '1' : '.5';\n  }\n  function cStart() { cStop(); cTimer = setInterval(function() { cShow(cIndex + 1); }, 5000); }\n  function cStop() { if (cTimer) { clearInterval(cTimer); cTimer = null; } }\n  if (cPrev) cPrev.addEventListener('click', function() { cShow(cIndex - 1); cStart(); });\n  if (cNext) cNext.addEventListener('click', function() { cShow(cIndex + 1); cStart(); });\n  for (var dd = 0; dd \u003c cDots.length; dd++) {\n    (function(node) {\n      node.addEventListener('click', function() { cShow(parseInt(node.getAttribute('data-i'), 10)); cStart(); });\n    })(cDots[dd]);\n  }\n  cShow(0);\n  cStart();\n\n  \/* ===== TIMER V60 ===== *\/\n  var SUFFIX = '-bonmatin';\n  var END_AT = 160;\n  var phases = [\n    { key: 1, t: 0,  pourLen: 10 },\n    { key: 2, t: 30, pourLen: 50 }\n  ];\n  var latte = {\n    cardBg:     '#f6f1ea',\n    cardBorder: '#c8a97e',\n    pillBg:     '#eadfce'\n  };\n  var details  = document.getElementById('v60Details'    + SUFFIX);\n  var startBtn = document.getElementById('v60StartBtn'   + SUFFIX);\n  var stopBtn  = document.getElementById('v60StopBtn'    + SUFFIX);\n  var timerEl  = document.getElementById('v60Timer'      + SUFFIX);\n  var statusEl = document.getElementById('v60WakeStatus' + SUFFIX);\n  var pills = {\n    1: document.getElementById('v60-pill-1' + SUFFIX),\n    2: document.getElementById('v60-pill-2' + SUFFIX)\n  };\n  var cards = {\n    1: document.getElementById('v60-card-1' + SUFFIX),\n    2: document.getElementById('v60-card-2' + SUFFIX)\n  };\n  function setCardActive(key) {\n    Object.keys(cards).forEach(function(k) {\n      var c = cards[k];\n      if (!c) return;\n      if (parseInt(k) === key) {\n        c.style.borderColor = latte.cardBorder;\n        c.style.background  = latte.cardBg;\n        c.style.boxShadow   = '0 0 0 2px rgba(200,169,126,.25) inset, 0 8px 22px rgba(200,169,126,.28)';\n      } else {\n        c.style.borderColor = 'rgba(0,0,0,.18)';\n        c.style.background  = 'transparent';\n        c.style.boxShadow   = 'none';\n      }\n    });\n  }\n  function setPillPhaseActive(key, doPulse) {\n    Object.keys(pills).forEach(function(k) {\n      var p = pills[k];\n      if (!p) return;\n      p.style.background  = 'rgba(0,0,0,.05)';\n      p.style.borderColor = 'rgba(0,0,0,.12)';\n      p.style.boxShadow   = 'none';\n      p.classList.remove('v60-pulse');\n    });\n    var pill = pills[key];\n    if (pill) {\n      pill.style.background  = latte.pillBg;\n      pill.style.borderColor = latte.cardBorder;\n      pill.style.boxShadow   = '0 0 0 2px rgba(200,169,126,.25) inset';\n      if (doPulse) {\n        pill.classList.remove('v60-pulse');\n        void pill.offsetWidth;\n        pill.classList.add('v60-pulse');\n      }\n    }\n  }\n  function resetPourPills() {\n    Object.values(pills).forEach(function(p) {\n      if (!p) return;\n      p.classList.remove('v60-pill-pour-active');\n    });\n  }\n  function setPourPillActive(key) {\n    resetPourPills();\n    if (!key) return;\n    var pill = pills[key];\n    if (pill) pill.classList.add('v60-pill-pour-active');\n  }\n  function clearAll() {\n    Object.values(cards).forEach(function(c) {\n      if (!c) return;\n      c.style.borderColor = 'rgba(0,0,0,.18)';\n      c.style.background  = 'transparent';\n      c.style.boxShadow   = 'none';\n    });\n    Object.values(pills).forEach(function(p) {\n      if (!p) return;\n      p.style.background  = 'rgba(0,0,0,.05)';\n      p.style.borderColor = 'rgba(0,0,0,.12)';\n      p.style.boxShadow   = 'none';\n      p.classList.remove('v60-pulse');\n      p.classList.remove('v60-pill-pour-active');\n    });\n  }\n  var wakeLock  = null;\n  var startTime = null;\n  var rafId     = null;\n  var lastPhaseKey = null;\n  var lastPourKey  = null;\n  function fmt(sec) {\n    sec = Math.max(0, Math.floor(sec));\n    var m = Math.floor(sec \/ 60);\n    var s = sec % 60;\n    return m + ':' + (s \u003c 10 ? '0' : '') + s;\n  }\n  function getCurrentPhaseKey(elapsed) {\n    var current = phases[0].key;\n    for (var i = 0; i \u003c phases.length; i++) if (elapsed \u003e= phases[i].t) current = phases[i].key;\n    return current;\n  }\n  function getPourKey(elapsed) {\n    for (var i = phases.length - 1; i \u003e= 0; i--) {\n      var p = phases[i];\n      if (elapsed \u003e= p.t \u0026\u0026 elapsed \u003c (p.t + p.pourLen)) return p.key;\n    }\n    return null;\n  }\n  function enableWakeLock() {\n    if (!('wakeLock' in navigator)) {\n      statusEl.textContent = '⚠️ Ton navigateur ne supporte pas le mode \\xe9cran allum\\xe9.';\n      return Promise.resolve();\n    }\n    return navigator.wakeLock.request('screen').then(function(wl) {\n      wakeLock = wl;\n      statusEl.textContent = '✅ \\xc9cran maintenu allum\\xe9 pendant la recette.';\n      wakeLock.addEventListener('release', function() {\n        statusEl.textContent = 'ℹ️ Mode \\xe9cran allum\\xe9 rel\\xe2ch\\xe9.';\n      });\n    }).catch(function() {\n      statusEl.textContent = '⚠️ Impossible d\\'activer le mode \\xe9cran allum\\xe9.';\n      wakeLock = null;\n    });\n  }\n  function disableWakeLock() {\n    if (wakeLock) { wakeLock.release(); wakeLock = null; }\n  }\n  function setButtons(running) {\n    startBtn.disabled = running;\n    stopBtn.disabled  = !running;\n    stopBtn.style.opacity = running ? '1' : '.5';\n  }\n  function tick() {\n    var elapsed = (Date.now() - startTime) \/ 1000;\n    timerEl.textContent = fmt(elapsed);\n    var phaseKey = getCurrentPhaseKey(elapsed);\n    if (phaseKey !== lastPhaseKey) {\n      setCardActive(phaseKey);\n      setPillPhaseActive(phaseKey, lastPhaseKey !== null);\n      lastPhaseKey = phaseKey;\n    }\n    var pourKey = getPourKey(elapsed);\n    if (pourKey !== lastPourKey) {\n      setPourPillActive(pourKey);\n      lastPourKey = pourKey;\n    }\n    if (elapsed \u003e= END_AT) { stopRecipe(true); return; }\n    rafId = requestAnimationFrame(tick);\n  }\n  function startRecipe() {\n    setButtons(true);\n    timerEl.textContent = '0:00';\n    lastPhaseKey = null;\n    lastPourKey  = null;\n    enableWakeLock().then(function() {\n      setCardActive(1);\n      setPillPhaseActive(1, false);\n      setPourPillActive(1);\n      lastPhaseKey = 1;\n      lastPourKey  = 1;\n      startTime = Date.now();\n      if (rafId) cancelAnimationFrame(rafId);\n      rafId = requestAnimationFrame(tick);\n    });\n  }\n  function stopRecipe(autoEnded) {\n    if (rafId) cancelAnimationFrame(rafId);\n    rafId     = null;\n    startTime = null;\n    disableWakeLock();\n    setButtons(false);\n    clearAll();\n    lastPhaseKey = null;\n    lastPourKey  = null;\n    if (autoEnded) {\n      statusEl.textContent = '✅ Recette termin\\xe9e — \\xe9cran lib\\xe9r\\xe9.';\n      timerEl.textContent  = fmt(END_AT);\n    } else {\n      statusEl.textContent = 'ℹ️ Recette arr\\xeat\\xe9e — \\xe9cran lib\\xe9r\\xe9.';\n    }\n  }\n  startBtn.addEventListener('click', startRecipe);\n  stopBtn.addEventListener('click', function() { stopRecipe(false); });\n  details.addEventListener('toggle', function() { if (!details.open) stopRecipe(false); });\n  document.addEventListener('visibilitychange', function() {\n    if (document.visibilityState === 'visible' \u0026\u0026 startTime \u0026\u0026 !wakeLock) enableWakeLock();\n  });\n})();\n\u003c\/script\u003e\n\u003c\/svg\u003e","brand":"ZAB","offers":[{"title":"300g","offer_id":39442646859851,"sku":"CAF-BLE-BONM-300","price":22.5,"currency_code":"CAD","in_stock":true},{"title":"808g","offer_id":39442646892619,"sku":"CAF-BLE-BONM-808","price":52.0,"currency_code":"CAD","in_stock":true},{"title":"2268g (5lbs)","offer_id":39442646925387,"sku":"CAF-BLE-BONM-2268","price":125.0,"currency_code":"CAD","in_stock":true},{"title":"100g","offer_id":51434083090741,"sku":"CAF-BLE-BONM-100","price":12.0,"currency_code":"CAD","in_stock":true},{"title":"Bucket - 5lbs (Livraison locale seulement)","offer_id":52569821315381,"sku":"CAF-BLE-BONM-BUCK-5","price":150.0,"currency_code":"CAD","in_stock":true},{"title":"Bucket - 15lbs (Livraison locale seulement)","offer_id":52569821348149,"sku":"CAF-BLE-BONM-BUCK-15","price":400.0,"currency_code":"CAD","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/2716\/1842\/files\/bon-matin-300g.jpg?v=1756855245"},{"product_id":"guatemala-famille-lemus","title":"GUATEMALA - FAMILLE LEMUS","description":"\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 1 : NOTES DE DÉGUSTATION\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto; border: 2px solid var(--product-box-background, #000); border-radius: 12px; overflow: hidden;\"\u003e\n\u003cdiv style=\"padding: 10px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center;\"\u003eNotes de dégustation\u003c\/div\u003e\n\u003cdiv style=\"padding: 16px 14px; font-weight: 900; text-transform: uppercase; font-size: 28px; letter-spacing: .05em; text-align: center; background: transparent;\"\u003eNOISETTE + CHOCOLAT NOIR + CARAMEL ÉCOSSAIS\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 1 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 2 : APPROVISIONNEMENT\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto;\"\u003e\n\u003cdiv style=\"padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center; border-radius: 12px 12px 0 0;\"\u003eApprovisionnement\u003c\/div\u003e\n\u003ctable border=\"3\" cellpadding=\"1\" cellspacing=\"1\" style=\"width: 100%; border-collapse: collapse; background: transparent;\"\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd style=\"width: 20%;\"\u003eORIGINE\u003c\/td\u003e\n\u003ctd\u003eVillage de Mataquescuintla, département de Jalapa, Guatemala\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePRODUCTEUR.RICES\u003c\/td\u003e\n\u003ctd\u003eFamille Lemus\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eFERME\u003c\/td\u003e\n\u003ctd\u003eEl Durazno\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eVARIÉTÉ\u003c\/td\u003e\n\u003ctd\u003ePache San Ramon\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePROCÉDÉ\u003c\/td\u003e\n\u003ctd\u003eLavé\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eALTITUDE\u003c\/td\u003e\n\u003ctd\u003e1900 m\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePARTENAIRES\u003c\/td\u003e\n\u003ctd\u003eSemilla\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eVOLUME ACHETÉ\u003c\/td\u003e\n\u003ctd\u003e690 kg\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eFAB\u003c\/td\u003e\n\u003ctd\u003e6,22 $ US\/LB\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePRIX LIVRÉ\u003c\/td\u003e\n\u003ctd\u003e9,15 $ CAD\/LB\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePRIX FARMGATE\u003c\/td\u003e\n\u003ctd\u003e2700 Quetzal\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eRELATION\u003c\/td\u003e\n\u003ctd\u003e6 ans\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003c\/tbody\u003e\n\u003c\/table\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 2 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 3 : INFORMATIONS SUR LE CAFÉ\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto;\"\u003e\n\u003cdiv style=\"padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center; border-radius: 12px 12px 0 0;\"\u003eInformations sur le café\u003c\/div\u003e\n\u003cdiv style=\"border: 2px solid var(--product-box-background, #000); border-top: none; border-radius: 0 0 12px 12px; padding: 16px 14px; background: transparent;\"\u003e\n\u003cp style=\"margin: 0 0 12px 0;\"\u003ePour la sixième année consécutive, le café de la famille Lemus est de retour avec ses arômes charmeurs et sa grande buvabilité. En filtre, il offre une tasse classique et gourmande, aux notes de chocolat et de noix. On a l'impression de prendre une gorgée de chocolat chaud. En espresso, c'est un accord naturel avec le lait : sa texture crémeuse et ses arômes de chocolat noir et de noisette en font une tasse délicieuse et polyvalente.\u003c\/p\u003e\n\u003cp style=\"margin: 0 0 12px 0;\"\u003eL'histoire de la culture du café dans la famille Lemus remonte à 1958, lorsque le grand-père de Juan Raul Lemus a commencé à cultiver le café. Vingt ans plus tard, son père, Baudelio, a suivi ses traces. Aujourd'hui, Juan Raul, ses frères et sa sœur se sont joints à l'entreprise familiale pour gérer les 13 hectares répartis en 4 parcelles de terre appartenant à la famille. La famille Lemus a une histoire longue et riche dans la culture du café à Mataquescuintla, ce qui leur a permis de développer bien plus d'infrastructures que le producteur moyen avec lequel travaille Semilla, notre importateur. Cela leur permet non seulement de transformer leurs propres cerises, mais aussi celles des producteur.rices avoisinant.es.\u003c\/p\u003e\n\u003cp style=\"margin: 0;\"\u003eJuan Raul et sa famille sont des activistes inspirants, se battant pour leur peuple, les Xincas. Ils font partie du Café Colis Resistencia, qui lutte contre une société minière canadienne exploitant une mine d'argent sur les terres du peuple Xinca, menaçant leur subsistance. Ils travaillent également à élargir les opportunités de vente de la communauté au-delà du marché local du café au Guatemala, qui achète des cerises à des prix dérisoires. Nous sommes très fiers de les soutenir grâce à notre partenariat avec Semilla, maintenant pour la cinquième année consécutive ! Leur café constitue une partie essentielle de notre initiative \"Retour à l'origine\", où 0,50 $ de chaque sac vendu est directement reversé au producteur.\u003c\/p\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 3 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 4 : PARAMÈTRES D'EXTRACTION — ESPRESSO\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto;\"\u003e\n\u003cdetails open=\"\" style=\"border: 2px solid var(--product-box-background, #000); border-radius: 12px; overflow: hidden; margin: 0 0 12px 0; background: rgba(255,255,255,0.5);\"\u003e\n\u003csummary style=\"cursor: pointer; list-style: none; padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center;\"\u003eEspresso — paramètres recommandés\u003c\/summary\u003e\n\u003cdiv style=\"padding: 12px 14px;\"\u003e\n\u003ctable style=\"width: 100%; border-collapse: collapse; background: transparent;\"\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd style=\"padding: 10px 0; font-weight: 800; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003eCafé moulu\u003c\/td\u003e\n\u003ctd style=\"padding: 10px 0; text-align: right; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003e18 g\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd style=\"padding: 10px 0; font-weight: 800; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003eCafé dans la tasse\u003c\/td\u003e\n\u003ctd style=\"padding: 10px 0; text-align: right; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003e37 g\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd style=\"padding: 10px 0; font-weight: 800;\"\u003eTemps d'extraction\u003c\/td\u003e\n\u003ctd style=\"padding: 10px 0; text-align: right;\"\u003e29 sec\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003c\/tbody\u003e\n\u003c\/table\u003e\n\u003cdiv style=\"margin-top: 10px; padding: 8px 10px; border-radius: 8px; background: rgba(0,0,0,.04); border: 1px dashed rgba(0,0,0,.2); font-size: 12px; opacity: .7; line-height: 1.4;\"\u003e\n\u003cstrong\u003eÀ noter —\u003c\/strong\u003e Recette optimisée pour un panier de \u003cstrong\u003e18 g\u003c\/strong\u003e. Consulte le manuel de ta machine pour connaître la capacité de ton panier.\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/details\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 4 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 5 : V60\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto;\"\u003e\n\u003cdetails id=\"v60Details-eldurazno\" open=\"\" style=\"border: 2px solid var(--product-box-background, #000); border-radius: 12px; overflow: hidden; margin: 0 0 12px 0; background: rgba(255,255,255,0.5);\"\u003e\n\u003csummary style=\"cursor: pointer; list-style: none; padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center;\"\u003eV60 – Recette\u003c\/summary\u003e\n\u003cdiv style=\"padding: 12px 14px;\"\u003e\n\u003cdiv style=\"padding: 10px 0 10px; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003e\n\u003cdiv style=\"font-weight: 900; font-size: 16px;\"\u003eRatio 1:15\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 4px; opacity: .7; font-size: 13px;\"\u003e15 g in – 225 g out\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 6px; font-size: 13px;\"\u003e\n\u003cstrong\u003eTempérature de l'eau :\u003c\/strong\u003e 92 °C\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; padding: 10px 0 8px;\"\u003e\n\u003cdiv style=\"display: flex; gap: 8px; align-items: center; flex-wrap: wrap;\"\u003e\n\u003cbutton style=\"cursor: pointer; border: 2px solid var(--product-box-background, #000); background: var(--product-box-background, #000); color: var(--product-box-text, #fff); font-weight: 900; padding: 8px 10px; border-radius: 10px; text-transform: uppercase; letter-spacing: .02em; font-size: 12px;\" type=\"button\" id=\"v60StartBtn-eldurazno\"\u003eDémarrer\u003c\/button\u003e \u003cbutton style=\"cursor: pointer; border: 2px solid var(--product-box-background, #000); background: var(--product-box-text, #fff); color: var(--product-box-background, #000); font-weight: 900; padding: 8px 10px; border-radius: 10px; text-transform: uppercase; letter-spacing: .02em; font-size: 12px; opacity: .5;\" disabled type=\"button\" id=\"v60StopBtn-eldurazno\"\u003eStop\u003c\/button\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; line-height: 1;\"\u003e\n\u003cspan style=\"opacity: .70; font-size: 12px; font-weight: 800; text-transform: uppercase; letter-spacing: .04em;\"\u003eTimer\u003c\/span\u003e \u003cspan style=\"font-weight: 950; font-size: 28px; letter-spacing: .01em;\" id=\"v60Timer-eldurazno\"\u003e0:00\u003c\/span\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"flex-basis: 100%; opacity: .6; font-size: 12px; line-height: 1.3; margin-top: 2px;\" id=\"v60WakeStatus-eldurazno\"\u003eℹ️ Appuie sur \"Démarrer\" pour garder l'écran allumé.\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 8px; display: grid; gap: 10px;\"\u003e\n\u003cdiv style=\"border: 1px solid rgba(0,0,0,.18); border-radius: 12px; padding: 10px 12px;\" id=\"v60-card-1-eldurazno\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; margin-bottom: 6px;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e0:00\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003ePhase 1 — Bloom\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 8px; flex-wrap: wrap; font-size: 12.5px; font-weight: 800;\"\u003e\n\u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\" id=\"v60-pill-1-eldurazno\"\u003eVerser pendant 0:10s\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\"\u003eTotal 45 g\u003c\/span\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"border: 1px solid rgba(0,0,0,.18); border-radius: 12px; padding: 10px 12px;\" id=\"v60-card-2-eldurazno\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; margin-bottom: 6px;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e0:35\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003ePhase 2\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 8px; flex-wrap: wrap; font-size: 12.5px; font-weight: 800;\"\u003e\n\u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\" id=\"v60-pill-2-eldurazno\"\u003eVerser pendant 0:10s\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\"\u003eTotal 105 g\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12); opacity: .6;\"\u003e+60 g\u003c\/span\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"border: 1px solid rgba(0,0,0,.18); border-radius: 12px; padding: 10px 12px;\" id=\"v60-card-3-eldurazno\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; margin-bottom: 6px;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e1:10\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003ePhase 3\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 8px; flex-wrap: wrap; font-size: 12.5px; font-weight: 800;\"\u003e\n\u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\" id=\"v60-pill-3-eldurazno\"\u003eVerser pendant 0:10s\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\"\u003eTotal 165 g\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12); opacity: .6;\"\u003e+60 g\u003c\/span\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"border: 1px solid rgba(0,0,0,.18); border-radius: 12px; padding: 10px 12px;\" id=\"v60-card-4-eldurazno\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; margin-bottom: 6px;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e1:45\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003ePhase 4\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 8px; flex-wrap: wrap; font-size: 12.5px; font-weight: 800;\"\u003e\n\u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\" id=\"v60-pill-4-eldurazno\"\u003eVerser pendant 0:15s\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\"\u003eTotal 225 g\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12); opacity: .6;\"\u003e+60 g\u003c\/span\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 12px; border-top: 1px solid rgba(0,0,0,.2); padding-top: 10px;\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e2:40\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003eTemps final écoulement complet\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 8px; padding: 8px 10px; border-radius: 8px; background: rgba(0,0,0,.04); border: 1px dashed rgba(0,0,0,.2); font-size: 12px; opacity: .6; line-height: 1.4;\"\u003e\n\u003cstrong\u003eℹ️ Astuce —\u003c\/strong\u003e Si le temps total est plus court, la mouture est probablement trop grosse. S'il est plus long, la mouture est probablement trop fine.\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/details\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 5 ========= --\u003e\u003csvg style=\"display: none;\"\u003e\n\u003cstyle\u003e\n  @keyframes v60PulsePhase {\n    0%   { transform: scale(1);    box-shadow: 0 0 0 0 rgba(200,169,126,.35); }\n    50%  { transform: scale(1.06); box-shadow: 0 0 0 10px rgba(200,169,126,0); }\n    100% { transform: scale(1);    box-shadow: 0 0 0 0 rgba(200,169,126,0); }\n  }\n  .v60-pulse-eldurazno {\n    animation: v60PulsePhase 700ms ease-out 1;\n    transform-origin: center;\n    will-change: transform;\n  }\n  @keyframes v60BlinkPill {\n    0%, 100% { opacity: 1; transform: scale(1); }\n    50%      { opacity: .22; transform: scale(1.03); }\n  }\n  .v60-pill-pour-active-eldurazno {\n    background: #ffe7b7 !important;\n    border: 2px solid #d2a44a !important;\n    color: #3b2a12 !important;\n    font-weight: 900 !important;\n    letter-spacing: .02em;\n    animation: v60BlinkPill 2500ms ease-in-out infinite;\n    box-shadow:\n      0 0 0 2px rgba(210,164,74,.18) inset,\n      0 10px 22px rgba(0,0,0,.12),\n      0 0 0 6px rgba(210,164,74,.10);\n  }\n  @media (prefers-reduced-motion: reduce) {\n    .v60-pill-pour-active-eldurazno { animation: none; }\n    .v60-pulse-eldurazno { animation: none; }\n  }\n\u003c\/style\u003e\n\u003cscript\u003e\n(function() {\n  var SUFFIX = '-eldurazno';\n  var END_AT = 160;\n  var phases = [\n    { key: 1, t: 0,   pourLen: 10 },\n    { key: 2, t: 35,  pourLen: 10 },\n    { key: 3, t: 70,  pourLen: 10 },\n    { key: 4, t: 105, pourLen: 15 }\n  ];\n  var latte = {\n    cardBg:     '#f6f1ea',\n    cardBorder: '#c8a97e',\n    pillBg:     '#eadfce'\n  };\n  var details  = document.getElementById('v60Details'    + SUFFIX);\n  var startBtn = document.getElementById('v60StartBtn'   + SUFFIX);\n  var stopBtn  = document.getElementById('v60StopBtn'    + SUFFIX);\n  var timerEl  = document.getElementById('v60Timer'      + SUFFIX);\n  var statusEl = document.getElementById('v60WakeStatus' + SUFFIX);\n  var pills = {\n    1: document.getElementById('v60-pill-1' + SUFFIX),\n    2: document.getElementById('v60-pill-2' + SUFFIX),\n    3: document.getElementById('v60-pill-3' + SUFFIX),\n    4: document.getElementById('v60-pill-4' + SUFFIX)\n  };\n  var cards = {\n    1: document.getElementById('v60-card-1' + SUFFIX),\n    2: document.getElementById('v60-card-2' + SUFFIX),\n    3: document.getElementById('v60-card-3' + SUFFIX),\n    4: document.getElementById('v60-card-4' + SUFFIX)\n  };\n\n  function setCardActive(key) {\n    Object.keys(cards).forEach(function(k) {\n      var c = cards[k];\n      if (!c) return;\n      if (parseInt(k) === key) {\n        c.style.borderColor = latte.cardBorder;\n        c.style.background  = latte.cardBg;\n        c.style.boxShadow   = '0 0 0 2px rgba(200,169,126,.25) inset, 0 8px 22px rgba(200,169,126,.28)';\n      } else {\n        c.style.borderColor = 'rgba(0,0,0,.18)';\n        c.style.background  = 'transparent';\n        c.style.boxShadow   = 'none';\n      }\n    });\n  }\n\n  function setPillPhaseActive(key, doPulse) {\n    Object.keys(pills).forEach(function(k) {\n      var p = pills[k];\n      if (!p) return;\n      p.style.background  = 'rgba(0,0,0,.05)';\n      p.style.borderColor = 'rgba(0,0,0,.12)';\n      p.style.boxShadow   = 'none';\n      p.classList.remove('v60-pulse-eldurazno');\n    });\n    var pill = pills[key];\n    if (pill) {\n      pill.style.background  = latte.pillBg;\n      pill.style.borderColor = latte.cardBorder;\n      pill.style.boxShadow   = '0 0 0 2px rgba(200,169,126,.25) inset';\n      if (doPulse) {\n        pill.classList.remove('v60-pulse-eldurazno');\n        void pill.offsetWidth;\n        pill.classList.add('v60-pulse-eldurazno');\n      }\n    }\n  }\n\n  function resetPourPills() {\n    Object.values(pills).forEach(function(p) {\n      if (!p) return;\n      p.classList.remove('v60-pill-pour-active-eldurazno');\n    });\n  }\n\n  function setPourPillActive(key) {\n    resetPourPills();\n    if (!key) return;\n    var pill = pills[key];\n    if (pill) pill.classList.add('v60-pill-pour-active-eldurazno');\n  }\n\n  function clearAll() {\n    Object.values(cards).forEach(function(c) {\n      if (!c) return;\n      c.style.borderColor = 'rgba(0,0,0,.18)';\n      c.style.background  = 'transparent';\n      c.style.boxShadow   = 'none';\n    });\n    Object.values(pills).forEach(function(p) {\n      if (!p) return;\n      p.style.background  = 'rgba(0,0,0,.05)';\n      p.style.borderColor = 'rgba(0,0,0,.12)';\n      p.style.boxShadow   = 'none';\n      p.classList.remove('v60-pulse-eldurazno');\n      p.classList.remove('v60-pill-pour-active-eldurazno');\n    });\n  }\n\n  var wakeLock  = null;\n  var startTime = null;\n  var rafId     = null;\n  var lastPhaseKey = null;\n  var lastPourKey  = null;\n\n  function fmt(sec) {\n    sec = Math.max(0, Math.floor(sec));\n    var m = Math.floor(sec \/ 60);\n    var s = sec % 60;\n    return m + ':' + (s \u0026lt; 10 ? '0' : '') + s;\n  }\n\n  function getCurrentPhaseKey(elapsed) {\n    var current = phases[0].key;\n    for (var i = 0; i \u0026lt; phases.length; i++) if (elapsed \u0026gt;= phases[i].t) current = phases[i].key;\n    return current;\n  }\n\n  function getPourKey(elapsed) {\n    for (var i = phases.length - 1; i \u0026gt;= 0; i--) {\n      var p = phases[i];\n      if (elapsed \u0026gt;= p.t \u0026amp;\u0026amp; elapsed \u0026lt; (p.t + p.pourLen)) return p.key;\n    }\n    return null;\n  }\n\n  function enableWakeLock() {\n    if (!('wakeLock' in navigator)) {\n      statusEl.textContent = '⚠️ Ton navigateur ne supporte pas le mode écran allumé.';\n      return Promise.resolve();\n    }\n    return navigator.wakeLock.request('screen').then(function(wl) {\n      wakeLock = wl;\n      statusEl.textContent = '✅ Écran maintenu allumé pendant la recette.';\n      wakeLock.addEventListener('release', function() {\n        statusEl.textContent = 'ℹ️ Mode écran allumé relâché.';\n      });\n    }).catch(function() {\n      statusEl.textContent = '⚠️ Impossible d\\'activer le mode écran allumé.';\n      wakeLock = null;\n    });\n  }\n\n  function disableWakeLock() {\n    if (wakeLock) { wakeLock.release(); wakeLock = null; }\n  }\n\n  function setButtons(running) {\n    startBtn.disabled = running;\n    stopBtn.disabled  = !running;\n    stopBtn.style.opacity = running ? '1' : '.5';\n  }\n\n  function tick() {\n    var elapsed = (Date.now() - startTime) \/ 1000;\n    timerEl.textContent = fmt(elapsed);\n    var phaseKey = getCurrentPhaseKey(elapsed);\n    if (phaseKey !== lastPhaseKey) {\n      setCardActive(phaseKey);\n      setPillPhaseActive(phaseKey, lastPhaseKey !== null);\n      lastPhaseKey = phaseKey;\n    }\n    var pourKey = getPourKey(elapsed);\n    if (pourKey !== lastPourKey) {\n      setPourPillActive(pourKey);\n      lastPourKey = pourKey;\n    }\n    if (elapsed \u0026gt;= END_AT) { stopRecipe(true); return; }\n    rafId = requestAnimationFrame(tick);\n  }\n\n  function startRecipe() {\n    setButtons(true);\n    timerEl.textContent = '0:00';\n    lastPhaseKey = null;\n    lastPourKey  = null;\n    enableWakeLock().then(function() {\n      setCardActive(1);\n      setPillPhaseActive(1, false);\n      setPourPillActive(1);\n      lastPhaseKey = 1;\n      lastPourKey  = 1;\n      startTime = Date.now();\n      if (rafId) cancelAnimationFrame(rafId);\n      rafId = requestAnimationFrame(tick);\n    });\n  }\n\n  function stopRecipe(autoEnded) {\n    if (rafId) cancelAnimationFrame(rafId);\n    rafId     = null;\n    startTime = null;\n    disableWakeLock();\n    setButtons(false);\n    clearAll();\n    lastPhaseKey = null;\n    lastPourKey  = null;\n    if (autoEnded) {\n      statusEl.textContent = '✅ Recette terminée — écran libéré.';\n      timerEl.textContent  = fmt(END_AT);\n    } else {\n      statusEl.textContent = 'ℹ️ Recette arrêtée — écran libéré.';\n    }\n  }\n\n  startBtn.addEventListener('click', startRecipe);\n  stopBtn.addEventListener('click', function() { stopRecipe(false); });\n  details.addEventListener('toggle', function() { if (!details.open) stopRecipe(false); });\n  document.addEventListener('visibilitychange', function() {\n    if (document.visibilityState === 'visible' \u0026amp;\u0026amp; startTime \u0026amp;\u0026amp; !wakeLock) enableWakeLock();\n  });\n})();\n\u003c\/script\u003e\n\u003c\/svg\u003e","brand":"ZAB","offers":[{"title":"300g","offer_id":48415415370037,"sku":"CAF-SIN-LEMU-300","price":28.5,"currency_code":"CAD","in_stock":false},{"title":"808g","offer_id":48415415402805,"sku":"CAF-SIN-LEMU-808","price":68.0,"currency_code":"CAD","in_stock":false},{"title":"2268g (5lbs)","offer_id":48415415435573,"sku":"CAF-SIN-LEMU-2268","price":175.0,"currency_code":"CAD","in_stock":false},{"title":"100g","offer_id":52331298881845,"sku":"CAF-SIN-LEMU-100","price":14.0,"currency_code":"CAD","in_stock":false},{"title":"Bucket - 5lbs (Livraison locale seulement)","offer_id":52568880742709,"sku":"CAF-SIN-LEMU-BUCK-5","price":200.0,"currency_code":"CAD","in_stock":false},{"title":"Bucket - 15lbs (Livraison locale seulement)","offer_id":52568880775477,"sku":"CAF-SIN-LEMU-BUCK-15","price":550.0,"currency_code":"CAD","in_stock":false}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/2716\/1842\/files\/lemus-300g-retour.jpg?v=1771862869"},{"product_id":"honduras-jesus-galeas","title":"HONDURAS - JESUS GALEAS","description":"\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 1 : NOTES DE DÉGUSTATION\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto; border: 2px solid var(--product-box-background, #000); border-radius: 12px; overflow: hidden;\"\u003e\n\u003cdiv style=\"padding: 10px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center;\"\u003eNotes de dégustation\u003c\/div\u003e\n\u003cdiv style=\"padding: 16px 14px; font-weight: 900; text-transform: uppercase; font-size: 28px; letter-spacing: .05em; text-align: center; background: transparent;\"\u003ePOMME VERTE + NOIX + SUCRE DE CANNE\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 1 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003cdiv style=\"position: relative; width: 100%; padding-bottom: 56.25%; height: 0; overflow: hidden; border-radius: 8px;\"\u003e\u003ciframe style=\"position: absolute; top: 0; left: 0; width: 100%; height: 100%; border: 0; border-radius: 8px;\" src=\"https:\/\/www.youtube.com\/embed\/1YALV1SU1QE?si=TCyjdZkwXAAKGLfI\"\u003e\u003c\/iframe\u003e\u003c\/div\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 2 : APPROVISIONNEMENT\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto;\"\u003e\n\u003cdiv style=\"padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center; border-radius: 12px 12px 0 0;\"\u003eApprovisionnement\u003c\/div\u003e\n\u003ctable border=\"3\" cellpadding=\"1\" cellspacing=\"1\" style=\"width: 100%; border-collapse: collapse; background: transparent;\"\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd style=\"width: 20%;\"\u003eORIGINE\u003c\/td\u003e\n\u003ctd\u003eSelguapa, département de Comayagua, Honduras\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePRODUCTEURS\u003c\/td\u003e\n\u003ctd\u003eJesus « Chungo » Galeas\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eFERME\u003c\/td\u003e\n\u003ctd\u003eLa Falda\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eVARIÉTÉ\u003c\/td\u003e\n\u003ctd\u003eVariées\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePROCÉDÉ\u003c\/td\u003e\n\u003ctd\u003eLavé anaérobique\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eALTITUDE\u003c\/td\u003e\n\u003ctd\u003e1700 m\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePARTENAIRES\u003c\/td\u003e\n\u003ctd\u003eSemilla\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eVOLUME ACHETÉ\u003c\/td\u003e\n\u003ctd\u003e690 kg\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eFAB\u003c\/td\u003e\n\u003ctd\u003e5,26 $ US\/lb\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePRIX LIVRÉ\u003c\/td\u003e\n\u003ctd\u003e10,04 $ CAD\/LB\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eRELATION\u003c\/td\u003e\n\u003ctd\u003e2 ans\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003c\/tbody\u003e\n\u003c\/table\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 2 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 3 : INFORMATIONS SUR LE CAFÉ\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto;\"\u003e\n\u003cdiv style=\"padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center; border-radius: 12px 12px 0 0;\"\u003eInformations sur le café\u003c\/div\u003e\n\u003cdiv style=\"border: 2px solid var(--product-box-background, #000); border-top: none; border-radius: 0 0 12px 12px; padding: 16px 14px; background: transparent;\"\u003e\n\u003cp style=\"margin: 0 0 12px 0;\"\u003eNous sommes super contents de te présenter le café de Jesús, non seulement parce qu'il est délicieux, mais surtout parce que Jesús joue un rôle clé dans la transformation de sa communauté en un véritable hub de production de cafés de spécialité.\u003c\/p\u003e\n\u003cp style=\"margin: 0 0 12px 0;\"\u003eJesus a travaillé durant sept ans au sein de l'Institut Hondurien du Café (IHCAFE), où il a aidé des producteur.rices à travers le pays en leur offrant des formations sur l'analyse des sols, les récoltes et le traitement du café. Fort de cette expérience, son objectif est clair : inspirer les producteur.rices à se lancer dans le café de spécialité et à adopter de meilleures pratiques agricoles. En 2018, grâce à son engagement et au soutien de Rony Game, son village natal de Selguapa a vu le nombre de producteurs et productrices de café de spécialité passer de 2 à 30 en seulement un an.\u003c\/p\u003e\n\u003cp style=\"margin: 0;\"\u003eSon parcours incarne parfaitement la vision de Semilla, notre partenaire importateur : offrir des prix justes et transparents qui permettent aux producteur.rices d'investir dans leurs fermes et leurs communautés. Avec Jesús et des visionnaires comme lui, nous sommes convaincus qu'un avenir durable pour le café est à portée de main.\u003c\/p\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 3 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 4 : PARAMÈTRES D'EXTRACTION — ESPRESSO\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto;\"\u003e\n\u003cdetails open=\"\" style=\"border: 2px solid var(--product-box-background, #000); border-radius: 12px; overflow: hidden; margin: 0 0 12px 0; background: rgba(255,255,255,0.5);\"\u003e\n\u003csummary style=\"cursor: pointer; list-style: none; padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center;\"\u003eEspresso — paramètres recommandés\u003c\/summary\u003e\n\u003cdiv style=\"padding: 12px 14px;\"\u003e\n\u003ctable style=\"width: 100%; border-collapse: collapse; background: transparent;\"\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd style=\"padding: 10px 0; font-weight: 800; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003eCafé moulu\u003c\/td\u003e\n\u003ctd style=\"padding: 10px 0; text-align: right; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003e18 g\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd style=\"padding: 10px 0; font-weight: 800; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003eCafé dans la tasse\u003c\/td\u003e\n\u003ctd style=\"padding: 10px 0; text-align: right; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003e33 g\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd style=\"padding: 10px 0; font-weight: 800;\"\u003eTemps d'extraction\u003c\/td\u003e\n\u003ctd style=\"padding: 10px 0; text-align: right;\"\u003e32 sec\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003c\/tbody\u003e\n\u003c\/table\u003e\n\u003cdiv style=\"margin-top: 10px; padding: 8px 10px; border-radius: 8px; background: rgba(0,0,0,.04); border: 1px dashed rgba(0,0,0,.2); font-size: 12px; opacity: .7; line-height: 1.4;\"\u003e\n\u003cstrong\u003eÀ noter —\u003c\/strong\u003e Recette optimisée pour un panier de \u003cstrong\u003e18 g\u003c\/strong\u003e. Consulte le manuel de ta machine pour connaître la capacité de ton panier.\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/details\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 4 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 5 : V60\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto;\"\u003e\n\u003cdetails id=\"v60Details-lafalda\" open=\"\" style=\"border: 2px solid var(--product-box-background, #000); border-radius: 12px; overflow: hidden; margin: 0 0 12px 0; background: rgba(255,255,255,0.5);\"\u003e\n\u003csummary style=\"cursor: pointer; list-style: none; padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center;\"\u003eV60 – Recette\u003c\/summary\u003e\n\u003cdiv style=\"padding: 12px 14px;\"\u003e\n\u003cdiv style=\"padding: 10px 0 10px; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003e\n\u003cdiv style=\"font-weight: 900; font-size: 16px;\"\u003eRatio 1:15\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 4px; opacity: .7; font-size: 13px;\"\u003e15 g in – 225 g out\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 6px; font-size: 13px;\"\u003e\n\u003cstrong\u003eTempérature de l'eau :\u003c\/strong\u003e 90 °C\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; padding: 10px 0 8px;\"\u003e\n\u003cdiv style=\"display: flex; gap: 8px; align-items: center; flex-wrap: wrap;\"\u003e\n\u003cbutton style=\"cursor: pointer; border: 2px solid var(--product-box-background, #000); background: var(--product-box-background, #000); color: var(--product-box-text, #fff); font-weight: 900; padding: 8px 10px; border-radius: 10px; text-transform: uppercase; letter-spacing: .02em; font-size: 12px;\" type=\"button\" id=\"v60StartBtn-lafalda\"\u003eDémarrer\u003c\/button\u003e \u003cbutton style=\"cursor: pointer; border: 2px solid var(--product-box-background, #000); background: var(--product-box-text, #fff); color: var(--product-box-background, #000); font-weight: 900; padding: 8px 10px; border-radius: 10px; text-transform: uppercase; letter-spacing: .02em; font-size: 12px; opacity: .5;\" disabled type=\"button\" id=\"v60StopBtn-lafalda\"\u003eStop\u003c\/button\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; line-height: 1;\"\u003e\n\u003cspan style=\"opacity: .70; font-size: 12px; font-weight: 800; text-transform: uppercase; letter-spacing: .04em;\"\u003eTimer\u003c\/span\u003e \u003cspan style=\"font-weight: 950; font-size: 28px; letter-spacing: .01em;\" id=\"v60Timer-lafalda\"\u003e0:00\u003c\/span\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"flex-basis: 100%; opacity: .6; font-size: 12px; line-height: 1.3; margin-top: 2px;\" id=\"v60WakeStatus-lafalda\"\u003eℹ️ Appuie sur \"Démarrer\" pour garder l'écran allumé.\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 8px; display: grid; gap: 10px;\"\u003e\n\u003cdiv style=\"border: 1px solid rgba(0,0,0,.18); border-radius: 12px; padding: 10px 12px;\" id=\"v60-card-1-lafalda\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; margin-bottom: 6px;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e0:00\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003ePhase 1 — Bloom\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 8px; flex-wrap: wrap; font-size: 12.5px; font-weight: 800;\"\u003e\n\u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\" id=\"v60-pill-1-lafalda\"\u003eVerser pendant 0:10s\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\"\u003eTotal 45 g\u003c\/span\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"border: 1px solid rgba(0,0,0,.18); border-radius: 12px; padding: 10px 12px;\" id=\"v60-card-2-lafalda\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; margin-bottom: 6px;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e0:45\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003ePhase 2\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 8px; flex-wrap: wrap; font-size: 12.5px; font-weight: 800;\"\u003e\n\u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\" id=\"v60-pill-2-lafalda\"\u003eVerser pendant 0:15s\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\"\u003eTotal 105 g\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12); opacity: .6;\"\u003e+60 g\u003c\/span\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"border: 1px solid rgba(0,0,0,.18); border-radius: 12px; padding: 10px 12px;\" id=\"v60-card-3-lafalda\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; margin-bottom: 6px;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e1:15\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003ePhase 3\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 8px; flex-wrap: wrap; font-size: 12.5px; font-weight: 800;\"\u003e\n\u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\" id=\"v60-pill-3-lafalda\"\u003eVerser pendant 0:20s\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\"\u003eTotal 170 g\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12); opacity: .6;\"\u003e+65 g\u003c\/span\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"border: 1px solid rgba(0,0,0,.18); border-radius: 12px; padding: 10px 12px;\" id=\"v60-card-4-lafalda\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; margin-bottom: 6px;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e1:50\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003ePhase 4\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 8px; flex-wrap: wrap; font-size: 12.5px; font-weight: 800;\"\u003e\n\u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\" id=\"v60-pill-4-lafalda\"\u003eVerser pendant 0:20s\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\"\u003eTotal 225 g\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12); opacity: .6;\"\u003e+55 g\u003c\/span\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 12px; border-top: 1px solid rgba(0,0,0,.2); padding-top: 10px;\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e2:50\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003eTemps final écoulement complet\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 8px; padding: 8px 10px; border-radius: 8px; background: rgba(0,0,0,.04); border: 1px dashed rgba(0,0,0,.2); font-size: 12px; opacity: .6; line-height: 1.4;\"\u003e\n\u003cstrong\u003eℹ️ Astuce —\u003c\/strong\u003e Si le temps total est plus court, la mouture est probablement trop grosse. S'il est plus long, la mouture est probablement trop fine.\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/details\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 5 ========= --\u003e\u003csvg style=\"display: none;\"\u003e\n\u003cstyle\u003e\n  @keyframes v60PulsePhase { 0% { transform: scale(1); box-shadow: 0 0 0 0 rgba(200,169,126,.35); } 50% { transform: scale(1.06); box-shadow: 0 0 0 10px rgba(200,169,126,0); } 100% { transform: scale(1); box-shadow: 0 0 0 0 rgba(200,169,126,0); } }\n  .v60-pulse { animation: v60PulsePhase 700ms ease-out 1; transform-origin: center; will-change: transform; }\n  @keyframes v60BlinkPill { 0%, 100% { opacity: 1; transform: scale(1); } 50% { opacity: .22; transform: scale(1.03); } }\n  .v60-pill-pour-active { background: #ffe7b7 !important; border: 2px solid #d2a44a !important; color: #3b2a12 !important; font-weight: 900 !important; letter-spacing: .02em; animation: v60BlinkPill 2500ms ease-in-out infinite; box-shadow: 0 0 0 2px rgba(210,164,74,.18) inset, 0 10px 22px rgba(0,0,0,.12), 0 0 0 6px rgba(210,164,74,.10); }\n  @media (prefers-reduced-motion: reduce) { .v60-pill-pour-active { animation: none; } .v60-pulse { animation: none; } }\n\u003c\/style\u003e\n\u003cscript\u003e\n(function() {\n  var SUFFIX = '-lafalda';\n  var END_AT = 170;\n  var phases = [ { key: 1, t: 0, pourLen: 10 }, { key: 2, t: 45, pourLen: 15 }, { key: 3, t: 75, pourLen: 20 }, { key: 4, t: 110, pourLen: 20 } ];\n  var latte = { cardBg: '#f6f1ea', cardBorder: '#c8a97e', pillBg: '#eadfce' };\n  var details = document.getElementById('v60Details' + SUFFIX);\n  var startBtn = document.getElementById('v60StartBtn' + SUFFIX);\n  var stopBtn = document.getElementById('v60StopBtn' + SUFFIX);\n  var timerEl = document.getElementById('v60Timer' + SUFFIX);\n  var statusEl = document.getElementById('v60WakeStatus' + SUFFIX);\n  var pills = { 1: document.getElementById('v60-pill-1' + SUFFIX), 2: document.getElementById('v60-pill-2' + SUFFIX), 3: document.getElementById('v60-pill-3' + SUFFIX), 4: document.getElementById('v60-pill-4' + SUFFIX) };\n  var cards = { 1: document.getElementById('v60-card-1' + SUFFIX), 2: document.getElementById('v60-card-2' + SUFFIX), 3: document.getElementById('v60-card-3' + SUFFIX), 4: document.getElementById('v60-card-4' + SUFFIX) };\n  function setCardActive(key) {\n    Object.keys(cards).forEach(function(k) {\n      var c = cards[k]; if (!c) return;\n      if (parseInt(k) === key) { c.style.borderColor = latte.cardBorder; c.style.background = latte.cardBg; c.style.boxShadow = '0 0 0 2px rgba(200,169,126,.25) inset, 0 8px 22px rgba(200,169,126,.28)'; }\n      else { c.style.borderColor = 'rgba(0,0,0,.18)'; c.style.background = 'transparent'; c.style.boxShadow = 'none'; }\n    });\n  }\n  function setPillPhaseActive(key, doPulse) {\n    Object.keys(pills).forEach(function(k) {\n      var p = pills[k]; if (!p) return;\n      p.style.background = 'rgba(0,0,0,.05)'; p.style.borderColor = 'rgba(0,0,0,.12)'; p.style.boxShadow = 'none'; p.classList.remove('v60-pulse');\n    });\n    var pill = pills[key];\n    if (pill) {\n      pill.style.background = latte.pillBg; pill.style.borderColor = latte.cardBorder; pill.style.boxShadow = '0 0 0 2px rgba(200,169,126,.25) inset';\n      if (doPulse) { pill.classList.remove('v60-pulse'); void pill.offsetWidth; pill.classList.add('v60-pulse'); }\n    }\n  }\n  function resetPourPills() { Object.values(pills).forEach(function(p) { if (!p) return; p.classList.remove('v60-pill-pour-active'); }); }\n  function setPourPillActive(key) { resetPourPills(); if (!key) return; var pill = pills[key]; if (pill) pill.classList.add('v60-pill-pour-active'); }\n  function clearAll() {\n    Object.values(cards).forEach(function(c) { if (!c) return; c.style.borderColor = 'rgba(0,0,0,.18)'; c.style.background = 'transparent'; c.style.boxShadow = 'none'; });\n    Object.values(pills).forEach(function(p) { if (!p) return; p.style.background = 'rgba(0,0,0,.05)'; p.style.borderColor = 'rgba(0,0,0,.12)'; p.style.boxShadow = 'none'; p.classList.remove('v60-pulse'); p.classList.remove('v60-pill-pour-active'); });\n  }\n  var wakeLock = null; var startTime = null; var rafId = null; var lastPhaseKey = null; var lastPourKey = null;\n  function fmt(sec) { sec = Math.max(0, Math.floor(sec)); var m = Math.floor(sec \/ 60); var s = sec % 60; return m + ':' + (s \u0026lt; 10 ? '0' : '') + s; }\n  function getCurrentPhaseKey(elapsed) { var current = phases[0].key; for (var i = 0; i \u0026lt; phases.length; i++) if (elapsed \u0026gt;= phases[i].t) current = phases[i].key; return current; }\n  function getPourKey(elapsed) { for (var i = phases.length - 1; i \u0026gt;= 0; i--) { var p = phases[i]; if (elapsed \u0026gt;= p.t \u0026amp;\u0026amp; elapsed \u0026lt; (p.t + p.pourLen)) return p.key; } return null; }\n  function enableWakeLock() {\n    if (!('wakeLock' in navigator)) { statusEl.textContent = '⚠️ Ton navigateur ne supporte pas le mode écran allumé.'; return Promise.resolve(); }\n    return navigator.wakeLock.request('screen').then(function(wl) {\n      wakeLock = wl; statusEl.textContent = '✅ Écran maintenu allumé pendant la recette.';\n      wakeLock.addEventListener('release', function() { statusEl.textContent = 'ℹ️ Mode écran allumé relâché.'; });\n    }).catch(function() { statusEl.textContent = '⚠️ Impossible d\\'activer le mode écran allumé.'; wakeLock = null; });\n  }\n  function disableWakeLock() { if (wakeLock) { wakeLock.release(); wakeLock = null; } }\n  function setButtons(running) { startBtn.disabled = running; stopBtn.disabled = !running; stopBtn.style.opacity = running ? '1' : '.5'; }\n  function tick() {\n    var elapsed = (Date.now() - startTime) \/ 1000;\n    timerEl.textContent = fmt(elapsed);\n    var phaseKey = getCurrentPhaseKey(elapsed);\n    if (phaseKey !== lastPhaseKey) { setCardActive(phaseKey); setPillPhaseActive(phaseKey, lastPhaseKey !== null); lastPhaseKey = phaseKey; }\n    var pourKey = getPourKey(elapsed);\n    if (pourKey !== lastPourKey) { setPourPillActive(pourKey); lastPourKey = pourKey; }\n    if (elapsed \u0026gt;= END_AT) { stopRecipe(true); return; }\n    rafId = requestAnimationFrame(tick);\n  }\n  function startRecipe() {\n    setButtons(true); timerEl.textContent = '0:00'; lastPhaseKey = null; lastPourKey = null;\n    enableWakeLock().then(function() {\n      setCardActive(1); setPillPhaseActive(1, false); setPourPillActive(1); lastPhaseKey = 1; lastPourKey = 1;\n      startTime = Date.now(); if (rafId) cancelAnimationFrame(rafId); rafId = requestAnimationFrame(tick);\n    });\n  }\n  function stopRecipe(autoEnded) {\n    if (rafId) cancelAnimationFrame(rafId); rafId = null; startTime = null; disableWakeLock(); setButtons(false); clearAll(); lastPhaseKey = null; lastPourKey = null;\n    if (autoEnded) { statusEl.textContent = '✅ Recette terminée — écran libéré.'; timerEl.textContent = fmt(END_AT); }\n    else { statusEl.textContent = 'ℹ️ Recette arrêtée — écran libéré.'; }\n  }\n  startBtn.addEventListener('click', startRecipe);\n  stopBtn.addEventListener('click', function() { stopRecipe(false); });\n  details.addEventListener('toggle', function() { if (!details.open) stopRecipe(false); });\n  document.addEventListener('visibilitychange', function() { if (document.visibilityState === 'visible' \u0026amp;\u0026amp; startTime \u0026amp;\u0026amp; !wakeLock) enableWakeLock(); });\n})();\n\u003c\/script\u003e\n\u003c\/svg\u003e","brand":"ZAB","offers":[{"title":"300g","offer_id":50752008454453,"sku":"CAF-SIN-JESU-300","price":31.0,"currency_code":"CAD","in_stock":true},{"title":"808g","offer_id":50752008487221,"sku":"CAF-SIN-JESU-808","price":76.0,"currency_code":"CAD","in_stock":true},{"title":"2268g (5lbs)","offer_id":50752008519989,"sku":"CAF-SIN-JESU-2268","price":200.0,"currency_code":"CAD","in_stock":true},{"title":"100g","offer_id":53138133811509,"sku":"CAF-SIN-JESU-100","price":15.5,"currency_code":"CAD","in_stock":true},{"title":"Bucket - 5lbs (Livraison locale seulement)","offer_id":53138133844277,"sku":"CAF-SIN-JESU-BUCK-5","price":225.0,"currency_code":"CAD","in_stock":true},{"title":"Bucket - 15lbs (Livraison locale seulement)","offer_id":53138133877045,"sku":"CAF-SIN-JESU-BUCK-15","price":625.0,"currency_code":"CAD","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/2716\/1842\/files\/jesus-300g-retour.jpg?v=1784320032"},{"product_id":"ethiopie-tero","title":"ÉTHIOPIE - TERO","description":"\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 1 : NOTES DE DÉGUSTATION\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto; border: 2px solid var(--product-box-background, #000); border-radius: 12px; overflow: hidden;\"\u003e\n\u003cdiv style=\"padding: 10px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center;\"\u003eNotes de dégustation\u003c\/div\u003e\n\u003cdiv style=\"padding: 16px 14px; font-weight: 900; text-transform: uppercase; font-size: 28px; letter-spacing: .05em; text-align: center; background: transparent;\"\u003eFRAMBOISE + CARAMEL + EARL GREY\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 1 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003cdiv style=\"position: relative; width: 100%; padding-bottom: 56.25%; height: 0; overflow: hidden; border-radius: 8px;\"\u003e\u003ciframe style=\"position: absolute; top: 0; left: 0; width: 100%; height: 100%; border: 0; border-radius: 8px;\" src=\"https:\/\/www.youtube.com\/embed\/ISfsfawrmVs\" title=\"YouTube video player\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" allowfullscreen=\"\"\u003e\n\u003c\/iframe\u003e\u003c\/div\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 2 : APPROVISIONNEMENT\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto;\"\u003e\n\u003cdiv style=\"padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center; border-radius: 12px 12px 0 0;\"\u003eApprovisionnement\u003c\/div\u003e\n\u003ctable border=\"3\" cellpadding=\"1\" cellspacing=\"1\" style=\"width: 100%; border-collapse: collapse; background: transparent;\"\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd style=\"width: 20%;\"\u003eORIGINE\u003c\/td\u003e\n\u003ctd\u003eZone de Guji, région d’Oromia, Éthiopie\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePRODUCTEURS\u003c\/td\u003e\n\u003ctd\u003e450 petit·es producteur·rices du groupe Dimtu Coffee Industry\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eFERME\u003c\/td\u003e\n\u003ctd\u003eTero\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eVARIÉTÉ\u003c\/td\u003e\n\u003ctd\u003e74110, 74158\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePROCÉDÉ\u003c\/td\u003e\n\u003ctd\u003eLavé\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eALTITUDE\u003c\/td\u003e\n\u003ctd\u003e2400 m\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePARTENAIRES\u003c\/td\u003e\n\u003ctd\u003eCrop to Cup\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eVOLUME ACHETÉ\u003c\/td\u003e\n\u003ctd\u003e600 kg\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eFAB\u003c\/td\u003e\n\u003ctd\u003e4,90 $ US\/lb\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eRELATION\u003c\/td\u003e\n\u003ctd\u003e3 ans\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003c\/tbody\u003e\n\u003c\/table\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 2 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 3 : INFORMATIONS SUR LE CAFÉ\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto;\"\u003e\n\u003cdiv style=\"padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center; border-radius: 12px 12px 0 0;\"\u003eInformations sur le café\u003c\/div\u003e\n\u003cdiv style=\"border: 2px solid var(--product-box-background, #000); border-top: none; border-radius: 0 0 12px 12px; padding: 16px 14px; background: transparent;\"\u003e\n\u003cp style=\"margin: 0 0 12px 0;\"\u003eDès la première gorgée, la framboise apporte une touche fruitée et délicatement acidulée. Le caramel s’installe ensuite avec une douceur gourmande et une texture crémeuse, accompagné de notes florales et bergamotées rappelant le thé Earl Grey. La finale douce et persistante révèle des notes de thé noir qui équilibrent la richesse du caramel et la fraîcheur de la framboise.\u003c\/p\u003e\n\u003cp style=\"margin: 0 0 12px 0;\"\u003eTero, c’est le nom de la ferme de Getachew Zeleke, le propriétaire du groupe d’exportation Dimtu. Tero est composé du café de Getachew ainsi que de celui de 450 petit·es producteur·rices des collines avoisinantes.\u003c\/p\u003e\n\u003cp style=\"margin: 0 0 12px 0;\"\u003eBien avant de cultiver du café, Getachew était comptable. Grâce à ses économies, il a réussi à s’acheter un terrain à Addis-Abeba. En 2008, avec la montée de l'immobilier, il revend ce terrain et utilise l’argent pour acheter une parcelle de terre, qui deviendra la ferme Tero.\u003c\/p\u003e\n\u003cp style=\"margin: 0 0 12px 0;\"\u003ePetit à petit, il commence à récolter ses propres cerises puis celles des producteur·rices de sa région, pour les revendre une fois séchées sur le marché local. En 2016, il construit sa propre station de lavage et passe au café de spécialité : Dimtu Coffee Industry est né.\u003c\/p\u003e\n\u003cp style=\"margin: 0;\"\u003eMais ce n’est pas tout. Insatisfait des centres de décorticage du café, trop lents et pas assez précis, Getachew décide d’en construire une lui-même. Résultat : un contrôle total sur chaque étape, de la cerise à l’exportation. Et c’est ça qu’on aime. Ce souci du détail, cet engagement pour la qualité, cette rigueur de comptable… tout ça fait de Getachew un partenaire exceptionnel !\u003c\/p\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 3 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 4 : PARAMÈTRES D'EXTRACTION — ESPRESSO\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto;\"\u003e\n\u003cdetails open=\"\" style=\"border: 2px solid var(--product-box-background, #000); border-radius: 12px; overflow: hidden; margin: 0 0 12px 0; background: rgba(255,255,255,0.5);\"\u003e\n\u003csummary style=\"cursor: pointer; list-style: none; padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center;\"\u003eEspresso — paramètres recommandés\u003c\/summary\u003e\n\u003cdiv style=\"padding: 12px 14px;\"\u003e\n\u003ctable style=\"width: 100%; border-collapse: collapse; background: transparent;\"\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd style=\"padding: 10px 0; font-weight: 800; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003eCafé moulu\u003c\/td\u003e\n\u003ctd style=\"padding: 10px 0; text-align: right; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003e18 g\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd style=\"padding: 10px 0; font-weight: 800; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003eCafé dans la tasse\u003c\/td\u003e\n\u003ctd style=\"padding: 10px 0; text-align: right; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003e37 g\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd style=\"padding: 10px 0; font-weight: 800;\"\u003eTemps d'extraction\u003c\/td\u003e\n\u003ctd style=\"padding: 10px 0; text-align: right;\"\u003e27 sec\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003c\/tbody\u003e\n\u003c\/table\u003e\n\u003cdiv style=\"margin-top: 10px; padding: 8px 10px; border-radius: 8px; background: rgba(0,0,0,.04); border: 1px dashed rgba(0,0,0,.2); font-size: 12px; opacity: .7; line-height: 1.4;\"\u003e\n\u003cstrong\u003eÀ noter —\u003c\/strong\u003e Recette optimisée pour un panier de \u003cstrong\u003e18 g\u003c\/strong\u003e. Consulte le manuel de ta machine pour connaître la capacité de ton panier.\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/details\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 4 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 5 : V60\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto;\"\u003e\n\u003cdetails id=\"v60Details-tero\" open=\"\" style=\"border: 2px solid var(--product-box-background, #000); border-radius: 12px; overflow: hidden; margin: 0 0 12px 0; background: rgba(255,255,255,0.5);\"\u003e\n\u003csummary style=\"cursor: pointer; list-style: none; padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center;\"\u003eV60 – Recette\u003c\/summary\u003e\n\u003cdiv style=\"padding: 12px 14px;\"\u003e\n\u003cdiv style=\"padding: 10px 0 10px; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003e\n\u003cdiv style=\"font-weight: 900; font-size: 16px;\"\u003eRatio 1:15\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 4px; opacity: .7; font-size: 13px;\"\u003e15 g in – 225 g out\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 6px; font-size: 13px;\"\u003e\n\u003cstrong\u003eTempérature de l'eau :\u003c\/strong\u003e 91 °C\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; padding: 10px 0 8px;\"\u003e\n\u003cdiv style=\"display: flex; gap: 8px; align-items: center; flex-wrap: wrap;\"\u003e\n\u003cbutton style=\"cursor: pointer; border: 2px solid var(--product-box-background, #000); background: var(--product-box-background, #000); color: var(--product-box-text, #fff); font-weight: 900; padding: 8px 10px; border-radius: 10px; text-transform: uppercase; letter-spacing: .02em; font-size: 12px;\" type=\"button\" id=\"v60StartBtn-tero\"\u003eDémarrer\u003c\/button\u003e \u003cbutton style=\"cursor: pointer; border: 2px solid var(--product-box-background, #000); background: var(--product-box-text, #fff); color: var(--product-box-background, #000); font-weight: 900; padding: 8px 10px; border-radius: 10px; text-transform: uppercase; letter-spacing: .02em; font-size: 12px; opacity: .5;\" disabled type=\"button\" id=\"v60StopBtn-tero\"\u003eStop\u003c\/button\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; line-height: 1;\"\u003e\n\u003cspan style=\"opacity: .70; font-size: 12px; font-weight: 800; text-transform: uppercase; letter-spacing: .04em;\"\u003eTimer\u003c\/span\u003e \u003cspan style=\"font-weight: 950; font-size: 28px; letter-spacing: .01em;\" id=\"v60Timer-tero\"\u003e0:00\u003c\/span\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"flex-basis: 100%; opacity: .6; font-size: 12px; line-height: 1.3; margin-top: 2px;\" id=\"v60WakeStatus-tero\"\u003eℹ️ Appuie sur \"Démarrer\" pour garder l'écran allumé.\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 8px; display: grid; gap: 10px;\"\u003e\n\u003cdiv style=\"border: 1px solid rgba(0,0,0,.18); border-radius: 12px; padding: 10px 12px;\" id=\"v60-card-1-tero\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; margin-bottom: 6px;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e0:00\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003ePhase 1 — Bloom\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 8px; flex-wrap: wrap; font-size: 12.5px; font-weight: 800;\"\u003e\n\u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\" id=\"v60-pill-1-tero\"\u003eVerser pendant 0:10s\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\"\u003eTotal 50 g\u003c\/span\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"border: 1px solid rgba(0,0,0,.18); border-radius: 12px; padding: 10px 12px;\" id=\"v60-card-2-tero\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; margin-bottom: 6px;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e0:40\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003ePhase 2\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 8px; flex-wrap: wrap; font-size: 12.5px; font-weight: 800;\"\u003e\n\u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\" id=\"v60-pill-2-tero\"\u003eVerser pendant 0:10s\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\"\u003eTotal 100 g\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12); opacity: .6;\"\u003e+50 g\u003c\/span\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"border: 1px solid rgba(0,0,0,.18); border-radius: 12px; padding: 10px 12px;\" id=\"v60-card-3-tero\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; margin-bottom: 6px;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e1:20\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003ePhase 3\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 8px; flex-wrap: wrap; font-size: 12.5px; font-weight: 800;\"\u003e\n\u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\" id=\"v60-pill-3-tero\"\u003eVerser pendant 0:10s\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\"\u003eTotal 170 g\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12); opacity: .6;\"\u003e+70 g\u003c\/span\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"border: 1px solid rgba(0,0,0,.18); border-radius: 12px; padding: 10px 12px;\" id=\"v60-card-4-tero\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; margin-bottom: 6px;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e1:55\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003ePhase 4\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 8px; flex-wrap: wrap; font-size: 12.5px; font-weight: 800;\"\u003e\n\u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\" id=\"v60-pill-4-tero\"\u003eVerser pendant 0:10s\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\"\u003eTotal 225 g\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12); opacity: .6;\"\u003e+55 g\u003c\/span\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 12px; border-top: 1px solid rgba(0,0,0,.2); padding-top: 10px;\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e2:40\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003eTemps final écoulement complet\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 8px; padding: 8px 10px; border-radius: 8px; background: rgba(0,0,0,.04); border: 1px dashed rgba(0,0,0,.2); font-size: 12px; opacity: .6; line-height: 1.4;\"\u003e\n\u003cstrong\u003eℹ️ Astuce —\u003c\/strong\u003e Si le temps total est plus court, la mouture est probablement trop grosse. S'il est plus long, la mouture est probablement trop fine.\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/details\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 5 ========= --\u003e\u003csvg style=\"display: none;\"\u003e\n\u003cstyle\u003e\n  @keyframes v60PulsePhase {\n    0%   { transform: scale(1);    box-shadow: 0 0 0 0 rgba(200,169,126,.35); }\n    50%  { transform: scale(1.06); box-shadow: 0 0 0 10px rgba(200,169,126,0); }\n    100% { transform: scale(1);    box-shadow: 0 0 0 0 rgba(200,169,126,0); }\n  }\n  .v60-pulse {\n    animation: v60PulsePhase 700ms ease-out 1;\n    transform-origin: center;\n    will-change: transform;\n  }\n  @keyframes v60BlinkPill {\n    0%, 100% { opacity: 1; transform: scale(1); }\n    50%      { opacity: .22; transform: scale(1.03); }\n  }\n  .v60-pill-pour-active {\n    background: #ffe7b7 !important;\n    border: 2px solid #d2a44a !important;\n    color: #3b2a12 !important;\n    font-weight: 900 !important;\n    letter-spacing: .02em;\n    animation: v60BlinkPill 2500ms ease-in-out infinite;\n    box-shadow:\n      0 0 0 2px rgba(210,164,74,.18) inset,\n      0 10px 22px rgba(0,0,0,.12),\n      0 0 0 6px rgba(210,164,74,.10);\n  }\n  @media (prefers-reduced-motion: reduce) {\n    .v60-pill-pour-active { animation: none; }\n    .v60-pulse { animation: none; }\n  }\n\u003c\/style\u003e\n\u003cscript\u003e\n(function() {\n  var SUFFIX = '-tero';\n  var END_AT = 160;\n  var phases = [\n    { key: 1, t: 0,   pourLen: 10 },\n    { key: 2, t: 40,  pourLen: 10 },\n    { key: 3, t: 80,  pourLen: 10 },\n    { key: 4, t: 115, pourLen: 10 }\n  ];\n  var latte = {\n    cardBg:     '#f6f1ea',\n    cardBorder: '#c8a97e',\n    pillBg:     '#eadfce'\n  };\n  var details  = document.getElementById('v60Details'    + SUFFIX);\n  var startBtn = document.getElementById('v60StartBtn'   + SUFFIX);\n  var stopBtn  = document.getElementById('v60StopBtn'    + SUFFIX);\n  var timerEl  = document.getElementById('v60Timer'      + SUFFIX);\n  var statusEl = document.getElementById('v60WakeStatus' + SUFFIX);\n  var pills = {\n    1: document.getElementById('v60-pill-1' + SUFFIX),\n    2: document.getElementById('v60-pill-2' + SUFFIX),\n    3: document.getElementById('v60-pill-3' + SUFFIX),\n    4: document.getElementById('v60-pill-4' + SUFFIX)\n  };\n  var cards = {\n    1: document.getElementById('v60-card-1' + SUFFIX),\n    2: document.getElementById('v60-card-2' + SUFFIX),\n    3: document.getElementById('v60-card-3' + SUFFIX),\n    4: document.getElementById('v60-card-4' + SUFFIX)\n  };\n  function setCardActive(key) {\n    Object.keys(cards).forEach(function(k) {\n      var c = cards[k];\n      if (!c) return;\n      if (parseInt(k) === key) {\n        c.style.borderColor = latte.cardBorder;\n        c.style.background  = latte.cardBg;\n        c.style.boxShadow   = '0 0 0 2px rgba(200,169,126,.25) inset, 0 8px 22px rgba(200,169,126,.28)';\n      } else {\n        c.style.borderColor = 'rgba(0,0,0,.18)';\n        c.style.background  = 'transparent';\n        c.style.boxShadow   = 'none';\n      }\n    });\n  }\n  function setPillPhaseActive(key, doPulse) {\n    Object.keys(pills).forEach(function(k) {\n      var p = pills[k];\n      if (!p) return;\n      p.style.background  = 'rgba(0,0,0,.05)';\n      p.style.borderColor = 'rgba(0,0,0,.12)';\n      p.style.boxShadow   = 'none';\n      p.classList.remove('v60-pulse');\n    });\n    var pill = pills[key];\n    if (pill) {\n      pill.style.background  = latte.pillBg;\n      pill.style.borderColor = latte.cardBorder;\n      pill.style.boxShadow   = '0 0 0 2px rgba(200,169,126,.25) inset';\n      if (doPulse) {\n        pill.classList.remove('v60-pulse');\n        void pill.offsetWidth;\n        pill.classList.add('v60-pulse');\n      }\n    }\n  }\n  function resetPourPills() {\n    Object.values(pills).forEach(function(p) {\n      if (!p) return;\n      p.classList.remove('v60-pill-pour-active');\n    });\n  }\n  function setPourPillActive(key) {\n    resetPourPills();\n    if (!key) return;\n    var pill = pills[key];\n    if (pill) pill.classList.add('v60-pill-pour-active');\n  }\n  function clearAll() {\n    Object.values(cards).forEach(function(c) {\n      if (!c) return;\n      c.style.borderColor = 'rgba(0,0,0,.18)';\n      c.style.background  = 'transparent';\n      c.style.boxShadow   = 'none';\n    });\n    Object.values(pills).forEach(function(p) {\n      if (!p) return;\n      p.style.background  = 'rgba(0,0,0,.05)';\n      p.style.borderColor = 'rgba(0,0,0,.12)';\n      p.style.boxShadow   = 'none';\n      p.classList.remove('v60-pulse');\n      p.classList.remove('v60-pill-pour-active');\n    });\n  }\n  var wakeLock  = null;\n  var startTime = null;\n  var rafId     = null;\n  var lastPhaseKey = null;\n  var lastPourKey  = null;\n  function fmt(sec) {\n    sec = Math.max(0, Math.floor(sec));\n    var m = Math.floor(sec \/ 60);\n    var s = sec % 60;\n    return m + ':' + (s \u0026lt; 10 ? '0' : '') + s;\n  }\n  function getCurrentPhaseKey(elapsed) {\n    var current = phases[0].key;\n    for (var i = 0; i \u0026lt; phases.length; i++) if (elapsed \u0026gt;= phases[i].t) current = phases[i].key;\n    return current;\n  }\n  function getPourKey(elapsed) {\n    for (var i = phases.length - 1; i \u0026gt;= 0; i--) {\n      var p = phases[i];\n      if (elapsed \u0026gt;= p.t \u0026amp;\u0026amp; elapsed \u0026lt; (p.t + p.pourLen)) return p.key;\n    }\n    return null;\n  }\n  function enableWakeLock() {\n    if (!('wakeLock' in navigator)) {\n      statusEl.textContent = '⚠️ Ton navigateur ne supporte pas le mode écran allumé.';\n      return Promise.resolve();\n    }\n    return navigator.wakeLock.request('screen').then(function(wl) {\n      wakeLock = wl;\n      statusEl.textContent = '✅ Écran maintenu allumé pendant la recette.';\n      wakeLock.addEventListener('release', function() {\n        statusEl.textContent = 'ℹ️ Mode écran allumé relâché.';\n      });\n    }).catch(function() {\n      statusEl.textContent = '⚠️ Impossible d\\'activer le mode écran allumé.';\n      wakeLock = null;\n    });\n  }\n  function disableWakeLock() {\n    if (wakeLock) { wakeLock.release(); wakeLock = null; }\n  }\n  function setButtons(running) {\n    startBtn.disabled = running;\n    stopBtn.disabled  = !running;\n    stopBtn.style.opacity = running ? '1' : '.5';\n  }\n  function tick() {\n    var elapsed = (Date.now() - startTime) \/ 1000;\n    timerEl.textContent = fmt(elapsed);\n    var phaseKey = getCurrentPhaseKey(elapsed);\n    if (phaseKey !== lastPhaseKey) {\n      setCardActive(phaseKey);\n      setPillPhaseActive(phaseKey, lastPhaseKey !== null);\n      lastPhaseKey = phaseKey;\n    }\n    var pourKey = getPourKey(elapsed);\n    if (pourKey !== lastPourKey) {\n      setPourPillActive(pourKey);\n      lastPourKey = pourKey;\n    }\n    if (elapsed \u0026gt;= END_AT) { stopRecipe(true); return; }\n    rafId = requestAnimationFrame(tick);\n  }\n  function startRecipe() {\n    setButtons(true);\n    timerEl.textContent = '0:00';\n    lastPhaseKey = null;\n    lastPourKey  = null;\n    enableWakeLock().then(function() {\n      setCardActive(1);\n      setPillPhaseActive(1, false);\n      setPourPillActive(1);\n      lastPhaseKey = 1;\n      lastPourKey  = 1;\n      startTime = Date.now();\n      if (rafId) cancelAnimationFrame(rafId);\n      rafId = requestAnimationFrame(tick);\n    });\n  }\n  function stopRecipe(autoEnded) {\n    if (rafId) cancelAnimationFrame(rafId);\n    rafId     = null;\n    startTime = null;\n    disableWakeLock();\n    setButtons(false);\n    clearAll();\n    lastPhaseKey = null;\n    lastPourKey  = null;\n    if (autoEnded) {\n      statusEl.textContent = '✅ Recette terminée — écran libéré.';\n      timerEl.textContent  = fmt(END_AT);\n    } else {\n      statusEl.textContent = 'ℹ️ Recette arrêtée — écran libéré.';\n    }\n  }\n  startBtn.addEventListener('click', startRecipe);\n  stopBtn.addEventListener('click', function() { stopRecipe(false); });\n  details.addEventListener('toggle', function() { if (!details.open) stopRecipe(false); });\n  document.addEventListener('visibilitychange', function() {\n    if (document.visibilityState === 'visible' \u0026amp;\u0026amp; startTime \u0026amp;\u0026amp; !wakeLock) enableWakeLock();\n  });\n})();\n\u003c\/script\u003e\n\u003c\/svg\u003e","brand":"ZAB","offers":[{"title":"300g","offer_id":51101415866677,"sku":"CAF-SIN-TERO-300","price":33.0,"currency_code":"CAD","in_stock":true},{"title":"808g","offer_id":51101415899445,"sku":"CAF-SIN-TERO-808","price":80.0,"currency_code":"CAD","in_stock":true},{"title":"2268g (5lbs)","offer_id":51101415932213,"sku":"CAF-SIN-TERO-2268","price":205.0,"currency_code":"CAD","in_stock":true},{"title":"100g","offer_id":53629276782901,"sku":"CAF-SIN-TERO-100","price":16.0,"currency_code":"CAD","in_stock":true},{"title":"Bucket - 5lbs (Livraison locale seulement)","offer_id":53629051601205,"sku":"CAF-SIN-TERO-BUCK-5","price":230.0,"currency_code":"CAD","in_stock":true},{"title":"Bucket - 15lbs (Livraison locale seulement)","offer_id":53629051633973,"sku":"CAF-SIN-TERO-BUCK-15","price":640.0,"currency_code":"CAD","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/2716\/1842\/files\/tero-300g-retour_0615c84f-aa3f-45b6-992d-5db4be0c19cf.jpg?v=1793119978"},{"product_id":"guatemala-raul-perez","title":"GUATEMALA - FAMILLE PEREZ","description":"\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 1 : NOTES DE DÉGUSTATION\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto; border: 2px solid var(--product-box-background, #000); border-radius: 12px; overflow: hidden;\"\u003e\n\u003cdiv style=\"padding: 10px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center;\"\u003eNotes de dégustation\u003c\/div\u003e\n\u003cdiv style=\"padding: 16px 14px; font-weight: 900; text-transform: uppercase; font-size: 28px; letter-spacing: .05em; text-align: center; background: transparent;\"\u003eFUDGE + CARAMEL + POMME ROUGE\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 1 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003cdiv style=\"position: relative; width: 100%; padding-bottom: 56.25%; height: 0; overflow: hidden; border-radius: 8px;\"\u003e\u003ciframe style=\"position: absolute; top: 0; left: 0; width: 100%; height: 100%; border: 0; border-radius: 8px;\" src=\"https:\/\/www.youtube.com\/embed\/emoBWvgfMF0\" title=\"YouTube video player\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" allowfullscreen=\"\"\u003e\n\u003c\/iframe\u003e\u003c\/div\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 2 : APPROVISIONNEMENT\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto;\"\u003e\n\u003cdiv style=\"padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center; border-radius: 12px 12px 0 0;\"\u003eApprovisionnement\u003c\/div\u003e\n\u003ctable border=\"3\" cellpadding=\"1\" cellspacing=\"1\" style=\"width: 100%; border-collapse: collapse; background: transparent;\"\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd style=\"width: 20%;\"\u003eORIGINE\u003c\/td\u003e\n\u003ctd\u003eAcatenango, Chimaltenango, Guatemala\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePRODUCTEURS\u003c\/td\u003e\n\u003ctd\u003eFamille Perez\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eFERME\u003c\/td\u003e\n\u003ctd\u003eFinca La Soledad\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eVARIÉTÉ\u003c\/td\u003e\n\u003ctd\u003eCaturra, Catuai\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePROCÉDÉ\u003c\/td\u003e\n\u003ctd\u003eLavé\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eALTITUDE\u003c\/td\u003e\n\u003ctd\u003e1400-1600 m\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePARTENAIRES\u003c\/td\u003e\n\u003ctd\u003eApex\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eVOLUME ACHETÉ\u003c\/td\u003e\n\u003ctd\u003e345 kg\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eFAB\u003c\/td\u003e\n\u003ctd\u003e4,75 $ US\/lb\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePRIX LIVRÉ\u003c\/td\u003e\n\u003ctd\u003e9,49 $ CAD\/LB\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eRELATION\u003c\/td\u003e\n\u003ctd\u003e3 ans\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003c\/tbody\u003e\n\u003c\/table\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 2 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 3 : INFORMATIONS SUR LE CAFÉ\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto;\"\u003e\n\u003cdiv style=\"padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center; border-radius: 12px 12px 0 0;\"\u003eInformations sur le café\u003c\/div\u003e\n\u003cdiv style=\"border: 2px solid var(--product-box-background, #000); border-top: none; border-radius: 0 0 12px 12px; padding: 16px 14px; background: transparent;\"\u003e\n\u003cp style=\"margin: 0 0 12px 0;\"\u003eUn café d'Amérique centrale avec le côté juteux et sucré de la pomme ainsi qu'une longueur en cacao et sucre. En espresso, sa texture et son sucre rappellent le caramel écossais. En filtre, on découvre un café avec une belle délicatesse et une vibrance qui nous ramène aux temps des pommes. Réconfortant, mais avec cette petite acidité qui nous donne envie de prendre une autre gorgée.\u003c\/p\u003e\n\u003cp style=\"margin: 0 0 12px 0;\"\u003eLa Finca La Soledad se trouve au cœur d'Acatenango, au Guatemala et couvre 90 hectares dont seulement la moitié est consacrée à la production ; le reste est laissé en forêt naturelle, un choix qui préserve l'écosystème et renforce la qualité du terroir.\u003c\/p\u003e\n\u003cp style=\"margin: 0 0 12px 0;\"\u003eRaúl Pérez est un producteur de sixième génération. Avec son père Henio, sa mère Mercedes et son frère José, ils affinent constamment leurs méthodes de transformation pour révéler tout le potentiel de leurs cafés. La Finca La Soledad est d'ailleurs reconnue pour son sens du détail et ses cafés lavés réalisés avec un soin exceptionnel.\u003c\/p\u003e\n\u003cp style=\"margin: 0;\"\u003eLa famille Perez utilise un procédé lavé traditionnel : les cerises mûres sont cueillies à la main, fermentées 40 à 45 heures, puis lavées et séchées sur lits africains pendant 12 à 18 jours. Ce processus donne une tasse propre et vive, aux notes florales, citronnées et tropicales, avec un corps soyeux et une belle complexité.\u003c\/p\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 3 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 4 : PARAMÈTRES D'EXTRACTION — ESPRESSO\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto;\"\u003e\n\u003cdetails open=\"\" style=\"border: 2px solid var(--product-box-background, #000); border-radius: 12px; overflow: hidden; margin: 0 0 12px 0; background: rgba(255,255,255,0.5);\"\u003e\n\u003csummary style=\"cursor: pointer; list-style: none; padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center;\"\u003eEspresso — paramètres recommandés\u003c\/summary\u003e\n\u003cdiv style=\"padding: 12px 14px;\"\u003e\n\u003ctable style=\"width: 100%; border-collapse: collapse; background: transparent;\"\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd style=\"padding: 10px 0; font-weight: 800; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003eCafé moulu\u003c\/td\u003e\n\u003ctd style=\"padding: 10px 0; text-align: right; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003e18 g\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd style=\"padding: 10px 0; font-weight: 800; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003eCafé dans la tasse\u003c\/td\u003e\n\u003ctd style=\"padding: 10px 0; text-align: right; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003e35 g\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd style=\"padding: 10px 0; font-weight: 800;\"\u003eTemps d'extraction\u003c\/td\u003e\n\u003ctd style=\"padding: 10px 0; text-align: right;\"\u003e30 sec\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003c\/tbody\u003e\n\u003c\/table\u003e\n\u003cdiv style=\"margin-top: 10px; padding: 8px 10px; border-radius: 8px; background: rgba(0,0,0,.04); border: 1px dashed rgba(0,0,0,.2); font-size: 12px; opacity: .7; line-height: 1.4;\"\u003e\n\u003cstrong\u003eÀ noter —\u003c\/strong\u003e Recette optimisée pour un panier de \u003cstrong\u003e18 g\u003c\/strong\u003e. Consulte le manuel de ta machine pour connaître la capacité de ton panier.\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/details\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 4 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 5 : V60\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto;\"\u003e\n\u003cdetails id=\"v60Details-perez\" open=\"\" style=\"border: 2px solid var(--product-box-background, #000); border-radius: 12px; overflow: hidden; margin: 0 0 12px 0; background: rgba(255,255,255,0.5);\"\u003e\n\u003csummary style=\"cursor: pointer; list-style: none; padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center;\"\u003eV60 – Recette\u003c\/summary\u003e\n\u003cdiv style=\"padding: 12px 14px;\"\u003e\n\u003cdiv style=\"padding: 10px 0 10px; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003e\n\u003cdiv style=\"font-weight: 900; font-size: 16px;\"\u003eRatio 1:15\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 4px; opacity: .7; font-size: 13px;\"\u003e15 g in – 225 g out\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 6px; font-size: 13px;\"\u003e\n\u003cstrong\u003eTempérature de l'eau :\u003c\/strong\u003e 93 °C\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; padding: 10px 0 8px;\"\u003e\n\u003cdiv style=\"display: flex; gap: 8px; align-items: center; flex-wrap: wrap;\"\u003e\n\u003cbutton style=\"cursor: pointer; border: 2px solid var(--product-box-background, #000); background: var(--product-box-background, #000); color: var(--product-box-text, #fff); font-weight: 900; padding: 8px 10px; border-radius: 10px; text-transform: uppercase; letter-spacing: .02em; font-size: 12px;\" type=\"button\" id=\"v60StartBtn-perez\"\u003eDémarrer\u003c\/button\u003e \u003cbutton style=\"cursor: pointer; border: 2px solid var(--product-box-background, #000); background: var(--product-box-text, #fff); color: var(--product-box-background, #000); font-weight: 900; padding: 8px 10px; border-radius: 10px; text-transform: uppercase; letter-spacing: .02em; font-size: 12px; opacity: .5;\" disabled type=\"button\" id=\"v60StopBtn-perez\"\u003eStop\u003c\/button\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; line-height: 1;\"\u003e\n\u003cspan style=\"opacity: .70; font-size: 12px; font-weight: 800; text-transform: uppercase; letter-spacing: .04em;\"\u003eTimer\u003c\/span\u003e \u003cspan style=\"font-weight: 950; font-size: 28px; letter-spacing: .01em;\" id=\"v60Timer-perez\"\u003e0:00\u003c\/span\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"flex-basis: 100%; opacity: .6; font-size: 12px; line-height: 1.3; margin-top: 2px;\" id=\"v60WakeStatus-perez\"\u003eℹ️ Appuie sur \"Démarrer\" pour garder l'écran allumé.\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 8px; display: grid; gap: 10px;\"\u003e\n\u003cdiv style=\"border: 1px solid rgba(0,0,0,.18); border-radius: 12px; padding: 10px 12px;\" id=\"v60-card-1-perez\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; margin-bottom: 6px;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e0:00\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003ePhase 1 — Bloom\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 8px; flex-wrap: wrap; font-size: 12.5px; font-weight: 800;\"\u003e\n\u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\" id=\"v60-pill-1-perez\"\u003eVerser pendant 0:10s\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\"\u003eTotal 40 g\u003c\/span\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"border: 1px solid rgba(0,0,0,.18); border-radius: 12px; padding: 10px 12px;\" id=\"v60-card-2-perez\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; margin-bottom: 6px;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e0:40\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003ePhase 2\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 8px; flex-wrap: wrap; font-size: 12.5px; font-weight: 800;\"\u003e\n\u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\" id=\"v60-pill-2-perez\"\u003eVerser pendant 0:30s\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\"\u003eTotal 160 g\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12); opacity: .6;\"\u003e+120 g\u003c\/span\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"border: 1px solid rgba(0,0,0,.18); border-radius: 12px; padding: 10px 12px;\" id=\"v60-card-3-perez\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; margin-bottom: 6px;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e1:20\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003ePhase 3\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 8px; flex-wrap: wrap; font-size: 12.5px; font-weight: 800;\"\u003e\n\u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\" id=\"v60-pill-3-perez\"\u003eVerser pendant 0:20s\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\"\u003eTotal 225 g\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12); opacity: .6;\"\u003e+65 g\u003c\/span\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 12px; border-top: 1px solid rgba(0,0,0,.2); padding-top: 10px;\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e2:45\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003eTemps final écoulement complet\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 8px; padding: 8px 10px; border-radius: 8px; background: rgba(0,0,0,.04); border: 1px dashed rgba(0,0,0,.2); font-size: 12px; opacity: .6; line-height: 1.4;\"\u003e\n\u003cstrong\u003eℹ️ Astuce —\u003c\/strong\u003e Si le temps total est plus court, la mouture est probablement trop grosse. S'il est plus long, la mouture est probablement trop fine.\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/details\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 5 ========= --\u003e\u003csvg style=\"display: none;\"\u003e\n\u003cstyle\u003e\n  @keyframes v60PulsePhase {\n    0%   { transform: scale(1);    box-shadow: 0 0 0 0 rgba(200,169,126,.35); }\n    50%  { transform: scale(1.06); box-shadow: 0 0 0 10px rgba(200,169,126,0); }\n    100% { transform: scale(1);    box-shadow: 0 0 0 0 rgba(200,169,126,0); }\n  }\n  .v60-pulse {\n    animation: v60PulsePhase 700ms ease-out 1;\n    transform-origin: center;\n    will-change: transform;\n  }\n  @keyframes v60BlinkPill {\n    0%, 100% { opacity: 1; transform: scale(1); }\n    50%      { opacity: .22; transform: scale(1.03); }\n  }\n  .v60-pill-pour-active {\n    background: #ffe7b7 !important;\n    border: 2px solid #d2a44a !important;\n    color: #3b2a12 !important;\n    font-weight: 900 !important;\n    letter-spacing: .02em;\n    animation: v60BlinkPill 2500ms ease-in-out infinite;\n    box-shadow:\n      0 0 0 2px rgba(210,164,74,.18) inset,\n      0 10px 22px rgba(0,0,0,.12),\n      0 0 0 6px rgba(210,164,74,.10);\n  }\n  @media (prefers-reduced-motion: reduce) {\n    .v60-pill-pour-active { animation: none; }\n    .v60-pulse { animation: none; }\n  }\n\u003c\/style\u003e\n\u003cscript\u003e\n(function() {\n  var SUFFIX = '-perez';\n  var END_AT = 165;\n  var phases = [\n    { key: 1, t: 0,  pourLen: 10 },\n    { key: 2, t: 40, pourLen: 30 },\n    { key: 3, t: 80, pourLen: 20 }\n  ];\n  var latte = {\n    cardBg:     '#f6f1ea',\n    cardBorder: '#c8a97e',\n    pillBg:     '#eadfce'\n  };\n  var details  = document.getElementById('v60Details'    + SUFFIX);\n  var startBtn = document.getElementById('v60StartBtn'   + SUFFIX);\n  var stopBtn  = document.getElementById('v60StopBtn'    + SUFFIX);\n  var timerEl  = document.getElementById('v60Timer'      + SUFFIX);\n  var statusEl = document.getElementById('v60WakeStatus' + SUFFIX);\n  var pills = {\n    1: document.getElementById('v60-pill-1' + SUFFIX),\n    2: document.getElementById('v60-pill-2' + SUFFIX),\n    3: document.getElementById('v60-pill-3' + SUFFIX)\n  };\n  var cards = {\n    1: document.getElementById('v60-card-1' + SUFFIX),\n    2: document.getElementById('v60-card-2' + SUFFIX),\n    3: document.getElementById('v60-card-3' + SUFFIX)\n  };\n  function setCardActive(key) {\n    Object.keys(cards).forEach(function(k) {\n      var c = cards[k];\n      if (!c) return;\n      if (parseInt(k) === key) {\n        c.style.borderColor = latte.cardBorder;\n        c.style.background  = latte.cardBg;\n        c.style.boxShadow   = '0 0 0 2px rgba(200,169,126,.25) inset, 0 8px 22px rgba(200,169,126,.28)';\n      } else {\n        c.style.borderColor = 'rgba(0,0,0,.18)';\n        c.style.background  = 'transparent';\n        c.style.boxShadow   = 'none';\n      }\n    });\n  }\n  function setPillPhaseActive(key, doPulse) {\n    Object.keys(pills).forEach(function(k) {\n      var p = pills[k];\n      if (!p) return;\n      p.style.background  = 'rgba(0,0,0,.05)';\n      p.style.borderColor = 'rgba(0,0,0,.12)';\n      p.style.boxShadow   = 'none';\n      p.classList.remove('v60-pulse');\n    });\n    var pill = pills[key];\n    if (pill) {\n      pill.style.background  = latte.pillBg;\n      pill.style.borderColor = latte.cardBorder;\n      pill.style.boxShadow   = '0 0 0 2px rgba(200,169,126,.25) inset';\n      if (doPulse) {\n        pill.classList.remove('v60-pulse');\n        void pill.offsetWidth;\n        pill.classList.add('v60-pulse');\n      }\n    }\n  }\n  function resetPourPills() {\n    Object.values(pills).forEach(function(p) {\n      if (!p) return;\n      p.classList.remove('v60-pill-pour-active');\n    });\n  }\n  function setPourPillActive(key) {\n    resetPourPills();\n    if (!key) return;\n    var pill = pills[key];\n    if (pill) pill.classList.add('v60-pill-pour-active');\n  }\n  function clearAll() {\n    Object.values(cards).forEach(function(c) {\n      if (!c) return;\n      c.style.borderColor = 'rgba(0,0,0,.18)';\n      c.style.background  = 'transparent';\n      c.style.boxShadow   = 'none';\n    });\n    Object.values(pills).forEach(function(p) {\n      if (!p) return;\n      p.style.background  = 'rgba(0,0,0,.05)';\n      p.style.borderColor = 'rgba(0,0,0,.12)';\n      p.style.boxShadow   = 'none';\n      p.classList.remove('v60-pulse');\n      p.classList.remove('v60-pill-pour-active');\n    });\n  }\n  var wakeLock  = null;\n  var startTime = null;\n  var rafId     = null;\n  var lastPhaseKey = null;\n  var lastPourKey  = null;\n  function fmt(sec) {\n    sec = Math.max(0, Math.floor(sec));\n    var m = Math.floor(sec \/ 60);\n    var s = sec % 60;\n    return m + ':' + (s \u0026lt; 10 ? '0' : '') + s;\n  }\n  function getCurrentPhaseKey(elapsed) {\n    var current = phases[0].key;\n    for (var i = 0; i \u0026lt; phases.length; i++) if (elapsed \u0026gt;= phases[i].t) current = phases[i].key;\n    return current;\n  }\n  function getPourKey(elapsed) {\n    for (var i = phases.length - 1; i \u0026gt;= 0; i--) {\n      var p = phases[i];\n      if (elapsed \u0026gt;= p.t \u0026amp;\u0026amp; elapsed \u0026lt; (p.t + p.pourLen)) return p.key;\n    }\n    return null;\n  }\n  function enableWakeLock() {\n    if (!('wakeLock' in navigator)) {\n      statusEl.textContent = '⚠️ Ton navigateur ne supporte pas le mode écran allumé.';\n      return Promise.resolve();\n    }\n    return navigator.wakeLock.request('screen').then(function(wl) {\n      wakeLock = wl;\n      statusEl.textContent = '✅ Écran maintenu allumé pendant la recette.';\n      wakeLock.addEventListener('release', function() {\n        statusEl.textContent = 'ℹ️ Mode écran allumé relâché.';\n      });\n    }).catch(function() {\n      statusEl.textContent = '⚠️ Impossible d\\'activer le mode écran allumé.';\n      wakeLock = null;\n    });\n  }\n  function disableWakeLock() {\n    if (wakeLock) { wakeLock.release(); wakeLock = null; }\n  }\n  function setButtons(running) {\n    startBtn.disabled = running;\n    stopBtn.disabled  = !running;\n    stopBtn.style.opacity = running ? '1' : '.5';\n  }\n  function tick() {\n    var elapsed = (Date.now() - startTime) \/ 1000;\n    timerEl.textContent = fmt(elapsed);\n    var phaseKey = getCurrentPhaseKey(elapsed);\n    if (phaseKey !== lastPhaseKey) {\n      setCardActive(phaseKey);\n      setPillPhaseActive(phaseKey, lastPhaseKey !== null);\n      lastPhaseKey = phaseKey;\n    }\n    var pourKey = getPourKey(elapsed);\n    if (pourKey !== lastPourKey) {\n      setPourPillActive(pourKey);\n      lastPourKey = pourKey;\n    }\n    if (elapsed \u0026gt;= END_AT) { stopRecipe(true); return; }\n    rafId = requestAnimationFrame(tick);\n  }\n  function startRecipe() {\n    setButtons(true);\n    timerEl.textContent = '0:00';\n    lastPhaseKey = null;\n    lastPourKey  = null;\n    enableWakeLock().then(function() {\n      setCardActive(1);\n      setPillPhaseActive(1, false);\n      setPourPillActive(1);\n      lastPhaseKey = 1;\n      lastPourKey  = 1;\n      startTime = Date.now();\n      if (rafId) cancelAnimationFrame(rafId);\n      rafId = requestAnimationFrame(tick);\n    });\n  }\n  function stopRecipe(autoEnded) {\n    if (rafId) cancelAnimationFrame(rafId);\n    rafId     = null;\n    startTime = null;\n    disableWakeLock();\n    setButtons(false);\n    clearAll();\n    lastPhaseKey = null;\n    lastPourKey  = null;\n    if (autoEnded) {\n      statusEl.textContent = '✅ Recette terminée — écran libéré.';\n      timerEl.textContent  = fmt(END_AT);\n    } else {\n      statusEl.textContent = 'ℹ️ Recette arrêtée — écran libéré.';\n    }\n  }\n  startBtn.addEventListener('click', startRecipe);\n  stopBtn.addEventListener('click', function() { stopRecipe(false); });\n  details.addEventListener('toggle', function() { if (!details.open) stopRecipe(false); });\n  document.addEventListener('visibilitychange', function() {\n    if (document.visibilityState === 'visible' \u0026amp;\u0026amp; startTime \u0026amp;\u0026amp; !wakeLock) enableWakeLock();\n  });\n})();\n\u003c\/script\u003e\n\u003c\/svg\u003e","brand":"ZAB","offers":[{"title":"300g","offer_id":51756481282357,"sku":"CAF-SIN-PERE-300","price":30.0,"currency_code":"CAD","in_stock":true},{"title":"808g","offer_id":51756481315125,"sku":"CAF-SIN-PERE-808","price":72.0,"currency_code":"CAD","in_stock":true},{"title":"2268g (5lbs)","offer_id":51756481347893,"sku":"CAF-SIN-PERE-2268","price":190.0,"currency_code":"CAD","in_stock":true},{"title":"100g","offer_id":51756481380661,"sku":"CAF-SIN-PERE-100","price":15.0,"currency_code":"CAD","in_stock":true},{"title":"Bucket - 5lbs (Livraison locale seulement)","offer_id":52568888115509,"sku":"CAF-SIN-PERE-BUCK-5","price":215.0,"currency_code":"CAD","in_stock":true},{"title":"Bucket - 15lbs (Livraison locale seulement)","offer_id":52568888148277,"sku":"CAF-SIN-PERE-BUCK-15","price":595.0,"currency_code":"CAD","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/2716\/1842\/files\/famille-perez-300g-retour_61700b9a-7699-4ac5-92d0-4f7a678e0631.jpg?v=1791466811"},{"product_id":"cism-perou-las-tabaconas","title":"PÉROU - TABACONAS","description":"\u003c!-- =========================================================\n  SECTION PROMO : RABAIS COMBINÉ AVEC IMAGES TASSE\n========================================================= --\u003e\u003c!-- =========================================================\n  SECTION 2 : APPROVISIONNEMENT\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto;\"\u003e\n\u003c!-- =========================================================\n  SECTION 1 : NOTES DE DÉGUSTATION\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto; border: 2px solid var(--product-box-background, #000); border-radius: 12px; overflow: hidden;\"\u003e\n\u003cdiv style=\"padding-top: 10px; padding-right: 14px; padding-bottom: 10px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: 0.02em; background: rgb(0, 0, 0); color: rgb(255, 255, 255); text-align: center;\"\u003e   Notes de dégustation\u003c\/div\u003e\n\u003cdiv style=\"padding: 16px 14px; font-weight: 900; text-transform: uppercase; font-size: 28px; letter-spacing: .05em; text-align: center; background: transparent;\"\u003eNECTARINE + CACAO + CARAMEL\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 1 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 2 : APPROVISIONNEMENT\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto;\"\u003e\n\u003cdiv style=\"padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center; border-radius: 12px 12px 0 0;\"\u003eApprovisionnement\u003c\/div\u003e\n\u003ctable border=\"3\" cellpadding=\"1\" cellspacing=\"1\" style=\"width: 100%; border-collapse: collapse; background: transparent;\"\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd style=\"width: 20%;\"\u003eORIGINE\u003c\/td\u003e\n\u003ctd\u003eDistrict de Tabacones, Région de San Ignacio, province de Cajamarca, Pérou\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePRODUCTEURS\u003c\/td\u003e\n\u003ctd\u003e18 petits producteurs\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eVARIÉTÉS\u003c\/td\u003e\n\u003ctd\u003eVariées\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePROCÉDÉ\u003c\/td\u003e\n\u003ctd\u003eLavé\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eALTITUDE\u003c\/td\u003e\n\u003ctd\u003e1500 - 1850 m\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePARTENAIRES\u003c\/td\u003e\n\u003ctd\u003eApex Coffee Imports\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eVOLUME ACHETÉ\u003c\/td\u003e\n\u003ctd\u003e1035 kg\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eFAB\u003c\/td\u003e\n\u003ctd\u003e3,77 $ US\/lb\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePRIX LIVRÉ\u003c\/td\u003e\n\u003ctd\u003e7,87 $ CAD\/lb\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eRELATION\u003c\/td\u003e\n\u003ctd\u003e1 an\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003c\/tbody\u003e\n\u003c\/table\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 2 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 3 : INFORMATIONS SUR LE CAFÉ\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto;\"\u003e\n\u003cdiv style=\"padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center; border-radius: 12px 12px 0 0;\"\u003eInformations sur le café\u003c\/div\u003e\n\u003cdiv style=\"border: 2px solid var(--product-box-background, #000); border-top: none; border-radius: 0 0 12px 12px; padding: 16px 14px; background: transparent;\"\u003e\n\u003cp style=\"margin: 0 0 12px 0;\"\u003eTabaconas, à San Ignacio, est une région caféière d'altitude idéale pour l'arabica de spécialité. Cinq cents familles y cultivent le Typica, le Bourbon ou le Caturra, souvent sous ombrage et de façon durable. Ce blend inclut 18 producteur·rices de la région et offre des notes de nectarine, de cacao et de caramel.\u003c\/p\u003e\n\u003cp style=\"margin: 0;\"\u003eCe café fait partie de l'initiative Café Solidario, créée en 2017 pour unir les producteurs et promouvoir des pratiques durables et équitables. Aujourd'hui, 255 producteurs (320 familles) cultivent plusieurs variétés certifiées, portés par la solidarité et le respect de l'environnement, avec l'ambition de devenir une référence nationale et internationale.\u003c\/p\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 3 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 4 : PARAMÈTRES D'EXTRACTION — ESPRESSO\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto;\"\u003e\n\u003cdetails open=\"\" style=\"border: 2px solid var(--product-box-background, #000); border-radius: 12px; overflow: hidden; margin: 0 0 12px 0; background: rgba(255,255,255,0.5);\"\u003e\n\u003csummary style=\"cursor: pointer; list-style: none; padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center;\"\u003eEspresso — paramètres recommandés\u003c\/summary\u003e\n\u003cdiv style=\"padding: 12px 14px;\"\u003e\n\u003ctable style=\"width: 100%; border-collapse: collapse; background: transparent;\"\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd style=\"padding: 10px 0; font-weight: 800; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003eCafé moulu\u003c\/td\u003e\n\u003ctd style=\"padding: 10px 0; text-align: right; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003e18,5 g\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd style=\"padding: 10px 0; font-weight: 800; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003eCafé dans la tasse\u003c\/td\u003e\n\u003ctd style=\"padding: 10px 0; text-align: right; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003e36 g\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd style=\"padding: 10px 0; font-weight: 800;\"\u003eTemps d'extraction\u003c\/td\u003e\n\u003ctd style=\"padding: 10px 0; text-align: right;\"\u003e30 sec\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003c\/tbody\u003e\n\u003c\/table\u003e\n\u003cdiv style=\"margin-top: 10px; padding: 8px 10px; border-radius: 8px; background: rgba(0,0,0,.04); border: 1px dashed rgba(0,0,0,.2); font-size: 12px; opacity: .7; line-height: 1.4;\"\u003e\n\u003cstrong\u003eÀ noter —\u003c\/strong\u003e Recette optimisée pour un panier de \u003cstrong\u003e18 g\u003c\/strong\u003e. Consulte le manuel de ta machine pour connaître la capacité de ton panier.\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/details\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 4 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 5 : V60\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto;\"\u003e\n\u003cdetails id=\"v60Details-tabacones\" open=\"\" style=\"border: 2px solid var(--product-box-background, #000); border-radius: 12px; overflow: hidden; margin: 0 0 12px 0; background: rgba(255,255,255,0.5);\"\u003e\n\u003csummary style=\"cursor: pointer; list-style: none; padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center;\"\u003eV60 – Recette\u003c\/summary\u003e\n\u003cdiv style=\"padding: 12px 14px;\"\u003e\n\u003cdiv style=\"padding: 10px 0 10px; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003e\n\u003cdiv style=\"font-weight: 900; font-size: 16px;\"\u003eRatio 1:15\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 4px; opacity: .7; font-size: 13px;\"\u003e15 g in – 225 g out\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 6px; font-size: 13px;\"\u003e\n\u003cstrong\u003eTempérature de l'eau :\u003c\/strong\u003e 90 °C\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; padding: 10px 0 8px;\"\u003e\n\u003cdiv style=\"display: flex; gap: 8px; align-items: center; flex-wrap: wrap;\"\u003e\n\u003cbutton style=\"cursor: pointer; border: 2px solid var(--product-box-background, #000); background: var(--product-box-background, #000); color: var(--product-box-text, #fff); font-weight: 900; padding: 8px 10px; border-radius: 10px; text-transform: uppercase; letter-spacing: .02em; font-size: 12px;\" type=\"button\" id=\"v60StartBtn-tabacones\"\u003eDémarrer\u003c\/button\u003e \u003cbutton style=\"cursor: pointer; border: 2px solid var(--product-box-background, #000); background: var(--product-box-text, #fff); color: var(--product-box-background, #000); font-weight: 900; padding: 8px 10px; border-radius: 10px; text-transform: uppercase; letter-spacing: .02em; font-size: 12px; opacity: .5;\" disabled type=\"button\" id=\"v60StopBtn-tabacones\"\u003eStop\u003c\/button\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; line-height: 1;\"\u003e\n\u003cspan style=\"opacity: .70; font-size: 12px; font-weight: 800; text-transform: uppercase; letter-spacing: .04em;\"\u003eTimer\u003c\/span\u003e \u003cspan style=\"font-weight: 950; font-size: 28px; letter-spacing: .01em;\" id=\"v60Timer-tabacones\"\u003e0:00\u003c\/span\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"flex-basis: 100%; opacity: .6; font-size: 12px; line-height: 1.3; margin-top: 2px;\" id=\"v60WakeStatus-tabacones\"\u003eℹ️ Appuie sur \"Démarrer\" pour garder l'écran allumé.\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 8px; display: grid; gap: 10px;\"\u003e\n\u003cdiv style=\"border: 1px solid rgba(0,0,0,.18); border-radius: 12px; padding: 10px 12px;\" id=\"v60-card-1-tabacones\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; margin-bottom: 6px;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e0:00\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003ePhase 1 — Bloom\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 8px; flex-wrap: wrap; font-size: 12.5px; font-weight: 800;\"\u003e\n\u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\" id=\"v60-pill-1-tabacones\"\u003eVerser pendant 0:10s\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\"\u003eTotal 35 g\u003c\/span\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"border: 1px solid rgba(0,0,0,.18); border-radius: 12px; padding: 10px 12px;\" id=\"v60-card-2-tabacones\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; margin-bottom: 6px;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e0:35\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003ePhase 2\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 8px; flex-wrap: wrap; font-size: 12.5px; font-weight: 800;\"\u003e\n\u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\" id=\"v60-pill-2-tabacones\"\u003eVerser pendant 0:30s\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\"\u003eTotal 170 g\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12); opacity: .6;\"\u003e+135 g\u003c\/span\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"border: 1px solid rgba(0,0,0,.18); border-radius: 12px; padding: 10px 12px;\" id=\"v60-card-3-tabacones\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; margin-bottom: 6px;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e1:30\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003ePhase 3\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 8px; flex-wrap: wrap; font-size: 12.5px; font-weight: 800;\"\u003e\n\u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\" id=\"v60-pill-3-tabacones\"\u003eVerser pendant 0:15s\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\"\u003eTotal 225 g\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12); opacity: .6;\"\u003e+55 g\u003c\/span\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 12px; border-top: 1px solid rgba(0,0,0,.2); padding-top: 10px;\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e2:50\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003eTemps final écoulement complet\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 8px; padding: 8px 10px; border-radius: 8px; background: rgba(0,0,0,.04); border: 1px dashed rgba(0,0,0,.2); font-size: 12px; opacity: .6; line-height: 1.4;\"\u003e\n\u003cstrong\u003eℹ️ Astuce —\u003c\/strong\u003e Si le temps total est plus court, la mouture est probablement trop grosse. S'il est plus long, la mouture est probablement trop fine.\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/details\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 5 ========= --\u003e \u003csvg style=\"display: none;\"\u003e\n\u003cstyle\u003e\n  @keyframes v60PulsePhase {\n    0%   { transform: scale(1);    box-shadow: 0 0 0 0 rgba(200,169,126,.35); }\n    50%  { transform: scale(1.06); box-shadow: 0 0 0 10px rgba(200,169,126,0); }\n    100% { transform: scale(1);    box-shadow: 0 0 0 0 rgba(200,169,126,0); }\n  }\n  .v60-pulse {\n    animation: v60PulsePhase 700ms ease-out 1;\n    transform-origin: center;\n    will-change: transform;\n  }\n  @keyframes v60BlinkPill {\n    0%, 100% { opacity: 1; transform: scale(1); }\n    50%      { opacity: .22; transform: scale(1.03); }\n  }\n  .v60-pill-pour-active {\n    background: #ffe7b7 !important;\n    border: 2px solid #d2a44a !important;\n    color: #3b2a12 !important;\n    font-weight: 900 !important;\n    letter-spacing: .02em;\n    animation: v60BlinkPill 2500ms ease-in-out infinite;\n    box-shadow:\n      0 0 0 2px rgba(210,164,74,.18) inset,\n      0 10px 22px rgba(0,0,0,.12),\n      0 0 0 6px rgba(210,164,74,.10);\n  }\n  @media (prefers-reduced-motion: reduce) {\n    .v60-pill-pour-active { animation: none; }\n    .v60-pulse { animation: none; }\n  }\n\u003c\/style\u003e\n\u003cscript\u003e\n(function() {\n  var SUFFIX = '-tabacones';\n  var END_AT = 170;\n  var phases = [\n    { key: 1, t: 0,   pourLen: 10 },\n    { key: 2, t: 35,  pourLen: 30 },\n    { key: 3, t: 90,  pourLen: 15 }\n  ];\n  var latte = {\n    cardBg:     '#f6f1ea',\n    cardBorder: '#c8a97e',\n    pillBg:     '#eadfce'\n  };\n  var details  = document.getElementById('v60Details'    + SUFFIX);\n  var startBtn = document.getElementById('v60StartBtn'   + SUFFIX);\n  var stopBtn  = document.getElementById('v60StopBtn'    + SUFFIX);\n  var timerEl  = document.getElementById('v60Timer'      + SUFFIX);\n  var statusEl = document.getElementById('v60WakeStatus' + SUFFIX);\n  var pills = {\n    1: document.getElementById('v60-pill-1' + SUFFIX),\n    2: document.getElementById('v60-pill-2' + SUFFIX),\n    3: document.getElementById('v60-pill-3' + SUFFIX)\n  };\n  var cards = {\n    1: document.getElementById('v60-card-1' + SUFFIX),\n    2: document.getElementById('v60-card-2' + SUFFIX),\n    3: document.getElementById('v60-card-3' + SUFFIX)\n  };\n  function setCardActive(key) {\n    Object.keys(cards).forEach(function(k) {\n      var c = cards[k];\n      if (!c) return;\n      if (parseInt(k) === key) {\n        c.style.borderColor = latte.cardBorder;\n        c.style.background  = latte.cardBg;\n        c.style.boxShadow   = '0 0 0 2px rgba(200,169,126,.25) inset, 0 8px 22px rgba(200,169,126,.28)';\n      } else {\n        c.style.borderColor = 'rgba(0,0,0,.18)';\n        c.style.background  = 'transparent';\n        c.style.boxShadow   = 'none';\n      }\n    });\n  }\n  function setPillPhaseActive(key, doPulse) {\n    Object.keys(pills).forEach(function(k) {\n      var p = pills[k];\n      if (!p) return;\n      p.style.background  = 'rgba(0,0,0,.05)';\n      p.style.borderColor = 'rgba(0,0,0,.12)';\n      p.style.boxShadow   = 'none';\n      p.classList.remove('v60-pulse');\n    });\n    var pill = pills[key];\n    if (pill) {\n      pill.style.background  = latte.pillBg;\n      pill.style.borderColor = latte.cardBorder;\n      pill.style.boxShadow   = '0 0 0 2px rgba(200,169,126,.25) inset';\n      if (doPulse) {\n        pill.classList.remove('v60-pulse');\n        void pill.offsetWidth;\n        pill.classList.add('v60-pulse');\n      }\n    }\n  }\n  function resetPourPills() {\n    Object.values(pills).forEach(function(p) {\n      if (!p) return;\n      p.classList.remove('v60-pill-pour-active');\n    });\n  }\n  function setPourPillActive(key) {\n    resetPourPills();\n    if (!key) return;\n    var pill = pills[key];\n    if (pill) pill.classList.add('v60-pill-pour-active');\n  }\n  function clearAll() {\n    Object.values(cards).forEach(function(c) {\n      if (!c) return;\n      c.style.borderColor = 'rgba(0,0,0,.18)';\n      c.style.background  = 'transparent';\n      c.style.boxShadow   = 'none';\n    });\n    Object.values(pills).forEach(function(p) {\n      if (!p) return;\n      p.style.background  = 'rgba(0,0,0,.05)';\n      p.style.borderColor = 'rgba(0,0,0,.12)';\n      p.style.boxShadow   = 'none';\n      p.classList.remove('v60-pulse');\n      p.classList.remove('v60-pill-pour-active');\n    });\n  }\n  var wakeLock  = null;\n  var startTime = null;\n  var rafId     = null;\n  var lastPhaseKey = null;\n  var lastPourKey  = null;\n  function fmt(sec) {\n    sec = Math.max(0, Math.floor(sec));\n    var m = Math.floor(sec \/ 60);\n    var s = sec % 60;\n    return m + ':' + (s \u0026lt; 10 ? '0' : '') + s;\n  }\n  function getCurrentPhaseKey(elapsed) {\n    var current = phases[0].key;\n    for (var i = 0; i \u0026lt; phases.length; i++) if (elapsed \u0026gt;= phases[i].t) current = phases[i].key;\n    return current;\n  }\n  function getPourKey(elapsed) {\n    for (var i = phases.length - 1; i \u0026gt;= 0; i--) {\n      var p = phases[i];\n      if (elapsed \u0026gt;= p.t \u0026amp;\u0026amp; elapsed \u0026lt; (p.t + p.pourLen)) return p.key;\n    }\n    return null;\n  }\n  function enableWakeLock() {\n    if (!('wakeLock' in navigator)) {\n      statusEl.textContent = '⚠️ Ton navigateur ne supporte pas le mode écran allumé.';\n      return Promise.resolve();\n    }\n    return navigator.wakeLock.request('screen').then(function(wl) {\n      wakeLock = wl;\n      statusEl.textContent = '✅ Écran maintenu allumé pendant la recette.';\n      wakeLock.addEventListener('release', function() {\n        statusEl.textContent = 'ℹ️ Mode écran allumé relâché.';\n      });\n    }).catch(function() {\n      statusEl.textContent = '⚠️ Impossible d\\'activer le mode écran allumé.';\n      wakeLock = null;\n    });\n  }\n  function disableWakeLock() {\n    if (wakeLock) { wakeLock.release(); wakeLock = null; }\n  }\n  function setButtons(running) {\n    startBtn.disabled = running;\n    stopBtn.disabled  = !running;\n    stopBtn.style.opacity = running ? '1' : '.5';\n  }\n  function tick() {\n    var elapsed = (Date.now() - startTime) \/ 1000;\n    timerEl.textContent = fmt(elapsed);\n    var phaseKey = getCurrentPhaseKey(elapsed);\n    if (phaseKey !== lastPhaseKey) {\n      setCardActive(phaseKey);\n      setPillPhaseActive(phaseKey, lastPhaseKey !== null);\n      lastPhaseKey = phaseKey;\n    }\n    var pourKey = getPourKey(elapsed);\n    if (pourKey !== lastPourKey) {\n      setPourPillActive(pourKey);\n      lastPourKey = pourKey;\n    }\n    if (elapsed \u0026gt;= END_AT) { stopRecipe(true); return; }\n    rafId = requestAnimationFrame(tick);\n  }\n  function startRecipe() {\n    setButtons(true);\n    timerEl.textContent = '0:00';\n    lastPhaseKey = null;\n    lastPourKey  = null;\n    enableWakeLock().then(function() {\n      setCardActive(1);\n      setPillPhaseActive(1, false);\n      setPourPillActive(1);\n      lastPhaseKey = 1;\n      lastPourKey  = 1;\n      startTime = Date.now();\n      if (rafId) cancelAnimationFrame(rafId);\n      rafId = requestAnimationFrame(tick);\n    });\n  }\n  function stopRecipe(autoEnded) {\n    if (rafId) cancelAnimationFrame(rafId);\n    rafId     = null;\n    startTime = null;\n    disableWakeLock();\n    setButtons(false);\n    clearAll();\n    lastPhaseKey = null;\n    lastPourKey  = null;\n    if (autoEnded) {\n      statusEl.textContent = '✅ Recette terminée — écran libéré.';\n      timerEl.textContent  = fmt(END_AT);\n    } else {\n      statusEl.textContent = 'ℹ️ Recette arrêtée — écran libéré.';\n    }\n  }\n  startBtn.addEventListener('click', startRecipe);\n  stopBtn.addEventListener('click', function() { stopRecipe(false); });\n  details.addEventListener('toggle', function() { if (!details.open) stopRecipe(false); });\n  document.addEventListener('visibilitychange', function() {\n    if (document.visibilityState === 'visible' \u0026amp;\u0026amp; startTime \u0026amp;\u0026amp; !wakeLock) enableWakeLock();\n  });\n})();\n\u003c\/script\u003e\n\u003c\/svg\u003e\n\u003c\/div\u003e","brand":"ZAB","offers":[{"title":"300g","offer_id":52331777655093,"sku":"CAF-SIN-TABA-300","price":26.5,"currency_code":"CAD","in_stock":false},{"title":"808g","offer_id":52331777687861,"sku":"CAF-SIN-TABA-808","price":62.0,"currency_code":"CAD","in_stock":true},{"title":"2268g (5lbs)","offer_id":52331777720629,"sku":"CAF-SIN-TABA-2268","price":160.0,"currency_code":"CAD","in_stock":true},{"title":"100g","offer_id":52331777753397,"sku":"CAF-SIN-TABA-100","price":13.25,"currency_code":"CAD","in_stock":true},{"title":"Bucket - 5lbs (Livraison locale seulement)","offer_id":52568956993845,"sku":"CAF-SIN-TABA-BUCK-5","price":185.0,"currency_code":"CAD","in_stock":true},{"title":"Bucket - 15lbs (Livraison locale seulement)","offer_id":52568957026613,"sku":"CAF-SIN-TABA-BUCK-15","price":505.0,"currency_code":"CAD","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/2716\/1842\/files\/tabaconas-300g.jpg?v=1779378844"},{"product_id":"ethiopie-elto","title":"ÉTHIOPIE - ELTO","description":"\u003c!-- =========================================================\n  SECTION 1 : NOTES DE DÉGUSTATION\n========================================================= --\u003e\n\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto; border: 2px solid var(--product-box-background, #000); border-radius: 12px; overflow: hidden;\"\u003e\n  \u003cdiv style=\"padding: 10px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center;\"\u003eNotes de dégustation\u003c\/div\u003e\n  \u003cdiv style=\"padding: 16px 14px; font-weight: 900; text-transform: uppercase; font-size: 28px; letter-spacing: .05em; text-align: center; background: transparent;\"\u003eFRAMBOISE + GOYAVE + EARL GREY\u003c\/div\u003e\n\u003c\/div\u003e\n\n\u003c!-- ========= FIN SECTION 1 ========= --\u003e\n\n\u003cp\u003e \u003c\/p\u003e\n\n\u003cdiv style=\"position: relative; width: 100%; padding-bottom: 56.25%; height: 0; overflow: hidden; border-radius: 8px;\"\u003e\u003ciframe style=\"position: absolute; top: 0; left: 0; width: 100%; height: 100%; border: 0; border-radius: 8px;\" src=\"https:\/\/www.youtube.com\/embed\/nOn5ieggbhM?si=Gdcr1YJ6tFaneKhL\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen\u003e\u003c\/iframe\u003e\u003c\/div\u003e\n\n\u003cp\u003e \u003c\/p\u003e\n\n\u003c!-- =========================================================\n  SECTION 2 : APPROVISIONNEMENT\n========================================================= --\u003e\n\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto;\"\u003e\n  \u003cdiv style=\"padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center; border-radius: 12px 12px 0 0;\"\u003eApprovisionnement\u003c\/div\u003e\n  \u003ctable border=\"3\" cellpadding=\"1\" cellspacing=\"1\" style=\"width: 100%; border-collapse: collapse; background: transparent;\"\u003e\n    \u003ctbody\u003e\n      \u003ctr\u003e\n\u003ctd style=\"width: 20%;\"\u003eORIGINE\u003c\/td\u003e\n\u003ctd\u003eRégion de Sidama, Éthiopie\u003c\/td\u003e\n\u003c\/tr\u003e\n      \u003ctr\u003e\n\u003ctd\u003ePRODUCTEURS\u003c\/td\u003e\n\u003ctd\u003eElto Coffee (Eliyas Dukamo \u0026amp; Atiklit Dejene)\u003c\/td\u003e\n\u003c\/tr\u003e\n      \u003ctr\u003e\n\u003ctd\u003eVARIÉTÉS\u003c\/td\u003e\n\u003ctd\u003e74158, 74165, 74110, 74112\u003c\/td\u003e\n\u003c\/tr\u003e\n      \u003ctr\u003e\n\u003ctd\u003ePROCÉDÉ\u003c\/td\u003e\n\u003ctd\u003eNaturel\u003c\/td\u003e\n\u003c\/tr\u003e\n      \u003ctr\u003e\n\u003ctd\u003eALTITUDE\u003c\/td\u003e\n\u003ctd\u003e2200 – 2300 m\u003c\/td\u003e\n\u003c\/tr\u003e\n      \u003ctr\u003e\n\u003ctd\u003ePARTENAIRES\u003c\/td\u003e\n\u003ctd\u003eCrop to Cup\u003c\/td\u003e\n\u003c\/tr\u003e\n      \u003ctr\u003e\n\u003ctd\u003eVOLUME ACHETÉ\u003c\/td\u003e\n\u003ctd\u003e600 kg\u003c\/td\u003e\n\u003c\/tr\u003e\n      \u003ctr\u003e\n\u003ctd\u003eFAB\u003c\/td\u003e\n\u003ctd\u003e5,35 $ US\/lb\u003c\/td\u003e\n\u003c\/tr\u003e\n      \u003ctr\u003e\n\u003ctd\u003ePRIX LIVRÉ\u003c\/td\u003e\n\u003ctd\u003e11,14 $ CAD\/lb\u003c\/td\u003e\n\u003c\/tr\u003e\n      \u003ctr\u003e\n\u003ctd\u003eRELATION\u003c\/td\u003e\n\u003ctd\u003e1 an\u003c\/td\u003e\n\u003c\/tr\u003e\n    \u003c\/tbody\u003e\n  \u003c\/table\u003e\n\u003c\/div\u003e\n\n\u003c!-- ========= FIN SECTION 2 ========= --\u003e\n\n\u003cp\u003e \u003c\/p\u003e\n\n\u003c!-- =========================================================\n  SECTION 3 : INFORMATIONS SUR LE CAFÉ\n========================================================= --\u003e\n\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto;\"\u003e\n  \u003cdiv style=\"padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center; border-radius: 12px 12px 0 0;\"\u003eInformations sur le café\u003c\/div\u003e\n  \u003cdiv style=\"border: 2px solid var(--product-box-background, #000); border-top: none; border-radius: 0 0 12px 12px; padding: 16px 14px; background: transparent;\"\u003e\n    \u003cp style=\"margin: 0 0 12px 0;\"\u003eElto est un exemple parfait de café éthiopien naturel — plein de caractère, de douceur et de fruits confits. En filtre, il offre une complexité fascinante : une acidité agréable avec des arômes floraux en tête, qui évolue vers des saveurs de petits fruits confits qui persistent en bouche. En espresso, l'acidité devient plus prononcée, révélant des notes de goyave juteuse et un corps crémeux. Avec du lait, il donne un cappuccino riche, presque dessert.\u003c\/p\u003e\n    \u003cp style=\"margin: 0 0 12px 0;\"\u003eEliyas Dukamo et Atiklit Dejene (« Mimi »), cofondateurs d'Elto Coffee, sont de véritables étoiles montantes de la scène du café de spécialité éthiopien. Eliyas est issu d'une famille de producteurs légendaires, tandis que Mimi a commencé sa carrière dans le contrôle qualité pour un projet de café de spécialité renommé.\u003c\/p\u003e\n    \u003cp style=\"margin: 0;\"\u003eLeur entreprise, Elto, exploite deux stations de séchage en Sidama et se concentre sur la production de micro-lots de haute qualité — certains même destinés à des compétitions de café — en suivant les meilleures pratiques de l'industrie. Le nom « Elto » porte un double sens en sidamo : abondance et plus que passion, ce qui reflète parfaitement l'esprit et l'ambition du duo.\u003c\/p\u003e\n  \u003c\/div\u003e\n\u003c\/div\u003e\n\n\u003c!-- ========= FIN SECTION 3 ========= --\u003e\n\n\u003cp\u003e \u003c\/p\u003e\n\n\u003c!-- =========================================================\n  SECTION 4 : PARAMÈTRES D'EXTRACTION — ESPRESSO\n========================================================= --\u003e\n\n\u003cdiv style=\"width: 100%; margin: 0 auto;\"\u003e\n  \u003cdetails open=\"\" style=\"border: 2px solid var(--product-box-background, #000); border-radius: 12px; overflow: hidden; margin: 0 0 12px 0; background: rgba(255,255,255,0.5);\"\u003e\n    \u003csummary style=\"cursor: pointer; list-style: none; padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center;\"\u003eEspresso — paramètres recommandés\u003c\/summary\u003e\n    \u003cdiv style=\"padding: 12px 14px;\"\u003e\n      \u003ctable style=\"width: 100%; border-collapse: collapse; background: transparent;\"\u003e\n        \u003ctbody\u003e\n          \u003ctr\u003e\n            \u003ctd style=\"padding: 10px 0; font-weight: 800; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003eCafé moulu\u003c\/td\u003e\n            \u003ctd style=\"padding: 10px 0; text-align: right; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003e18,5 g\u003c\/td\u003e\n          \u003c\/tr\u003e\n          \u003ctr\u003e\n            \u003ctd style=\"padding: 10px 0; font-weight: 800; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003eCafé dans la tasse\u003c\/td\u003e\n            \u003ctd style=\"padding: 10px 0; text-align: right; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003e37 g\u003c\/td\u003e\n          \u003c\/tr\u003e\n          \u003ctr\u003e\n            \u003ctd style=\"padding: 10px 0; font-weight: 800;\"\u003eTemps d'extraction\u003c\/td\u003e\n            \u003ctd style=\"padding: 10px 0; text-align: right;\"\u003e27 sec\u003c\/td\u003e\n          \u003c\/tr\u003e\n        \u003c\/tbody\u003e\n      \u003c\/table\u003e\n      \u003cdiv style=\"margin-top: 10px; padding: 8px 10px; border-radius: 8px; background: rgba(0,0,0,.04); border: 1px dashed rgba(0,0,0,.2); font-size: 12px; opacity: .7; line-height: 1.4;\"\u003e\n        \u003cstrong\u003eÀ noter —\u003c\/strong\u003e Recette optimisée pour un panier de \u003cstrong\u003e18 g\u003c\/strong\u003e. Consulte le manuel de ta machine pour connaître la capacité de ton panier.\n      \u003c\/div\u003e\n    \u003c\/div\u003e\n  \u003c\/details\u003e\n\u003c\/div\u003e\n\n\u003c!-- ========= FIN SECTION 4 ========= --\u003e\n\n\u003cp\u003e \u003c\/p\u003e\n\n\u003c!-- =========================================================\n  SECTION 5 : V60\n========================================================= --\u003e\n\n\u003cdiv style=\"width: 100%; margin: 0 auto;\"\u003e\n  \u003cdetails id=\"v60Details-elto\" open=\"\" style=\"border: 2px solid var(--product-box-background, #000); border-radius: 12px; overflow: hidden; margin: 0 0 12px 0; background: rgba(255,255,255,0.5);\"\u003e\n    \u003csummary style=\"cursor: pointer; list-style: none; padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center;\"\u003eV60 – Recette\u003c\/summary\u003e\n    \u003cdiv style=\"padding: 12px 14px;\"\u003e\n      \u003cdiv style=\"padding: 10px 0 10px; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003e\n        \u003cdiv style=\"font-weight: 900; font-size: 16px;\"\u003eRatio 1:16\u003c\/div\u003e\n        \u003cdiv style=\"margin-top: 4px; opacity: .7; font-size: 13px;\"\u003e15 g in – 240 g out\u003c\/div\u003e\n        \u003cdiv style=\"margin-top: 6px; font-size: 13px;\"\u003e\n\u003cstrong\u003eTempérature de l'eau :\u003c\/strong\u003e 93 °C\u003c\/div\u003e\n      \u003c\/div\u003e\n      \u003cdiv style=\"display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; padding: 10px 0 8px;\"\u003e\n        \u003cdiv style=\"display: flex; gap: 8px; align-items: center; flex-wrap: wrap;\"\u003e\n          \u003cbutton style=\"cursor: pointer; border: 2px solid var(--product-box-background, #000); background: var(--product-box-background, #000); color: var(--product-box-text, #fff); font-weight: 900; padding: 8px 10px; border-radius: 10px; text-transform: uppercase; letter-spacing: .02em; font-size: 12px;\" type=\"button\" id=\"v60StartBtn-elto\"\u003eDémarrer\u003c\/button\u003e\n          \u003cbutton style=\"cursor: pointer; border: 2px solid var(--product-box-background, #000); background: var(--product-box-text, #fff); color: var(--product-box-background, #000); font-weight: 900; padding: 8px 10px; border-radius: 10px; text-transform: uppercase; letter-spacing: .02em; font-size: 12px; opacity: .5;\" disabled type=\"button\" id=\"v60StopBtn-elto\"\u003eStop\u003c\/button\u003e\n        \u003c\/div\u003e\n        \u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; line-height: 1;\"\u003e\n          \u003cspan style=\"opacity: .70; font-size: 12px; font-weight: 800; text-transform: uppercase; letter-spacing: .04em;\"\u003eTimer\u003c\/span\u003e\n          \u003cspan style=\"font-weight: 950; font-size: 28px; letter-spacing: .01em;\" id=\"v60Timer-elto\"\u003e0:00\u003c\/span\u003e\n        \u003c\/div\u003e\n        \u003cdiv style=\"flex-basis: 100%; opacity: .6; font-size: 12px; line-height: 1.3; margin-top: 2px;\" id=\"v60WakeStatus-elto\"\u003eℹ️ Appuie sur \"Démarrer\" pour garder l'écran allumé.\u003c\/div\u003e\n      \u003c\/div\u003e\n      \u003cdiv style=\"margin-top: 8px; display: grid; gap: 10px;\"\u003e\n        \u003cdiv style=\"border: 1px solid rgba(0,0,0,.18); border-radius: 12px; padding: 10px 12px;\" id=\"v60-card-1-elto\"\u003e\n          \u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; margin-bottom: 6px;\"\u003e\n            \u003cdiv style=\"font-weight: 900;\"\u003e0:00\u003c\/div\u003e\n            \u003cdiv style=\"font-weight: 900;\"\u003ePhase 1 — Bloom\u003c\/div\u003e\n          \u003c\/div\u003e\n          \u003cdiv style=\"display: flex; gap: 8px; flex-wrap: wrap; font-size: 12.5px; font-weight: 800;\"\u003e\n            \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\" id=\"v60-pill-1-elto\"\u003eVerser pendant 0:10s\u003c\/span\u003e\n            \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\"\u003eTotal 50 g\u003c\/span\u003e\n          \u003c\/div\u003e\n        \u003c\/div\u003e\n        \u003cdiv style=\"border: 1px solid rgba(0,0,0,.18); border-radius: 12px; padding: 10px 12px;\" id=\"v60-card-2-elto\"\u003e\n          \u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; margin-bottom: 6px;\"\u003e\n            \u003cdiv style=\"font-weight: 900;\"\u003e0:40\u003c\/div\u003e\n            \u003cdiv style=\"font-weight: 900;\"\u003ePhase 2\u003c\/div\u003e\n          \u003c\/div\u003e\n          \u003cdiv style=\"display: flex; gap: 8px; flex-wrap: wrap; font-size: 12.5px; font-weight: 800;\"\u003e\n            \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\" id=\"v60-pill-2-elto\"\u003eVerser pendant 0:30s\u003c\/span\u003e\n            \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\"\u003eTotal 155 g\u003c\/span\u003e\n            \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12); opacity: .6;\"\u003e+105 g\u003c\/span\u003e\n          \u003c\/div\u003e\n        \u003c\/div\u003e\n        \u003cdiv style=\"border: 1px solid rgba(0,0,0,.18); border-radius: 12px; padding: 10px 12px;\" id=\"v60-card-3-elto\"\u003e\n          \u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; margin-bottom: 6px;\"\u003e\n            \u003cdiv style=\"font-weight: 900;\"\u003e1:25\u003c\/div\u003e\n            \u003cdiv style=\"font-weight: 900;\"\u003ePhase 3\u003c\/div\u003e\n          \u003c\/div\u003e\n          \u003cdiv style=\"display: flex; gap: 8px; flex-wrap: wrap; font-size: 12.5px; font-weight: 800;\"\u003e\n            \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\" id=\"v60-pill-3-elto\"\u003eVerser pendant 0:25s\u003c\/span\u003e\n            \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\"\u003eTotal 240 g\u003c\/span\u003e\n            \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12); opacity: .6;\"\u003e+85 g\u003c\/span\u003e\n          \u003c\/div\u003e\n        \u003c\/div\u003e\n      \u003c\/div\u003e\n      \u003cdiv style=\"margin-top: 12px; border-top: 1px solid rgba(0,0,0,.2); padding-top: 10px;\"\u003e\n        \u003cdiv style=\"display: flex; gap: 10px; align-items: baseline;\"\u003e\n          \u003cdiv style=\"font-weight: 900;\"\u003e2:25\u003c\/div\u003e\n          \u003cdiv style=\"font-weight: 900;\"\u003eTemps final écoulement complet\u003c\/div\u003e\n        \u003c\/div\u003e\n        \u003cdiv style=\"margin-top: 8px; padding: 8px 10px; border-radius: 8px; background: rgba(0,0,0,.04); border: 1px dashed rgba(0,0,0,.2); font-size: 12px; opacity: .6; line-height: 1.4;\"\u003e\n          \u003cstrong\u003eℹ️ Astuce —\u003c\/strong\u003e Si le temps total est plus court, la mouture est probablement trop grosse. S'il est plus long, la mouture est probablement trop fine.\n        \u003c\/div\u003e\n      \u003c\/div\u003e\n    \u003c\/div\u003e\n  \u003c\/details\u003e\n\u003c\/div\u003e\n\n\u003c!-- ========= FIN SECTION 5 ========= --\u003e\n\n\u003csvg style=\"display: none;\"\u003e\n\u003cstyle\u003e\n  @keyframes v60PulsePhase {\n    0%   { transform: scale(1);    box-shadow: 0 0 0 0 rgba(200,169,126,.35); }\n    50%  { transform: scale(1.06); box-shadow: 0 0 0 10px rgba(200,169,126,0); }\n    100% { transform: scale(1);    box-shadow: 0 0 0 0 rgba(200,169,126,0); }\n  }\n  .v60-pulse { animation: v60PulsePhase 700ms ease-out 1; transform-origin: center; will-change: transform; }\n  @keyframes v60BlinkPill {\n    0%, 100% { opacity: 1; transform: scale(1); }\n    50%      { opacity: .22; transform: scale(1.03); }\n  }\n  .v60-pill-pour-active {\n    background: #ffe7b7 !important; border: 2px solid #d2a44a !important;\n    color: #3b2a12 !important; font-weight: 900 !important; letter-spacing: .02em;\n    animation: v60BlinkPill 2500ms ease-in-out infinite;\n    box-shadow: 0 0 0 2px rgba(210,164,74,.18) inset, 0 10px 22px rgba(0,0,0,.12), 0 0 0 6px rgba(210,164,74,.10);\n  }\n  @media (prefers-reduced-motion: reduce) { .v60-pill-pour-active { animation: none; } .v60-pulse { animation: none; } }\n\u003c\/style\u003e\n\u003cscript\u003e\n(function() {\n  var SUFFIX = '-elto';\n  var END_AT = 145;\n  var phases = [\n    { key: 1, t: 0,  pourLen: 10 },\n    { key: 2, t: 40, pourLen: 30 },\n    { key: 3, t: 85, pourLen: 25 }\n  ];\n  var latte = { cardBg: '#f6f1ea', cardBorder: '#c8a97e', pillBg: '#eadfce' };\n  var details  = document.getElementById('v60Details'    + SUFFIX);\n  var startBtn = document.getElementById('v60StartBtn'   + SUFFIX);\n  var stopBtn  = document.getElementById('v60StopBtn'    + SUFFIX);\n  var timerEl  = document.getElementById('v60Timer'      + SUFFIX);\n  var statusEl = document.getElementById('v60WakeStatus' + SUFFIX);\n  var pills = { 1: document.getElementById('v60-pill-1' + SUFFIX), 2: document.getElementById('v60-pill-2' + SUFFIX), 3: document.getElementById('v60-pill-3' + SUFFIX) };\n  var cards = { 1: document.getElementById('v60-card-1' + SUFFIX), 2: document.getElementById('v60-card-2' + SUFFIX), 3: document.getElementById('v60-card-3' + SUFFIX) };\n  function setCardActive(key) {\n    Object.keys(cards).forEach(function(k) {\n      var c = cards[k]; if (!c) return;\n      if (parseInt(k) === key) { c.style.borderColor = latte.cardBorder; c.style.background = latte.cardBg; c.style.boxShadow = '0 0 0 2px rgba(200,169,126,.25) inset, 0 8px 22px rgba(200,169,126,.28)'; }\n      else { c.style.borderColor = 'rgba(0,0,0,.18)'; c.style.background = 'transparent'; c.style.boxShadow = 'none'; }\n    });\n  }\n  function setPillPhaseActive(key, doPulse) {\n    Object.keys(pills).forEach(function(k) { var p = pills[k]; if (!p) return; p.style.background = 'rgba(0,0,0,.05)'; p.style.borderColor = 'rgba(0,0,0,.12)'; p.style.boxShadow = 'none'; p.classList.remove('v60-pulse'); });\n    var pill = pills[key];\n    if (pill) { pill.style.background = latte.pillBg; pill.style.borderColor = latte.cardBorder; pill.style.boxShadow = '0 0 0 2px rgba(200,169,126,.25) inset'; if (doPulse) { pill.classList.remove('v60-pulse'); void pill.offsetWidth; pill.classList.add('v60-pulse'); } }\n  }\n  function resetPourPills() { Object.values(pills).forEach(function(p) { if (!p) return; p.classList.remove('v60-pill-pour-active'); }); }\n  function setPourPillActive(key) { resetPourPills(); if (!key) return; var pill = pills[key]; if (pill) pill.classList.add('v60-pill-pour-active'); }\n  function clearAll() {\n    Object.values(cards).forEach(function(c) { if (!c) return; c.style.borderColor = 'rgba(0,0,0,.18)'; c.style.background = 'transparent'; c.style.boxShadow = 'none'; });\n    Object.values(pills).forEach(function(p) { if (!p) return; p.style.background = 'rgba(0,0,0,.05)'; p.style.borderColor = 'rgba(0,0,0,.12)'; p.style.boxShadow = 'none'; p.classList.remove('v60-pulse'); p.classList.remove('v60-pill-pour-active'); });\n  }\n  var wakeLock = null, startTime = null, rafId = null, lastPhaseKey = null, lastPourKey = null;\n  function fmt(sec) { sec = Math.max(0, Math.floor(sec)); var m = Math.floor(sec \/ 60), s = sec % 60; return m + ':' + (s \u003c 10 ? '0' : '') + s; }\n  function getCurrentPhaseKey(elapsed) { var current = phases[0].key; for (var i = 0; i \u003c phases.length; i++) if (elapsed \u003e= phases[i].t) current = phases[i].key; return current; }\n  function getPourKey(elapsed) { for (var i = phases.length - 1; i \u003e= 0; i--) { var p = phases[i]; if (elapsed \u003e= p.t \u0026\u0026 elapsed \u003c (p.t + p.pourLen)) return p.key; } return null; }\n  function enableWakeLock() {\n    if (!('wakeLock' in navigator)) { statusEl.textContent = '⚠️ Ton navigateur ne supporte pas le mode écran allumé.'; return Promise.resolve(); }\n    return navigator.wakeLock.request('screen').then(function(wl) { wakeLock = wl; statusEl.textContent = '✅ Écran maintenu allumé pendant la recette.'; wakeLock.addEventListener('release', function() { statusEl.textContent = 'ℹ️ Mode écran allumé relâché.'; }); }).catch(function() { statusEl.textContent = '⚠️ Impossible d\\'activer le mode écran allumé.'; wakeLock = null; });\n  }\n  function disableWakeLock() { if (wakeLock) { wakeLock.release(); wakeLock = null; } }\n  function setButtons(running) { startBtn.disabled = running; stopBtn.disabled = !running; stopBtn.style.opacity = running ? '1' : '.5'; }\n  function tick() {\n    var elapsed = (Date.now() - startTime) \/ 1000;\n    timerEl.textContent = fmt(elapsed);\n    var phaseKey = getCurrentPhaseKey(elapsed);\n    if (phaseKey !== lastPhaseKey) { setCardActive(phaseKey); setPillPhaseActive(phaseKey, lastPhaseKey !== null); lastPhaseKey = phaseKey; }\n    var pourKey = getPourKey(elapsed);\n    if (pourKey !== lastPourKey) { setPourPillActive(pourKey); lastPourKey = pourKey; }\n    if (elapsed \u003e= END_AT) { stopRecipe(true); return; }\n    rafId = requestAnimationFrame(tick);\n  }\n  function startRecipe() {\n    setButtons(true); timerEl.textContent = '0:00'; lastPhaseKey = null; lastPourKey = null;\n    enableWakeLock().then(function() { setCardActive(1); setPillPhaseActive(1, false); setPourPillActive(1); lastPhaseKey = 1; lastPourKey = 1; startTime = Date.now(); if (rafId) cancelAnimationFrame(rafId); rafId = requestAnimationFrame(tick); });\n  }\n  function stopRecipe(autoEnded) {\n    if (rafId) cancelAnimationFrame(rafId); rafId = null; startTime = null; disableWakeLock(); setButtons(false); clearAll(); lastPhaseKey = null; lastPourKey = null;\n    if (autoEnded) { statusEl.textContent = '✅ Recette terminée — écran libéré.'; timerEl.textContent = fmt(END_AT); } else { statusEl.textContent = 'ℹ️ Recette arrêtée — écran libéré.'; }\n  }\n  startBtn.addEventListener('click', startRecipe);\n  stopBtn.addEventListener('click', function() { stopRecipe(false); });\n  details.addEventListener('toggle', function() { if (!details.open) stopRecipe(false); });\n  document.addEventListener('visibilitychange', function() { if (document.visibilityState === 'visible' \u0026\u0026 startTime \u0026\u0026 !wakeLock) enableWakeLock(); });\n})();\n\u003c\/script\u003e\n\u003c\/svg\u003e","brand":"ZAB","offers":[{"title":"250g","offer_id":52378849902901,"sku":"CAF-SIN-ELTO-250","price":30.0,"currency_code":"CAD","in_stock":true},{"title":"808g","offer_id":52378849935669,"sku":"CAF-SIN-ELTO-808","price":85.0,"currency_code":"CAD","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/2716\/1842\/files\/elto-250g.jpg?v=1772636655"},{"product_id":"colombie-edison-argote-co-ferment-melon-deau","title":"COLOMBIE - CHOC THERMIQUE - EDINSON ARGOTE CO-FERMENT MELON D'EAU","description":"\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 1 : NOTES DE DÉGUSTATION\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto; border: 2px solid var(--product-box-background, #000); border-radius: 12px; overflow: hidden;\"\u003e\n\u003cdiv style=\"padding: 10px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center;\"\u003eNotes de dégustation\u003c\/div\u003e\n\u003cdiv style=\"padding: 16px 14px; font-weight: 900; text-transform: uppercase; font-size: 28px; letter-spacing: .05em; text-align: center; background: transparent;\"\u003eMELON D'EAU + THÉ GLACÉ + TRANCHE D'ORANGE\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 1 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003cdiv style=\"position: relative; width: 100%; padding-bottom: 56.25%; height: 0; overflow: hidden; border-radius: 8px;\"\u003e\u003ciframe style=\"position: absolute; top: 0; left: 0; width: 100%; height: 100%; border: 0; border-radius: 8px;\" src=\"https:\/\/www.youtube.com\/embed\/2G2YI8Ozqts?si=BvPpHGCl8XXAvywr\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" allowfullscreen\u003e\u003c\/iframe\u003e\u003c\/div\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 2 : APPROVISIONNEMENT\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto;\"\u003e\n\u003cdiv style=\"padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center; border-radius: 12px 12px 0 0;\"\u003eApprovisionnement\u003c\/div\u003e\n\u003ctable style=\"width: 100%; border-collapse: collapse; background: transparent;\" cellspacing=\"1\" cellpadding=\"1\" border=\"3\"\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd style=\"width: 20%;\"\u003eORIGINE\u003c\/td\u003e\n\u003ctd\u003eMunicipalité d'Oporapa, département de Huila\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePRODUCTEURS\u003c\/td\u003e\n\u003ctd\u003eEdinson Argote\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eFERME\u003c\/td\u003e\n\u003ctd\u003eQuebraditas\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eVARIÉTÉ\u003c\/td\u003e\n\u003ctd\u003eCaturra\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePROCÉDÉ\u003c\/td\u003e\n\u003ctd\u003eChoc thermique et co-fermenté\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eALTITUDE\u003c\/td\u003e\n\u003ctd\u003e1600 – 1800 m\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePARTENAIRES\u003c\/td\u003e\n\u003ctd\u003eTravesia\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eVOLUME ACHETÉ\u003c\/td\u003e\n\u003ctd\u003e192 kg\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eFAB\u003c\/td\u003e\n\u003ctd\u003e13,96 $ US\/lb\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eRELATION\u003c\/td\u003e\n\u003ctd\u003e1 an\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003c\/tbody\u003e\n\u003c\/table\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 2 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 3 : INFORMATIONS SUR LE CAFÉ\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto;\"\u003e\n\u003cdiv style=\"padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center; border-radius: 12px 12px 0 0;\"\u003eInformations sur le café\u003c\/div\u003e\n\u003cdiv style=\"border: 2px solid var(--product-box-background, #000); border-top: none; border-radius: 0 0 12px 12px; padding: 16px 14px; background: transparent;\"\u003e\n\u003cp style=\"margin: 0 0 12px 0;\"\u003eUn beau petit coup de fraîcheur avec ce superbe café co-fermenté ! Edinson Argote travaille ses cafés avec une expertise extraordinaire, fruit de ses années d'expérience dans le café de spécialité avant de lancer son propre projet, Quebraditas, avec sa partenaire Angela Rojas et leurs familles.\u003c\/p\u003e\n\u003cp style=\"margin: 0 0 12px 0;\"\u003eLe procédé utilisé pour ce café est complexe et réalisé avec une grande précision. Les cerises sont d'abord laissées au repos pendant 24 heures, puis dépulpées et mises en fermentation. Lors de cette étape, du melon d'eau ainsi que des levures sont ajoutés à la cuve de fermentation remplie d'eau. Les grains sont ensuite laissés en co-fermentation pendant un total de 72 heures. Un choc thermique est également appliqué : les grains sont d'abord immergés dans de l'eau chaude, puis rapidement refroidis dans de l'eau très froide. Combiné à la co-fermentation, ce procédé contribue au profil explosif que tu retrouveras en tasse.\u003c\/p\u003e\n\u003cp style=\"margin: 0;\"\u003eQuebraditas est un projet familial dédié à la production de cafés de spécialité aux profils aromatiques uniques. Pour y parvenir, la ferme met en place des pratiques agronomiques axées sur la santé des sols, comme l'ombrage stratégique, l'utilisation de matière organique et le maintien d'un pH équilibré grâce à des amendements et des apports de chaux. Ces soins apportés dès la culture permettent d'améliorer la qualité en tasse, avant d'être transformés avec le plus grand soin. Cela donne des cafés superbes, originaux, explosifs et vraiment recherchés !\u003c\/p\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 3 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 4 : V60 ET ORIGAMI\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto;\"\u003e\n\u003cdetails id=\"v60Details-quebraditas\" open=\"\" style=\"border: 2px solid var(--product-box-background, #000); border-radius: 12px; overflow: hidden; margin: 0 0 12px 0; background: rgba(255,255,255,0.5);\"\u003e\n\u003csummary style=\"cursor: pointer; list-style: none; padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center;\"\u003eV60 et Origami – Recette\u003c\/summary\u003e\n\u003cdiv style=\"padding: 12px 14px;\"\u003e\n\u003cdiv style=\"padding: 10px 0 10px; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003e\n\u003cdiv style=\"font-weight: 900; font-size: 16px;\"\u003eRatio 1:15\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 4px; opacity: .7; font-size: 13px;\"\u003e13 g in – 200 g out\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 6px; font-size: 13px;\"\u003e\n\u003cstrong\u003eTempérature de l'eau :\u003c\/strong\u003e 92 °C\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; padding: 10px 0 8px;\"\u003e\n\u003cdiv style=\"display: flex; gap: 8px; align-items: center; flex-wrap: wrap;\"\u003e\n\u003cbutton style=\"cursor: pointer; border: 2px solid var(--product-box-background, #000); background: var(--product-box-background, #000); color: var(--product-box-text, #fff); font-weight: 900; padding: 8px 10px; border-radius: 10px; text-transform: uppercase; letter-spacing: .02em; font-size: 12px;\" type=\"button\" id=\"v60StartBtn-quebraditas\"\u003eDémarrer\u003c\/button\u003e\n\u003cbutton style=\"cursor: pointer; border: 2px solid var(--product-box-background, #000); background: var(--product-box-text, #fff); color: var(--product-box-background, #000); font-weight: 900; padding: 8px 10px; border-radius: 10px; text-transform: uppercase; letter-spacing: .02em; font-size: 12px; opacity: .5;\" disabled type=\"button\" id=\"v60StopBtn-quebraditas\"\u003eStop\u003c\/button\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; line-height: 1;\"\u003e\n\u003cspan style=\"opacity: .70; font-size: 12px; font-weight: 800; text-transform: uppercase; letter-spacing: .04em;\"\u003eTimer\u003c\/span\u003e\n\u003cspan style=\"font-weight: 950; font-size: 28px; letter-spacing: .01em;\" id=\"v60Timer-quebraditas\"\u003e0:00\u003c\/span\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"flex-basis: 100%; opacity: .6; font-size: 12px; line-height: 1.3; margin-top: 2px;\" id=\"v60WakeStatus-quebraditas\"\u003eℹ️ Appuie sur \"Démarrer\" pour garder l'écran allumé.\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 8px; display: grid; gap: 10px;\"\u003e\n\u003cdiv style=\"border: 1px solid rgba(0,0,0,.18); border-radius: 12px; padding: 10px 12px;\" id=\"v60-card-1-quebraditas\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; margin-bottom: 6px;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e0:00\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003ePhase 1 — Bloom\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 8px; flex-wrap: wrap; font-size: 12.5px; font-weight: 800;\"\u003e\n\u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\" id=\"v60-pill-1-quebraditas\"\u003eVerser pendant 0:10s\u003c\/span\u003e\n\u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\"\u003eTotal 50 g\u003c\/span\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"border: 1px solid rgba(0,0,0,.18); border-radius: 12px; padding: 10px 12px;\" id=\"v60-card-2-quebraditas\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; margin-bottom: 6px;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e0:30\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003ePhase 2\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 8px; flex-wrap: wrap; font-size: 12.5px; font-weight: 800;\"\u003e\n\u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\" id=\"v60-pill-2-quebraditas\"\u003eVerser pendant 0:10s\u003c\/span\u003e\n\u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\"\u003eTotal 100 g\u003c\/span\u003e\n\u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12); opacity: .6;\"\u003e+50 g\u003c\/span\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"border: 1px solid rgba(0,0,0,.18); border-radius: 12px; padding: 10px 12px;\" id=\"v60-card-3-quebraditas\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; margin-bottom: 6px;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e1:00\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003ePhase 3\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 8px; flex-wrap: wrap; font-size: 12.5px; font-weight: 800;\"\u003e\n\u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\" id=\"v60-pill-3-quebraditas\"\u003eVerser pendant 0:10s\u003c\/span\u003e\n\u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\"\u003eTotal 150 g\u003c\/span\u003e\n\u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12); opacity: .6;\"\u003e+50 g\u003c\/span\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"border: 1px solid rgba(0,0,0,.18); border-radius: 12px; padding: 10px 12px;\" id=\"v60-card-4-quebraditas\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; margin-bottom: 6px;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e1:30\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003ePhase 4\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 8px; flex-wrap: wrap; font-size: 12.5px; font-weight: 800;\"\u003e\n\u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\" id=\"v60-pill-4-quebraditas\"\u003eVerser pendant 0:10s\u003c\/span\u003e\n\u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\"\u003eTotal 200 g\u003c\/span\u003e\n\u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12); opacity: .6;\"\u003e+50 g\u003c\/span\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 12px; border-top: 1px solid rgba(0,0,0,.2); padding-top: 10px;\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e2:10\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003eTemps final écoulement complet\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 8px; padding: 8px 10px; border-radius: 8px; background: rgba(0,0,0,.04); border: 1px dashed rgba(0,0,0,.2); font-size: 12px; opacity: .6; line-height: 1.4;\"\u003e\n\u003cstrong\u003eℹ️ Astuce —\u003c\/strong\u003e Si le temps total est plus court, la mouture est probablement trop grosse. S'il est plus long, la mouture est probablement trop fine.\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/details\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 4 ========= --\u003e\u003csvg style=\"display: none;\"\u003e\n\u003cstyle\u003e\n@keyframes v60PulsePhase {\n0% { transform: scale(1); box-shadow: 0 0 0 0 rgba(200,169,126,.35); }\n50% { transform: scale(1.06); box-shadow: 0 0 0 10px rgba(200,169,126,0); }\n100% { transform: scale(1); box-shadow: 0 0 0 0 rgba(200,169,126,0); }\n}\n.v60-pulse {\nanimation: v60PulsePhase 700ms ease-out 1;\ntransform-origin: center;\nwill-change: transform;\n}\n@keyframes v60BlinkPill {\n0%, 100% { opacity: 1; transform: scale(1); }\n50% { opacity: .22; transform: scale(1.03); }\n}\n.v60-pill-pour-active {\nbackground: #ffe7b7 !important;\nborder: 2px solid #d2a44a !important;\ncolor: #3b2a12 !important;\nfont-weight: 900 !important;\nletter-spacing: .02em;\nanimation: v60BlinkPill 2500ms ease-in-out infinite;\nbox-shadow:\n0 0 0 2px rgba(210,164,74,.18) inset,\n0 10px 22px rgba(0,0,0,.12),\n0 0 0 6px rgba(210,164,74,.10);\n}\n@media (prefers-reduced-motion: reduce) {\n.v60-pill-pour-active { animation: none; }\n.v60-pulse { animation: none; }\n}\n\u003c\/style\u003e\n\u003cscript\u003e\n(function() {\nvar SUFFIX = '-quebraditas';\nvar END_AT = 130;\nvar phases = [\n{ key: 1, t: 0, pourLen: 10 },\n{ key: 2, t: 30, pourLen: 10 },\n{ key: 3, t: 60, pourLen: 10 },\n{ key: 4, t: 90, pourLen: 10 }\n];\nvar latte = {\ncardBg: '#f6f1ea',\ncardBorder: '#c8a97e',\npillBg: '#eadfce'\n};\nvar details = document.getElementById('v60Details' + SUFFIX);\nvar startBtn = document.getElementById('v60StartBtn' + SUFFIX);\nvar stopBtn = document.getElementById('v60StopBtn' + SUFFIX);\nvar timerEl = document.getElementById('v60Timer' + SUFFIX);\nvar statusEl = document.getElementById('v60WakeStatus' + SUFFIX);\nvar pills = {\n1: document.getElementById('v60-pill-1' + SUFFIX),\n2: document.getElementById('v60-pill-2' + SUFFIX),\n3: document.getElementById('v60-pill-3' + SUFFIX),\n4: document.getElementById('v60-pill-4' + SUFFIX)\n};\nvar cards = {\n1: document.getElementById('v60-card-1' + SUFFIX),\n2: document.getElementById('v60-card-2' + SUFFIX),\n3: document.getElementById('v60-card-3' + SUFFIX),\n4: document.getElementById('v60-card-4' + SUFFIX)\n};\nfunction setCardActive(key) {\nObject.keys(cards).forEach(function(k) {\nvar c = cards[k];\nif (!c) return;\nif (parseInt(k) === key) {\nc.style.borderColor = latte.cardBorder;\nc.style.background = latte.cardBg;\nc.style.boxShadow = '0 0 0 2px rgba(200,169,126,.25) inset, 0 8px 22px rgba(200,169,126,.28)';\n} else {\nc.style.borderColor = 'rgba(0,0,0,.18)';\nc.style.background = 'transparent';\nc.style.boxShadow = 'none';\n}\n});\n}\nfunction setPillPhaseActive(key, doPulse) {\nObject.keys(pills).forEach(function(k) {\nvar p = pills[k];\nif (!p) return;\np.style.background = 'rgba(0,0,0,.05)';\np.style.borderColor = 'rgba(0,0,0,.12)';\np.style.boxShadow = 'none';\np.classList.remove('v60-pulse');\n});\nvar pill = pills[key];\nif (pill) {\npill.style.background = latte.pillBg;\npill.style.borderColor = latte.cardBorder;\npill.style.boxShadow = '0 0 0 2px rgba(200,169,126,.25) inset';\nif (doPulse) {\npill.classList.remove('v60-pulse');\nvoid pill.offsetWidth;\npill.classList.add('v60-pulse');\n}\n}\n}\nfunction resetPourPills() {\nObject.values(pills).forEach(function(p) {\nif (!p) return;\np.classList.remove('v60-pill-pour-active');\n});\n}\nfunction setPourPillActive(key) {\nresetPourPills();\nif (!key) return;\nvar pill = pills[key];\nif (pill) pill.classList.add('v60-pill-pour-active');\n}\nfunction clearAll() {\nObject.values(cards).forEach(function(c) {\nif (!c) return;\nc.style.borderColor = 'rgba(0,0,0,.18)';\nc.style.background = 'transparent';\nc.style.boxShadow = 'none';\n});\nObject.values(pills).forEach(function(p) {\nif (!p) return;\np.style.background = 'rgba(0,0,0,.05)';\np.style.borderColor = 'rgba(0,0,0,.12)';\np.style.boxShadow = 'none';\np.classList.remove('v60-pulse');\np.classList.remove('v60-pill-pour-active');\n});\n}\nvar wakeLock = null;\nvar startTime = null;\nvar rafId = null;\nvar lastPhaseKey = null;\nvar lastPourKey = null;\nfunction fmt(sec) {\nsec = Math.max(0, Math.floor(sec));\nvar m = Math.floor(sec \/ 60);\nvar s = sec % 60;\nreturn m + ':' + (s \u003c 10 ? '0' : '') + s;\n}\nfunction getCurrentPhaseKey(elapsed) {\nvar current = phases[0].key;\nfor (var i = 0; i \u003c phases.length; i++) if (elapsed \u003e= phases[i].t) current = phases[i].key;\nreturn current;\n}\nfunction getPourKey(elapsed) {\nfor (var i = phases.length - 1; i \u003e= 0; i--) {\nvar p = phases[i];\nif (elapsed \u003e= p.t \u0026\u0026 elapsed \u003c (p.t + p.pourLen)) return p.key;\n}\nreturn null;\n}\nfunction enableWakeLock() {\nif (!('wakeLock' in navigator)) {\nstatusEl.textContent = '⚠️ Ton navigateur ne supporte pas le mode écran allumé.';\nreturn Promise.resolve();\n}\nreturn navigator.wakeLock.request('screen').then(function(wl) {\nwakeLock = wl;\nstatusEl.textContent = '✅ Écran maintenu allumé pendant la recette.';\nwakeLock.addEventListener('release', function() {\nstatusEl.textContent = 'ℹ️ Mode écran allumé relâché.';\n});\n}).catch(function() {\nstatusEl.textContent = '⚠️ Impossible d\\'activer le mode écran allumé.';\nwakeLock = null;\n});\n}\nfunction disableWakeLock() {\nif (wakeLock) { wakeLock.release(); wakeLock = null; }\n}\nfunction setButtons(running) {\nstartBtn.disabled = running;\nstopBtn.disabled = !running;\nstopBtn.style.opacity = running ? '1' : '.5';\n}\nfunction tick() {\nvar elapsed = (Date.now() - startTime) \/ 1000;\ntimerEl.textContent = fmt(elapsed);\nvar phaseKey = getCurrentPhaseKey(elapsed);\nif (phaseKey !== lastPhaseKey) {\nsetCardActive(phaseKey);\nsetPillPhaseActive(phaseKey, lastPhaseKey !== null);\nlastPhaseKey = phaseKey;\n}\nvar pourKey = getPourKey(elapsed);\nif (pourKey !== lastPourKey) {\nsetPourPillActive(pourKey);\nlastPourKey = pourKey;\n}\nif (elapsed \u003e= END_AT) { stopRecipe(true); return; }\nrafId = requestAnimationFrame(tick);\n}\nfunction startRecipe() {\nsetButtons(true);\ntimerEl.textContent = '0:00';\nlastPhaseKey = null;\nlastPourKey = null;\nenableWakeLock().then(function() {\nsetCardActive(1);\nsetPillPhaseActive(1, false);\nsetPourPillActive(1);\nlastPhaseKey = 1;\nlastPourKey = 1;\nstartTime = Date.now();\nif (rafId) cancelAnimationFrame(rafId);\nrafId = requestAnimationFrame(tick);\n});\n}\nfunction stopRecipe(autoEnded) {\nif (rafId) cancelAnimationFrame(rafId);\nrafId = null;\nstartTime = null;\ndisableWakeLock();\nsetButtons(false);\nclearAll();\nlastPhaseKey = null;\nlastPourKey = null;\nif (autoEnded) {\nstatusEl.textContent = '✅ Recette terminée — écran libéré.';\ntimerEl.textContent = fmt(END_AT);\n} else {\nstatusEl.textContent = 'ℹ️ Recette arrêtée — écran libéré.';\n}\n}\nstartBtn.addEventListener('click', startRecipe);\nstopBtn.addEventListener('click', function() { stopRecipe(false); });\ndetails.addEventListener('toggle', function() { if (!details.open) stopRecipe(false); });\ndocument.addEventListener('visibilitychange', function() {\nif (document.visibilityState === 'visible' \u0026\u0026 startTime \u0026\u0026 !wakeLock) enableWakeLock();\n});\n})();\n\u003c\/script\u003e\n\u003c\/svg\u003e","brand":"ZAB","offers":[{"title":"200g","offer_id":52429418529077,"sku":"CAF-SIN-EDIN-MELO-GB","price":30.0,"currency_code":"CAD","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/2716\/1842\/files\/melon-deau-200g.jpg?v=1774886018"},{"product_id":"colombie-francy-castillo-varietes-rares","title":"COLOMBIE - FRANCY CASTILLO: VARIÉTÉS RARES","description":"\u003c!-- =========================================================\n  SECTION 1 : NOTES DE DÉGUSTATION\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto; border: 2px solid var(--product-box-background, #000); border-radius: 12px; overflow: hidden;\"\u003e\n\u003cdiv style=\"padding: 10px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center;\"\u003eNotes de dégustation\u003c\/div\u003e\n\u003cdiv style=\"padding: 16px 14px; font-weight: 900; text-transform: uppercase; font-size: 28px; letter-spacing: .05em; text-align: center; background: transparent;\"\u003eMELON MIEL + TANGERINE + OOLONG\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 1 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 2 : APPROVISIONNEMENT\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto;\"\u003e\n\u003cdiv style=\"padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center; border-radius: 12px 12px 0 0;\"\u003eApprovisionnement\u003c\/div\u003e\n\u003ctable border=\"3\" cellpadding=\"1\" cellspacing=\"1\" style=\"width: 100%; border-collapse: collapse; background: transparent;\"\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd style=\"width: 20%;\"\u003eORIGINE\u003c\/td\u003e\n\u003ctd\u003eRégion d'Arboleda, département de Nariño, Colombie\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePRODUCTEURS\u003c\/td\u003e\n\u003ctd\u003eFrancy Castillo\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eFERME\u003c\/td\u003e\n\u003ctd\u003eEl Ubérrimo\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eVARIÉTÉ\u003c\/td\u003e\n\u003ctd\u003eBourbon rose, Geisha, Sidra et Wush wush\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePROCÉDÉ\u003c\/td\u003e\n\u003ctd\u003eLavé\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eALTITUDE\u003c\/td\u003e\n\u003ctd\u003e2118 m\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePARTENAIRES\u003c\/td\u003e\n\u003ctd\u003eApex\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eVOLUME ACHETÉ\u003c\/td\u003e\n\u003ctd\u003e96 kg\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eFAB\u003c\/td\u003e\n\u003ctd\u003e8,44 $ US\/lb\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePRIX LIVRÉ\u003c\/td\u003e\n\u003ctd\u003e18,22 $ CAD\/LB\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eRELATION\u003c\/td\u003e\n\u003ctd\u003e4 ans\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003c\/tbody\u003e\n\u003c\/table\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 2 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 3 : INFORMATIONS SUR LE CAFÉ\n========================================================= --\u003e\n\u003cdiv style=\"position: relative; width: 100%; padding-bottom: 56.25%; height: 0; overflow: hidden; border-radius: 8px;\"\u003e\u003ciframe style=\"position: absolute; top: 0; left: 0; width: 100%; height: 100%; border: 0; border-radius: 8px;\" src=\"https:\/\/www.youtube.com\/embed\/PasUD7LZEUQ?si=aqQ2pJqOIrqiiNWr\"\u003e\u003c\/iframe\u003e\u003c\/div\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto;\"\u003e\n\u003cdiv style=\"padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center; border-radius: 12px 12px 0 0;\"\u003eInformations sur le café\u003c\/div\u003e\n\u003cdiv style=\"border: 2px solid var(--product-box-background, #000); border-top: none; border-radius: 0 0 12px 12px; padding: 16px 14px; background: transparent;\"\u003e\n\u003cp style=\"margin: 0 0 12px 0;\"\u003eNous avons eu la chance, durant l'été 2023, d'être accueillis en Colombie dans la région de Nariño par nul autre que la remarquable Francy Castillo. C'est en suivant ses pas enthousiastes et son rire éclatant que nous nous sommes rendus à 2000 mètres d'altitude, à travers un petit sentier étroit et ardu, pour finalement arriver à sa ferme de caféiers. La vue à travers les montagnes était incroyable, et l'accueil de Francy encore plus remarquable.\u003c\/p\u003e\n\u003cp style=\"margin: 0;\"\u003eFrancy est une femme impressionnante, non seulement pour son expertise hors du commun, mais aussi pour le dévouement dont elle fait preuve pour sa communauté. Elle travaille sur sa ferme ainsi que sur les terres familiales, mais aussi avec plus de 900 petits producteurs et productrices de sa région. Elle supervise le projet Berruecos, qui regroupe les cerises des petits producteurs de la région à son point de collecte. Cette initiative permet aux producteurs isolés d'accéder au marché du café de spécialité, leur offrant ainsi la possibilité de toucher des prix premium. Le projet génère des lots plus grands et plus faciles à gérer, provenant de fermes et de producteurs exceptionnels.\u003c\/p\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 3 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 4 : V60\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto;\"\u003e\n\u003cdetails id=\"v60Details-francycastillo\" open=\"\" style=\"border: 2px solid var(--product-box-background, #000); border-radius: 12px; overflow: hidden; margin: 0 0 12px 0; background: rgba(255,255,255,0.5);\"\u003e\n\u003csummary style=\"cursor: pointer; list-style: none; padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center;\"\u003eV60 – Recette\u003c\/summary\u003e\n\u003cdiv style=\"padding: 12px 14px;\"\u003e\n\u003cdiv style=\"padding: 10px 0 10px; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003e\n\u003cdiv style=\"font-weight: 900; font-size: 16px;\"\u003eRatio 1:16\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 4px; opacity: .7; font-size: 13px;\"\u003e15 g in – 240 g out\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 6px; font-size: 13px;\"\u003e\n\u003cstrong\u003eTempérature de l'eau :\u003c\/strong\u003e 92 °C\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; padding: 10px 0 8px;\"\u003e\n\u003cdiv style=\"display: flex; gap: 8px; align-items: center; flex-wrap: wrap;\"\u003e\n\u003cbutton style=\"cursor: pointer; border: 2px solid var(--product-box-background, #000); background: var(--product-box-background, #000); color: var(--product-box-text, #fff); font-weight: 900; padding: 8px 10px; border-radius: 10px; text-transform: uppercase; letter-spacing: .02em; font-size: 12px;\" type=\"button\" id=\"v60StartBtn-francycastillo\"\u003eDémarrer\u003c\/button\u003e \u003cbutton style=\"cursor: pointer; border: 2px solid var(--product-box-background, #000); background: var(--product-box-text, #fff); color: var(--product-box-background, #000); font-weight: 900; padding: 8px 10px; border-radius: 10px; text-transform: uppercase; letter-spacing: .02em; font-size: 12px; opacity: .5;\" disabled type=\"button\" id=\"v60StopBtn-francycastillo\"\u003eStop\u003c\/button\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; line-height: 1;\"\u003e\n\u003cspan style=\"opacity: .70; font-size: 12px; font-weight: 800; text-transform: uppercase; letter-spacing: .04em;\"\u003eTimer\u003c\/span\u003e \u003cspan style=\"font-weight: 950; font-size: 28px; letter-spacing: .01em;\" id=\"v60Timer-francycastillo\"\u003e0:00\u003c\/span\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"flex-basis: 100%; opacity: .6; font-size: 12px; line-height: 1.3; margin-top: 2px;\" id=\"v60WakeStatus-francycastillo\"\u003eℹ️ Appuie sur \"Démarrer\" pour garder l'écran allumé.\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 8px; display: grid; gap: 10px;\"\u003e\n\u003cdiv style=\"border: 1px solid rgba(0,0,0,.18); border-radius: 12px; padding: 10px 12px;\" id=\"v60-card-1-francycastillo\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; margin-bottom: 6px;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e0:00\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003ePhase 1 — Bloom\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 8px; flex-wrap: wrap; font-size: 12.5px; font-weight: 800;\"\u003e\n\u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\" id=\"v60-pill-1-francycastillo\"\u003eVerser pendant 0:10s\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\"\u003eTotal 50 g\u003c\/span\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"border: 1px solid rgba(0,0,0,.18); border-radius: 12px; padding: 10px 12px;\" id=\"v60-card-2-francycastillo\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; margin-bottom: 6px;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e0:30\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003ePhase 2\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 8px; flex-wrap: wrap; font-size: 12.5px; font-weight: 800;\"\u003e\n\u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\" id=\"v60-pill-2-francycastillo\"\u003eVerser pendant 0:30s\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\"\u003eTotal 115 g\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12); opacity: .6;\"\u003e+65 g\u003c\/span\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"border: 1px solid rgba(0,0,0,.18); border-radius: 12px; padding: 10px 12px;\" id=\"v60-card-3-francycastillo\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; margin-bottom: 6px;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e1:15\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003ePhase 3\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 8px; flex-wrap: wrap; font-size: 12.5px; font-weight: 800;\"\u003e\n\u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\" id=\"v60-pill-3-francycastillo\"\u003eVerser pendant 0:20s\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\"\u003eTotal 170 g\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12); opacity: .6;\"\u003e+55 g\u003c\/span\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"border: 1px solid rgba(0,0,0,.18); border-radius: 12px; padding: 10px 12px;\" id=\"v60-card-4-francycastillo\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; margin-bottom: 6px;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e1:50\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003ePhase 4\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 8px; flex-wrap: wrap; font-size: 12.5px; font-weight: 800;\"\u003e\n\u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\" id=\"v60-pill-4-francycastillo\"\u003eVerser pendant 0:25s\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\"\u003eTotal 240 g\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12); opacity: .6;\"\u003e+70 g\u003c\/span\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 12px; border-top: 1px solid rgba(0,0,0,.2); padding-top: 10px;\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e3:00\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003eTemps final écoulement complet\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 8px; padding: 8px 10px; border-radius: 8px; background: rgba(0,0,0,.04); border: 1px dashed rgba(0,0,0,.2); font-size: 12px; opacity: .6; line-height: 1.4;\"\u003e\n\u003cstrong\u003eℹ️ Astuce —\u003c\/strong\u003e Si le temps total est plus court, la mouture est probablement trop grosse. S'il est plus long, la mouture est probablement trop fine.\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/details\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 4 ========= --\u003e\u003csvg style=\"display: none;\"\u003e\n\u003cstyle\u003e\n  @keyframes v60PulsePhase {\n    0%   { transform: scale(1);    box-shadow: 0 0 0 0 rgba(200,169,126,.35); }\n    50%  { transform: scale(1.06); box-shadow: 0 0 0 10px rgba(200,169,126,0); }\n    100% { transform: scale(1);    box-shadow: 0 0 0 0 rgba(200,169,126,0); }\n  }\n  .v60-pulse {\n    animation: v60PulsePhase 700ms ease-out 1;\n    transform-origin: center;\n    will-change: transform;\n  }\n  @keyframes v60BlinkPill {\n    0%, 100% { opacity: 1; transform: scale(1); }\n    50%      { opacity: .22; transform: scale(1.03); }\n  }\n  .v60-pill-pour-active {\n    background: #ffe7b7 !important;\n    border: 2px solid #d2a44a !important;\n    color: #3b2a12 !important;\n    font-weight: 900 !important;\n    letter-spacing: .02em;\n    animation: v60BlinkPill 2500ms ease-in-out infinite;\n    box-shadow:\n      0 0 0 2px rgba(210,164,74,.18) inset,\n      0 10px 22px rgba(0,0,0,.12),\n      0 0 0 6px rgba(210,164,74,.10);\n  }\n  @media (prefers-reduced-motion: reduce) {\n    .v60-pill-pour-active { animation: none; }\n    .v60-pulse { animation: none; }\n  }\n\u003c\/style\u003e\n\u003cscript\u003e\n(function() {\n  var SUFFIX = '-francycastillo';\n  var END_AT = 180;\n  var phases = [\n    { key: 1, t: 0,   pourLen: 10 },\n    { key: 2, t: 30,  pourLen: 30 },\n    { key: 3, t: 75,  pourLen: 20 },\n    { key: 4, t: 110, pourLen: 25 }\n  ];\n  var latte = {\n    cardBg:     '#f6f1ea',\n    cardBorder: '#c8a97e',\n    pillBg:     '#eadfce'\n  };\n  var details  = document.getElementById('v60Details'    + SUFFIX);\n  var startBtn = document.getElementById('v60StartBtn'   + SUFFIX);\n  var stopBtn  = document.getElementById('v60StopBtn'    + SUFFIX);\n  var timerEl  = document.getElementById('v60Timer'      + SUFFIX);\n  var statusEl = document.getElementById('v60WakeStatus' + SUFFIX);\n  var pills = {\n    1: document.getElementById('v60-pill-1' + SUFFIX),\n    2: document.getElementById('v60-pill-2' + SUFFIX),\n    3: document.getElementById('v60-pill-3' + SUFFIX),\n    4: document.getElementById('v60-pill-4' + SUFFIX)\n  };\n  var cards = {\n    1: document.getElementById('v60-card-1' + SUFFIX),\n    2: document.getElementById('v60-card-2' + SUFFIX),\n    3: document.getElementById('v60-card-3' + SUFFIX),\n    4: document.getElementById('v60-card-4' + SUFFIX)\n  };\n  function setCardActive(key) {\n    Object.keys(cards).forEach(function(k) {\n      var c = cards[k];\n      if (!c) return;\n      if (parseInt(k) === key) {\n        c.style.borderColor = latte.cardBorder;\n        c.style.background  = latte.cardBg;\n        c.style.boxShadow   = '0 0 0 2px rgba(200,169,126,.25) inset, 0 8px 22px rgba(200,169,126,.28)';\n      } else {\n        c.style.borderColor = 'rgba(0,0,0,.18)';\n        c.style.background  = 'transparent';\n        c.style.boxShadow   = 'none';\n      }\n    });\n  }\n  function setPillPhaseActive(key, doPulse) {\n    Object.keys(pills).forEach(function(k) {\n      var p = pills[k];\n      if (!p) return;\n      p.style.background  = 'rgba(0,0,0,.05)';\n      p.style.borderColor = 'rgba(0,0,0,.12)';\n      p.style.boxShadow   = 'none';\n      p.classList.remove('v60-pulse');\n    });\n    var pill = pills[key];\n    if (pill) {\n      pill.style.background  = latte.pillBg;\n      pill.style.borderColor = latte.cardBorder;\n      pill.style.boxShadow   = '0 0 0 2px rgba(200,169,126,.25) inset';\n      if (doPulse) {\n        pill.classList.remove('v60-pulse');\n        void pill.offsetWidth;\n        pill.classList.add('v60-pulse');\n      }\n    }\n  }\n  function resetPourPills() {\n    Object.values(pills).forEach(function(p) {\n      if (!p) return;\n      p.classList.remove('v60-pill-pour-active');\n    });\n  }\n  function setPourPillActive(key) {\n    resetPourPills();\n    if (!key) return;\n    var pill = pills[key];\n    if (pill) pill.classList.add('v60-pill-pour-active');\n  }\n  function clearAll() {\n    Object.values(cards).forEach(function(c) {\n      if (!c) return;\n      c.style.borderColor = 'rgba(0,0,0,.18)';\n      c.style.background  = 'transparent';\n      c.style.boxShadow   = 'none';\n    });\n    Object.values(pills).forEach(function(p) {\n      if (!p) return;\n      p.style.background  = 'rgba(0,0,0,.05)';\n      p.style.borderColor = 'rgba(0,0,0,.12)';\n      p.style.boxShadow   = 'none';\n      p.classList.remove('v60-pulse');\n      p.classList.remove('v60-pill-pour-active');\n    });\n  }\n  var wakeLock  = null;\n  var startTime = null;\n  var rafId     = null;\n  var lastPhaseKey = null;\n  var lastPourKey  = null;\n  function fmt(sec) {\n    sec = Math.max(0, Math.floor(sec));\n    var m = Math.floor(sec \/ 60);\n    var s = sec % 60;\n    return m + ':' + (s \u0026lt; 10 ? '0' : '') + s;\n  }\n  function getCurrentPhaseKey(elapsed) {\n    var current = phases[0].key;\n    for (var i = 0; i \u0026lt; phases.length; i++) if (elapsed \u0026gt;= phases[i].t) current = phases[i].key;\n    return current;\n  }\n  function getPourKey(elapsed) {\n    for (var i = phases.length - 1; i \u0026gt;= 0; i--) {\n      var p = phases[i];\n      if (elapsed \u0026gt;= p.t \u0026amp;\u0026amp; elapsed \u0026lt; (p.t + p.pourLen)) return p.key;\n    }\n    return null;\n  }\n  function enableWakeLock() {\n    if (!('wakeLock' in navigator)) {\n      statusEl.textContent = '⚠️ Ton navigateur ne supporte pas le mode écran allumé.';\n      return Promise.resolve();\n    }\n    return navigator.wakeLock.request('screen').then(function(wl) {\n      wakeLock = wl;\n      statusEl.textContent = '✅ Écran maintenu allumé pendant la recette.';\n      wakeLock.addEventListener('release', function() {\n        statusEl.textContent = 'ℹ️ Mode écran allumé relâché.';\n      });\n    }).catch(function() {\n      statusEl.textContent = '⚠️ Impossible d\\'activer le mode écran allumé.';\n      wakeLock = null;\n    });\n  }\n  function disableWakeLock() {\n    if (wakeLock) { wakeLock.release(); wakeLock = null; }\n  }\n  function setButtons(running) {\n    startBtn.disabled = running;\n    stopBtn.disabled  = !running;\n    stopBtn.style.opacity = running ? '1' : '.5';\n  }\n  function tick() {\n    var elapsed = (Date.now() - startTime) \/ 1000;\n    timerEl.textContent = fmt(elapsed);\n    var phaseKey = getCurrentPhaseKey(elapsed);\n    if (phaseKey !== lastPhaseKey) {\n      setCardActive(phaseKey);\n      setPillPhaseActive(phaseKey, lastPhaseKey !== null);\n      lastPhaseKey = phaseKey;\n    }\n    var pourKey = getPourKey(elapsed);\n    if (pourKey !== lastPourKey) {\n      setPourPillActive(pourKey);\n      lastPourKey = pourKey;\n    }\n    if (elapsed \u0026gt;= END_AT) { stopRecipe(true); return; }\n    rafId = requestAnimationFrame(tick);\n  }\n  function startRecipe() {\n    setButtons(true);\n    timerEl.textContent = '0:00';\n    lastPhaseKey = null;\n    lastPourKey  = null;\n    enableWakeLock().then(function() {\n      setCardActive(1);\n      setPillPhaseActive(1, false);\n      setPourPillActive(1);\n      lastPhaseKey = 1;\n      lastPourKey  = 1;\n      startTime = Date.now();\n      if (rafId) cancelAnimationFrame(rafId);\n      rafId = requestAnimationFrame(tick);\n    });\n  }\n  function stopRecipe(autoEnded) {\n    if (rafId) cancelAnimationFrame(rafId);\n    rafId     = null;\n    startTime = null;\n    disableWakeLock();\n    setButtons(false);\n    clearAll();\n    lastPhaseKey = null;\n    lastPourKey  = null;\n    if (autoEnded) {\n      statusEl.textContent = '✅ Recette terminée — écran libéré.';\n      timerEl.textContent  = fmt(END_AT);\n    } else {\n      statusEl.textContent = 'ℹ️ Recette arrêtée — écran libéré.';\n    }\n  }\n  startBtn.addEventListener('click', startRecipe);\n  stopBtn.addEventListener('click', function() { stopRecipe(false); });\n  details.addEventListener('toggle', function() { if (!details.open) stopRecipe(false); });\n  document.addEventListener('visibilitychange', function() {\n    if (document.visibilityState === 'visible' \u0026amp;\u0026amp; startTime \u0026amp;\u0026amp; !wakeLock) enableWakeLock();\n  });\n})();\n\u003c\/script\u003e\n\u003c\/svg\u003e","brand":"ZAB","offers":[{"title":"200g","offer_id":52990481629493,"sku":"CAF-SIN-FRAN-FANC-GB","price":35.0,"currency_code":"CAD","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/2716\/1842\/files\/francy-spring2026-200g.jpg?v=1781285595"},{"product_id":"colombie-nogales","title":"COLOMBIE - NOGALES","description":"\u003c!-- =========================================================\n  SECTION 1 : NOTES DE DÉGUSTATION\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto; border: 2px solid var(--product-box-background, #000); border-radius: 12px; overflow: hidden;\"\u003e\n\u003cdiv style=\"padding: 10px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center;\"\u003eNotes de dégustation\u003c\/div\u003e\n\u003cdiv style=\"padding: 16px 14px; font-weight: 900; text-transform: uppercase; font-size: 28px; letter-spacing: .05em; text-align: center; background: transparent;\"\u003eCERISE + PAMPLEMOUSSE ROSE + BANANE + FLORAL\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 1 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 2 : APPROVISIONNEMENT\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto;\"\u003e\n\u003cdiv style=\"padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center; border-radius: 12px 12px 0 0;\"\u003eApprovisionnement\u003c\/div\u003e\n\u003ctable border=\"3\" cellpadding=\"1\" cellspacing=\"1\" style=\"width: 100%; border-collapse: collapse; background: transparent;\"\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd style=\"width: 20%;\"\u003eORIGINE\u003c\/td\u003e\n\u003ctd\u003eMunicipalité de Bruselas, région de Huila, Colombie\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePRODUCTEURS\u003c\/td\u003e\n\u003ctd\u003eFamille Hernández\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eFERME\u003c\/td\u003e\n\u003ctd\u003eNogales\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eVARIÉTÉ\u003c\/td\u003e\n\u003ctd\u003eTypica\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePROCÉDÉ\u003c\/td\u003e\n\u003ctd\u003eLavé et fermentation avancée\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eALTITUDE\u003c\/td\u003e\n\u003ctd\u003e1900 m\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePARTENAIRES\u003c\/td\u003e\n\u003ctd\u003eApex Coffee Import\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eVOLUME ACHETÉ\u003c\/td\u003e\n\u003ctd\u003e48 kg\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eFAB\u003c\/td\u003e\n\u003ctd\u003e10,25 $ US\/lb\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePRIX LIVRÉ\u003c\/td\u003e\n\u003ctd\u003e20,33 $ CAD\/LB\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eRELATION\u003c\/td\u003e\n\u003ctd\u003e1 an\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003c\/tbody\u003e\n\u003c\/table\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 2 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 3 : INFORMATIONS SUR LE CAFÉ\n========================================================= --\u003e\n\u003cdiv style=\"position: relative; width: 100%; padding-bottom: 56.25%; height: 0; overflow: hidden; border-radius: 8px;\"\u003e\u003ciframe style=\"position: absolute; top: 0; left: 0; width: 100%; height: 100%; border: 0; border-radius: 8px;\" src=\"https:\/\/www.youtube.com\/embed\/Nee_D0sJqAE?si=RKeYTkIXfSST_Q3Q\"\u003e\u003c\/iframe\u003e\u003c\/div\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto;\"\u003e\n\u003cdiv style=\"padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center; border-radius: 12px 12px 0 0;\"\u003eInformations sur le café\u003c\/div\u003e\n\u003cdiv style=\"border: 2px solid var(--product-box-background, #000); border-top: none; border-radius: 0 0 12px 12px; padding: 16px 14px; background: transparent;\"\u003e\n\u003cp style=\"margin: 0 0 12px 0;\"\u003eC'est toujours intéressant de goûter un café dont le procédé plus avancé nous permet d'explorer un univers gustatif plus complexe. Dans le cas du Nogales de la famille Hernandez, on sent en premier lieu une odeur prononcée de bubble-gum mélangée à la banane. Dans la tasse, les arômes semblent plus équilibrés qu'à l'odeur. On a d'abord le goût de fruits séchés ou bien de rouleau aux fruits, ensuite une acidité similaire aux agrumes, puis la banane qui fait son retour.\u003c\/p\u003e\n\u003cp style=\"margin: 0 0 12px 0;\"\u003eC'est grâce à leur souci d'innovation que la famille Hernandez se démarque, tant dans son procédé que dans le soin apporté à la sélection des variétés. Le procédé utilisé pour ce café, fait avec un soin et un savoir-faire exceptionnel, lui donne vraiment beaucoup de caractère. Pour débuter, les cerises sont brièvement plongées dans l'eau chaude pour libérer leurs sucres naturels. Elles sont ensuite dépulpées en conservant un maximum de jus, qui servira à une fermentation de sept jours avec des levures sélectionnées provenant du même café. Cette méthode aide à créer un café plus complexe et expressif, tout en mettant en valeur les caractéristiques uniques de son terroir.\u003c\/p\u003e\n\u003cp style=\"margin: 0;\"\u003eLe Groupe Nogales est un projet familial qui allie tradition, innovation et engagement envers sa communauté. Reconnu pour la qualité de ses cafés depuis sa victoire à la Cup of Excellence en 2005, il poursuit aujourd'hui son développement à travers des projets novateurs, une approche durable de l'agriculture et une maîtrise complète de la production. En 2025, l'acquisition de la ferme Niebla, située à 2 150 mètres d'altitude, marque une nouvelle étape avec la plantation de variétés prestigieuses et la production de cafés entièrement élaborés à la ferme, de la semence à la tasse.\u003c\/p\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 3 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 4 : V60\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto;\"\u003e\n\u003cdetails id=\"v60Details-hernandez\" open=\"\" style=\"border: 2px solid var(--product-box-background, #000); border-radius: 12px; overflow: hidden; margin: 0 0 12px 0; background: rgba(255,255,255,0.5);\"\u003e\n\u003csummary style=\"cursor: pointer; list-style: none; padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center;\"\u003eV60 – Recette\u003c\/summary\u003e\n\u003cdiv style=\"padding: 12px 14px;\"\u003e\n\u003cdiv style=\"padding: 10px 0 10px; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003e\n\u003cdiv style=\"font-weight: 900; font-size: 16px;\"\u003eRatio 1:15\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 4px; opacity: .7; font-size: 13px;\"\u003e15 g in – 225 g out\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 6px; font-size: 13px;\"\u003e\n\u003cstrong\u003eTempérature de l'eau :\u003c\/strong\u003e 90 °C\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; padding: 10px 0 8px;\"\u003e\n\u003cdiv style=\"display: flex; gap: 8px; align-items: center; flex-wrap: wrap;\"\u003e\n\u003cbutton style=\"cursor: pointer; border: 2px solid var(--product-box-background, #000); background: var(--product-box-background, #000); color: var(--product-box-text, #fff); font-weight: 900; padding: 8px 10px; border-radius: 10px; text-transform: uppercase; letter-spacing: .02em; font-size: 12px;\" type=\"button\" id=\"v60StartBtn-hernandez\"\u003eDémarrer\u003c\/button\u003e \u003cbutton style=\"cursor: pointer; border: 2px solid var(--product-box-background, #000); background: var(--product-box-text, #fff); color: var(--product-box-background, #000); font-weight: 900; padding: 8px 10px; border-radius: 10px; text-transform: uppercase; letter-spacing: .02em; font-size: 12px; opacity: .5;\" disabled type=\"button\" id=\"v60StopBtn-hernandez\"\u003eStop\u003c\/button\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; line-height: 1;\"\u003e\n\u003cspan style=\"opacity: .70; font-size: 12px; font-weight: 800; text-transform: uppercase; letter-spacing: .04em;\"\u003eTimer\u003c\/span\u003e \u003cspan style=\"font-weight: 950; font-size: 28px; letter-spacing: .01em;\" id=\"v60Timer-hernandez\"\u003e0:00\u003c\/span\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"flex-basis: 100%; opacity: .6; font-size: 12px; line-height: 1.3; margin-top: 2px;\" id=\"v60WakeStatus-hernandez\"\u003eℹ️ Appuie sur \"Démarrer\" pour garder l'écran allumé.\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 8px; display: grid; gap: 10px;\"\u003e\n\u003cdiv style=\"border: 1px solid rgba(0,0,0,.18); border-radius: 12px; padding: 10px 12px;\" id=\"v60-card-1-hernandez\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; margin-bottom: 6px;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e0:00\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003ePhase 1 — Bloom\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 8px; flex-wrap: wrap; font-size: 12.5px; font-weight: 800;\"\u003e\n\u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\" id=\"v60-pill-1-hernandez\"\u003eVerser pendant 0:10s\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\"\u003eTotal 40 g\u003c\/span\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"border: 1px solid rgba(0,0,0,.18); border-radius: 12px; padding: 10px 12px;\" id=\"v60-card-2-hernandez\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; margin-bottom: 6px;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e0:45\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003ePhase 2\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 8px; flex-wrap: wrap; font-size: 12.5px; font-weight: 800;\"\u003e\n\u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\" id=\"v60-pill-2-hernandez\"\u003eVerser pendant 0:30s\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\"\u003eTotal 115 g\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12); opacity: .6;\"\u003e+75 g\u003c\/span\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"border: 1px solid rgba(0,0,0,.18); border-radius: 12px; padding: 10px 12px;\" id=\"v60-card-3-hernandez\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; margin-bottom: 6px;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e1:15\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003ePhase 3\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 8px; flex-wrap: wrap; font-size: 12.5px; font-weight: 800;\"\u003e\n\u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\" id=\"v60-pill-3-hernandez\"\u003eVerser pendant 0:20s\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\"\u003eTotal 170 g\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12); opacity: .6;\"\u003e+55 g\u003c\/span\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"border: 1px solid rgba(0,0,0,.18); border-radius: 12px; padding: 10px 12px;\" id=\"v60-card-4-hernandez\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; margin-bottom: 6px;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e1:50\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003ePhase 4\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 8px; flex-wrap: wrap; font-size: 12.5px; font-weight: 800;\"\u003e\n\u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\" id=\"v60-pill-4-hernandez\"\u003eVerser pendant 0:20s\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\"\u003eTotal 225 g\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12); opacity: .6;\"\u003e+55 g\u003c\/span\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 12px; border-top: 1px solid rgba(0,0,0,.2); padding-top: 10px;\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e2:50\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003eTemps final écoulement complet\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 8px; padding: 8px 10px; border-radius: 8px; background: rgba(0,0,0,.04); border: 1px dashed rgba(0,0,0,.2); font-size: 12px; opacity: .6; line-height: 1.4;\"\u003e\n\u003cstrong\u003eℹ️ Astuce —\u003c\/strong\u003e Si le temps total est plus court, la mouture est probablement trop grosse. S'il est plus long, la mouture est probablement trop fine.\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/details\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 4 ========= --\u003e\u003csvg style=\"display: none;\"\u003e\n\u003cstyle\u003e\n  @keyframes v60PulsePhase {\n    0%   { transform: scale(1);    box-shadow: 0 0 0 0 rgba(200,169,126,.35); }\n    50%  { transform: scale(1.06); box-shadow: 0 0 0 10px rgba(200,169,126,0); }\n    100% { transform: scale(1);    box-shadow: 0 0 0 0 rgba(200,169,126,0); }\n  }\n  .v60-pulse {\n    animation: v60PulsePhase 700ms ease-out 1;\n    transform-origin: center;\n    will-change: transform;\n  }\n  @keyframes v60BlinkPill {\n    0%, 100% { opacity: 1; transform: scale(1); }\n    50%      { opacity: .22; transform: scale(1.03); }\n  }\n  .v60-pill-pour-active {\n    background: #ffe7b7 !important;\n    border: 2px solid #d2a44a !important;\n    color: #3b2a12 !important;\n    font-weight: 900 !important;\n    letter-spacing: .02em;\n    animation: v60BlinkPill 2500ms ease-in-out infinite;\n    box-shadow:\n      0 0 0 2px rgba(210,164,74,.18) inset,\n      0 10px 22px rgba(0,0,0,.12),\n      0 0 0 6px rgba(210,164,74,.10);\n  }\n  @media (prefers-reduced-motion: reduce) {\n    .v60-pill-pour-active { animation: none; }\n    .v60-pulse { animation: none; }\n  }\n\u003c\/style\u003e\n\u003cscript\u003e\n(function() {\n  var SUFFIX = '-hernandez';\n  var END_AT = 170;\n  var phases = [\n    { key: 1, t: 0,   pourLen: 10 },\n    { key: 2, t: 45,  pourLen: 30 },\n    { key: 3, t: 75,  pourLen: 20 },\n    { key: 4, t: 110, pourLen: 20 }\n  ];\n  var latte = {\n    cardBg:     '#f6f1ea',\n    cardBorder: '#c8a97e',\n    pillBg:     '#eadfce'\n  };\n  var details  = document.getElementById('v60Details'    + SUFFIX);\n  var startBtn = document.getElementById('v60StartBtn'   + SUFFIX);\n  var stopBtn  = document.getElementById('v60StopBtn'    + SUFFIX);\n  var timerEl  = document.getElementById('v60Timer'      + SUFFIX);\n  var statusEl = document.getElementById('v60WakeStatus' + SUFFIX);\n  var pills = {\n    1: document.getElementById('v60-pill-1' + SUFFIX),\n    2: document.getElementById('v60-pill-2' + SUFFIX),\n    3: document.getElementById('v60-pill-3' + SUFFIX),\n    4: document.getElementById('v60-pill-4' + SUFFIX)\n  };\n  var cards = {\n    1: document.getElementById('v60-card-1' + SUFFIX),\n    2: document.getElementById('v60-card-2' + SUFFIX),\n    3: document.getElementById('v60-card-3' + SUFFIX),\n    4: document.getElementById('v60-card-4' + SUFFIX)\n  };\n  function setCardActive(key) {\n    Object.keys(cards).forEach(function(k) {\n      var c = cards[k];\n      if (!c) return;\n      if (parseInt(k) === key) {\n        c.style.borderColor = latte.cardBorder;\n        c.style.background  = latte.cardBg;\n        c.style.boxShadow   = '0 0 0 2px rgba(200,169,126,.25) inset, 0 8px 22px rgba(200,169,126,.28)';\n      } else {\n        c.style.borderColor = 'rgba(0,0,0,.18)';\n        c.style.background  = 'transparent';\n        c.style.boxShadow   = 'none';\n      }\n    });\n  }\n  function setPillPhaseActive(key, doPulse) {\n    Object.keys(pills).forEach(function(k) {\n      var p = pills[k];\n      if (!p) return;\n      p.style.background  = 'rgba(0,0,0,.05)';\n      p.style.borderColor = 'rgba(0,0,0,.12)';\n      p.style.boxShadow   = 'none';\n      p.classList.remove('v60-pulse');\n    });\n    var pill = pills[key];\n    if (pill) {\n      pill.style.background  = latte.pillBg;\n      pill.style.borderColor = latte.cardBorder;\n      pill.style.boxShadow   = '0 0 0 2px rgba(200,169,126,.25) inset';\n      if (doPulse) {\n        pill.classList.remove('v60-pulse');\n        void pill.offsetWidth;\n        pill.classList.add('v60-pulse');\n      }\n    }\n  }\n  function resetPourPills() {\n    Object.values(pills).forEach(function(p) {\n      if (!p) return;\n      p.classList.remove('v60-pill-pour-active');\n    });\n  }\n  function setPourPillActive(key) {\n    resetPourPills();\n    if (!key) return;\n    var pill = pills[key];\n    if (pill) pill.classList.add('v60-pill-pour-active');\n  }\n  function clearAll() {\n    Object.values(cards).forEach(function(c) {\n      if (!c) return;\n      c.style.borderColor = 'rgba(0,0,0,.18)';\n      c.style.background  = 'transparent';\n      c.style.boxShadow   = 'none';\n    });\n    Object.values(pills).forEach(function(p) {\n      if (!p) return;\n      p.style.background  = 'rgba(0,0,0,.05)';\n      p.style.borderColor = 'rgba(0,0,0,.12)';\n      p.style.boxShadow   = 'none';\n      p.classList.remove('v60-pulse');\n      p.classList.remove('v60-pill-pour-active');\n    });\n  }\n  var wakeLock  = null;\n  var startTime = null;\n  var rafId     = null;\n  var lastPhaseKey = null;\n  var lastPourKey  = null;\n  function fmt(sec) {\n    sec = Math.max(0, Math.floor(sec));\n    var m = Math.floor(sec \/ 60);\n    var s = sec % 60;\n    return m + ':' + (s \u0026lt; 10 ? '0' : '') + s;\n  }\n  function getCurrentPhaseKey(elapsed) {\n    var current = phases[0].key;\n    for (var i = 0; i \u0026lt; phases.length; i++) if (elapsed \u0026gt;= phases[i].t) current = phases[i].key;\n    return current;\n  }\n  function getPourKey(elapsed) {\n    for (var i = phases.length - 1; i \u0026gt;= 0; i--) {\n      var p = phases[i];\n      if (elapsed \u0026gt;= p.t \u0026amp;\u0026amp; elapsed \u0026lt; (p.t + p.pourLen)) return p.key;\n    }\n    return null;\n  }\n  function enableWakeLock() {\n    if (!('wakeLock' in navigator)) {\n      statusEl.textContent = '⚠️ Ton navigateur ne supporte pas le mode écran allumé.';\n      return Promise.resolve();\n    }\n    return navigator.wakeLock.request('screen').then(function(wl) {\n      wakeLock = wl;\n      statusEl.textContent = '✅ Écran maintenu allumé pendant la recette.';\n      wakeLock.addEventListener('release', function() {\n        statusEl.textContent = 'ℹ️ Mode écran allumé relâché.';\n      });\n    }).catch(function() {\n      statusEl.textContent = '⚠️ Impossible d\\'activer le mode écran allumé.';\n      wakeLock = null;\n    });\n  }\n  function disableWakeLock() {\n    if (wakeLock) { wakeLock.release(); wakeLock = null; }\n  }\n  function setButtons(running) {\n    startBtn.disabled = running;\n    stopBtn.disabled  = !running;\n    stopBtn.style.opacity = running ? '1' : '.5';\n  }\n  function tick() {\n    var elapsed = (Date.now() - startTime) \/ 1000;\n    timerEl.textContent = fmt(elapsed);\n    var phaseKey = getCurrentPhaseKey(elapsed);\n    if (phaseKey !== lastPhaseKey) {\n      setCardActive(phaseKey);\n      setPillPhaseActive(phaseKey, lastPhaseKey !== null);\n      lastPhaseKey = phaseKey;\n    }\n    var pourKey = getPourKey(elapsed);\n    if (pourKey !== lastPourKey) {\n      setPourPillActive(pourKey);\n      lastPourKey = pourKey;\n    }\n    if (elapsed \u0026gt;= END_AT) { stopRecipe(true); return; }\n    rafId = requestAnimationFrame(tick);\n  }\n  function startRecipe() {\n    setButtons(true);\n    timerEl.textContent = '0:00';\n    lastPhaseKey = null;\n    lastPourKey  = null;\n    enableWakeLock().then(function() {\n      setCardActive(1);\n      setPillPhaseActive(1, false);\n      setPourPillActive(1);\n      lastPhaseKey = 1;\n      lastPourKey  = 1;\n      startTime = Date.now();\n      if (rafId) cancelAnimationFrame(rafId);\n      rafId = requestAnimationFrame(tick);\n    });\n  }\n  function stopRecipe(autoEnded) {\n    if (rafId) cancelAnimationFrame(rafId);\n    rafId     = null;\n    startTime = null;\n    disableWakeLock();\n    setButtons(false);\n    clearAll();\n    lastPhaseKey = null;\n    lastPourKey  = null;\n    if (autoEnded) {\n      statusEl.textContent = '✅ Recette terminée — écran libéré.';\n      timerEl.textContent  = fmt(END_AT);\n    } else {\n      statusEl.textContent = 'ℹ️ Recette arrêtée — écran libéré.';\n    }\n  }\n  startBtn.addEventListener('click', startRecipe);\n  stopBtn.addEventListener('click', function() { stopRecipe(false); });\n  details.addEventListener('toggle', function() { if (!details.open) stopRecipe(false); });\n  document.addEventListener('visibilitychange', function() {\n    if (document.visibilityState === 'visible' \u0026amp;\u0026amp; startTime \u0026amp;\u0026amp; !wakeLock) enableWakeLock();\n  });\n})();\n\u003c\/script\u003e\n\u003c\/svg\u003e","brand":"ZAB","offers":[{"title":"200g","offer_id":52992309002549,"sku":"CAF-SIN-NOGA-GB","price":39.0,"currency_code":"CAD","in_stock":false}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/2716\/1842\/files\/nogales-200g_c21692ad-e1bb-4284-8e31-0d2afb7fa94f.jpg?v=1781886041"},{"product_id":"perou-famille-minga","title":"PÉROU - FAMILLE MINGA","description":"\u003c!-- =========================================================\n  SECTION 1 : NOTES DE DÉGUSTATION\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto; border: 2px solid var(--product-box-background, #000); border-radius: 12px; overflow: hidden;\"\u003e\n\u003cdiv style=\"padding: 10px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center;\"\u003eNotes de dégustation\u003c\/div\u003e\n\u003cdiv style=\"padding: 16px 14px; font-weight: 900; text-transform: uppercase; font-size: 28px; letter-spacing: .05em; text-align: center; background: transparent;\"\u003ePRUNE JAUNE + DATTE + CHOCOLAT NOIR\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 1 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 2 : APPROVISIONNEMENT\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto;\"\u003e\n\u003cdiv style=\"padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center; border-radius: 12px 12px 0 0;\"\u003eApprovisionnement\u003c\/div\u003e\n\u003ctable border=\"3\" cellpadding=\"1\" cellspacing=\"1\" style=\"width: 100%; border-collapse: collapse; background: transparent;\"\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd style=\"width: 20%;\"\u003eORIGINE\u003c\/td\u003e\n\u003ctd\u003eRégion de San Ignacio, province de Cajamarca, Pérou\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePRODUCTEURS\u003c\/td\u003e\n\u003ctd\u003eFamille Minga\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eVARIÉTÉ\u003c\/td\u003e\n\u003ctd\u003eBourbon, caturra, pache\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePROCÉDÉ\u003c\/td\u003e\n\u003ctd\u003eLavé\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eALTITUDE\u003c\/td\u003e\n\u003ctd\u003e1800–1950 m\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePARTENAIRES\u003c\/td\u003e\n\u003ctd\u003eApex Coffee Imports\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eVOLUME ACHETÉ\u003c\/td\u003e\n\u003ctd\u003e690 kg\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eFAB\u003c\/td\u003e\n\u003ctd\u003e3,77 $ US\/lb\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePRIX LIVRÉ\u003c\/td\u003e\n\u003ctd\u003e8,08 $ CAD\/LB\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eRELATION\u003c\/td\u003e\n\u003ctd\u003e1 an\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003c\/tbody\u003e\n\u003c\/table\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 2 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 3 : INFORMATIONS SUR LE CAFÉ\n========================================================= --\u003e\n\u003cdiv style=\"position: relative; width: 100%; padding-bottom: 56.25%; height: 0; overflow: hidden; border-radius: 8px;\"\u003e\u003ciframe style=\"position: absolute; top: 0; left: 0; width: 100%; height: 100%; border: 0; border-radius: 8px;\" src=\"https:\/\/www.youtube.com\/embed\/VYr1yer-5sg?si=6y7HNEgZFpIZVP_0\"\u003e\u003c\/iframe\u003e\u003c\/div\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto;\"\u003e\n\u003cdiv style=\"padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center; border-radius: 12px 12px 0 0;\"\u003eInformations sur le café\u003c\/div\u003e\n\u003cdiv style=\"border: 2px solid var(--product-box-background, #000); border-top: none; border-radius: 0 0 12px 12px; padding: 16px 14px; background: transparent;\"\u003e\n\u003cp style=\"margin: 0 0 12px 0;\"\u003eLa famille Minga cultive son café dans la région montagneuse de Cajamarca, au nord du Pérou, où l'altitude élevée, les sols riches et le climat tempéré créent des conditions idéales pour la production de cafés de spécialité. Comme plusieurs producteur.rices de la région, la famille mise sur des pratiques agricoles durables et un travail minutieux à chaque étape de la récolte et de la transformation, afin de mettre en valeur tout le potentiel de son terroir.\u003c\/p\u003e\n\u003cp style=\"margin: 0;\"\u003eMembre de l'association Café Solidario, la famille Minga participe à un projet collectif qui rassemble aujourd'hui plus de 250 producteur.rices engagé.es dans la traçabilité, la qualité et le développement durable. Fondée en 2017, cette organisation soutient les familles productrices en favorisant des pratiques responsables, une meilleure valorisation de leur café et un impact positif au sein de leurs communautés. Chaque lot issu de Solidario reflète ainsi non seulement le savoir-faire des producteur.rices, mais aussi un engagement concret envers l'équité et l'avenir de la caféiculture péruvienne.\u003c\/p\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 3 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 4 : PARAMÈTRES D'EXTRACTION — ESPRESSO\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto;\"\u003e\n\u003cdetails open=\"\" style=\"border: 2px solid var(--product-box-background, #000); border-radius: 12px; overflow: hidden; margin: 0 0 12px 0; background: rgba(255,255,255,0.5);\"\u003e\n\u003csummary style=\"cursor: pointer; list-style: none; padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center;\"\u003eEspresso — paramètres recommandés\u003c\/summary\u003e\n\u003cdiv style=\"padding: 12px 14px;\"\u003e\n\u003ctable style=\"width: 100%; border-collapse: collapse; background: transparent;\"\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd style=\"padding: 10px 0; font-weight: 800; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003eCafé moulu\u003c\/td\u003e\n\u003ctd style=\"padding: 10px 0; text-align: right; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003e18 g\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd style=\"padding: 10px 0; font-weight: 800; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003eCafé dans la tasse\u003c\/td\u003e\n\u003ctd style=\"padding: 10px 0; text-align: right; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003e34 g\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd style=\"padding: 10px 0; font-weight: 800;\"\u003eTemps d'extraction\u003c\/td\u003e\n\u003ctd style=\"padding: 10px 0; text-align: right;\"\u003e28 sec\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003c\/tbody\u003e\n\u003c\/table\u003e\n\u003cdiv style=\"margin-top: 10px; padding: 8px 10px; border-radius: 8px; background: rgba(0,0,0,.04); border: 1px dashed rgba(0,0,0,.2); font-size: 12px; opacity: .7; line-height: 1.4;\"\u003e\n\u003cstrong\u003eÀ noter —\u003c\/strong\u003e Recette optimisée pour un panier de \u003cstrong\u003e18 g\u003c\/strong\u003e. Consulte le manuel de ta machine pour connaître la capacité de ton panier.\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/details\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 4 ========= --\u003e","brand":"ZAB","offers":[{"title":"300g","offer_id":53006152433973,"sku":"CAF-SIN-MING-300","price":26.5,"currency_code":"CAD","in_stock":false},{"title":"808g","offer_id":53006152466741,"sku":"CAF-SIN-MING-808","price":62.0,"currency_code":"CAD","in_stock":false},{"title":"2268g (5lbs)","offer_id":53006152499509,"sku":"CAF-SIN-MING-2268","price":160.0,"currency_code":"CAD","in_stock":false},{"title":"100g","offer_id":53006152532277,"sku":"CAF-SIN-MING-100","price":13.25,"currency_code":"CAD","in_stock":false},{"title":"Bucket - 5lbs (Livraison locale seulement)","offer_id":53006152565045,"sku":"CAF-SIN-MING-BUCK-5","price":185.0,"currency_code":"CAD","in_stock":false},{"title":"Bucket - 15lbs (Livraison locale seulement)","offer_id":53006152597813,"sku":"CAF-SIN-MING-BUCK-15","price":505.0,"currency_code":"CAD","in_stock":false}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/2716\/1842\/files\/minga-300g.jpg?v=1781893597"},{"product_id":"colombie-frank-torres-1","title":"COLOMBIE - FRANK TORRES","description":"\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 1 : NOTES DE DÉGUSTATION\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto; border: 2px solid var(--product-box-background, #000); border-radius: 12px; overflow: hidden;\"\u003e\n\u003cdiv style=\"padding: 10px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center;\"\u003eNotes de dégustation\u003c\/div\u003e\n\u003cdiv style=\"padding: 16px 14px; font-weight: 900; text-transform: uppercase; font-size: 28px; letter-spacing: .05em; text-align: center; background: transparent;\"\u003eFRAMBOISE + CERISE NOIRE + MOUSSE AU CHOCOLAT + ÉPICES\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 1 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003cdiv style=\"position: relative; width: 100%; padding-bottom: 56.25%; height: 0; overflow: hidden; border-radius: 8px;\"\u003e\u003ciframe style=\"position: absolute; top: 0; left: 0; width: 100%; height: 100%; border: 0; border-radius: 8px;\" src=\"https:\/\/www.youtube.com\/embed\/k_m6QRPaKwA?si=VFFSxu2aolAbwHhb\"\u003e\u003c\/iframe\u003e\u003c\/div\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 2 : APPROVISIONNEMENT\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto;\"\u003e\n\u003cdiv style=\"padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center; border-radius: 12px 12px 0 0;\"\u003eApprovisionnement\u003c\/div\u003e\n\u003ctable border=\"3\" cellpadding=\"1\" cellspacing=\"1\" style=\"width: 100%; border-collapse: collapse; background: transparent;\"\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd style=\"width: 20%;\"\u003eORIGINE\u003c\/td\u003e\n\u003ctd\u003eRégion de la Union, province de Nariño, Colombie\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePRODUCTEURS\u003c\/td\u003e\n\u003ctd\u003eFrank Torres\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eFERME\u003c\/td\u003e\n\u003ctd\u003eLa Indonesia\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eVARIÉTÉ\u003c\/td\u003e\n\u003ctd\u003eBourbon rose\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePROCÉDÉ\u003c\/td\u003e\n\u003ctd\u003eLavé\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eALTITUDE\u003c\/td\u003e\n\u003ctd\u003e1750 m\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePARTENAIRES\u003c\/td\u003e\n\u003ctd\u003eApex Coffee Imports\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eVOLUME ACHETÉ\u003c\/td\u003e\n\u003ctd\u003e96 kg\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eFAB\u003c\/td\u003e\n\u003ctd\u003e10,95 $ US\/lb\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePRIX LIVRÉ\u003c\/td\u003e\n\u003ctd\u003e21,75 $ CAD\/LB\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eRELATION\u003c\/td\u003e\n\u003ctd\u003e2 ans\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003c\/tbody\u003e\n\u003c\/table\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 2 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 3 : INFORMATIONS SUR LE CAFÉ\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto;\"\u003e\n\u003cdiv style=\"padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center; border-radius: 12px 12px 0 0;\"\u003eInformations sur le café\u003c\/div\u003e\n\u003cdiv style=\"border: 2px solid var(--product-box-background, #000); border-top: none; border-radius: 0 0 12px 12px; padding: 16px 14px; background: transparent;\"\u003e\n\u003cp style=\"margin: 0 0 12px 0;\"\u003eFrank Torres vient d'une famille avec une longue tradition caféière à La Unión, en Colombie, où son grand-père, Marco Antonio Torres, a été l'un des premiers à cultiver le café il y a plus de 80 ans.\u003c\/p\u003e\n\u003cp style=\"margin: 0 0 12px 0;\"\u003eAujourd'hui, Frank est le principal gestionnaire de la Finca La Indonesia, une partie de la propriété familiale dont il supervise l'ensemble des pratiques agricoles et de transformation. Il cherche constamment à améliorer les pratiques agricoles, avec un fort accent sur la durabilité : santé des sols, gestion responsable de l'eau, intégration d'arbres d'ombrage et diversification des cultures. Grâce à ses efforts, 90 % de l'exploitation est aujourd'hui convertie à l'agriculture biologique. Il se distingue aussi par son travail en transformation, nourri par son expérience et son goût pour l'expérimentation.\u003c\/p\u003e\n\u003cp style=\"margin: 0 0 12px 0;\"\u003ePour ce Bourbon Rose, les cerises sont d'abord dépulpées puis fermentées en bioréacteur, un environnement fermé qui permet de contrôler très précisément le processus. On y ajoute une petite portion de « moût », un liquide issu d'une fermentation précédente qui agit comme un « starter » naturel, riche en sucres et en micro-organismes. La fermentation se déroule ensuite sous CO₂, sans contact avec l'oxygène, pendant environ 48 heures, à pression stable. Tout au long du processus, les paramètres clés sont surveillés afin d'assurer une évolution optimale du café.\u003c\/p\u003e\n\u003cp style=\"margin: 0;\"\u003eUn procédé hautement contrôlé et précis, qui donne naissance à un café singulier et met en valeur tout le savoir-faire de Frank Torres.\u003c\/p\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 3 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 4 : V60\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto;\"\u003e\n\u003cdetails id=\"v60Details-laindonesia\" open=\"\" style=\"border: 2px solid var(--product-box-background, #000); border-radius: 12px; overflow: hidden; margin: 0 0 12px 0; background: rgba(255,255,255,0.5);\"\u003e\n\u003csummary style=\"cursor: pointer; list-style: none; padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center;\"\u003eV60 – Recette\u003c\/summary\u003e\n\u003cdiv style=\"padding: 12px 14px;\"\u003e\n\u003cdiv style=\"padding: 10px 0 10px; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003e\n\u003cdiv style=\"font-weight: 900; font-size: 16px;\"\u003eRatio 1:15\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 4px; opacity: .7; font-size: 13px;\"\u003e15 g in – 225 g out\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 6px; font-size: 13px;\"\u003e\n\u003cstrong\u003eTempérature de l'eau :\u003c\/strong\u003e 92 °C\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; padding: 10px 0 8px;\"\u003e\n\u003cdiv style=\"display: flex; gap: 8px; align-items: center; flex-wrap: wrap;\"\u003e\n\u003cbutton style=\"cursor: pointer; border: 2px solid var(--product-box-background, #000); background: var(--product-box-background, #000); color: var(--product-box-text, #fff); font-weight: 900; padding: 8px 10px; border-radius: 10px; text-transform: uppercase; letter-spacing: .02em; font-size: 12px;\" type=\"button\" id=\"v60StartBtn-laindonesia\"\u003eDémarrer\u003c\/button\u003e \u003cbutton style=\"cursor: pointer; border: 2px solid var(--product-box-background, #000); background: var(--product-box-text, #fff); color: var(--product-box-background, #000); font-weight: 900; padding: 8px 10px; border-radius: 10px; text-transform: uppercase; letter-spacing: .02em; font-size: 12px; opacity: .5;\" disabled type=\"button\" id=\"v60StopBtn-laindonesia\"\u003eStop\u003c\/button\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; line-height: 1;\"\u003e\n\u003cspan style=\"opacity: .70; font-size: 12px; font-weight: 800; text-transform: uppercase; letter-spacing: .04em;\"\u003eTimer\u003c\/span\u003e \u003cspan style=\"font-weight: 950; font-size: 28px; letter-spacing: .01em;\" id=\"v60Timer-laindonesia\"\u003e0:00\u003c\/span\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"flex-basis: 100%; opacity: .6; font-size: 12px; line-height: 1.3; margin-top: 2px;\" id=\"v60WakeStatus-laindonesia\"\u003eℹ️ Appuie sur \"Démarrer\" pour garder l'écran allumé.\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 8px; display: grid; gap: 10px;\"\u003e\n\u003cdiv style=\"border: 1px solid rgba(0,0,0,.18); border-radius: 12px; padding: 10px 12px;\" id=\"v60-card-1-laindonesia\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; margin-bottom: 6px;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e0:00\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003ePhase 1 — Bloom\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 8px; flex-wrap: wrap; font-size: 12.5px; font-weight: 800;\"\u003e\n\u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\" id=\"v60-pill-1-laindonesia\"\u003eVerser pendant 0:10s\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\"\u003eTotal 45 g\u003c\/span\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"border: 1px solid rgba(0,0,0,.18); border-radius: 12px; padding: 10px 12px;\" id=\"v60-card-2-laindonesia\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; margin-bottom: 6px;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e0:45\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003ePhase 2\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 8px; flex-wrap: wrap; font-size: 12.5px; font-weight: 800;\"\u003e\n\u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\" id=\"v60-pill-2-laindonesia\"\u003eVerser pendant 0:10s\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\"\u003eTotal 105 g\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12); opacity: .6;\"\u003e+60 g\u003c\/span\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"border: 1px solid rgba(0,0,0,.18); border-radius: 12px; padding: 10px 12px;\" id=\"v60-card-3-laindonesia\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; margin-bottom: 6px;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e1:15\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003ePhase 3\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 8px; flex-wrap: wrap; font-size: 12.5px; font-weight: 800;\"\u003e\n\u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\" id=\"v60-pill-3-laindonesia\"\u003eVerser pendant 0:10s\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\"\u003eTotal 170 g\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12); opacity: .6;\"\u003e+65 g\u003c\/span\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"border: 1px solid rgba(0,0,0,.18); border-radius: 12px; padding: 10px 12px;\" id=\"v60-card-4-laindonesia\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; margin-bottom: 6px;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e1:50\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003ePhase 4\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 8px; flex-wrap: wrap; font-size: 12.5px; font-weight: 800;\"\u003e\n\u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\" id=\"v60-pill-4-laindonesia\"\u003eVerser pendant 0:10s\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\"\u003eTotal 225 g\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12); opacity: .6;\"\u003e+55 g\u003c\/span\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 12px; border-top: 1px solid rgba(0,0,0,.2); padding-top: 10px;\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e2:50\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003eTemps final écoulement complet\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 8px; padding: 8px 10px; border-radius: 8px; background: rgba(0,0,0,.04); border: 1px dashed rgba(0,0,0,.2); font-size: 12px; opacity: .6; line-height: 1.4;\"\u003e\n\u003cstrong\u003eℹ️ Astuce —\u003c\/strong\u003e Si le temps total est plus court, la mouture est probablement trop grosse. S'il est plus long, la mouture est probablement trop fine.\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/details\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 4 ========= --\u003e\u003csvg style=\"display: none;\"\u003e\n\u003cstyle\u003e\n  @keyframes v60PulsePhase {\n    0%   { transform: scale(1);    box-shadow: 0 0 0 0 rgba(200,169,126,.35); }\n    50%  { transform: scale(1.06); box-shadow: 0 0 0 10px rgba(200,169,126,0); }\n    100% { transform: scale(1);    box-shadow: 0 0 0 0 rgba(200,169,126,0); }\n  }\n  .v60-pulse {\n    animation: v60PulsePhase 700ms ease-out 1;\n    transform-origin: center;\n    will-change: transform;\n  }\n  @keyframes v60BlinkPill {\n    0%, 100% { opacity: 1; transform: scale(1); }\n    50%      { opacity: .22; transform: scale(1.03); }\n  }\n  .v60-pill-pour-active {\n    background: #ffe7b7 !important;\n    border: 2px solid #d2a44a !important;\n    color: #3b2a12 !important;\n    font-weight: 900 !important;\n    letter-spacing: .02em;\n    animation: v60BlinkPill 2500ms ease-in-out infinite;\n    box-shadow:\n      0 0 0 2px rgba(210,164,74,.18) inset,\n      0 10px 22px rgba(0,0,0,.12),\n      0 0 0 6px rgba(210,164,74,.10);\n  }\n  @media (prefers-reduced-motion: reduce) {\n    .v60-pill-pour-active { animation: none; }\n    .v60-pulse { animation: none; }\n  }\n\u003c\/style\u003e\n\u003cscript\u003e\n(function() {\n  var SUFFIX = '-laindonesia';\n  var END_AT = 170;\n  var phases = [\n    { key: 1, t: 0,   pourLen: 10 },\n    { key: 2, t: 45,  pourLen: 10 },\n    { key: 3, t: 75,  pourLen: 10 },\n    { key: 4, t: 110, pourLen: 10 }\n  ];\n  var latte = {\n    cardBg:     '#f6f1ea',\n    cardBorder: '#c8a97e',\n    pillBg:     '#eadfce'\n  };\n  var details  = document.getElementById('v60Details'    + SUFFIX);\n  var startBtn = document.getElementById('v60StartBtn'   + SUFFIX);\n  var stopBtn  = document.getElementById('v60StopBtn'    + SUFFIX);\n  var timerEl  = document.getElementById('v60Timer'      + SUFFIX);\n  var statusEl = document.getElementById('v60WakeStatus' + SUFFIX);\n  var pills = {\n    1: document.getElementById('v60-pill-1' + SUFFIX),\n    2: document.getElementById('v60-pill-2' + SUFFIX),\n    3: document.getElementById('v60-pill-3' + SUFFIX),\n    4: document.getElementById('v60-pill-4' + SUFFIX)\n  };\n  var cards = {\n    1: document.getElementById('v60-card-1' + SUFFIX),\n    2: document.getElementById('v60-card-2' + SUFFIX),\n    3: document.getElementById('v60-card-3' + SUFFIX),\n    4: document.getElementById('v60-card-4' + SUFFIX)\n  };\n  function setCardActive(key) {\n    Object.keys(cards).forEach(function(k) {\n      var c = cards[k];\n      if (!c) return;\n      if (parseInt(k) === key) {\n        c.style.borderColor = latte.cardBorder;\n        c.style.background  = latte.cardBg;\n        c.style.boxShadow   = '0 0 0 2px rgba(200,169,126,.25) inset, 0 8px 22px rgba(200,169,126,.28)';\n      } else {\n        c.style.borderColor = 'rgba(0,0,0,.18)';\n        c.style.background  = 'transparent';\n        c.style.boxShadow   = 'none';\n      }\n    });\n  }\n  function setPillPhaseActive(key, doPulse) {\n    Object.keys(pills).forEach(function(k) {\n      var p = pills[k];\n      if (!p) return;\n      p.style.background  = 'rgba(0,0,0,.05)';\n      p.style.borderColor = 'rgba(0,0,0,.12)';\n      p.style.boxShadow   = 'none';\n      p.classList.remove('v60-pulse');\n    });\n    var pill = pills[key];\n    if (pill) {\n      pill.style.background  = latte.pillBg;\n      pill.style.borderColor = latte.cardBorder;\n      pill.style.boxShadow   = '0 0 0 2px rgba(200,169,126,.25) inset';\n      if (doPulse) {\n        pill.classList.remove('v60-pulse');\n        void pill.offsetWidth;\n        pill.classList.add('v60-pulse');\n      }\n    }\n  }\n  function resetPourPills() {\n    Object.values(pills).forEach(function(p) {\n      if (!p) return;\n      p.classList.remove('v60-pill-pour-active');\n    });\n  }\n  function setPourPillActive(key) {\n    resetPourPills();\n    if (!key) return;\n    var pill = pills[key];\n    if (pill) pill.classList.add('v60-pill-pour-active');\n  }\n  function clearAll() {\n    Object.values(cards).forEach(function(c) {\n      if (!c) return;\n      c.style.borderColor = 'rgba(0,0,0,.18)';\n      c.style.background  = 'transparent';\n      c.style.boxShadow   = 'none';\n    });\n    Object.values(pills).forEach(function(p) {\n      if (!p) return;\n      p.style.background  = 'rgba(0,0,0,.05)';\n      p.style.borderColor = 'rgba(0,0,0,.12)';\n      p.style.boxShadow   = 'none';\n      p.classList.remove('v60-pulse');\n      p.classList.remove('v60-pill-pour-active');\n    });\n  }\n  var wakeLock  = null;\n  var startTime = null;\n  var rafId     = null;\n  var lastPhaseKey = null;\n  var lastPourKey  = null;\n  function fmt(sec) {\n    sec = Math.max(0, Math.floor(sec));\n    var m = Math.floor(sec \/ 60);\n    var s = sec % 60;\n    return m + ':' + (s \u0026lt; 10 ? '0' : '') + s;\n  }\n  function getCurrentPhaseKey(elapsed) {\n    var current = phases[0].key;\n    for (var i = 0; i \u0026lt; phases.length; i++) if (elapsed \u0026gt;= phases[i].t) current = phases[i].key;\n    return current;\n  }\n  function getPourKey(elapsed) {\n    for (var i = phases.length - 1; i \u0026gt;= 0; i--) {\n      var p = phases[i];\n      if (elapsed \u0026gt;= p.t \u0026amp;\u0026amp; elapsed \u0026lt; (p.t + p.pourLen)) return p.key;\n    }\n    return null;\n  }\n  function enableWakeLock() {\n    if (!('wakeLock' in navigator)) {\n      statusEl.textContent = '⚠️ Ton navigateur ne supporte pas le mode écran allumé.';\n      return Promise.resolve();\n    }\n    return navigator.wakeLock.request('screen').then(function(wl) {\n      wakeLock = wl;\n      statusEl.textContent = '✅ Écran maintenu allumé pendant la recette.';\n      wakeLock.addEventListener('release', function() {\n        statusEl.textContent = 'ℹ️ Mode écran allumé relâché.';\n      });\n    }).catch(function() {\n      statusEl.textContent = '⚠️ Impossible d\\'activer le mode écran allumé.';\n      wakeLock = null;\n    });\n  }\n  function disableWakeLock() {\n    if (wakeLock) { wakeLock.release(); wakeLock = null; }\n  }\n  function setButtons(running) {\n    startBtn.disabled = running;\n    stopBtn.disabled  = !running;\n    stopBtn.style.opacity = running ? '1' : '.5';\n  }\n  function tick() {\n    var elapsed = (Date.now() - startTime) \/ 1000;\n    timerEl.textContent = fmt(elapsed);\n    var phaseKey = getCurrentPhaseKey(elapsed);\n    if (phaseKey !== lastPhaseKey) {\n      setCardActive(phaseKey);\n      setPillPhaseActive(phaseKey, lastPhaseKey !== null);\n      lastPhaseKey = phaseKey;\n    }\n    var pourKey = getPourKey(elapsed);\n    if (pourKey !== lastPourKey) {\n      setPourPillActive(pourKey);\n      lastPourKey = pourKey;\n    }\n    if (elapsed \u0026gt;= END_AT) { stopRecipe(true); return; }\n    rafId = requestAnimationFrame(tick);\n  }\n  function startRecipe() {\n    setButtons(true);\n    timerEl.textContent = '0:00';\n    lastPhaseKey = null;\n    lastPourKey  = null;\n    enableWakeLock().then(function() {\n      setCardActive(1);\n      setPillPhaseActive(1, false);\n      setPourPillActive(1);\n      lastPhaseKey = 1;\n      lastPourKey  = 1;\n      startTime = Date.now();\n      if (rafId) cancelAnimationFrame(rafId);\n      rafId = requestAnimationFrame(tick);\n    });\n  }\n  function stopRecipe(autoEnded) {\n    if (rafId) cancelAnimationFrame(rafId);\n    rafId     = null;\n    startTime = null;\n    disableWakeLock();\n    setButtons(false);\n    clearAll();\n    lastPhaseKey = null;\n    lastPourKey  = null;\n    if (autoEnded) {\n      statusEl.textContent = '✅ Recette terminée — écran libéré.';\n      timerEl.textContent  = fmt(END_AT);\n    } else {\n      statusEl.textContent = 'ℹ️ Recette arrêtée — écran libéré.';\n    }\n  }\n  startBtn.addEventListener('click', startRecipe);\n  stopBtn.addEventListener('click', function() { stopRecipe(false); });\n  details.addEventListener('toggle', function() { if (!details.open) stopRecipe(false); });\n  document.addEventListener('visibilitychange', function() {\n    if (document.visibilityState === 'visible' \u0026amp;\u0026amp; startTime \u0026amp;\u0026amp; !wakeLock) enableWakeLock();\n  });\n})();\n\u003c\/script\u003e\n\u003c\/svg\u003e","brand":"ZAB","offers":[{"title":"200g","offer_id":53100163531061,"sku":"CAF-SIN-FRAN-TORR-GB","price":42.0,"currency_code":"CAD","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/2716\/1842\/files\/frank-torres-200g.jpg?v=1784050501"},{"product_id":"joyeux-roger-cafe-instantane","title":"JOYEUX ROGER - CAFÉ INSTANTANÉ","description":"\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 1 : NOTES DE DÉGUSTATION\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto; border: 2px solid var(--product-box-background, #000); border-radius: 12px; overflow: hidden;\"\u003e\n\u003cdiv style=\"padding: 10px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center;\"\u003eNotes de dégustation\u003c\/div\u003e\n\u003cdiv style=\"padding: 16px 14px; font-weight: 900; text-transform: uppercase; font-size: 28px; letter-spacing: .05em; text-align: center; background: transparent;\"\u003eBROWNIE + NOISETTE + CRÉMEUX\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c!-- =========================================================\n  SECTION 3 : INFORMATIONS SUR LE CAFÉ\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto;\"\u003e\n\u003cdiv style=\"padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center; border-radius: 12px 12px 0 0;\"\u003eZAB INSTANT-N'IMPORTE QUAND!\u003c\/div\u003e\n\u003cdiv style=\"border: 2px solid var(--product-box-background, #000); border-top: none; border-radius: 0 0 12px 12px; padding: 16px 14px; background: transparent;\"\u003e\n\u003ch3 style=\"margin: 0px 0px 16px; text-align: center;\"\u003e\u003cstrong\u003eNous voici enfin avec la version instantanée de notre super star le\u003cbr\u003e⋆·˚˚°✦\u003ca href=\"https:\/\/zabcafe.com\/collections\/cafes\/products\/joyeux-roger\" target=\"_blank\" rel=\"noopener\"\u003eJoyeux Roger\u003c\/a\u003e✦°˚˚·⋆\u003c\/strong\u003e\u003c\/h3\u003e\n\u003cp\u003eMaintenant tu n'as aucune excuse pour boire du mauvais café quand tu es en camping. On a décidé de régler ce problème-là avec nos ami.e.s de chez Hasty Coffee.\u003c\/p\u003e\n\u003cp\u003eTout ce que t'as à faire c'est verser le contenu du sachet dans une tasse, verser de l'eau chaude ou froide dessus et brasser. \u003cbr\u003e\u003cstrong\u003eC'EST TOUT! C'est tu pas assez beau la vie?\u003c\/strong\u003e\u003c\/p\u003e\n\u003cul\u003e\n\u003cli\u003eChaque boite contient 4 sachets de café instant\u003c\/li\u003e\n\u003cli\u003eUn sachet = une tasse de café (240ml à 300ml)\u003c\/li\u003e\n\u003cli\u003eBon été :)\u003c\/li\u003e\n\u003c\/ul\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e","brand":"ZAB","offers":[{"title":"Default Title","offer_id":53106867503413,"sku":"CAF-INS-JOYE-ROGE-4","price":14.5,"currency_code":"CAD","in_stock":false}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/2716\/1842\/files\/instant-joyeux-4poches.jpg?v=1783533364"},{"product_id":"honduras-efren-sanchez","title":"HONDURAS - EFREN SANCHEZ","description":"\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 1 : NOTES DE DÉGUSTATION\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto; border: 2px solid var(--product-box-background, #000); border-radius: 12px; overflow: hidden;\"\u003e\n\u003cdiv style=\"padding: 10px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center;\"\u003eNotes de dégustation\u003c\/div\u003e\n\u003cdiv style=\"padding: 16px 14px; font-weight: 900; text-transform: uppercase; font-size: 28px; letter-spacing: .05em; text-align: center; background: transparent;\"\u003eTANGERINE + CARAMEL AU BEURRE + CACAO\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 1 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003cdiv style=\"position: relative; width: 100%; padding-bottom: 56.25%; height: 0; overflow: hidden; border-radius: 8px;\"\u003e\u003ciframe src=\"https:\/\/www.youtube.com\/embed\/Ah07vnT9SOY?si=xF-JkRB42Cw0sJeg\" style=\"position: absolute; top: 0; left: 0; width: 100%; height: 100%; border: 0; border-radius: 8px;\"\u003e\u003c\/iframe\u003e\u003c\/div\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 2 : APPROVISIONNEMENT\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto;\"\u003e\n\u003cdiv style=\"padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center; border-radius: 12px 12px 0 0;\"\u003eApprovisionnement\u003c\/div\u003e\n\u003ctable style=\"width: 100%; border-collapse: collapse; background: transparent;\" cellspacing=\"1\" cellpadding=\"1\" border=\"3\"\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd style=\"width: 20%;\"\u003eORIGINE\u003c\/td\u003e\n\u003ctd\u003eMunicipalité de El Paraíso, département de El Paraíso, Honduras\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePRODUCTEURS\u003c\/td\u003e\n\u003ctd\u003eEfren Nefrali Sanchez\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eFERME\u003c\/td\u003e\n\u003ctd\u003eLa Esmeranda\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eVARIÉTÉ\u003c\/td\u003e\n\u003ctd\u003eParainema\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePROCÉDÉ\u003c\/td\u003e\n\u003ctd\u003eLavé\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eALTITUDE\u003c\/td\u003e\n\u003ctd\u003e1400 m\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePARTENAIRES\u003c\/td\u003e\n\u003ctd\u003eSemilla\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eVOLUME ACHETÉ\u003c\/td\u003e\n\u003ctd\u003e552 kg\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eFAB\u003c\/td\u003e\n\u003ctd\u003e4,50 $ US\/lb\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePRIX LIVRÉ\u003c\/td\u003e\n\u003ctd\u003e10,04 $ CAD\/LB\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eRELATION\u003c\/td\u003e\n\u003ctd\u003e1 an\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003c\/tbody\u003e\n\u003c\/table\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 2 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 3 : INFORMATIONS SUR LE CAFÉ\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto;\"\u003e\n\u003cdiv style=\"padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center; border-radius: 12px 12px 0 0;\"\u003eInformations sur le café\u003c\/div\u003e\n\u003cdiv style=\"border: 2px solid var(--product-box-background, #000); border-top: none; border-radius: 0 0 12px 12px; padding: 16px 14px; background: transparent;\"\u003e\n\u003cp style=\"margin: 0 0 12px 0;\"\u003eEfren est un jeune producteur de café qui perpétue une tradition familiale transmise de génération en génération. Issu d'une famille caféicultrice, il a appris le métier auprès de ses grands-parents, dont les connaissances et l'expérience continuent d'influencer son travail aujourd'hui. Après avoir travaillé de nombreuses années aux côtés de sa famille, il a commencé à gérer sa propre parcelle il y a une dizaine d'années et se consacre depuis à la production de cafés de grande qualité sous son propre nom.\u003c\/p\u003e\n\u003cp style=\"margin: 0;\"\u003eSon objectif est de créer un produit distinctif qui reflète tout le potentiel de sa ferme, tout en lui permettant d'augmenter ses revenus, de réinvestir dans son exploitation et d'accéder à de nouveaux marchés à travers le monde. L'année 2025 marque une étape importante pour Efren, puisqu'il s'agit de sa première exportation de café par l'entremise de Semilla, notre partenaire importateur. C'est un privilège de pouvoir l'accompagner dans cette aventure, et nous sommes ravis de voir ses cafés être dégustés bien au-delà des frontières du Honduras.\u003c\/p\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 3 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 4 : PARAMÈTRES D'EXTRACTION — ESPRESSO\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto;\"\u003e\n\u003cdetails style=\"border: 2px solid var(--product-box-background, #000); border-radius: 12px; overflow: hidden; margin: 0 0 12px 0; background: rgba(255,255,255,0.5);\" open=\"\"\u003e\n\u003csummary style=\"cursor: pointer; list-style: none; padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center;\"\u003eEspresso — paramètres recommandés\u003c\/summary\u003e\n\u003cdiv style=\"padding: 12px 14px;\"\u003e\n\u003ctable style=\"width: 100%; border-collapse: collapse; background: transparent;\"\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd style=\"padding: 10px 0; font-weight: 800; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003eCafé moulu\u003c\/td\u003e\n\u003ctd style=\"padding: 10px 0; text-align: right; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003e18 g\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd style=\"padding: 10px 0; font-weight: 800; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003eCafé dans la tasse\u003c\/td\u003e\n\u003ctd style=\"padding: 10px 0; text-align: right; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003e35 g\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd style=\"padding: 10px 0; font-weight: 800;\"\u003eTemps d'extraction\u003c\/td\u003e\n\u003ctd style=\"padding: 10px 0; text-align: right;\"\u003e26 sec\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003c\/tbody\u003e\n\u003c\/table\u003e\n\u003cdiv style=\"margin-top: 10px; padding: 8px 10px; border-radius: 8px; background: rgba(0,0,0,.04); border: 1px dashed rgba(0,0,0,.2); font-size: 12px; opacity: .7; line-height: 1.4;\"\u003e\n\u003cstrong\u003eÀ noter —\u003c\/strong\u003e Recette optimisée pour un panier de \u003cstrong\u003e18 g\u003c\/strong\u003e. Consulte le manuel de ta machine pour connaître la capacité de ton panier.\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/details\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 4 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 5 : V60\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto;\"\u003e\n\u003cdetails style=\"border: 2px solid var(--product-box-background, #000); border-radius: 12px; overflow: hidden; margin: 0 0 12px 0; background: rgba(255,255,255,0.5);\" open=\"\" id=\"v60Details-laesmeranda\"\u003e\n\u003csummary style=\"cursor: pointer; list-style: none; padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center;\"\u003eV60 – Recette\u003c\/summary\u003e\n\u003cdiv style=\"padding: 12px 14px;\"\u003e\n\u003cdiv style=\"padding: 10px 0 10px; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003e\n\u003cdiv style=\"font-weight: 900; font-size: 16px;\"\u003eRatio 1:15\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 4px; opacity: .7; font-size: 13px;\"\u003e15 g in – 225 g out\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 6px; font-size: 13px;\"\u003e\n\u003cstrong\u003eTempérature de l'eau :\u003c\/strong\u003e 90 °C\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; padding: 10px 0 8px;\"\u003e\n\u003cdiv style=\"display: flex; gap: 8px; align-items: center; flex-wrap: wrap;\"\u003e\n\u003cbutton id=\"v60StartBtn-laesmeranda\" type=\"button\" style=\"cursor: pointer; border: 2px solid var(--product-box-background, #000); background: var(--product-box-background, #000); color: var(--product-box-text, #fff); font-weight: 900; padding: 8px 10px; border-radius: 10px; text-transform: uppercase; letter-spacing: .02em; font-size: 12px;\"\u003eDémarrer\u003c\/button\u003e \u003cbutton id=\"v60StopBtn-laesmeranda\" type=\"button\" disabled style=\"cursor: pointer; border: 2px solid var(--product-box-background, #000); background: var(--product-box-text, #fff); color: var(--product-box-background, #000); font-weight: 900; padding: 8px 10px; border-radius: 10px; text-transform: uppercase; letter-spacing: .02em; font-size: 12px; opacity: .5;\"\u003eStop\u003c\/button\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; line-height: 1;\"\u003e\n\u003cspan style=\"opacity: .70; font-size: 12px; font-weight: 800; text-transform: uppercase; letter-spacing: .04em;\"\u003eTimer\u003c\/span\u003e \u003cspan id=\"v60Timer-laesmeranda\" style=\"font-weight: 950; font-size: 28px; letter-spacing: .01em;\"\u003e0:00\u003c\/span\u003e\n\u003c\/div\u003e\n\u003cdiv id=\"v60WakeStatus-laesmeranda\" style=\"flex-basis: 100%; opacity: .6; font-size: 12px; line-height: 1.3; margin-top: 2px;\"\u003eℹ️ Appuie sur \"Démarrer\" pour garder l'écran allumé.\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 8px; display: grid; gap: 10px;\"\u003e\n\u003cdiv id=\"v60-card-1-laesmeranda\" style=\"border: 1px solid rgba(0,0,0,.18); border-radius: 12px; padding: 10px 12px;\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; margin-bottom: 6px;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e0:00\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003ePhase 1 — Bloom\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 8px; flex-wrap: wrap; font-size: 12.5px; font-weight: 800;\"\u003e\n\u003cspan id=\"v60-pill-1-laesmeranda\" style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\"\u003eVerser pendant 0:10s\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\"\u003eTotal 35 g\u003c\/span\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv id=\"v60-card-2-laesmeranda\" style=\"border: 1px solid rgba(0,0,0,.18); border-radius: 12px; padding: 10px 12px;\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; margin-bottom: 6px;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e0:40\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003ePhase 2\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 8px; flex-wrap: wrap; font-size: 12.5px; font-weight: 800;\"\u003e\n\u003cspan id=\"v60-pill-2-laesmeranda\" style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\"\u003eVerser pendant 0:30s\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\"\u003eTotal 170 g\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12); opacity: .6;\"\u003e+135 g\u003c\/span\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv id=\"v60-card-3-laesmeranda\" style=\"border: 1px solid rgba(0,0,0,.18); border-radius: 12px; padding: 10px 12px;\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; margin-bottom: 6px;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e1:25\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003ePhase 3\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 8px; flex-wrap: wrap; font-size: 12.5px; font-weight: 800;\"\u003e\n\u003cspan id=\"v60-pill-3-laesmeranda\" style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\"\u003eVerser pendant 0:30s\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\"\u003eTotal 225 g\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12); opacity: .6;\"\u003e+55 g\u003c\/span\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 12px; border-top: 1px solid rgba(0,0,0,.2); padding-top: 10px;\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e2:50\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003eTemps final écoulement complet\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 8px; padding: 8px 10px; border-radius: 8px; background: rgba(0,0,0,.04); border: 1px dashed rgba(0,0,0,.2); font-size: 12px; opacity: .6; line-height: 1.4;\"\u003e\n\u003cstrong\u003eℹ️ Astuce —\u003c\/strong\u003e Si le temps total est plus court, la mouture est probablement trop grosse. S'il est plus long, la mouture est probablement trop fine.\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/details\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 5 ========= --\u003e\u003csvg style=\"display: none;\"\u003e\n\u003cstyle\u003e\n  @keyframes v60PulsePhase { 0% { transform: scale(1); box-shadow: 0 0 0 0 rgba(200,169,126,.35); } 50% { transform: scale(1.06); box-shadow: 0 0 0 10px rgba(200,169,126,0); } 100% { transform: scale(1); box-shadow: 0 0 0 0 rgba(200,169,126,0); } }\n  .v60-pulse { animation: v60PulsePhase 700ms ease-out 1; transform-origin: center; will-change: transform; }\n  @keyframes v60BlinkPill { 0%, 100% { opacity: 1; transform: scale(1); } 50% { opacity: .22; transform: scale(1.03); } }\n  .v60-pill-pour-active { background: #ffe7b7 !important; border: 2px solid #d2a44a !important; color: #3b2a12 !important; font-weight: 900 !important; letter-spacing: .02em; animation: v60BlinkPill 2500ms ease-in-out infinite; box-shadow: 0 0 0 2px rgba(210,164,74,.18) inset, 0 10px 22px rgba(0,0,0,.12), 0 0 0 6px rgba(210,164,74,.10); }\n  @media (prefers-reduced-motion: reduce) { .v60-pill-pour-active { animation: none; } .v60-pulse { animation: none; } }\n\u003c\/style\u003e\n\u003cscript\u003e\n(function() {\n  var SUFFIX = '-laesmeranda';\n  var END_AT = 170;\n  var phases = [ { key: 1, t: 0, pourLen: 10 }, { key: 2, t: 40, pourLen: 30 }, { key: 3, t: 85, pourLen: 30 } ];\n  var latte = { cardBg: '#f6f1ea', cardBorder: '#c8a97e', pillBg: '#eadfce' };\n  var details = document.getElementById('v60Details' + SUFFIX);\n  var startBtn = document.getElementById('v60StartBtn' + SUFFIX);\n  var stopBtn = document.getElementById('v60StopBtn' + SUFFIX);\n  var timerEl = document.getElementById('v60Timer' + SUFFIX);\n  var statusEl = document.getElementById('v60WakeStatus' + SUFFIX);\n  var pills = { 1: document.getElementById('v60-pill-1' + SUFFIX), 2: document.getElementById('v60-pill-2' + SUFFIX), 3: document.getElementById('v60-pill-3' + SUFFIX) };\n  var cards = { 1: document.getElementById('v60-card-1' + SUFFIX), 2: document.getElementById('v60-card-2' + SUFFIX), 3: document.getElementById('v60-card-3' + SUFFIX) };\n  function setCardActive(key) {\n    Object.keys(cards).forEach(function(k) {\n      var c = cards[k]; if (!c) return;\n      if (parseInt(k) === key) { c.style.borderColor = latte.cardBorder; c.style.background = latte.cardBg; c.style.boxShadow = '0 0 0 2px rgba(200,169,126,.25) inset, 0 8px 22px rgba(200,169,126,.28)'; }\n      else { c.style.borderColor = 'rgba(0,0,0,.18)'; c.style.background = 'transparent'; c.style.boxShadow = 'none'; }\n    });\n  }\n  function setPillPhaseActive(key, doPulse) {\n    Object.keys(pills).forEach(function(k) {\n      var p = pills[k]; if (!p) return;\n      p.style.background = 'rgba(0,0,0,.05)'; p.style.borderColor = 'rgba(0,0,0,.12)'; p.style.boxShadow = 'none'; p.classList.remove('v60-pulse');\n    });\n    var pill = pills[key];\n    if (pill) {\n      pill.style.background = latte.pillBg; pill.style.borderColor = latte.cardBorder; pill.style.boxShadow = '0 0 0 2px rgba(200,169,126,.25) inset';\n      if (doPulse) { pill.classList.remove('v60-pulse'); void pill.offsetWidth; pill.classList.add('v60-pulse'); }\n    }\n  }\n  function resetPourPills() { Object.values(pills).forEach(function(p) { if (!p) return; p.classList.remove('v60-pill-pour-active'); }); }\n  function setPourPillActive(key) { resetPourPills(); if (!key) return; var pill = pills[key]; if (pill) pill.classList.add('v60-pill-pour-active'); }\n  function clearAll() {\n    Object.values(cards).forEach(function(c) { if (!c) return; c.style.borderColor = 'rgba(0,0,0,.18)'; c.style.background = 'transparent'; c.style.boxShadow = 'none'; });\n    Object.values(pills).forEach(function(p) { if (!p) return; p.style.background = 'rgba(0,0,0,.05)'; p.style.borderColor = 'rgba(0,0,0,.12)'; p.style.boxShadow = 'none'; p.classList.remove('v60-pulse'); p.classList.remove('v60-pill-pour-active'); });\n  }\n  var wakeLock = null; var startTime = null; var rafId = null; var lastPhaseKey = null; var lastPourKey = null;\n  function fmt(sec) { sec = Math.max(0, Math.floor(sec)); var m = Math.floor(sec \/ 60); var s = sec % 60; return m + ':' + (s \u0026lt; 10 ? '0' : '') + s; }\n  function getCurrentPhaseKey(elapsed) { var current = phases[0].key; for (var i = 0; i \u0026lt; phases.length; i++) if (elapsed \u0026gt;= phases[i].t) current = phases[i].key; return current; }\n  function getPourKey(elapsed) { for (var i = phases.length - 1; i \u0026gt;= 0; i--) { var p = phases[i]; if (elapsed \u0026gt;= p.t \u0026amp;\u0026amp; elapsed \u0026lt; (p.t + p.pourLen)) return p.key; } return null; }\n  function enableWakeLock() {\n    if (!('wakeLock' in navigator)) { statusEl.textContent = '⚠️ Ton navigateur ne supporte pas le mode écran allumé.'; return Promise.resolve(); }\n    return navigator.wakeLock.request('screen').then(function(wl) {\n      wakeLock = wl; statusEl.textContent = '✅ Écran maintenu allumé pendant la recette.';\n      wakeLock.addEventListener('release', function() { statusEl.textContent = 'ℹ️ Mode écran allumé relâché.'; });\n    }).catch(function() { statusEl.textContent = '⚠️ Impossible d\\'activer le mode écran allumé.'; wakeLock = null; });\n  }\n  function disableWakeLock() { if (wakeLock) { wakeLock.release(); wakeLock = null; } }\n  function setButtons(running) { startBtn.disabled = running; stopBtn.disabled = !running; stopBtn.style.opacity = running ? '1' : '.5'; }\n  function tick() {\n    var elapsed = (Date.now() - startTime) \/ 1000;\n    timerEl.textContent = fmt(elapsed);\n    var phaseKey = getCurrentPhaseKey(elapsed);\n    if (phaseKey !== lastPhaseKey) { setCardActive(phaseKey); setPillPhaseActive(phaseKey, lastPhaseKey !== null); lastPhaseKey = phaseKey; }\n    var pourKey = getPourKey(elapsed);\n    if (pourKey !== lastPourKey) { setPourPillActive(pourKey); lastPourKey = pourKey; }\n    if (elapsed \u0026gt;= END_AT) { stopRecipe(true); return; }\n    rafId = requestAnimationFrame(tick);\n  }\n  function startRecipe() {\n    setButtons(true); timerEl.textContent = '0:00'; lastPhaseKey = null; lastPourKey = null;\n    enableWakeLock().then(function() {\n      setCardActive(1); setPillPhaseActive(1, false); setPourPillActive(1); lastPhaseKey = 1; lastPourKey = 1;\n      startTime = Date.now(); if (rafId) cancelAnimationFrame(rafId); rafId = requestAnimationFrame(tick);\n    });\n  }\n  function stopRecipe(autoEnded) {\n    if (rafId) cancelAnimationFrame(rafId); rafId = null; startTime = null; disableWakeLock(); setButtons(false); clearAll(); lastPhaseKey = null; lastPourKey = null;\n    if (autoEnded) { statusEl.textContent = '✅ Recette terminée — écran libéré.'; timerEl.textContent = fmt(END_AT); }\n    else { statusEl.textContent = 'ℹ️ Recette arrêtée — écran libéré.'; }\n  }\n  startBtn.addEventListener('click', startRecipe);\n  stopBtn.addEventListener('click', function() { stopRecipe(false); });\n  details.addEventListener('toggle', function() { if (!details.open) stopRecipe(false); });\n  document.addEventListener('visibilitychange', function() { if (document.visibilityState === 'visible' \u0026amp;\u0026amp; startTime \u0026amp;\u0026amp; !wakeLock) enableWakeLock(); });\n})();\n\u003c\/script\u003e\n\u003c\/svg\u003e","brand":"ZAB","offers":[{"title":"300g","offer_id":53138912969013,"sku":"CAF-SIN-EFRE-300","price":31.0,"currency_code":"CAD","in_stock":true},{"title":"808g","offer_id":53138913001781,"sku":"CAF-SIN-EFRE-808","price":76.0,"currency_code":"CAD","in_stock":true},{"title":"2268g (5lbs)","offer_id":53138913034549,"sku":"CAF-SIN-EFRE-2268","price":200.0,"currency_code":"CAD","in_stock":true},{"title":"100g","offer_id":53138913067317,"sku":"CAF-SIN-EFRE-100","price":15.5,"currency_code":"CAD","in_stock":true},{"title":"Bucket - 5lbs (Livraison locale seulement)","offer_id":53138913100085,"sku":"CAF-SIN-EFRE-BUCK-5","price":225.0,"currency_code":"CAD","in_stock":true},{"title":"Bucket - 15lbs (Livraison locale seulement)","offer_id":53138913132853,"sku":"CAF-SIN-EFRE-BUCK-15","price":625.0,"currency_code":"CAD","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/2716\/1842\/files\/efren-300g_35ae5a66-ce26-4c1d-ba72-061c088b80d2.jpg?v=1784319953"},{"product_id":"demi-caf-espresso","title":"DEMI-CAF - ESPRESSO","description":"\u003c!-- =========================================================\n  SECTION 1 : NOTES DE DÉGUSTATION\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto; border: 2px solid var(--product-box-background, #000); border-radius: 12px; overflow: hidden;\"\u003e\n\u003cdiv style=\"padding: 10px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center;\"\u003eNotes de dégustation\u003c\/div\u003e\n\u003cdiv style=\"padding: 16px 14px; font-weight: 900; text-transform: uppercase; font-size: 28px; letter-spacing: .05em; text-align: center; background: transparent;\"\u003ePÉPITE DE CHOCOLAT + SUCRE CARAMÉLISÉ + NOISETTE\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 1 ========= --\u003e\n\n\u003cp\u003e \u003c\/p\u003e\n\n\u003cdiv style=\"position: relative; width: 100%; padding-bottom: 56.25%; height: 0; overflow: hidden; border-radius: 8px;\"\u003e\u003ciframe style=\"position: absolute; top: 0; left: 0; width: 100%; height: 100%; border: 0; border-radius: 8px;\" src=\"https:\/\/www.youtube.com\/embed\/wLQxuB5RRqg?si=LleA40C9NC9V6Jo4\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen\u003e\u003c\/iframe\u003e\u003c\/div\u003e\n\n\u003cp\u003e \u003c\/p\u003e\n\n\u003c!-- =========================================================\n  SECTION 2 : APPROVISIONNEMENT (mélange 50\/50)\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto;\"\u003e\n\u003cdiv style=\"padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center; border-radius: 12px 12px 0 0;\"\u003eApprovisionnement — Joyeux Roger (50 %)\u003c\/div\u003e\n\u003ctable style=\"width: 100%; border-collapse: collapse; background: transparent;\" cellspacing=\"1\" cellpadding=\"1\" border=\"3\"\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd style=\"width: 20%;\"\u003eORIGINE\u003c\/td\u003e\n\u003ctd\u003eCampo das Vertentes, Minas Gerais, Brésil\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePRODUCTEUR.RICE\u003c\/td\u003e\n\u003ctd\u003ePlusieurs producteur.rices de Sancoffee\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eVARIÉTÉS\u003c\/td\u003e\n\u003ctd\u003eCatucai jaune, Mundo Novo, Catuai rouge, Topázio\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePROCÉDÉ\u003c\/td\u003e\n\u003ctd\u003eNaturel\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eALTITUDE\u003c\/td\u003e\n\u003ctd\u003e900 – 1200 m\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePARTENAIRES\u003c\/td\u003e\n\u003ctd\u003eCrop to Cup\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eVOLUME ACHETÉ\u003c\/td\u003e\n\u003ctd\u003e96 600 kg\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eFAB\u003c\/td\u003e\n\u003ctd\u003e2,40 $ US\/LB\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePRIX LIVRÉ\u003c\/td\u003e\n\u003ctd\u003e4,55 $ CAD\/LB\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eRELATION\u003c\/td\u003e\n\u003ctd\u003e2 ans\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003c\/tbody\u003e\n\u003c\/table\u003e\n\u003cp style=\"margin: 6px 0 0 0; font-size: 13px;\"\u003e \u003c\/p\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto;\"\u003e\n\u003cdiv style=\"padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center; border-radius: 12px 12px 0 0;\"\u003eApprovisionnement — Décaf Colombie (50 %)\u003c\/div\u003e\n\u003ctable style=\"width: 100%; border-collapse: collapse; background: transparent;\" cellspacing=\"1\" cellpadding=\"1\" border=\"3\"\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd style=\"width: 20%;\"\u003eORIGINE\u003c\/td\u003e\n\u003ctd\u003eMunicipalité de Buesaco, département de Nariño, Colombie\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePRODUCTEURS\u003c\/td\u003e\n\u003ctd\u003ePlusieurs petit·es producteur·rices\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eVARIÉTÉ\u003c\/td\u003e\n\u003ctd\u003eVariées\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePROCÉDÉ\u003c\/td\u003e\n\u003ctd\u003eLavé et décaféiné à l’acétate d’éthyle\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eALTITUDE\u003c\/td\u003e\n\u003ctd\u003e2100 à 2400 m\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePARTENAIRES\u003c\/td\u003e\n\u003ctd\u003eApex Coffee Imports\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eVOLUME ACHETÉ\u003c\/td\u003e\n\u003ctd\u003e5600 kg\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eFAB\u003c\/td\u003e\n\u003ctd\u003e4,20 $ US\/lb\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePRIX LIVRÉ\u003c\/td\u003e\n\u003ctd\u003e8,30 $ CAD\/LB\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eRELATION\u003c\/td\u003e\n\u003ctd\u003e1 an\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003c\/tbody\u003e\n\u003c\/table\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 2 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\n\u003c!-- =========================================================\n  SECTION 3 : INFORMATIONS SUR LE CAFÉ\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto;\"\u003e\n\u003cdiv style=\"padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center; border-radius: 12px 12px 0 0;\"\u003eInformations sur le café\u003c\/div\u003e\n\u003cdiv style=\"border: 2px solid var(--product-box-background, #000); border-top: none; border-radius: 0 0 12px 12px; padding: 16px 14px; background: transparent;\"\u003e\n\u003cp style=\"margin: 0 0 12px 0;\"\u003eQuand c'est le cœur qui veut un autre café, mais que le corps hésite un peu, on a trouvé le compromis parfait : un café qui garde tout son caractère, avec un peu moins de caféine. Notre demi-caf combine café régulier et décaféiné pour une tasse pleine de douceur, de goût et de réconfort.\u003c\/p\u003e\n\u003cp style=\"margin: 0 0 12px 0;\"\u003ePour cette édition, nous avons assemblé notre classique Joyeux Roger, un café brésilien aux notes généreuses de chocolat et de noix, avec notre décaf colombien de Buesaco, dans le Nariño. Produit avec des partenaires engagés comme Sancoffee au Brésil et Apex Coffee Imports en Colombie, cet assemblage offre le meilleur des deux mondes : une tasse gourmande aux accents de cacao, une texture ronde et une finale douce et sucrée.\u003c\/p\u003e\n\u003cp style=\"margin: 0;\"\u003eTout le plaisir d'un bon café, avec juste un peu moins de caféine.\u003c\/p\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 3 ========= --\u003e\n\n\u003cp\u003e \u003c\/p\u003e\n\n\u003c!-- =========================================================\n  SECTION 4 : PARAMÈTRES D'EXTRACTION — ESPRESSO\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto;\"\u003e\n\u003cdetails open=\"\" style=\"border: 2px solid var(--product-box-background, #000); border-radius: 12px; overflow: hidden; margin: 0 0 12px 0; background: rgba(255,255,255,0.5);\"\u003e\n\u003csummary style=\"cursor: pointer; list-style: none; padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center;\"\u003eEspresso — paramètres recommandés\u003c\/summary\u003e\n\u003cdiv style=\"padding: 12px 14px;\"\u003e\n\u003ctable style=\"width: 100%; border-collapse: collapse; background: transparent;\"\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd style=\"padding: 10px 0; font-weight: 800; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003eCafé moulu\u003c\/td\u003e\n\u003ctd style=\"padding: 10px 0; text-align: right; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003e18 g\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd style=\"padding: 10px 0; font-weight: 800; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003eCafé dans la tasse\u003c\/td\u003e\n\u003ctd style=\"padding: 10px 0; text-align: right; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003e34 g\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd style=\"padding: 10px 0; font-weight: 800;\"\u003eTemps d'extraction\u003c\/td\u003e\n\u003ctd style=\"padding: 10px 0; text-align: right;\"\u003e31 sec\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003c\/tbody\u003e\n\u003c\/table\u003e\n\u003cdiv style=\"margin-top: 10px; padding: 8px 10px; border-radius: 8px; background: rgba(0,0,0,.04); border: 1px dashed rgba(0,0,0,.2); font-size: 12px; opacity: .7; line-height: 1.4;\"\u003e\n\u003cstrong\u003eÀ noter —\u003c\/strong\u003e Recette optimisée pour un panier de \u003cstrong\u003e18 g\u003c\/strong\u003e. Consulte le manuel de ta machine pour connaître la capacité de ton panier.\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/details\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 4 ========= --\u003e","brand":"ZAB","offers":[{"title":"300g","offer_id":53223415447861,"sku":"CAF-BLE-HALF-ESPR-300","price":26.0,"currency_code":"CAD","in_stock":true},{"title":"808g","offer_id":53223415480629,"sku":"CAF-BLE-HALF-ESPR-808","price":61.5,"currency_code":"CAD","in_stock":true},{"title":"2268g (5lbs)","offer_id":53223415513397,"sku":"CAF-BLE-HALF-ESPR-2268","price":155.0,"currency_code":"CAD","in_stock":true},{"title":"100g","offer_id":53223415546165,"sku":"CAF-BLE-HALF-ESPR-100","price":13.5,"currency_code":"CAD","in_stock":true},{"title":"Bucket - 5lbs (Livraison locale seulement)","offer_id":53223415578933,"sku":"CAF-BLE-HALF-ESPR-B5","price":180.0,"currency_code":"CAD","in_stock":true},{"title":"Bucket - 15lbs (Livraison locale seulement)","offer_id":53223415611701,"sku":"CAF-BLE-HALF-ESPR-B15","price":490.0,"currency_code":"CAD","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/2716\/1842\/files\/half-caf-espresso-300g.jpg?v=1785765998"},{"product_id":"indonesie-frinsa-estate","title":"INDONÉSIE - FRINSA ESTATE","description":"\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 1 : NOTES DE DÉGUSTATION\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto; border: 2px solid var(--product-box-background, #000); border-radius: 12px; overflow: hidden;\"\u003e\n\u003cdiv style=\"padding: 10px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center;\"\u003eNotes de dégustation\u003c\/div\u003e\n\u003cdiv style=\"padding: 16px 14px; font-weight: 900; text-transform: uppercase; font-size: 28px; letter-spacing: .05em; text-align: center; background: transparent;\"\u003eRAISIN + FRAISE + BONBON COLA\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 1 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003cdiv style=\"position: relative; width: 100%; padding-bottom: 56.25%; height: 0; overflow: hidden; border-radius: 8px;\"\u003e\u003ciframe style=\"position: absolute; top: 0; left: 0; width: 100%; height: 100%; border: 0; border-radius: 8px;\" src=\"https:\/\/www.youtube.com\/embed\/jFCCEUBPii0?si=nOgVxI8MYCAhxKPP\" title=\"YouTube video player\"\u003e\n\u003c\/iframe\u003e\u003c\/div\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 2 : APPROVISIONNEMENT\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto;\"\u003e\n\u003cdiv style=\"padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center; border-radius: 12px 12px 0 0;\"\u003eApprovisionnement\u003c\/div\u003e\n\u003ctable border=\"3\" cellpadding=\"1\" cellspacing=\"1\" style=\"width: 100%; border-collapse: collapse; background: transparent;\"\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd style=\"width: 20%;\"\u003eORIGINE\u003c\/td\u003e\n\u003ctd\u003eHauts plateaux de Bandung, province de Jawa Barat, Indonésie\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePRODUCTEURS\u003c\/td\u003e\n\u003ctd\u003eJava Frinsa Estate\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eVARIÉTÉ\u003c\/td\u003e\n\u003ctd\u003eVariées\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePROCÉDÉ\u003c\/td\u003e\n\u003ctd\u003eNaturel avec fermentation lactique\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eALTITUDE\u003c\/td\u003e\n\u003ctd\u003e1300-1700 m\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePARTENAIRES\u003c\/td\u003e\n\u003ctd\u003eAcross Indonesian Seas\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eVOLUME ACHETÉ\u003c\/td\u003e\n\u003ctd\u003e420 kg\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePRIX LIVRÉ\u003c\/td\u003e\n\u003ctd\u003e13,61 $ CAD\/LB\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eRELATION\u003c\/td\u003e\n\u003ctd\u003e1 an\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003c\/tbody\u003e\n\u003c\/table\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 2 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 3 : INFORMATIONS SUR LE CAFÉ\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto;\"\u003e\n\u003cdiv style=\"padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center; border-radius: 12px 12px 0 0;\"\u003eInformations sur le café\u003c\/div\u003e\n\u003cdiv style=\"border: 2px solid var(--product-box-background, #000); border-top: none; border-radius: 0 0 12px 12px; padding: 16px 14px; background: transparent;\"\u003e\n\u003cp style=\"margin: 0 0 12px 0;\"\u003eFondé en 2012 par Wildan Mustofa et Atieq Mustikaningtyas, Java Frinsa Estate est un domaine familial situé dans les hauts plateaux de Bandung, en Java occidental. Leur vision : produire des cafés d'exception tout en régénérant les terres et en adoptant des pratiques agricoles durables.\u003c\/p\u003e\n\u003cp style=\"margin: 0 0 12px 0;\"\u003eCultivé sous couvert forestier et transformé avec une grande précision, le café de Frinsa reflète un terroir montagneux unique où qualité, biodiversité et savoir-faire familial se rencontrent.\u003c\/p\u003e\n\u003cp style=\"margin: 0;\"\u003eLa fermentation lactique de ce café est ce qui le rend particulier : une fermentation contrôlée favorisant l'activité des bactéries lactiques afin de développer une tasse plus expressive, avec une texture crémeuse, une acidité délicate et des notes fruitées.\u003c\/p\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 3 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 4 : PARAMÈTRES D'EXTRACTION — ESPRESSO\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto;\"\u003e\n\u003cdetails open=\"\" style=\"border: 2px solid var(--product-box-background, #000); border-radius: 12px; overflow: hidden; margin: 0 0 12px 0; background: rgba(255,255,255,0.5);\"\u003e\n\u003csummary style=\"cursor: pointer; list-style: none; padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center;\"\u003eEspresso — paramètres recommandés\u003c\/summary\u003e\n\u003cdiv style=\"padding: 12px 14px;\"\u003e\n\u003ctable style=\"width: 100%; border-collapse: collapse; background: transparent;\"\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd style=\"padding: 10px 0; font-weight: 800; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003eCafé moulu\u003c\/td\u003e\n\u003ctd style=\"padding: 10px 0; text-align: right; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003e18 g\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd style=\"padding: 10px 0; font-weight: 800; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003eCafé dans la tasse\u003c\/td\u003e\n\u003ctd style=\"padding: 10px 0; text-align: right; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003e38 g\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd style=\"padding: 10px 0; font-weight: 800;\"\u003eTemps d'extraction\u003c\/td\u003e\n\u003ctd style=\"padding: 10px 0; text-align: right;\"\u003e26 sec\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003c\/tbody\u003e\n\u003c\/table\u003e\n\u003cdiv style=\"margin-top: 10px; padding: 8px 10px; border-radius: 8px; background: rgba(0,0,0,.04); border: 1px dashed rgba(0,0,0,.2); font-size: 12px; opacity: .7; line-height: 1.4;\"\u003e\n\u003cstrong\u003eÀ noter —\u003c\/strong\u003e Recette optimisée pour un panier de \u003cstrong\u003e18 g\u003c\/strong\u003e. Consulte le manuel de ta machine pour connaître la capacité de ton panier.\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/details\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 4 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 5 : V60\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto;\"\u003e\n\u003cdetails id=\"v60Details-javafrinsa\" open=\"\" style=\"border: 2px solid var(--product-box-background, #000); border-radius: 12px; overflow: hidden; margin: 0 0 12px 0; background: rgba(255,255,255,0.5);\"\u003e\n\u003csummary style=\"cursor: pointer; list-style: none; padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center;\"\u003eV60 – Recette\u003c\/summary\u003e\n\u003cdiv style=\"padding: 12px 14px;\"\u003e\n\u003cdiv style=\"padding: 10px 0 10px; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003e\n\u003cdiv style=\"font-weight: 900; font-size: 16px;\"\u003eRatio 1:15\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 4px; opacity: .7; font-size: 13px;\"\u003e15 g in – 225 g out\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 6px; font-size: 13px;\"\u003e\n\u003cstrong\u003eTempérature de l'eau :\u003c\/strong\u003e 90 °C\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; padding: 10px 0 8px;\"\u003e\n\u003cdiv style=\"display: flex; gap: 8px; align-items: center; flex-wrap: wrap;\"\u003e\n\u003cbutton style=\"cursor: pointer; border: 2px solid var(--product-box-background, #000); background: var(--product-box-background, #000); color: var(--product-box-text, #fff); font-weight: 900; padding: 8px 10px; border-radius: 10px; text-transform: uppercase; letter-spacing: .02em; font-size: 12px;\" type=\"button\" id=\"v60StartBtn-javafrinsa\"\u003eDémarrer\u003c\/button\u003e \u003cbutton style=\"cursor: pointer; border: 2px solid var(--product-box-background, #000); background: var(--product-box-text, #fff); color: var(--product-box-background, #000); font-weight: 900; padding: 8px 10px; border-radius: 10px; text-transform: uppercase; letter-spacing: .02em; font-size: 12px; opacity: .5;\" disabled type=\"button\" id=\"v60StopBtn-javafrinsa\"\u003eStop\u003c\/button\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; line-height: 1;\"\u003e\n\u003cspan style=\"opacity: .70; font-size: 12px; font-weight: 800; text-transform: uppercase; letter-spacing: .04em;\"\u003eTimer\u003c\/span\u003e \u003cspan style=\"font-weight: 950; font-size: 28px; letter-spacing: .01em;\" id=\"v60Timer-javafrinsa\"\u003e0:00\u003c\/span\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"flex-basis: 100%; opacity: .6; font-size: 12px; line-height: 1.3; margin-top: 2px;\" id=\"v60WakeStatus-javafrinsa\"\u003eℹ️ Appuie sur \"Démarrer\" pour garder l'écran allumé.\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 8px; display: grid; gap: 10px;\"\u003e\n\u003cdiv style=\"border: 1px solid rgba(0,0,0,.18); border-radius: 12px; padding: 10px 12px;\" id=\"v60-card-1-javafrinsa\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; margin-bottom: 6px;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e0:00\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003ePhase 1 — Bloom\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 8px; flex-wrap: wrap; font-size: 12.5px; font-weight: 800;\"\u003e\n\u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\" id=\"v60-pill-1-javafrinsa\"\u003eVerser pendant 0:10s\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\"\u003eTotal 45 g\u003c\/span\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"border: 1px solid rgba(0,0,0,.18); border-radius: 12px; padding: 10px 12px;\" id=\"v60-card-2-javafrinsa\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; margin-bottom: 6px;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e0:45\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003ePhase 2\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 8px; flex-wrap: wrap; font-size: 12.5px; font-weight: 800;\"\u003e\n\u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\" id=\"v60-pill-2-javafrinsa\"\u003eVerser pendant 0:30s\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\"\u003eTotal 170 g\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12); opacity: .6;\"\u003e+125 g\u003c\/span\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"border: 1px solid rgba(0,0,0,.18); border-radius: 12px; padding: 10px 12px;\" id=\"v60-card-3-javafrinsa\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; margin-bottom: 6px;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e1:50\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003ePhase 3\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 8px; flex-wrap: wrap; font-size: 12.5px; font-weight: 800;\"\u003e\n\u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\" id=\"v60-pill-3-javafrinsa\"\u003eVerser pendant 0:25s\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\"\u003eTotal 225 g\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12); opacity: .6;\"\u003e+55 g\u003c\/span\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 12px; border-top: 1px solid rgba(0,0,0,.2); padding-top: 10px;\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e2:55\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003eTemps final écoulement complet\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 8px; padding: 8px 10px; border-radius: 8px; background: rgba(0,0,0,.04); border: 1px dashed rgba(0,0,0,.2); font-size: 12px; opacity: .6; line-height: 1.4;\"\u003e\n\u003cstrong\u003eℹ️ Astuce —\u003c\/strong\u003e Si le temps total est plus court, la mouture est probablement trop grosse. S'il est plus long, la mouture est probablement trop fine.\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/details\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 5 ========= --\u003e\u003csvg style=\"display: none;\"\u003e\n\u003cstyle\u003e\n  @keyframes v60PulsePhase {\n    0%   { transform: scale(1);    box-shadow: 0 0 0 0 rgba(200,169,126,.35); }\n    50%  { transform: scale(1.06); box-shadow: 0 0 0 10px rgba(200,169,126,0); }\n    100% { transform: scale(1);    box-shadow: 0 0 0 0 rgba(200,169,126,0); }\n  }\n  .v60-pulse {\n    animation: v60PulsePhase 700ms ease-out 1;\n    transform-origin: center;\n    will-change: transform;\n  }\n  @keyframes v60BlinkPill {\n    0%, 100% { opacity: 1; transform: scale(1); }\n    50%      { opacity: .22; transform: scale(1.03); }\n  }\n  .v60-pill-pour-active {\n    background: #ffe7b7 !important;\n    border: 2px solid #d2a44a !important;\n    color: #3b2a12 !important;\n    font-weight: 900 !important;\n    letter-spacing: .02em;\n    animation: v60BlinkPill 2500ms ease-in-out infinite;\n    box-shadow:\n      0 0 0 2px rgba(210,164,74,.18) inset,\n      0 10px 22px rgba(0,0,0,.12),\n      0 0 0 6px rgba(210,164,74,.10);\n  }\n  @media (prefers-reduced-motion: reduce) {\n    .v60-pill-pour-active { animation: none; }\n    .v60-pulse { animation: none; }\n  }\n\u003c\/style\u003e\n\u003cscript\u003e\n(function() {\n  var SUFFIX = '-javafrinsa';\n  var END_AT = 175;\n  var phases = [\n    { key: 1, t: 0,   pourLen: 10 },\n    { key: 2, t: 45,  pourLen: 30 },\n    { key: 3, t: 110, pourLen: 25 }\n  ];\n  var latte = {\n    cardBg:     '#f6f1ea',\n    cardBorder: '#c8a97e',\n    pillBg:     '#eadfce'\n  };\n  var details  = document.getElementById('v60Details'    + SUFFIX);\n  var startBtn = document.getElementById('v60StartBtn'   + SUFFIX);\n  var stopBtn  = document.getElementById('v60StopBtn'    + SUFFIX);\n  var timerEl  = document.getElementById('v60Timer'      + SUFFIX);\n  var statusEl = document.getElementById('v60WakeStatus' + SUFFIX);\n  var pills = {\n    1: document.getElementById('v60-pill-1' + SUFFIX),\n    2: document.getElementById('v60-pill-2' + SUFFIX),\n    3: document.getElementById('v60-pill-3' + SUFFIX)\n  };\n  var cards = {\n    1: document.getElementById('v60-card-1' + SUFFIX),\n    2: document.getElementById('v60-card-2' + SUFFIX),\n    3: document.getElementById('v60-card-3' + SUFFIX)\n  };\n  function setCardActive(key) {\n    Object.keys(cards).forEach(function(k) {\n      var c = cards[k];\n      if (!c) return;\n      if (parseInt(k) === key) {\n        c.style.borderColor = latte.cardBorder;\n        c.style.background  = latte.cardBg;\n        c.style.boxShadow   = '0 0 0 2px rgba(200,169,126,.25) inset, 0 8px 22px rgba(200,169,126,.28)';\n      } else {\n        c.style.borderColor = 'rgba(0,0,0,.18)';\n        c.style.background  = 'transparent';\n        c.style.boxShadow   = 'none';\n      }\n    });\n  }\n  function setPillPhaseActive(key, doPulse) {\n    Object.keys(pills).forEach(function(k) {\n      var p = pills[k];\n      if (!p) return;\n      p.style.background  = 'rgba(0,0,0,.05)';\n      p.style.borderColor = 'rgba(0,0,0,.12)';\n      p.style.boxShadow   = 'none';\n      p.classList.remove('v60-pulse');\n    });\n    var pill = pills[key];\n    if (pill) {\n      pill.style.background  = latte.pillBg;\n      pill.style.borderColor = latte.cardBorder;\n      pill.style.boxShadow   = '0 0 0 2px rgba(200,169,126,.25) inset';\n      if (doPulse) {\n        pill.classList.remove('v60-pulse');\n        void pill.offsetWidth;\n        pill.classList.add('v60-pulse');\n      }\n    }\n  }\n  function resetPourPills() {\n    Object.values(pills).forEach(function(p) {\n      if (!p) return;\n      p.classList.remove('v60-pill-pour-active');\n    });\n  }\n  function setPourPillActive(key) {\n    resetPourPills();\n    if (!key) return;\n    var pill = pills[key];\n    if (pill) pill.classList.add('v60-pill-pour-active');\n  }\n  function clearAll() {\n    Object.values(cards).forEach(function(c) {\n      if (!c) return;\n      c.style.borderColor = 'rgba(0,0,0,.18)';\n      c.style.background  = 'transparent';\n      c.style.boxShadow   = 'none';\n    });\n    Object.values(pills).forEach(function(p) {\n      if (!p) return;\n      p.style.background  = 'rgba(0,0,0,.05)';\n      p.style.borderColor = 'rgba(0,0,0,.12)';\n      p.style.boxShadow   = 'none';\n      p.classList.remove('v60-pulse');\n      p.classList.remove('v60-pill-pour-active');\n    });\n  }\n  var wakeLock  = null;\n  var startTime = null;\n  var rafId     = null;\n  var lastPhaseKey = null;\n  var lastPourKey  = null;\n  function fmt(sec) {\n    sec = Math.max(0, Math.floor(sec));\n    var m = Math.floor(sec \/ 60);\n    var s = sec % 60;\n    return m + ':' + (s \u0026lt; 10 ? '0' : '') + s;\n  }\n  function getCurrentPhaseKey(elapsed) {\n    var current = phases[0].key;\n    for (var i = 0; i \u0026lt; phases.length; i++) if (elapsed \u0026gt;= phases[i].t) current = phases[i].key;\n    return current;\n  }\n  function getPourKey(elapsed) {\n    for (var i = phases.length - 1; i \u0026gt;= 0; i--) {\n      var p = phases[i];\n      if (elapsed \u0026gt;= p.t \u0026amp;\u0026amp; elapsed \u0026lt; (p.t + p.pourLen)) return p.key;\n    }\n    return null;\n  }\n  function enableWakeLock() {\n    if (!('wakeLock' in navigator)) {\n      statusEl.textContent = '⚠️ Ton navigateur ne supporte pas le mode écran allumé.';\n      return Promise.resolve();\n    }\n    return navigator.wakeLock.request('screen').then(function(wl) {\n      wakeLock = wl;\n      statusEl.textContent = '✅ Écran maintenu allumé pendant la recette.';\n      wakeLock.addEventListener('release', function() {\n        statusEl.textContent = 'ℹ️ Mode écran allumé relâché.';\n      });\n    }).catch(function() {\n      statusEl.textContent = '⚠️ Impossible d\\'activer le mode écran allumé.';\n      wakeLock = null;\n    });\n  }\n  function disableWakeLock() {\n    if (wakeLock) { wakeLock.release(); wakeLock = null; }\n  }\n  function setButtons(running) {\n    startBtn.disabled = running;\n    stopBtn.disabled  = !running;\n    stopBtn.style.opacity = running ? '1' : '.5';\n  }\n  function tick() {\n    var elapsed = (Date.now() - startTime) \/ 1000;\n    timerEl.textContent = fmt(elapsed);\n    var phaseKey = getCurrentPhaseKey(elapsed);\n    if (phaseKey !== lastPhaseKey) {\n      setCardActive(phaseKey);\n      setPillPhaseActive(phaseKey, lastPhaseKey !== null);\n      lastPhaseKey = phaseKey;\n    }\n    var pourKey = getPourKey(elapsed);\n    if (pourKey !== lastPourKey) {\n      setPourPillActive(pourKey);\n      lastPourKey = pourKey;\n    }\n    if (elapsed \u0026gt;= END_AT) { stopRecipe(true); return; }\n    rafId = requestAnimationFrame(tick);\n  }\n  function startRecipe() {\n    setButtons(true);\n    timerEl.textContent = '0:00';\n    lastPhaseKey = null;\n    lastPourKey  = null;\n    enableWakeLock().then(function() {\n      setCardActive(1);\n      setPillPhaseActive(1, false);\n      setPourPillActive(1);\n      lastPhaseKey = 1;\n      lastPourKey  = 1;\n      startTime = Date.now();\n      if (rafId) cancelAnimationFrame(rafId);\n      rafId = requestAnimationFrame(tick);\n    });\n  }\n  function stopRecipe(autoEnded) {\n    if (rafId) cancelAnimationFrame(rafId);\n    rafId     = null;\n    startTime = null;\n    disableWakeLock();\n    setButtons(false);\n    clearAll();\n    lastPhaseKey = null;\n    lastPourKey  = null;\n    if (autoEnded) {\n      statusEl.textContent = '✅ Recette terminée — écran libéré.';\n      timerEl.textContent  = fmt(END_AT);\n    } else {\n      statusEl.textContent = 'ℹ️ Recette arrêtée — écran libéré.';\n    }\n  }\n  startBtn.addEventListener('click', startRecipe);\n  stopBtn.addEventListener('click', function() { stopRecipe(false); });\n  details.addEventListener('toggle', function() { if (!details.open) stopRecipe(false); });\n  document.addEventListener('visibilitychange', function() {\n    if (document.visibilityState === 'visible' \u0026amp;\u0026amp; startTime \u0026amp;\u0026amp; !wakeLock) enableWakeLock();\n  });\n})();\n\u003c\/script\u003e\n\u003c\/svg\u003e","brand":"ZAB","offers":[{"title":"250g","offer_id":53252202791221,"sku":"CAF-SIN-FRIN-250","price":35.0,"currency_code":"CAD","in_stock":false},{"title":"808g","offer_id":53252202823989,"sku":"CAF-SIN-FRIN-808","price":105.0,"currency_code":"CAD","in_stock":false}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/2716\/1842\/files\/frinsa-250g_8c18fad6-f9a3-4428-8617-061b45cc8cd4.jpg?v=1787674162"},{"product_id":"ethiopie-kossa-geshe","title":"ÉTHIOPIE - KOSSA GESHE","description":"\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 1 : NOTES DE DÉGUSTATION\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto; border: 2px solid var(--product-box-background, #000); border-radius: 12px; overflow: hidden;\"\u003e\n\u003cdiv style=\"padding: 10px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center;\"\u003eNotes de dégustation\u003c\/div\u003e\n\u003cdiv style=\"padding: 16px 14px; font-weight: 900; text-transform: uppercase; font-size: 28px; letter-spacing: .05em; text-align: center; background: transparent;\"\u003eCONFITURE DE FRAMBOISE + FLORAL + CHOCOLAT NOIR\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 1 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003cdiv style=\"position: relative; width: 100%; padding-bottom: 56.25%; height: 0; overflow: hidden; border-radius: 8px;\"\u003e\u003ciframe style=\"position: absolute; top: 0; left: 0; width: 100%; height: 100%; border: 0; border-radius: 8px;\" src=\"https:\/\/www.youtube.com\/embed\/0y9jPTHd9n0\" title=\"YouTube video player\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" allowfullscreen=\"\"\u003e\n\u003c\/iframe\u003e\u003c\/div\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 2 : APPROVISIONNEMENT\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto;\"\u003e\n\u003cdiv style=\"padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center; border-radius: 12px 12px 0 0;\"\u003eApprovisionnement\u003c\/div\u003e\n\u003ctable border=\"3\" cellpadding=\"1\" cellspacing=\"1\" style=\"width: 100%; border-collapse: collapse; background: transparent;\"\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd style=\"width: 20%;\"\u003eORIGINE\u003c\/td\u003e\n\u003ctd\u003eDistrict de Limmu Kossa, zone de Jimma, région d'Oromia, Éthiopie\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePRODUCTEURS\u003c\/td\u003e\n\u003ctd\u003eGroupe Kossa Geshe\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eGESTIONNAIRE DU LOT\u003c\/td\u003e\n\u003ctd\u003eAbdulwahid Sherif\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eVARIÉTÉ\u003c\/td\u003e\n\u003ctd\u003e74110, 74140, 74112, 74166\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePROCÉDÉ\u003c\/td\u003e\n\u003ctd\u003eNaturel\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eALTITUDE\u003c\/td\u003e\n\u003ctd\u003e1800 m\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePARTENAIRES\u003c\/td\u003e\n\u003ctd\u003eCrop to Cup\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eVOLUME ACHETÉ\u003c\/td\u003e\n\u003ctd\u003e1200 kg\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eFAB\u003c\/td\u003e\n\u003ctd\u003e4,20 $ US\/lb\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePRIX LIVRÉ\u003c\/td\u003e\n\u003ctd\u003e7,83 $ CAD\/LB\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eRELATION\u003c\/td\u003e\n\u003ctd\u003e2 ans\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003c\/tbody\u003e\n\u003c\/table\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 2 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 3 : INFORMATIONS SUR LE CAFÉ\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto;\"\u003e\n\u003cdiv style=\"padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center; border-radius: 12px 12px 0 0;\"\u003eInformations sur le café\u003c\/div\u003e\n\u003cdiv style=\"border: 2px solid var(--product-box-background, #000); border-top: none; border-radius: 0 0 12px 12px; padding: 16px 14px; background: transparent;\"\u003e\n\u003cp style=\"margin: 0 0 12px 0;\"\u003eKossa Geshe est une ferme de 1 000 hectares située dans les hauts plateaux de la forêt de Kebena, dans le district de Limmu Kossa. Fondée en 2009 sur des terres accordées par l'État éthiopien, la ferme a été créée avec pour objectif de préserver l'un des derniers grands massifs de forêt dense du pays.\u003c\/p\u003e\n\u003cp style=\"margin: 0;\"\u003eAbdulwahid Sherif assure la gestion de Kossa Geshe depuis la toute première récolte en 2016. Ses cafés se sont rapidement démarqués par leur qualité, remportant notamment un Good Food Award en 2018. Depuis, il continue d'investir dans la qualité, les infrastructures et les conditions de vie des travailleurs, notamment avec la construction d'une école sur la ferme.\u003c\/p\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 3 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 4 : PARAMÈTRES D'EXTRACTION — ESPRESSO\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto;\"\u003e\n\u003cdetails open=\"\" style=\"border: 2px solid var(--product-box-background, #000); border-radius: 12px; overflow: hidden; margin: 0 0 12px 0; background: rgba(255,255,255,0.5);\"\u003e\n\u003csummary style=\"cursor: pointer; list-style: none; padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center;\"\u003eEspresso — paramètres recommandés\u003c\/summary\u003e\n\u003cdiv style=\"padding: 12px 14px;\"\u003e\n\u003ctable style=\"width: 100%; border-collapse: collapse; background: transparent;\"\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd style=\"padding: 10px 0; font-weight: 800; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003eCafé moulu\u003c\/td\u003e\n\u003ctd style=\"padding: 10px 0; text-align: right; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003e18 g\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd style=\"padding: 10px 0; font-weight: 800; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003eCafé dans la tasse\u003c\/td\u003e\n\u003ctd style=\"padding: 10px 0; text-align: right; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003e37 g\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd style=\"padding: 10px 0; font-weight: 800;\"\u003eTemps d'extraction\u003c\/td\u003e\n\u003ctd style=\"padding: 10px 0; text-align: right;\"\u003e27 sec\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003c\/tbody\u003e\n\u003c\/table\u003e\n\u003cdiv style=\"margin-top: 10px; padding: 8px 10px; border-radius: 8px; background: rgba(0,0,0,.04); border: 1px dashed rgba(0,0,0,.2); font-size: 12px; opacity: .7; line-height: 1.4;\"\u003e\n\u003cstrong\u003eÀ noter —\u003c\/strong\u003e Recette optimisée pour un panier de \u003cstrong\u003e18 g\u003c\/strong\u003e. Consulte le manuel de ta machine pour connaître la capacité de ton panier.\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/details\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 4 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 5 : V60\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto;\"\u003e\n\u003cdetails id=\"v60Details-kossageshe\" open=\"\" style=\"border: 2px solid var(--product-box-background, #000); border-radius: 12px; overflow: hidden; margin: 0 0 12px 0; background: rgba(255,255,255,0.5);\"\u003e\n\u003csummary style=\"cursor: pointer; list-style: none; padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center;\"\u003eV60 – Recette\u003c\/summary\u003e\n\u003cdiv style=\"padding: 12px 14px;\"\u003e\n\u003cdiv style=\"padding: 10px 0 10px; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003e\n\u003cdiv style=\"font-weight: 900; font-size: 16px;\"\u003eRatio 1:15\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 4px; opacity: .7; font-size: 13px;\"\u003e15 g in – 225 g out\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 6px; font-size: 13px;\"\u003e\n\u003cstrong\u003eTempérature de l'eau :\u003c\/strong\u003e 89 °C\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; padding: 10px 0 8px;\"\u003e\n\u003cdiv style=\"display: flex; gap: 8px; align-items: center; flex-wrap: wrap;\"\u003e\n\u003cbutton style=\"cursor: pointer; border: 2px solid var(--product-box-background, #000); background: var(--product-box-background, #000); color: var(--product-box-text, #fff); font-weight: 900; padding: 8px 10px; border-radius: 10px; text-transform: uppercase; letter-spacing: .02em; font-size: 12px;\" type=\"button\" id=\"v60StartBtn-kossageshe\"\u003eDémarrer\u003c\/button\u003e \u003cbutton style=\"cursor: pointer; border: 2px solid var(--product-box-background, #000); background: var(--product-box-text, #fff); color: var(--product-box-background, #000); font-weight: 900; padding: 8px 10px; border-radius: 10px; text-transform: uppercase; letter-spacing: .02em; font-size: 12px; opacity: .5;\" disabled type=\"button\" id=\"v60StopBtn-kossageshe\"\u003eStop\u003c\/button\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; line-height: 1;\"\u003e\n\u003cspan style=\"opacity: .70; font-size: 12px; font-weight: 800; text-transform: uppercase; letter-spacing: .04em;\"\u003eTimer\u003c\/span\u003e \u003cspan style=\"font-weight: 950; font-size: 28px; letter-spacing: .01em;\" id=\"v60Timer-kossageshe\"\u003e0:00\u003c\/span\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"flex-basis: 100%; opacity: .6; font-size: 12px; line-height: 1.3; margin-top: 2px;\" id=\"v60WakeStatus-kossageshe\"\u003eℹ️ Appuie sur \"Démarrer\" pour garder l'écran allumé.\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 8px; display: grid; gap: 10px;\"\u003e\n\u003cdiv style=\"border: 1px solid rgba(0,0,0,.18); border-radius: 12px; padding: 10px 12px;\" id=\"v60-card-1-kossageshe\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; margin-bottom: 6px;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e0:00\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003ePhase 1 — Bloom\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 8px; flex-wrap: wrap; font-size: 12.5px; font-weight: 800;\"\u003e\n\u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\" id=\"v60-pill-1-kossageshe\"\u003eVerser pendant 0:10s\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\"\u003eTotal 50 g\u003c\/span\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"border: 1px solid rgba(0,0,0,.18); border-radius: 12px; padding: 10px 12px;\" id=\"v60-card-2-kossageshe\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; margin-bottom: 6px;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e0:40\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003ePhase 2\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 8px; flex-wrap: wrap; font-size: 12.5px; font-weight: 800;\"\u003e\n\u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\" id=\"v60-pill-2-kossageshe\"\u003eVerser pendant 0:20s\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\"\u003eTotal 140 g\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12); opacity: .6;\"\u003e+90 g\u003c\/span\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"border: 1px solid rgba(0,0,0,.18); border-radius: 12px; padding: 10px 12px;\" id=\"v60-card-3-kossageshe\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; margin-bottom: 6px;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e1:25\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003ePhase 3\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 8px; flex-wrap: wrap; font-size: 12.5px; font-weight: 800;\"\u003e\n\u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\" id=\"v60-pill-3-kossageshe\"\u003eVerser pendant 0:20s\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\"\u003eTotal 225 g\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12); opacity: .6;\"\u003e+85 g\u003c\/span\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 12px; border-top: 1px solid rgba(0,0,0,.2); padding-top: 10px;\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e3:00\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003eTemps final écoulement complet\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 8px; padding: 8px 10px; border-radius: 8px; background: rgba(0,0,0,.04); border: 1px dashed rgba(0,0,0,.2); font-size: 12px; opacity: .6; line-height: 1.4;\"\u003e\n\u003cstrong\u003eℹ️ Astuce —\u003c\/strong\u003e Si le temps total est plus court, la mouture est probablement trop grosse. S'il est plus long, la mouture est probablement trop fine.\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/details\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 5 ========= --\u003e\u003csvg style=\"display: none;\"\u003e\n\u003cstyle\u003e\n  @keyframes v60PulsePhase {\n    0%   { transform: scale(1);    box-shadow: 0 0 0 0 rgba(200,169,126,.35); }\n    50%  { transform: scale(1.06); box-shadow: 0 0 0 10px rgba(200,169,126,0); }\n    100% { transform: scale(1);    box-shadow: 0 0 0 0 rgba(200,169,126,0); }\n  }\n  .v60-pulse {\n    animation: v60PulsePhase 700ms ease-out 1;\n    transform-origin: center;\n    will-change: transform;\n  }\n  @keyframes v60BlinkPill {\n    0%, 100% { opacity: 1; transform: scale(1); }\n    50%      { opacity: .22; transform: scale(1.03); }\n  }\n  .v60-pill-pour-active {\n    background: #ffe7b7 !important;\n    border: 2px solid #d2a44a !important;\n    color: #3b2a12 !important;\n    font-weight: 900 !important;\n    letter-spacing: .02em;\n    animation: v60BlinkPill 2500ms ease-in-out infinite;\n    box-shadow:\n      0 0 0 2px rgba(210,164,74,.18) inset,\n      0 10px 22px rgba(0,0,0,.12),\n      0 0 0 6px rgba(210,164,74,.10);\n  }\n  @media (prefers-reduced-motion: reduce) {\n    .v60-pill-pour-active { animation: none; }\n    .v60-pulse { animation: none; }\n  }\n\u003c\/style\u003e\n\u003cscript\u003e\n(function() {\n  var SUFFIX = '-kossageshe';\n  var END_AT = 180;\n  var phases = [\n    { key: 1, t: 0,  pourLen: 10 },\n    { key: 2, t: 40, pourLen: 20 },\n    { key: 3, t: 85, pourLen: 20 }\n  ];\n  var latte = {\n    cardBg:     '#f6f1ea',\n    cardBorder: '#c8a97e',\n    pillBg:     '#eadfce'\n  };\n  var details  = document.getElementById('v60Details'    + SUFFIX);\n  var startBtn = document.getElementById('v60StartBtn'   + SUFFIX);\n  var stopBtn  = document.getElementById('v60StopBtn'    + SUFFIX);\n  var timerEl  = document.getElementById('v60Timer'      + SUFFIX);\n  var statusEl = document.getElementById('v60WakeStatus' + SUFFIX);\n  var pills = {\n    1: document.getElementById('v60-pill-1' + SUFFIX),\n    2: document.getElementById('v60-pill-2' + SUFFIX),\n    3: document.getElementById('v60-pill-3' + SUFFIX)\n  };\n  var cards = {\n    1: document.getElementById('v60-card-1' + SUFFIX),\n    2: document.getElementById('v60-card-2' + SUFFIX),\n    3: document.getElementById('v60-card-3' + SUFFIX)\n  };\n  function setCardActive(key) {\n    Object.keys(cards).forEach(function(k) {\n      var c = cards[k];\n      if (!c) return;\n      if (parseInt(k) === key) {\n        c.style.borderColor = latte.cardBorder;\n        c.style.background  = latte.cardBg;\n        c.style.boxShadow   = '0 0 0 2px rgba(200,169,126,.25) inset, 0 8px 22px rgba(200,169,126,.28)';\n      } else {\n        c.style.borderColor = 'rgba(0,0,0,.18)';\n        c.style.background  = 'transparent';\n        c.style.boxShadow   = 'none';\n      }\n    });\n  }\n  function setPillPhaseActive(key, doPulse) {\n    Object.keys(pills).forEach(function(k) {\n      var p = pills[k];\n      if (!p) return;\n      p.style.background  = 'rgba(0,0,0,.05)';\n      p.style.borderColor = 'rgba(0,0,0,.12)';\n      p.style.boxShadow   = 'none';\n      p.classList.remove('v60-pulse');\n    });\n    var pill = pills[key];\n    if (pill) {\n      pill.style.background  = latte.pillBg;\n      pill.style.borderColor = latte.cardBorder;\n      pill.style.boxShadow   = '0 0 0 2px rgba(200,169,126,.25) inset';\n      if (doPulse) {\n        pill.classList.remove('v60-pulse');\n        void pill.offsetWidth;\n        pill.classList.add('v60-pulse');\n      }\n    }\n  }\n  function resetPourPills() {\n    Object.values(pills).forEach(function(p) {\n      if (!p) return;\n      p.classList.remove('v60-pill-pour-active');\n    });\n  }\n  function setPourPillActive(key) {\n    resetPourPills();\n    if (!key) return;\n    var pill = pills[key];\n    if (pill) pill.classList.add('v60-pill-pour-active');\n  }\n  function clearAll() {\n    Object.values(cards).forEach(function(c) {\n      if (!c) return;\n      c.style.borderColor = 'rgba(0,0,0,.18)';\n      c.style.background  = 'transparent';\n      c.style.boxShadow   = 'none';\n    });\n    Object.values(pills).forEach(function(p) {\n      if (!p) return;\n      p.style.background  = 'rgba(0,0,0,.05)';\n      p.style.borderColor = 'rgba(0,0,0,.12)';\n      p.style.boxShadow   = 'none';\n      p.classList.remove('v60-pulse');\n      p.classList.remove('v60-pill-pour-active');\n    });\n  }\n  var wakeLock  = null;\n  var startTime = null;\n  var rafId     = null;\n  var lastPhaseKey = null;\n  var lastPourKey  = null;\n  function fmt(sec) {\n    sec = Math.max(0, Math.floor(sec));\n    var m = Math.floor(sec \/ 60);\n    var s = sec % 60;\n    return m + ':' + (s \u0026lt; 10 ? '0' : '') + s;\n  }\n  function getCurrentPhaseKey(elapsed) {\n    var current = phases[0].key;\n    for (var i = 0; i \u0026lt; phases.length; i++) if (elapsed \u0026gt;= phases[i].t) current = phases[i].key;\n    return current;\n  }\n  function getPourKey(elapsed) {\n    for (var i = phases.length - 1; i \u0026gt;= 0; i--) {\n      var p = phases[i];\n      if (elapsed \u0026gt;= p.t \u0026amp;\u0026amp; elapsed \u0026lt; (p.t + p.pourLen)) return p.key;\n    }\n    return null;\n  }\n  function enableWakeLock() {\n    if (!('wakeLock' in navigator)) {\n      statusEl.textContent = '⚠️ Ton navigateur ne supporte pas le mode écran allumé.';\n      return Promise.resolve();\n    }\n    return navigator.wakeLock.request('screen').then(function(wl) {\n      wakeLock = wl;\n      statusEl.textContent = '✅ Écran maintenu allumé pendant la recette.';\n      wakeLock.addEventListener('release', function() {\n        statusEl.textContent = 'ℹ️ Mode écran allumé relâché.';\n      });\n    }).catch(function() {\n      statusEl.textContent = '⚠️ Impossible d\\'activer le mode écran allumé.';\n      wakeLock = null;\n    });\n  }\n  function disableWakeLock() {\n    if (wakeLock) { wakeLock.release(); wakeLock = null; }\n  }\n  function setButtons(running) {\n    startBtn.disabled = running;\n    stopBtn.disabled  = !running;\n    stopBtn.style.opacity = running ? '1' : '.5';\n  }\n  function tick() {\n    var elapsed = (Date.now() - startTime) \/ 1000;\n    timerEl.textContent = fmt(elapsed);\n    var phaseKey = getCurrentPhaseKey(elapsed);\n    if (phaseKey !== lastPhaseKey) {\n      setCardActive(phaseKey);\n      setPillPhaseActive(phaseKey, lastPhaseKey !== null);\n      lastPhaseKey = phaseKey;\n    }\n    var pourKey = getPourKey(elapsed);\n    if (pourKey !== lastPourKey) {\n      setPourPillActive(pourKey);\n      lastPourKey = pourKey;\n    }\n    if (elapsed \u0026gt;= END_AT) { stopRecipe(true); return; }\n    rafId = requestAnimationFrame(tick);\n  }\n  function startRecipe() {\n    setButtons(true);\n    timerEl.textContent = '0:00';\n    lastPhaseKey = null;\n    lastPourKey  = null;\n    enableWakeLock().then(function() {\n      setCardActive(1);\n      setPillPhaseActive(1, false);\n      setPourPillActive(1);\n      lastPhaseKey = 1;\n      lastPourKey  = 1;\n      startTime = Date.now();\n      if (rafId) cancelAnimationFrame(rafId);\n      rafId = requestAnimationFrame(tick);\n    });\n  }\n  function stopRecipe(autoEnded) {\n    if (rafId) cancelAnimationFrame(rafId);\n    rafId     = null;\n    startTime = null;\n    disableWakeLock();\n    setButtons(false);\n    clearAll();\n    lastPhaseKey = null;\n    lastPourKey  = null;\n    if (autoEnded) {\n      statusEl.textContent = '✅ Recette terminée — écran libéré.';\n      timerEl.textContent  = fmt(END_AT);\n    } else {\n      statusEl.textContent = 'ℹ️ Recette arrêtée — écran libéré.';\n    }\n  }\n  startBtn.addEventListener('click', startRecipe);\n  stopBtn.addEventListener('click', function() { stopRecipe(false); });\n  details.addEventListener('toggle', function() { if (!details.open) stopRecipe(false); });\n  document.addEventListener('visibilitychange', function() {\n    if (document.visibilityState === 'visible' \u0026amp;\u0026amp; startTime \u0026amp;\u0026amp; !wakeLock) enableWakeLock();\n  });\n})();\n\u003c\/script\u003e\n\u003c\/svg\u003e","brand":"ZAB","offers":[{"title":"300g","offer_id":53628922200373,"sku":"CAF-SIN-KOSS-300","price":26.5,"currency_code":"CAD","in_stock":true},{"title":"808g","offer_id":53628922233141,"sku":"CAF-SIN-KOSS-808","price":62.0,"currency_code":"CAD","in_stock":true},{"title":"2268g (5lbs)","offer_id":53628922265909,"sku":"CAF-SIN-KOSS-2268","price":160.0,"currency_code":"CAD","in_stock":true},{"title":"100g","offer_id":53628922298677,"sku":"CAF-SIN-KOSS-100","price":13.25,"currency_code":"CAD","in_stock":true},{"title":"Bucket - 5lbs (Livraison locale seulement)","offer_id":53628922331445,"sku":"CAF-SIN-KOSS-BUCK-5","price":185.0,"currency_code":"CAD","in_stock":true},{"title":"Bucket - 15lbs (Livraison locale seulement)","offer_id":53628922364213,"sku":"CAF-SIN-KOSS-BUCK-15","price":505.0,"currency_code":"CAD","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/2716\/1842\/files\/kossa-300g-retour.jpg?v=1791468779"},{"product_id":"kenya-rungeto-kiangoi","title":"KENYA - KIANGOI","description":"\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 1 : NOTES DE DÉGUSTATION\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto; border: 2px solid var(--product-box-background, #000); border-radius: 12px; overflow: hidden;\"\u003e\n\u003cdiv style=\"padding: 10px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center;\"\u003eNotes de dégustation\u003c\/div\u003e\n\u003cdiv style=\"padding: 16px 14px; font-weight: 900; text-transform: uppercase; font-size: 28px; letter-spacing: .05em; text-align: center; background: transparent;\"\u003eCAMERISE + PAMPLEMOUSSE + VANILLE\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 1 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003cdiv style=\"position: relative; width: 100%; padding-bottom: 56.25%; height: 0; overflow: hidden; border-radius: 8px;\"\u003e\u003ciframe style=\"position: absolute; top: 0; left: 0; width: 100%; height: 100%; border: 0; border-radius: 8px;\" src=\"https:\/\/www.youtube.com\/embed\/PAlWZj5F3lk\" title=\"YouTube video player\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" allowfullscreen=\"\"\u003e\n\u003c\/iframe\u003e\u003c\/div\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 2 : APPROVISIONNEMENT\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto;\"\u003e\n\u003cdiv style=\"padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center; border-radius: 12px 12px 0 0;\"\u003eApprovisionnement\u003c\/div\u003e\n\u003ctable border=\"3\" cellpadding=\"1\" cellspacing=\"1\" style=\"width: 100%; border-collapse: collapse; background: transparent;\"\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd style=\"width: 20%;\"\u003eORIGINE\u003c\/td\u003e\n\u003ctd\u003eZone de Gichugu, comté de Kirinyaga, Kenya\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePRODUCTEURS\u003c\/td\u003e\n\u003ctd\u003ePlusieurs petit·es producteur·rices\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eCOOPÉRATIVE\u003c\/td\u003e\n\u003ctd\u003eKiangoi\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eVARIÉTÉ\u003c\/td\u003e\n\u003ctd\u003eBatian, SL-34, Ruiru 11, SL-28\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePROCÉDÉ\u003c\/td\u003e\n\u003ctd\u003eLavé\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eALTITUDE\u003c\/td\u003e\n\u003ctd\u003e1600 à 1800 m\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePARTENAIRES\u003c\/td\u003e\n\u003ctd\u003eApex Coffee imports\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eVOLUME ACHETÉ\u003c\/td\u003e\n\u003ctd\u003e180 kg\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eFAB\u003c\/td\u003e\n\u003ctd\u003e5,84 $ US\/lb\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePRIX LIVRÉ\u003c\/td\u003e\n\u003ctd\u003e12,20 $ CAD\/LB\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eRELATION\u003c\/td\u003e\n\u003ctd\u003e1 an\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003c\/tbody\u003e\n\u003c\/table\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 2 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 3 : INFORMATIONS SUR LE CAFÉ\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto;\"\u003e\n\u003cdiv style=\"padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center; border-radius: 12px 12px 0 0;\"\u003eInformations sur le café\u003c\/div\u003e\n\u003cdiv style=\"border: 2px solid var(--product-box-background, #000); border-top: none; border-radius: 0 0 12px 12px; padding: 16px 14px; background: transparent;\"\u003e\n\u003cp style=\"margin: 0 0 12px 0;\"\u003eUn café lumineux qui, en filtre, nous offre une belle complexité, balançant l’amertume douce du pamplemousse et l’acidité vive de la camerise, avec un fond tout en sucre. En espresso, on vise un shot long, mais rapide, sacrifiant le corps pour nous laisser avec un café vif et expressif, qui goûte la mûre et le jus d’orange, miam!\u003c\/p\u003e\n\u003cp style=\"margin: 0 0 12px 0;\"\u003eLa station de lavage Kiangoi est à Gichugu, dans le comté de Kirinyaga, au cœur du Kenya. Elle a été fondée dans les années 60 et elle travaille avec les producteur·rices des villages de Kiangoro et Karinga. La station est certifiée Fairtrade et se trouve dans une région où les arbres indigènes font encore partie du paysage. On y trie aussi les cerises à la main, question de garder uniquement les plus mûres, et ainsi avoir la meilleure qualité de grains possible.\u003c\/p\u003e\n\u003cp style=\"margin: 0;\"\u003eLe café est dépulpé pour ensuite être mis en fermentation pour une période de 8 à 12 heures. Les grains sont ensuite lavés, immergés dans de l’eau pendant 16 à 18 heures, puis séchés au soleil sur des lits surélevés pendant près de deux semaines. Un travail minutieux, du fruit au grain vert, pour préserver toute la qualité du café. Et ça, ça se sent clairement dans la tasse!\u003c\/p\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 3 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 3 BIS : CARROUSEL PHOTOS\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto;\"\u003e\n\u003cdiv id=\"zabCar-kiangoi\" style=\"display: flex; overflow-x: auto; scroll-snap-type: x mandatory; scroll-behavior: smooth; border: 2px solid var(--product-box-background, #000); border-radius: 12px; scrollbar-width: none;\"\u003e\n\u003cimg src=\"https:\/\/cdn.shopify.com\/s\/files\/1\/2716\/1842\/files\/2026-11-01-kiangoi-01-web.jpg?v=1793546185\" alt=\"Homme souriant portant une casquette grise et un polo blanc, devant un bâtiment de bois et de la verdure\" loading=\"lazy\" width=\"1600\" height=\"1067\" style=\"flex: 0 0 100%; width: 100%; height: auto; aspect-ratio: 3 \/ 2; object-fit: cover; scroll-snap-align: center; display: block;\"\u003e\n\u003cimg src=\"https:\/\/cdn.shopify.com\/s\/files\/1\/2716\/1842\/files\/2026-11-01-kiangoi-02-web.jpg?v=1793546185\" alt=\"Mur de briques de la station Kiangoi, enseigne « Rungeto Farmers Co-op Society – Kiangoi Coffee Factory »\" loading=\"lazy\" width=\"1600\" height=\"1067\" style=\"flex: 0 0 100%; width: 100%; height: auto; aspect-ratio: 3 \/ 2; object-fit: cover; scroll-snap-align: center; display: block;\"\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; justify-content: center; gap: 8px; margin-top: 8px;\"\u003e\n\u003cbutton type=\"button\" id=\"zabCarDot-1-kiangoi\" aria-label=\"Photo 1\" style=\"cursor: pointer; width: 10px; height: 10px; padding: 0; border-radius: 999px; border: 2px solid var(--product-box-background, #000); background: #000;\"\u003e\u003c\/button\u003e \u003cbutton type=\"button\" id=\"zabCarDot-2-kiangoi\" aria-label=\"Photo 2\" style=\"cursor: pointer; width: 10px; height: 10px; padding: 0; border-radius: 999px; border: 2px solid var(--product-box-background, #000); background: transparent;\"\u003e\u003c\/button\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 3 BIS ========= --\u003e\u003csvg style=\"display: none;\"\u003e\n\u003cscript\u003e\n(function() {\n  var SUFFIX = '-kiangoi';\n  var N = 2;\n  var track = document.getElementById('zabCar' + SUFFIX);\n  if (!track) return;\n  function dot(i) { return document.getElementById('zabCarDot-' + i + SUFFIX); }\n  function setActive(k) {\n    for (var i = 1; i \u0026lt;= N; i++) { var d = dot(i); if (d) d.style.background = (i === k) ? '#000' : 'transparent'; }\n  }\n  var DELAY = 3000;\n  var cur = 1;\n  var timer = null;\n  var reduce = window.matchMedia ? window.matchMedia('(prefers-reduced-motion: reduce)').matches : false;\n  function go(k) { track.scrollTo({ left: (k - 1) * track.clientWidth, behavior: 'smooth' }); }\n  function stop() { if (timer) { clearInterval(timer); timer = null; } }\n  function start() {\n    stop();\n    if (reduce) return;\n    timer = setInterval(function() { cur = (cur % N) + 1; go(cur); }, DELAY);\n  }\n  for (var i = 1; i \u0026lt;= N; i++) {\n    (function(k) {\n      var d = dot(k);\n      if (d) d.addEventListener('click', function() { cur = k; go(k); start(); });\n    })(i);\n  }\n  track.addEventListener('scroll', function() {\n    cur = Math.round(track.scrollLeft \/ Math.max(1, track.clientWidth)) + 1;\n    setActive(cur);\n  });\n  track.addEventListener('mouseenter', stop);\n  track.addEventListener('mouseleave', start);\n  track.addEventListener('touchstart', stop, { passive: true });\n  track.addEventListener('touchend', start);\n  document.addEventListener('visibilitychange', function() {\n    if (document.visibilityState === 'visible') { start(); } else { stop(); }\n  });\n  start();\n})();\n\u003c\/script\u003e\n\u003c\/svg\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 4 : PARAMÈTRES D'EXTRACTION — ESPRESSO\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto;\"\u003e\n\u003cdetails open=\"\" style=\"border: 2px solid var(--product-box-background, #000); border-radius: 12px; overflow: hidden; margin: 0 0 12px 0; background: rgba(255,255,255,0.5);\"\u003e\n\u003csummary style=\"cursor: pointer; list-style: none; padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center;\"\u003eEspresso — paramètres recommandés\u003c\/summary\u003e\n\u003cdiv style=\"padding: 12px 14px;\"\u003e\n\u003ctable style=\"width: 100%; border-collapse: collapse; background: transparent;\"\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd style=\"padding: 10px 0; font-weight: 800; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003eCafé moulu\u003c\/td\u003e\n\u003ctd style=\"padding: 10px 0; text-align: right; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003e18 g\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd style=\"padding: 10px 0; font-weight: 800; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003eCafé dans la tasse\u003c\/td\u003e\n\u003ctd style=\"padding: 10px 0; text-align: right; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003e42 g\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd style=\"padding: 10px 0; font-weight: 800;\"\u003eTemps d'extraction\u003c\/td\u003e\n\u003ctd style=\"padding: 10px 0; text-align: right;\"\u003e21 sec\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003c\/tbody\u003e\n\u003c\/table\u003e\n\u003cdiv style=\"margin-top: 10px; padding: 8px 10px; border-radius: 8px; background: rgba(0,0,0,.04); border: 1px dashed rgba(0,0,0,.2); font-size: 12px; opacity: .7; line-height: 1.4;\"\u003e\n\u003cstrong\u003eÀ noter —\u003c\/strong\u003e Recette optimisée pour un panier de \u003cstrong\u003e18 g\u003c\/strong\u003e. Consulte le manuel de ta machine pour connaître la capacité de ton panier.\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/details\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 4 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 5 : V60\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto;\"\u003e\n\u003cdetails id=\"v60Details-kiangoi\" open=\"\" style=\"border: 2px solid var(--product-box-background, #000); border-radius: 12px; overflow: hidden; margin: 0 0 12px 0; background: rgba(255,255,255,0.5);\"\u003e\n\u003csummary style=\"cursor: pointer; list-style: none; padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center;\"\u003eV60 – Recette\u003c\/summary\u003e\n\u003cdiv style=\"padding: 12px 14px;\"\u003e\n\u003cdiv style=\"padding: 10px 0 10px; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003e\n\u003cdiv style=\"font-weight: 900; font-size: 16px;\"\u003eRatio 1:15\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 4px; opacity: .7; font-size: 13px;\"\u003e15 g in – 225 g out\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 6px; font-size: 13px;\"\u003e\n\u003cstrong\u003eTempérature de l'eau :\u003c\/strong\u003e 91 °C\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; padding: 10px 0 8px;\"\u003e\n\u003cdiv style=\"display: flex; gap: 8px; align-items: center; flex-wrap: wrap;\"\u003e\n\u003cbutton style=\"cursor: pointer; border: 2px solid var(--product-box-background, #000); background: var(--product-box-background, #000); color: var(--product-box-text, #fff); font-weight: 900; padding: 8px 10px; border-radius: 10px; text-transform: uppercase; letter-spacing: .02em; font-size: 12px;\" type=\"button\" id=\"v60StartBtn-kiangoi\"\u003eDémarrer\u003c\/button\u003e \u003cbutton style=\"cursor: pointer; border: 2px solid var(--product-box-background, #000); background: var(--product-box-text, #fff); color: var(--product-box-background, #000); font-weight: 900; padding: 8px 10px; border-radius: 10px; text-transform: uppercase; letter-spacing: .02em; font-size: 12px; opacity: .5;\" disabled type=\"button\" id=\"v60StopBtn-kiangoi\"\u003eStop\u003c\/button\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; line-height: 1;\"\u003e\n\u003cspan style=\"opacity: .70; font-size: 12px; font-weight: 800; text-transform: uppercase; letter-spacing: .04em;\"\u003eTimer\u003c\/span\u003e \u003cspan style=\"font-weight: 950; font-size: 28px; letter-spacing: .01em;\" id=\"v60Timer-kiangoi\"\u003e0:00\u003c\/span\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"flex-basis: 100%; opacity: .6; font-size: 12px; line-height: 1.3; margin-top: 2px;\" id=\"v60WakeStatus-kiangoi\"\u003eℹ️ Appuie sur \"Démarrer\" pour garder l'écran allumé.\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 8px; display: grid; gap: 10px;\"\u003e\n\u003cdiv style=\"border: 1px solid rgba(0,0,0,.18); border-radius: 12px; padding: 10px 12px;\" id=\"v60-card-1-kiangoi\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; margin-bottom: 6px;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e0:00\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003ePhase 1 — Bloom\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 8px; flex-wrap: wrap; font-size: 12.5px; font-weight: 800;\"\u003e\n\u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\" id=\"v60-pill-1-kiangoi\"\u003eVerser pendant 0:10s\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\"\u003eTotal 50 g\u003c\/span\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"border: 1px solid rgba(0,0,0,.18); border-radius: 12px; padding: 10px 12px;\" id=\"v60-card-2-kiangoi\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; margin-bottom: 6px;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e0:40\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003ePhase 2\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 8px; flex-wrap: wrap; font-size: 12.5px; font-weight: 800;\"\u003e\n\u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\" id=\"v60-pill-2-kiangoi\"\u003eVerser pendant 0:10s\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\"\u003eTotal 100 g\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12); opacity: .6;\"\u003e+50 g\u003c\/span\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"border: 1px solid rgba(0,0,0,.18); border-radius: 12px; padding: 10px 12px;\" id=\"v60-card-3-kiangoi\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; margin-bottom: 6px;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e1:20\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003ePhase 3\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 8px; flex-wrap: wrap; font-size: 12.5px; font-weight: 800;\"\u003e\n\u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\" id=\"v60-pill-3-kiangoi\"\u003eVerser pendant 0:10s\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\"\u003eTotal 170 g\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12); opacity: .6;\"\u003e+70 g\u003c\/span\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"border: 1px solid rgba(0,0,0,.18); border-radius: 12px; padding: 10px 12px;\" id=\"v60-card-4-kiangoi\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; margin-bottom: 6px;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e1:55\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003ePhase 4\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 8px; flex-wrap: wrap; font-size: 12.5px; font-weight: 800;\"\u003e\n\u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\" id=\"v60-pill-4-kiangoi\"\u003eVerser pendant 0:10s\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\"\u003eTotal 225 g\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12); opacity: .6;\"\u003e+55 g\u003c\/span\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 12px; border-top: 1px solid rgba(0,0,0,.2); padding-top: 10px;\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e2:45\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003eTemps final écoulement complet\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 8px; padding: 8px 10px; border-radius: 8px; background: rgba(0,0,0,.04); border: 1px dashed rgba(0,0,0,.2); font-size: 12px; opacity: .6; line-height: 1.4;\"\u003e\n\u003cstrong\u003eℹ️ Astuce —\u003c\/strong\u003e Si le temps total est plus court, la mouture est probablement trop grosse. S'il est plus long, la mouture est probablement trop fine.\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/details\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 5 ========= --\u003e\u003csvg style=\"display: none;\"\u003e\n\u003cstyle\u003e\n  @keyframes v60PulsePhase {\n    0%   { transform: scale(1);    box-shadow: 0 0 0 0 rgba(200,169,126,.35); }\n    50%  { transform: scale(1.06); box-shadow: 0 0 0 10px rgba(200,169,126,0); }\n    100% { transform: scale(1);    box-shadow: 0 0 0 0 rgba(200,169,126,0); }\n  }\n  .v60-pulse {\n    animation: v60PulsePhase 700ms ease-out 1;\n    transform-origin: center;\n    will-change: transform;\n  }\n  @keyframes v60BlinkPill {\n    0%, 100% { opacity: 1; transform: scale(1); }\n    50%      { opacity: .22; transform: scale(1.03); }\n  }\n  .v60-pill-pour-active {\n    background: #ffe7b7 !important;\n    border: 2px solid #d2a44a !important;\n    color: #3b2a12 !important;\n    font-weight: 900 !important;\n    letter-spacing: .02em;\n    animation: v60BlinkPill 2500ms ease-in-out infinite;\n    box-shadow:\n      0 0 0 2px rgba(210,164,74,.18) inset,\n      0 10px 22px rgba(0,0,0,.12),\n      0 0 0 6px rgba(210,164,74,.10);\n  }\n  @media (prefers-reduced-motion: reduce) {\n    .v60-pill-pour-active { animation: none; }\n    .v60-pulse { animation: none; }\n  }\n\u003c\/style\u003e\n\u003cscript\u003e\n(function() {\n  var SUFFIX = '-kiangoi';\n  var END_AT = 165;\n  var phases = [\n    { key: 1, t: 0, pourLen: 10 },\n    { key: 2, t: 40, pourLen: 10 },\n    { key: 3, t: 80, pourLen: 10 },\n    { key: 4, t: 115, pourLen: 10 }\n  ];\n  var latte = {\n    cardBg:     '#f6f1ea',\n    cardBorder: '#c8a97e',\n    pillBg:     '#eadfce'\n  };\n  var details  = document.getElementById('v60Details'    + SUFFIX);\n  var startBtn = document.getElementById('v60StartBtn'   + SUFFIX);\n  var stopBtn  = document.getElementById('v60StopBtn'    + SUFFIX);\n  var timerEl  = document.getElementById('v60Timer'      + SUFFIX);\n  var statusEl = document.getElementById('v60WakeStatus' + SUFFIX);\n  var pills = {\n    1: document.getElementById('v60-pill-1' + SUFFIX),\n    2: document.getElementById('v60-pill-2' + SUFFIX),\n    3: document.getElementById('v60-pill-3' + SUFFIX),\n    4: document.getElementById('v60-pill-4' + SUFFIX)\n  };\n  var cards = {\n    1: document.getElementById('v60-card-1' + SUFFIX),\n    2: document.getElementById('v60-card-2' + SUFFIX),\n    3: document.getElementById('v60-card-3' + SUFFIX),\n    4: document.getElementById('v60-card-4' + SUFFIX)\n  };\n  function setCardActive(key) {\n    Object.keys(cards).forEach(function(k) {\n      var c = cards[k];\n      if (!c) return;\n      if (parseInt(k) === key) {\n        c.style.borderColor = latte.cardBorder;\n        c.style.background  = latte.cardBg;\n        c.style.boxShadow   = '0 0 0 2px rgba(200,169,126,.25) inset, 0 8px 22px rgba(200,169,126,.28)';\n      } else {\n        c.style.borderColor = 'rgba(0,0,0,.18)';\n        c.style.background  = 'transparent';\n        c.style.boxShadow   = 'none';\n      }\n    });\n  }\n  function setPillPhaseActive(key, doPulse) {\n    Object.keys(pills).forEach(function(k) {\n      var p = pills[k];\n      if (!p) return;\n      p.style.background  = 'rgba(0,0,0,.05)';\n      p.style.borderColor = 'rgba(0,0,0,.12)';\n      p.style.boxShadow   = 'none';\n      p.classList.remove('v60-pulse');\n    });\n    var pill = pills[key];\n    if (pill) {\n      pill.style.background  = latte.pillBg;\n      pill.style.borderColor = latte.cardBorder;\n      pill.style.boxShadow   = '0 0 0 2px rgba(200,169,126,.25) inset';\n      if (doPulse) {\n        pill.classList.remove('v60-pulse');\n        void pill.offsetWidth;\n        pill.classList.add('v60-pulse');\n      }\n    }\n  }\n  function resetPourPills() {\n    Object.values(pills).forEach(function(p) {\n      if (!p) return;\n      p.classList.remove('v60-pill-pour-active');\n    });\n  }\n  function setPourPillActive(key) {\n    resetPourPills();\n    if (!key) return;\n    var pill = pills[key];\n    if (pill) pill.classList.add('v60-pill-pour-active');\n  }\n  function clearAll() {\n    Object.values(cards).forEach(function(c) {\n      if (!c) return;\n      c.style.borderColor = 'rgba(0,0,0,.18)';\n      c.style.background  = 'transparent';\n      c.style.boxShadow   = 'none';\n    });\n    Object.values(pills).forEach(function(p) {\n      if (!p) return;\n      p.style.background  = 'rgba(0,0,0,.05)';\n      p.style.borderColor = 'rgba(0,0,0,.12)';\n      p.style.boxShadow   = 'none';\n      p.classList.remove('v60-pulse');\n      p.classList.remove('v60-pill-pour-active');\n    });\n  }\n  var wakeLock  = null;\n  var startTime = null;\n  var rafId     = null;\n  var lastPhaseKey = null;\n  var lastPourKey  = null;\n  function fmt(sec) {\n    sec = Math.max(0, Math.floor(sec));\n    var m = Math.floor(sec \/ 60);\n    var s = sec % 60;\n    return m + ':' + (s \u0026lt; 10 ? '0' : '') + s;\n  }\n  function getCurrentPhaseKey(elapsed) {\n    var current = phases[0].key;\n    for (var i = 0; i \u0026lt; phases.length; i++) if (elapsed \u0026gt;= phases[i].t) current = phases[i].key;\n    return current;\n  }\n  function getPourKey(elapsed) {\n    for (var i = phases.length - 1; i \u0026gt;= 0; i--) {\n      var p = phases[i];\n      if (elapsed \u0026gt;= p.t \u0026amp;\u0026amp; elapsed \u0026lt; (p.t + p.pourLen)) return p.key;\n    }\n    return null;\n  }\n  function enableWakeLock() {\n    if (!('wakeLock' in navigator)) {\n      statusEl.textContent = '⚠️ Ton navigateur ne supporte pas le mode écran allumé.';\n      return Promise.resolve();\n    }\n    return navigator.wakeLock.request('screen').then(function(wl) {\n      wakeLock = wl;\n      statusEl.textContent = '✅ Écran maintenu allumé pendant la recette.';\n      wakeLock.addEventListener('release', function() {\n        statusEl.textContent = 'ℹ️ Mode écran allumé relâché.';\n      });\n    }).catch(function() {\n      statusEl.textContent = '⚠️ Impossible d\\'activer le mode écran allumé.';\n      wakeLock = null;\n    });\n  }\n  function disableWakeLock() {\n    if (wakeLock) { wakeLock.release(); wakeLock = null; }\n  }\n  function setButtons(running) {\n    startBtn.disabled = running;\n    stopBtn.disabled  = !running;\n    stopBtn.style.opacity = running ? '1' : '.5';\n  }\n  function tick() {\n    var elapsed = (Date.now() - startTime) \/ 1000;\n    timerEl.textContent = fmt(elapsed);\n    var phaseKey = getCurrentPhaseKey(elapsed);\n    if (phaseKey !== lastPhaseKey) {\n      setCardActive(phaseKey);\n      setPillPhaseActive(phaseKey, lastPhaseKey !== null);\n      lastPhaseKey = phaseKey;\n    }\n    var pourKey = getPourKey(elapsed);\n    if (pourKey !== lastPourKey) {\n      setPourPillActive(pourKey);\n      lastPourKey = pourKey;\n    }\n    if (elapsed \u0026gt;= END_AT) { stopRecipe(true); return; }\n    rafId = requestAnimationFrame(tick);\n  }\n  function startRecipe() {\n    setButtons(true);\n    timerEl.textContent = '0:00';\n    lastPhaseKey = null;\n    lastPourKey  = null;\n    enableWakeLock().then(function() {\n      setCardActive(1);\n      setPillPhaseActive(1, false);\n      setPourPillActive(1);\n      lastPhaseKey = 1;\n      lastPourKey  = 1;\n      startTime = Date.now();\n      if (rafId) cancelAnimationFrame(rafId);\n      rafId = requestAnimationFrame(tick);\n    });\n  }\n  function stopRecipe(autoEnded) {\n    if (rafId) cancelAnimationFrame(rafId);\n    rafId     = null;\n    startTime = null;\n    disableWakeLock();\n    setButtons(false);\n    clearAll();\n    lastPhaseKey = null;\n    lastPourKey  = null;\n    if (autoEnded) {\n      statusEl.textContent = '✅ Recette terminée — écran libéré.';\n      timerEl.textContent  = fmt(END_AT);\n    } else {\n      statusEl.textContent = 'ℹ️ Recette arrêtée — écran libéré.';\n    }\n  }\n  startBtn.addEventListener('click', startRecipe);\n  stopBtn.addEventListener('click', function() { stopRecipe(false); });\n  details.addEventListener('toggle', function() { if (!details.open) stopRecipe(false); });\n  document.addEventListener('visibilitychange', function() {\n    if (document.visibilityState === 'visible' \u0026amp;\u0026amp; startTime \u0026amp;\u0026amp; !wakeLock) enableWakeLock();\n  });\n})();\n\u003c\/script\u003e\n\u003c\/svg\u003e\n","brand":"ZAB","offers":[{"title":"250g","offer_id":53629325312309,"sku":"CAF-SIN-RUNG-250","price":32.0,"currency_code":"CAD","in_stock":true},{"title":"808g","offer_id":53629325345077,"sku":"CAF-SIN-RUNG-808","price":90.0,"currency_code":"CAD","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/2716\/1842\/files\/kiangoi-250g-new.jpg?v=1793544333"},{"product_id":"colombie-augusto-ortega","title":"COLOMBIE - AUGUSTO ORTEGA","description":"\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 1 : NOTES DE DÉGUSTATION\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto; border: 2px solid var(--product-box-background, #000); border-radius: 12px; overflow: hidden;\"\u003e\n\u003cdiv style=\"padding: 10px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center;\"\u003eNotes de dégustation\u003c\/div\u003e\n\u003cdiv style=\"padding: 16px 14px; font-weight: 900; text-transform: uppercase; font-size: 28px; letter-spacing: .05em; text-align: center; background: transparent;\"\u003eNECTARINE BLANCHE + MELON MIEL + FLORAL + SUCRE DE CANNE\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 1 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003cdiv style=\"position: relative; width: 100%; padding-bottom: 56.25%; height: 0; overflow: hidden; border-radius: 8px;\"\u003e\u003ciframe style=\"position: absolute; top: 0; left: 0; width: 100%; height: 100%; border: 0; border-radius: 8px;\" src=\"https:\/\/www.youtube.com\/embed\/I9VhuDSxBl8\" title=\"YouTube video player\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" allowfullscreen=\"\"\u003e\n\u003c\/iframe\u003e\u003c\/div\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 2 : APPROVISIONNEMENT\n========================================================= --\u003e\n\u003cdiv style=\"display: flex; flex-wrap: wrap; gap: 12px; align-items: stretch; width: 100%; margin: 0 auto 12px auto;\"\u003e\n\u003cdiv class=\"photo-producteur\" style=\"flex: 1 1 220px; max-width: 100%;\"\u003e\u003cimg src=\"https:\/\/cdn.shopify.com\/s\/files\/1\/2716\/1842\/files\/2026-11-01-augusto-ortega-producteur.jpg?v=1793545354\" alt=\"Augusto Ortega tenant une feuille de caféier dans sa plantation, à San Agustín en Colombie\" width=\"900\" height=\"1200\" loading=\"lazy\" style=\"display: block; width: 100%; height: 100%; min-height: 280px; object-fit: cover; object-position: 15% center; border: 2px solid var(--product-box-background, #000); border-radius: 12px;\"\u003e\u003c\/div\u003e\n\u003cdiv style=\"flex: 2 1 320px; min-width: 0;\"\u003e\n\u003cdiv style=\"width: 100%; margin: 0;\"\u003e\n\u003cdiv style=\"padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center; border-radius: 12px 12px 0 0;\"\u003eApprovisionnement\u003c\/div\u003e\n\u003ctable border=\"3\" cellpadding=\"1\" cellspacing=\"1\" style=\"width: 100%; border-collapse: collapse; background: transparent;\"\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd style=\"width: 20%;\"\u003eORIGINE\u003c\/td\u003e\n\u003ctd\u003eVillage de Kennedy, Municipalité de San Agustin, Département de Huila, Colombie\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePRODUCTEURS\u003c\/td\u003e\n\u003ctd\u003eAugusto Ortega\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eFERME\u003c\/td\u003e\n\u003ctd\u003eFinca Las Asturias\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eVARIÉTÉ\u003c\/td\u003e\n\u003ctd\u003eSidra\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePROCÉDÉ\u003c\/td\u003e\n\u003ctd\u003eLavé\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eALTITUDE\u003c\/td\u003e\n\u003ctd\u003e1680 m\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePARTENAIRES\u003c\/td\u003e\n\u003ctd\u003eSemilla et Monkaaba\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eVOLUME ACHETÉ\u003c\/td\u003e\n\u003ctd\u003e180 kg\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eFAB\u003c\/td\u003e\n\u003ctd\u003e8,27 $ US\/lb\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePRIX LIVRÉ\u003c\/td\u003e\n\u003ctd\u003e15,55 $ CAD\/LB\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePRIX FARMGATE\u003c\/td\u003e\n\u003ctd\u003e5 000 000 $COP \/ Carga\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eRELATION\u003c\/td\u003e\n\u003ctd\u003e3 ans\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003c\/tbody\u003e\n\u003c\/table\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 2 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 3 : INFORMATIONS SUR LE CAFÉ\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto;\"\u003e\n\u003cdiv style=\"padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center; border-radius: 12px 12px 0 0;\"\u003eInformations sur le café\u003c\/div\u003e\n\u003cdiv style=\"border: 2px solid var(--product-box-background, #000); border-top: none; border-radius: 0 0 12px 12px; padding: 16px 14px; background: transparent;\"\u003e\n\u003cp style=\"margin: 0 0 12px 0;\"\u003eUn café délicat qui s’ouvre sur des arômes floraux et de fruits à noyau, comme la nectarine blanche. En refroidissant, il dévoile une douceur de melon miel et de sucre de canne, accompagnée d’une texture soyeuse. Son acidité, qui rappelle la pomme et la poire, lui apporte une belle vivacité.\u003c\/p\u003e\n\u003cp style=\"margin: 0 0 12px 0;\"\u003eAugusto a fondé Finca Las Asturias en 1985, devenant l’un des premier·ère·s producteur·rice·s de café de sa région, malgré les défis liés aux sols arides et aux glissements de terrain. C’est en 2000 qu’il s’est tourné vers le café de spécialité. Aujourd’hui, Augusto joue un rôle clé dans le développement de Semilla, notre importateur de café, à San Agustín. Respecté dans sa communauté, il a contribué à rapprocher de nombreu·ses producteur·rice·s du projet et à bâtir des relations fondées sur la confiance.\u003c\/p\u003e\n\u003cp style=\"margin: 0 0 12px 0;\"\u003ePour l’avenir, Augusto souhaite continuer à relever les défis de la caféiculture en plantant de nouvelles variétés et en encourageant le partage des connaissances et l’entraide entre producteur·rice·s.\u003c\/p\u003e\n\u003cp style=\"margin: 0;\"\u003eCe café est rendu possible grâce au travail de Semilla comme importateur et de Monkaaba à l’origine. Basée à San Agustín, en Colombie, Monkaaba est une initiative menée par Esnaider Ortega Gómez qui accompagne les producteur·rice·s de café dans le développement de leur savoir-faire et l’accès à de meilleurs marchés. Par le partage de connaissances et des séances de dégustation collectives, Monkaaba favorise leur autonomie et des relations plus durables dans la filière du café de spécialité. Semilla soutient cette démarche en créant des liens entre les producteur·rice·s et les torréfacteur·rice·s.\u003c\/p\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 3 ========= --\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!-- =========================================================\n  SECTION 4 : V60\n========================================================= --\u003e\n\u003cdiv style=\"width: 100%; margin: 0 auto;\"\u003e\n\u003cdetails id=\"v60Details-augustoortega\" open=\"\" style=\"border: 2px solid var(--product-box-background, #000); border-radius: 12px; overflow: hidden; margin: 0 0 12px 0; background: rgba(255,255,255,0.5);\"\u003e\n\u003csummary style=\"cursor: pointer; list-style: none; padding: 12px 14px; font-weight: 800; text-transform: uppercase; font-size: 14px; letter-spacing: .02em; background: var(--product-box-background, #000); color: var(--product-box-text, #fff); text-align: center;\"\u003eV60 – Recette\u003c\/summary\u003e\n\u003cdiv style=\"padding: 12px 14px;\"\u003e\n\u003cdiv style=\"padding: 10px 0 10px; border-bottom: 1px solid rgba(0,0,0,.2);\"\u003e\n\u003cdiv style=\"font-weight: 900; font-size: 16px;\"\u003eRatio 1:15\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 4px; opacity: .7; font-size: 13px;\"\u003e15 g in – 225 g out\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 6px; font-size: 13px;\"\u003e\n\u003cstrong\u003eTempérature de l'eau :\u003c\/strong\u003e 91 °C\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; padding: 10px 0 8px;\"\u003e\n\u003cdiv style=\"display: flex; gap: 8px; align-items: center; flex-wrap: wrap;\"\u003e\n\u003cbutton style=\"cursor: pointer; border: 2px solid var(--product-box-background, #000); background: var(--product-box-background, #000); color: var(--product-box-text, #fff); font-weight: 900; padding: 8px 10px; border-radius: 10px; text-transform: uppercase; letter-spacing: .02em; font-size: 12px;\" type=\"button\" id=\"v60StartBtn-augustoortega\"\u003eDémarrer\u003c\/button\u003e \u003cbutton style=\"cursor: pointer; border: 2px solid var(--product-box-background, #000); background: var(--product-box-text, #fff); color: var(--product-box-background, #000); font-weight: 900; padding: 8px 10px; border-radius: 10px; text-transform: uppercase; letter-spacing: .02em; font-size: 12px; opacity: .5;\" disabled type=\"button\" id=\"v60StopBtn-augustoortega\"\u003eStop\u003c\/button\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; line-height: 1;\"\u003e\n\u003cspan style=\"opacity: .70; font-size: 12px; font-weight: 800; text-transform: uppercase; letter-spacing: .04em;\"\u003eTimer\u003c\/span\u003e \u003cspan style=\"font-weight: 950; font-size: 28px; letter-spacing: .01em;\" id=\"v60Timer-augustoortega\"\u003e0:00\u003c\/span\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"flex-basis: 100%; opacity: .6; font-size: 12px; line-height: 1.3; margin-top: 2px;\" id=\"v60WakeStatus-augustoortega\"\u003eℹ️ Appuie sur \"Démarrer\" pour garder l'écran allumé.\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 8px; display: grid; gap: 10px;\"\u003e\n\u003cdiv style=\"border: 1px solid rgba(0,0,0,.18); border-radius: 12px; padding: 10px 12px;\" id=\"v60-card-1-augustoortega\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; margin-bottom: 6px;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e0:00\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003ePhase 1 — Bloom\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 8px; flex-wrap: wrap; font-size: 12.5px; font-weight: 800;\"\u003e\n\u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\" id=\"v60-pill-1-augustoortega\"\u003eVerser pendant 0:10s\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\"\u003eTotal 40 g\u003c\/span\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"border: 1px solid rgba(0,0,0,.18); border-radius: 12px; padding: 10px 12px;\" id=\"v60-card-2-augustoortega\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; margin-bottom: 6px;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e0:40\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003ePhase 2\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 8px; flex-wrap: wrap; font-size: 12.5px; font-weight: 800;\"\u003e\n\u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\" id=\"v60-pill-2-augustoortega\"\u003eVerser pendant 0:10s\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\"\u003eTotal 100 g\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12); opacity: .6;\"\u003e+60 g\u003c\/span\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"border: 1px solid rgba(0,0,0,.18); border-radius: 12px; padding: 10px 12px;\" id=\"v60-card-3-augustoortega\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; margin-bottom: 6px;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e1:20\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003ePhase 3\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 8px; flex-wrap: wrap; font-size: 12.5px; font-weight: 800;\"\u003e\n\u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\" id=\"v60-pill-3-augustoortega\"\u003eVerser pendant 0:10s\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\"\u003eTotal 170 g\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12); opacity: .6;\"\u003e+70 g\u003c\/span\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"border: 1px solid rgba(0,0,0,.18); border-radius: 12px; padding: 10px 12px;\" id=\"v60-card-4-augustoortega\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline; margin-bottom: 6px;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e1:55\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003ePhase 4\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"display: flex; gap: 8px; flex-wrap: wrap; font-size: 12.5px; font-weight: 800;\"\u003e\n\u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\" id=\"v60-pill-4-augustoortega\"\u003eVerser pendant 0:10s\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12);\"\u003eTotal 225 g\u003c\/span\u003e \u003cspan style=\"padding: 5px 9px; border-radius: 999px; background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.12); opacity: .6;\"\u003e+55 g\u003c\/span\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 12px; border-top: 1px solid rgba(0,0,0,.2); padding-top: 10px;\"\u003e\n\u003cdiv style=\"display: flex; gap: 10px; align-items: baseline;\"\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003e2:30\u003c\/div\u003e\n\u003cdiv style=\"font-weight: 900;\"\u003eTemps final écoulement complet\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv style=\"margin-top: 8px; padding: 8px 10px; border-radius: 8px; background: rgba(0,0,0,.04); border: 1px dashed rgba(0,0,0,.2); font-size: 12px; opacity: .6; line-height: 1.4;\"\u003e\n\u003cstrong\u003eℹ️ Astuce —\u003c\/strong\u003e Si le temps total est plus court, la mouture est probablement trop grosse. S'il est plus long, la mouture est probablement trop fine.\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/details\u003e\n\u003c\/div\u003e\n\u003c!-- ========= FIN SECTION 4 ========= --\u003e\u003csvg style=\"display: none;\"\u003e\n\u003cstyle\u003e\n  @keyframes v60PulsePhase {\n    0%   { transform: scale(1);    box-shadow: 0 0 0 0 rgba(200,169,126,.35); }\n    50%  { transform: scale(1.06); box-shadow: 0 0 0 10px rgba(200,169,126,0); }\n    100% { transform: scale(1);    box-shadow: 0 0 0 0 rgba(200,169,126,0); }\n  }\n  .v60-pulse {\n    animation: v60PulsePhase 700ms ease-out 1;\n    transform-origin: center;\n    will-change: transform;\n  }\n  @keyframes v60BlinkPill {\n    0%, 100% { opacity: 1; transform: scale(1); }\n    50%      { opacity: .22; transform: scale(1.03); }\n  }\n  .v60-pill-pour-active {\n    background: #ffe7b7 !important;\n    border: 2px solid #d2a44a !important;\n    color: #3b2a12 !important;\n    font-weight: 900 !important;\n    letter-spacing: .02em;\n    animation: v60BlinkPill 2500ms ease-in-out infinite;\n    box-shadow:\n      0 0 0 2px rgba(210,164,74,.18) inset,\n      0 10px 22px rgba(0,0,0,.12),\n      0 0 0 6px rgba(210,164,74,.10);\n  }\n  @media (prefers-reduced-motion: reduce) {\n    .v60-pill-pour-active { animation: none; }\n    .v60-pulse { animation: none; }\n  }\n\u003c\/style\u003e\n\u003cscript\u003e\n(function() {\n  var SUFFIX = '-augustoortega';\n  var END_AT = 150;\n  var phases = [\n    { key: 1, t: 0, pourLen: 10 },\n    { key: 2, t: 40, pourLen: 10 },\n    { key: 3, t: 80, pourLen: 10 },\n    { key: 4, t: 115, pourLen: 10 }\n  ];\n  var latte = {\n    cardBg:     '#f6f1ea',\n    cardBorder: '#c8a97e',\n    pillBg:     '#eadfce'\n  };\n  var details  = document.getElementById('v60Details'    + SUFFIX);\n  var startBtn = document.getElementById('v60StartBtn'   + SUFFIX);\n  var stopBtn  = document.getElementById('v60StopBtn'    + SUFFIX);\n  var timerEl  = document.getElementById('v60Timer'      + SUFFIX);\n  var statusEl = document.getElementById('v60WakeStatus' + SUFFIX);\n  var pills = {\n    1: document.getElementById('v60-pill-1' + SUFFIX),\n    2: document.getElementById('v60-pill-2' + SUFFIX),\n    3: document.getElementById('v60-pill-3' + SUFFIX),\n    4: document.getElementById('v60-pill-4' + SUFFIX)\n  };\n  var cards = {\n    1: document.getElementById('v60-card-1' + SUFFIX),\n    2: document.getElementById('v60-card-2' + SUFFIX),\n    3: document.getElementById('v60-card-3' + SUFFIX),\n    4: document.getElementById('v60-card-4' + SUFFIX)\n  };\n  function setCardActive(key) {\n    Object.keys(cards).forEach(function(k) {\n      var c = cards[k];\n      if (!c) return;\n      if (parseInt(k) === key) {\n        c.style.borderColor = latte.cardBorder;\n        c.style.background  = latte.cardBg;\n        c.style.boxShadow   = '0 0 0 2px rgba(200,169,126,.25) inset, 0 8px 22px rgba(200,169,126,.28)';\n      } else {\n        c.style.borderColor = 'rgba(0,0,0,.18)';\n        c.style.background  = 'transparent';\n        c.style.boxShadow   = 'none';\n      }\n    });\n  }\n  function setPillPhaseActive(key, doPulse) {\n    Object.keys(pills).forEach(function(k) {\n      var p = pills[k];\n      if (!p) return;\n      p.style.background  = 'rgba(0,0,0,.05)';\n      p.style.borderColor = 'rgba(0,0,0,.12)';\n      p.style.boxShadow   = 'none';\n      p.classList.remove('v60-pulse');\n    });\n    var pill = pills[key];\n    if (pill) {\n      pill.style.background  = latte.pillBg;\n      pill.style.borderColor = latte.cardBorder;\n      pill.style.boxShadow   = '0 0 0 2px rgba(200,169,126,.25) inset';\n      if (doPulse) {\n        pill.classList.remove('v60-pulse');\n        void pill.offsetWidth;\n        pill.classList.add('v60-pulse');\n      }\n    }\n  }\n  function resetPourPills() {\n    Object.values(pills).forEach(function(p) {\n      if (!p) return;\n      p.classList.remove('v60-pill-pour-active');\n    });\n  }\n  function setPourPillActive(key) {\n    resetPourPills();\n    if (!key) return;\n    var pill = pills[key];\n    if (pill) pill.classList.add('v60-pill-pour-active');\n  }\n  function clearAll() {\n    Object.values(cards).forEach(function(c) {\n      if (!c) return;\n      c.style.borderColor = 'rgba(0,0,0,.18)';\n      c.style.background  = 'transparent';\n      c.style.boxShadow   = 'none';\n    });\n    Object.values(pills).forEach(function(p) {\n      if (!p) return;\n      p.style.background  = 'rgba(0,0,0,.05)';\n      p.style.borderColor = 'rgba(0,0,0,.12)';\n      p.style.boxShadow   = 'none';\n      p.classList.remove('v60-pulse');\n      p.classList.remove('v60-pill-pour-active');\n    });\n  }\n  var wakeLock  = null;\n  var startTime = null;\n  var rafId     = null;\n  var lastPhaseKey = null;\n  var lastPourKey  = null;\n  function fmt(sec) {\n    sec = Math.max(0, Math.floor(sec));\n    var m = Math.floor(sec \/ 60);\n    var s = sec % 60;\n    return m + ':' + (s \u0026lt; 10 ? '0' : '') + s;\n  }\n  function getCurrentPhaseKey(elapsed) {\n    var current = phases[0].key;\n    for (var i = 0; i \u0026lt; phases.length; i++) if (elapsed \u0026gt;= phases[i].t) current = phases[i].key;\n    return current;\n  }\n  function getPourKey(elapsed) {\n    for (var i = phases.length - 1; i \u0026gt;= 0; i--) {\n      var p = phases[i];\n      if (elapsed \u0026gt;= p.t \u0026amp;\u0026amp; elapsed \u0026lt; (p.t + p.pourLen)) return p.key;\n    }\n    return null;\n  }\n  function enableWakeLock() {\n    if (!('wakeLock' in navigator)) {\n      statusEl.textContent = '⚠️ Ton navigateur ne supporte pas le mode écran allumé.';\n      return Promise.resolve();\n    }\n    return navigator.wakeLock.request('screen').then(function(wl) {\n      wakeLock = wl;\n      statusEl.textContent = '✅ Écran maintenu allumé pendant la recette.';\n      wakeLock.addEventListener('release', function() {\n        statusEl.textContent = 'ℹ️ Mode écran allumé relâché.';\n      });\n    }).catch(function() {\n      statusEl.textContent = '⚠️ Impossible d\\'activer le mode écran allumé.';\n      wakeLock = null;\n    });\n  }\n  function disableWakeLock() {\n    if (wakeLock) { wakeLock.release(); wakeLock = null; }\n  }\n  function setButtons(running) {\n    startBtn.disabled = running;\n    stopBtn.disabled  = !running;\n    stopBtn.style.opacity = running ? '1' : '.5';\n  }\n  function tick() {\n    var elapsed = (Date.now() - startTime) \/ 1000;\n    timerEl.textContent = fmt(elapsed);\n    var phaseKey = getCurrentPhaseKey(elapsed);\n    if (phaseKey !== lastPhaseKey) {\n      setCardActive(phaseKey);\n      setPillPhaseActive(phaseKey, lastPhaseKey !== null);\n      lastPhaseKey = phaseKey;\n    }\n    var pourKey = getPourKey(elapsed);\n    if (pourKey !== lastPourKey) {\n      setPourPillActive(pourKey);\n      lastPourKey = pourKey;\n    }\n    if (elapsed \u0026gt;= END_AT) { stopRecipe(true); return; }\n    rafId = requestAnimationFrame(tick);\n  }\n  function startRecipe() {\n    setButtons(true);\n    timerEl.textContent = '0:00';\n    lastPhaseKey = null;\n    lastPourKey  = null;\n    enableWakeLock().then(function() {\n      setCardActive(1);\n      setPillPhaseActive(1, false);\n      setPourPillActive(1);\n      lastPhaseKey = 1;\n      lastPourKey  = 1;\n      startTime = Date.now();\n      if (rafId) cancelAnimationFrame(rafId);\n      rafId = requestAnimationFrame(tick);\n    });\n  }\n  function stopRecipe(autoEnded) {\n    if (rafId) cancelAnimationFrame(rafId);\n    rafId     = null;\n    startTime = null;\n    disableWakeLock();\n    setButtons(false);\n    clearAll();\n    lastPhaseKey = null;\n    lastPourKey  = null;\n    if (autoEnded) {\n      statusEl.textContent = '✅ Recette terminée — écran libéré.';\n      timerEl.textContent  = fmt(END_AT);\n    } else {\n      statusEl.textContent = 'ℹ️ Recette arrêtée — écran libéré.';\n    }\n  }\n  startBtn.addEventListener('click', startRecipe);\n  stopBtn.addEventListener('click', function() { stopRecipe(false); });\n  details.addEventListener('toggle', function() { if (!details.open) stopRecipe(false); });\n  document.addEventListener('visibilitychange', function() {\n    if (document.visibilityState === 'visible' \u0026amp;\u0026amp; startTime \u0026amp;\u0026amp; !wakeLock) enableWakeLock();\n  });\n})();\n\u003c\/script\u003e\n\u003c\/svg\u003e\n","brand":"ZAB","offers":[{"title":"200g","offer_id":53634220687669,"sku":"CAF-SIN-AUGU-200","price":32.0,"currency_code":"CAD","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/2716\/1842\/files\/augusto-ortega-200g-new.jpg?v=1793544436"}],"url":"https:\/\/zabcafe.com\/collections\/meilleurs-vendeurs.oembed","provider":"Zab Café","version":"1.0","type":"link"}