{"product_id":"colombie-fidencio-castillo-1","title":"COLOMBIA - FIDENCIO CASTILLO","description":"\u003cp\u003e \u003c\/p\u003e\n\n\u003c!-- =========================================================\n  SECTION 1 : TASTING NOTES\n========================================================= --\u003e\n\n\u003cdiv style=\"width: 100%; margin: 0 auto 12px auto; border: 2px solid #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: #000; color: #fff; text-align: center;\"\u003eTasting Notes\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;\"\u003eBLUEBERRY JAM + RASPBERRY + COCOA + BROWN SUGAR\u003c\/div\u003e\n\u003c\/div\u003e\n\n\u003c!-- ========= END 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\/2JGq3eyeD5g?si=2FSLZ-zPJTCLshZO\" 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 : SOURCING\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: #000; color: #fff; text-align: center; border-radius: 12px 12px 0 0;\"\u003eSourcing\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%;\"\u003eORIGIN\u003c\/td\u003e\n        \u003ctd\u003eVillage of Berruecos, Municipality of Arboleda, Department of Nariño, Colombia\u003c\/td\u003e\n      \u003c\/tr\u003e\n      \u003ctr\u003e\n        \u003ctd\u003ePRODUCERS\u003c\/td\u003e\n        \u003ctd\u003eFidencio Castillo\u003c\/td\u003e\n      \u003c\/tr\u003e\n      \u003ctr\u003e\n        \u003ctd\u003eFARM\u003c\/td\u003e\n        \u003ctd\u003eEl Pedregal\u003c\/td\u003e\n      \u003c\/tr\u003e\n      \u003ctr\u003e\n        \u003ctd\u003eVARIETY\u003c\/td\u003e\n        \u003ctd\u003eCaturra, Colombia\u003c\/td\u003e\n      \u003c\/tr\u003e\n      \u003ctr\u003e\n        \u003ctd\u003ePROCESS\u003c\/td\u003e\n        \u003ctd\u003eHoney\u003c\/td\u003e\n      \u003c\/tr\u003e\n      \u003ctr\u003e\n        \u003ctd\u003eALTITUDE\u003c\/td\u003e\n        \u003ctd\u003e2036 m\u003c\/td\u003e\n      \u003c\/tr\u003e\n      \u003ctr\u003e\n        \u003ctd\u003ePARTNERS\u003c\/td\u003e\n        \u003ctd\u003eApex Coffee Imports\u003c\/td\u003e\n      \u003c\/tr\u003e\n      \u003ctr\u003e\n        \u003ctd\u003eVOLUME PURCHASED\u003c\/td\u003e\n        \u003ctd\u003e192 kg\u003c\/td\u003e\n      \u003c\/tr\u003e\n      \u003ctr\u003e\n        \u003ctd\u003eFOB\u003c\/td\u003e\n        \u003ctd\u003e$5.60 USD\/lb\u003c\/td\u003e\n      \u003c\/tr\u003e\n      \u003ctr\u003e\n        \u003ctd\u003eDELIVERED PRICE\u003c\/td\u003e\n        \u003ctd\u003e$12.10 CAD\/lb\u003c\/td\u003e\n      \u003c\/tr\u003e\n      \u003ctr\u003e\n        \u003ctd\u003eRELATIONSHIP\u003c\/td\u003e\n        \u003ctd\u003e2 years\u003c\/td\u003e\n      \u003c\/tr\u003e\n    \u003c\/tbody\u003e\n  \u003c\/table\u003e\n\u003c\/div\u003e\n\n\u003c!-- ========= END SECTION 2 ========= --\u003e\n\n\u003cp\u003e \u003c\/p\u003e\n\n\u003c!-- =========================================================\n  SECTION 3 : ABOUT THIS COFFEE\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: #000; color: #fff; text-align: center; border-radius: 12px 12px 0 0;\"\u003eAbout This Coffee\u003c\/div\u003e\n  \u003cdiv style=\"border: 2px solid #000; border-top: none; border-radius: 0 0 12px 12px; padding: 16px 14px; background: transparent;\"\u003e\n    \u003cp style=\"margin: 0 0 12px 0;\"\u003eFidencio gives us a highly complex and aromatic filter cup. You'll notice an acidity reminiscent of raspberry and pomegranate. The sweetness lingers on the palate, and the texture brings to mind chocolate syrup and dark sugar. As espresso, it's an explosion of flavour — blueberry jam up front, with a round body and a very juicy finish.\u003c\/p\u003e\n    \u003cp style=\"margin: 0 0 12px 0;\"\u003eNearly 30 years ago, Don Fidencio Castillo began his journey as a coffee grower, planting his first 1,500 trees of the Caturra and Colombia varieties. Today, no fewer than 20,000 trees are in full production — a success made possible by the unwavering support of his family: his wife Esmeralda and their five daughters, who have turned El Pedregal into a true family enterprise. Inspired by their father's passion for coffee, three of his daughters — including the talented producer Francy — went on to study agronomy and food processing.\u003c\/p\u003e\n    \u003cp style=\"margin: 0;\"\u003eFinca El Pedregal was a pioneer in coffee cultivation in Arboleda. At the time, neighbours weren't growing coffee because of the low temperatures, which could dip as low as 10 to 12 °C. Despite that challenge, the farm's rich ecosystem makes it an exceptional place for producing high-quality coffee. You'll taste the terroir immediately in the cup!\u003c\/p\u003e\n  \u003c\/div\u003e\n\u003c\/div\u003e\n\n\u003c!-- ========= END SECTION 3 ========= --\u003e\n\n\u003cp\u003e \u003c\/p\u003e\n\n\u003c!-- =========================================================\n  SECTION 4 : ESPRESSO PARAMETERS\n========================================================= --\u003e\n\n\u003cdiv style=\"width: 100%; margin: 0 auto;\"\u003e\n  \u003cdetails open=\"\" style=\"border: 2px solid #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: #000; color: #fff; text-align: center;\"\u003eEspresso — Recommended Parameters\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);\"\u003eGround coffee\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);\"\u003eCoffee in the cup\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;\"\u003eExtraction time\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\u003eNote —\u003c\/strong\u003e Recipe optimized for an \u003cstrong\u003e18 g\u003c\/strong\u003e basket. Consult your machine's manual to find the capacity of your portafilter basket.\u003c\/div\u003e\n    \u003c\/div\u003e\n  \u003c\/details\u003e\n\u003c\/div\u003e\n\n\u003c!-- ========= END 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-elpedregal\" open=\"\" style=\"border: 2px solid #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: #000; color: #fff; text-align: center;\"\u003eV60 – Recipe\u003c\/summary\u003e\n    \u003cdiv style=\"padding: 12px 14px;\"\u003e\n\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\u003cstrong\u003eWater temperature:\u003c\/strong\u003e 90 °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 #000; background: #000; color: #fff; font-weight: 900; padding: 8px 10px; border-radius: 10px; text-transform: uppercase; letter-spacing: .02em; font-size: 12px;\" type=\"button\" id=\"v60StartBtn-elpedregal\"\u003eStart\u003c\/button\u003e\n          \u003cbutton style=\"cursor: pointer; border: 2px solid #000; background: #fff; color: #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-elpedregal\"\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-elpedregal\"\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-elpedregal\"\u003eℹ️ Press \"Start\" to keep your screen on.\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-elpedregal\"\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-elpedregal\"\u003ePour for 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 40 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-elpedregal\"\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-elpedregal\"\u003ePour for 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 160 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+120 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-3-elpedregal\"\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-elpedregal\"\u003ePour for 0:20s\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+65 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:45\u003c\/div\u003e\n          \u003cdiv style=\"font-weight: 900;\"\u003eTarget total drawdown time\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ℹ️ Tip —\u003c\/strong\u003e If the total time is shorter, your grind is likely too coarse. If it's longer, your grind is likely too fine.\u003c\/div\u003e\n      \u003c\/div\u003e\n\n    \u003c\/div\u003e\n  \u003c\/details\u003e\n\u003c\/div\u003e\n\n\u003c!-- ========= END 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 {\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 = '-elpedregal';\n  var END_AT = 165; \/\/ 2m45\n\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\n  var latte = {\n    cardBg:     '#f6f1ea',\n    cardBorder: '#c8a97e',\n    pillBg:     '#eadfce'\n  };\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\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\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\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');\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\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\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\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\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 \u003c 10 ? '0' : '') + s;\n  }\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\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\n  function enableWakeLock() {\n    if (!('wakeLock' in navigator)) {\n      statusEl.textContent = '⚠️ Your browser does not support the wake lock feature.';\n      return Promise.resolve();\n    }\n    return navigator.wakeLock.request('screen').then(function(wl) {\n      wakeLock = wl;\n      statusEl.textContent = '✅ Screen kept on during the recipe.';\n      wakeLock.addEventListener('release', function() {\n        statusEl.textContent = 'ℹ️ Wake lock released.';\n      });\n    }).catch(function() {\n      statusEl.textContent = '⚠️ Unable to activate the wake lock.';\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\n    var phaseKey = getCurrentPhaseKey(elapsed);\n    if (phaseKey !== lastPhaseKey) {\n      setCardActive(phaseKey);\n      setPillPhaseActive(phaseKey, lastPhaseKey !== null);\n      lastPhaseKey = phaseKey;\n    }\n\n    var pourKey = getPourKey(elapsed);\n    if (pourKey !== lastPourKey) {\n      setPourPillActive(pourKey);\n      lastPourKey = pourKey;\n    }\n\n    if (elapsed \u003e= 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 = '✅ Recipe complete — screen released.';\n      timerEl.textContent  = fmt(END_AT);\n    } else {\n      statusEl.textContent = 'ℹ️ Recipe stopped — screen released.';\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' \u0026\u0026 startTime \u0026\u0026 !wakeLock) enableWakeLock();\n  });\n})();\n\u003c\/script\u003e\n\u003c\/svg\u003e","brand":"ZAB","offers":[{"title":"250g","offer_id":52931732898101,"sku":"CAF-SIN-FIDE-250","price":19.95,"currency_code":"EUR","in_stock":true},{"title":"808g","offer_id":52931732930869,"sku":"CAF-SIN-FIDE-808","price":55.95,"currency_code":"EUR","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/2716\/1842\/files\/fidencio-250g-new.jpg?v=1779894682","url":"https:\/\/zabcafe.com\/en\/products\/colombie-fidencio-castillo-1","provider":"Zab Café","version":"1.0","type":"link"}