<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
     xmlns:content="http://purl.org/rss/1.0/modules/content/"
     xmlns:dc="http://purl.org/dc/elements/1.1/"
     xmlns:dcterms="http://purl.org/dc/terms/"
     xmlns:media="http://search.yahoo.com/mrss/"
     xmlns:atom="http://www.w3.org/2005/Atom"
     xmlns:cf="https://www.futureplc.com/rss/content-flags"
>
    <channel>
                    <atom:link href="https://www.tomsguide.com/feeds/tag/home-appliances" rel="self" type="application/rss+xml" />
                            <title><![CDATA[ Latest from Tom's Guide in Home-appliances ]]></title>
                <link>https://www.tomsguide.com/home/home-appliances</link>
        <description><![CDATA[ All the latest home-appliances content from the Tom's Guide team ]]></description>
                                    <lastBuildDate>Thu, 10 Sep 2026 08:00:00 +0000</lastBuildDate>
                            <language>en</language>
                                <item>
                                                            <title><![CDATA[ I got a first look at Ooni’s Halo Core spiral mixer: Three things I love and one thing I don’t ]]></title>
                                                                                                <dc:content><![CDATA[ <p>When Ooni announced the new<a href="https://www.tomsguide.com/home/kitchen-dining/watch-out-kitchenaid-oonis-launching-its-second-stand-mixer-and-at-usd599-it-price-matches-the-artisan-pro"> Halo Core spiral mixer</a>, one thought immediately crossed my mind: KitchenAid is in for some serious competition. </p><p>Available for <a href="https://www.amazon.com/Ooni-Spiral-Dough-Mixer-Stand/dp/B0H5RCW4W2/ref=sr_1_1?">$599 at Amazon,</a> it hits the exact price as the iconic<a href="https://www.tomsguide.com/home/kitchenaid-artisan-plus-mixer-review"> KitchenAid Artisan Plus</a>, but offers a more compact and home-kitchen-friendly footprint than the high-end<a href="https://www.tomsguide.com/home/home-appliances/ooni-halo-pro-spiral-stand-mixer-review"> Ooni Halo Pro spiral mixer</a> — currently our top pick for bread making in our <a href="https://www.tomsguide.com/best-picks/best-stand-mixers">best standing mixer buying guide</a>.</p><p>While $599 is still a real investment, the Halo Core feels far more accessible than the Ooni Halo Pro, which is <a href="https://www.amazon.com/dp/B0F746CZ3L?">$799 at Amazon, </a>plus it won't take up as much countertop space in your kitchen.</p><p>I’ve been putting the Halo Core through its paces, and there’s a lot to like. I’ll follow up with a full review in a couple of weeks, but for now, here are three things I loved and one thing you should know.</p><div class="product"><a data-dimension112="a5697ee6-ac5f-11f1-9d67-15deb1193abc" data-action="Deal Block" data-label="Halo Core Spiral Mixer" data-dimension48="Halo Core Spiral Mixer" data-dimension25="$599" href="https://www.amazon.com/Ooni-Spiral-Dough-Mixer-Stand/dp/B0H5RCW4W2?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:424px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="wcvYr66Fer4q8dWMPz26jb" name="Ooni Halo Core stand mixer in Black" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/wcvYr66Fer4q8dWMPz26jb.png" mos="" align="middle" fullscreen="" width="424" height="424" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>The Ooni Halo Core spiral mixer uses the same dual-kneading action that pro bakers trust. The spiral dough hook and breaker bar work with the rotating bowl to build a strong gluten structure, resulting in a light, soft dough. The mixer also comes complete with a 4-8 qt bowl, a dual-geared whisk and an angled silicone edge beater for making cake batters, cookies and whisking cream and meringues. <a class="view-deal button" href="https://www.amazon.com/Ooni-Spiral-Dough-Mixer-Stand/dp/B0H5RCW4W2?" target="_blank" rel="nofollow" data-dimension112="a5697ee6-ac5f-11f1-9d67-15deb1193abc" data-action="Deal Block" data-label="Halo Core Spiral Mixer" data-dimension48="Halo Core Spiral Mixer" data-dimension25="$599">View Deal</a></p></div><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-Oajm5X"></div>                            </div>                            <script src="https://kwizly.com/embed/Oajm5X.js" async></script><h3 class="article-body__section" id="section-ooni-halo-core-spiral-mixer-what-i-like"><span>Ooni Halo Core spiral mixer: What I like</span></h3><h2 id="1-perfect-dough">1. Perfect dough</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="V3UWaYeKvCNTVk2UHEhaKe" name="Ooni Halo Core dough hook and breaker bar" alt="Ooni Halo Core dough hook and breaker bar" src="https://cdn.mos.cms.futurecdn.net/V3UWaYeKvCNTVk2UHEhaKe.png" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Camilla Sharman)</span></figcaption></figure><p>The Halo Core spiral mixer, like its older sibling, is designed specifically for bread making. Instead of the planetary stand mixers home bakers are used to, Ooni’s design brings professional-grade spiral mixing into our kitchens.</p><p>How does it work? The dough hook and bowl rotate around a breaker bar — a stationary vertical metal rod that sits in the mixing bowl. Although watching the rotating bowl is fun to watch, it’s not a gimmick.  </p><p>The breaker bar removes dough from the hook as it spins during mixing, preventing it from climbing up the dough hook and stopping you from pausing the mix to remove the dough. It also stretches the dough for a stronger gluten structure.</p><p>I’ve been experimenting with making bread and pizza dough, and although the pizza dough is currently proving in my kitchen, the bread tasted exceptional. In fact, my husband didn’t realize it was homemade. </p><p>I also found that the kneading process was smooth. The usual mixers I test move around my countertop when the dough hook is in action, and it almost seems like too much for the appliance’s motor. There was a clear difference when using the Ooni Halo Core. The mixer stayed steady, and there was no hint of any electric smell or the motor burning out. </p><h2 id="2-pause-and-go-again">2. Pause and go again</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="xvxCmZ72M4HgX76QvbkzgJ" name="Ooni Halo Core control" alt="Ooni Halo Core stand mixer control" src="https://cdn.mos.cms.futurecdn.net/xvxCmZ72M4HgX76QvbkzgJ.png" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Camilla Sharman)</span></figcaption></figure><p>The controls of the Halo Core work differently from any stand mixer I’ve previously tested, but in a good way. The control knob is positioned on top of the appliance, so it’s easy to access whether you’re right- or left-handed. What’s more, it works in percentages, with 20 speeds. Turn it clockwise once for 5% at 60 rpm, and turn it up to 100% for 300 rpm. </p><p>The control lights up in sections, so you can clearly see which speed setting you're on. This is quite clever in itself, but what impressed me more was that you can simply press the knob and the appliance will pause. Press it again, and it will start from where it left off. It may seem like a small thing, but I found it took away the hassle of turning down the speed when you want to pause the mix.</p><h2 id="3-double-whisk">3. Double whisk </h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="meZBSQFjrR6TbefkE39twD" name="Ooni Halo Core stand mixer" alt="Ooni Halo Core stand mixer" src="https://cdn.mos.cms.futurecdn.net/meZBSQFjrR6TbefkE39twD.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Camilla Sharman)</span></figcaption></figure><p>I’ve never made butter before, but since my colleague made butter with the Halo Pro, I followed suit. I started by attaching the dual-geared whisk attachment — it even has a built-in gearbox for rapid whipping! </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="3WnNedwWrnXHs2HuURMsVU" name="Ooni Halo Core stand mixer buttermilk separating" alt="Ooni Halo Core stand mixer buttermilk separating" src="https://cdn.mos.cms.futurecdn.net/3WnNedwWrnXHs2HuURMsVU.png" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Camilla Sharman)</span></figcaption></figure><p>The whisk really came into its own, whipping the heavy cream into what looked like scrambled eggs until the fat and buttermilk separated. Apart from the speed, it’s fascinating to watch, and if you’ve never made butter before, I recommend giving it a go. </p><p>The whisk attachment proved that the Halo Core isn’t just good at making dough; it has a firm place in the kitchen for other baking tasks. </p><h3 class="article-body__section" id="section-ooni-halo-core-spiral-mixer-what-i-don-t-like"><span>Ooni Halo Core spiral mixer: What I don't like</span></h3><h2 id="it-wasn-39-t-great-at-mixing-cake-batter">It wasn't great at mixing cake batter</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="ubR55uboGghEWXDKiHxLhD" name="Ooni Halo Core stand mixer" alt="Ooni Halo Core stand mixer" src="https://cdn.mos.cms.futurecdn.net/ubR55uboGghEWXDKiHxLhD.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Camilla Sharman)</span></figcaption></figure><p>After the whisk's success, I was excited to try the angled silicone-edge beater to make an all-in-one cake batter. I love the silicone beater I’ve used with the KitchenAid Artisan Plus, as it swipes around the edge of the bowl, incorporating the whole mixture — so you don’t need to stop midway through to scrape the ingredients off the side.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="kToJx2jJvD2CzLkw74AwjJ" name="Ooni Halo Core stand mixer cake batter" alt="Ooni Halo Core stand mixer making cake batter" src="https://cdn.mos.cms.futurecdn.net/kToJx2jJvD2CzLkw74AwjJ.png" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Camilla Sharman)</span></figcaption></figure><p>The Halo Core did the same, but it seemed to struggle to incorporate the butter into the mixture, even though it was soft when I added it to the bowl. Then, when I raised the mixer’s head, I noticed a large clump of butter was still attached to the beater. </p><p>I’m going to keep testing its cake-making ability, since other reviews have given it more positive results. So keep an eye out for my full review.</p><p><strong>Over to you</strong></p><p>Are you thinking about buying an Ooni mixer, or have you already invested in one? I’d love to read your thoughts and experiences in the comments below.</p><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h3><ul><li><a href="https://www.tomsguide.com/home/kitchenaid-vs-cuisinart-which-stand-mixer-is-best">KitchenAid vs Cuisinart: Which stand mixer is best?</a></li><li><a href="https://www.tomsguide.com/home/smegs-newest-stand-mixer-gives-kitchenaid-a-run-for-its-money-heres-why-it-won-me-over">Smeg’s newest retro stand mixer gives KitchenAid a run for its money — here’s why it won me over</a></li><li><a href="https://www.tomsguide.com/home/home-appliances/i-tested-oonis-new-rotating-stone-and-its-your-ticket-to-perfect-pizza-at-home">I tested Ooni's new Rotating Stone — and it's your ticket to perfect pizza at home</a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/home/home-appliances/i-got-a-first-look-at-oonis-halo-core-spiral-mixer-three-things-i-love-and-one-thing-i-dont</link>
                                                                            <description>
                            <![CDATA[ Ooni’s Halo Core Spiral Mixer is impressive, but it’s not quite perfect. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">yach34Xxmy7hnYRdgrGLyD</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/eqfbZQsffwyta5HQWBUmX7-1280-80.png" type="image/png" length="0"></enclosure>
                                                                        <pubDate>Thu, 10 Sep 2026 08:00:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Home Appliances]]></category>
                                                    <category><![CDATA[Kitchen & Dining]]></category>
                                                    <category><![CDATA[Home]]></category>
                                                                                                <author><![CDATA[ camilla.sharman@futurenet.com (Camilla Sharman) ]]></author>                    <dc:creator><![CDATA[ Camilla Sharman ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/nY4nvWzofHKHpvzAqN5LVH.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Camilla is the Homes Staff Writer and covers everything to do with homes and gardens. She has a wealth of editorial experience, mounting over 30 years, and covers news and features, tests products for reviews and compiles buying guides.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;p&gt;Her work has appeared in business and consumer titles, including Ideal Home, Real Homes, House Beautiful, Homebuilding &amp;amp; Renovation, and Kitchen &amp;amp; Bathroom Business. She’s even appeared on the cover of Your Home, writing about her own house renovation.&lt;/p&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;p&gt;Although she’s obsessed with decorating her home, she also enjoys baking and trying out the latest kitchen appliances. But when she’s not inside, you’ll find her pottering about in her yard, tending to her vegetable patch or taking in her prized hydrangeas. She also enjoys keeping fit, and if she&#039;s not on a spin bike trying to keep up with the class, she&#039;ll be in the pool, or trying to perfect her headstand in a yoga class.&lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                <media:content type="image/png" url="https://cdn.mos.cms.futurecdn.net/eqfbZQsffwyta5HQWBUmX7-1280-80.png">
                                                            <media:credit><![CDATA[Future / Camilla Sharman]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Camilla Sharman with Ooni Halo Core spiral mixer]]></media:description>                                                            <media:text><![CDATA[Camilla Sharman with Ooni Halo Core spiral mixer]]></media:text>
                                <media:title type="plain"><![CDATA[Camilla Sharman with Ooni Halo Core spiral mixer]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/eqfbZQsffwyta5HQWBUmX7-1280-80.png" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>When Ooni announced the new<a href="https://www.tomsguide.com/home/kitchen-dining/watch-out-kitchenaid-oonis-launching-its-second-stand-mixer-and-at-usd599-it-price-matches-the-artisan-pro"> Halo Core spiral mixer</a>, one thought immediately crossed my mind: KitchenAid is in for some serious competition. </p><p>Available for <a href="https://www.amazon.com/Ooni-Spiral-Dough-Mixer-Stand/dp/B0H5RCW4W2/ref=sr_1_1?">$599 at Amazon,</a> it hits the exact price as the iconic<a href="https://www.tomsguide.com/home/kitchenaid-artisan-plus-mixer-review"> KitchenAid Artisan Plus</a>, but offers a more compact and home-kitchen-friendly footprint than the high-end<a href="https://www.tomsguide.com/home/home-appliances/ooni-halo-pro-spiral-stand-mixer-review"> Ooni Halo Pro spiral mixer</a> — currently our top pick for bread making in our <a href="https://www.tomsguide.com/best-picks/best-stand-mixers">best standing mixer buying guide</a>.</p><p>While $599 is still a real investment, the Halo Core feels far more accessible than the Ooni Halo Pro, which is <a href="https://www.amazon.com/dp/B0F746CZ3L?">$799 at Amazon, </a>plus it won't take up as much countertop space in your kitchen.</p><p>I’ve been putting the Halo Core through its paces, and there’s a lot to like. I’ll follow up with a full review in a couple of weeks, but for now, here are three things I loved and one thing you should know.</p><div class="product"><a data-dimension112="a5697ee6-ac5f-11f1-9d67-15deb1193abc" data-action="Deal Block" data-label="Halo Core Spiral Mixer" data-dimension48="Halo Core Spiral Mixer" data-dimension25="$599" href="https://www.amazon.com/Ooni-Spiral-Dough-Mixer-Stand/dp/B0H5RCW4W2?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:424px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="wcvYr66Fer4q8dWMPz26jb" name="Ooni Halo Core stand mixer in Black" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/wcvYr66Fer4q8dWMPz26jb.png" mos="" align="middle" fullscreen="" width="424" height="424" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>The Ooni Halo Core spiral mixer uses the same dual-kneading action that pro bakers trust. The spiral dough hook and breaker bar work with the rotating bowl to build a strong gluten structure, resulting in a light, soft dough. The mixer also comes complete with a 4-8 qt bowl, a dual-geared whisk and an angled silicone edge beater for making cake batters, cookies and whisking cream and meringues. <a class="view-deal button" href="https://www.amazon.com/Ooni-Spiral-Dough-Mixer-Stand/dp/B0H5RCW4W2?" target="_blank" rel="nofollow" data-dimension112="a5697ee6-ac5f-11f1-9d67-15deb1193abc" data-action="Deal Block" data-label="Halo Core Spiral Mixer" data-dimension48="Halo Core Spiral Mixer" data-dimension25="$599">View Deal</a></p></div><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-Oajm5X"></div>                            </div>                            <script src="https://kwizly.com/embed/Oajm5X.js" async></script><h3 class="article-body__section" id="section-ooni-halo-core-spiral-mixer-what-i-like"><span>Ooni Halo Core spiral mixer: What I like</span></h3><h2 id="1-perfect-dough">1. Perfect dough</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="V3UWaYeKvCNTVk2UHEhaKe" name="Ooni Halo Core dough hook and breaker bar" alt="Ooni Halo Core dough hook and breaker bar" src="https://cdn.mos.cms.futurecdn.net/V3UWaYeKvCNTVk2UHEhaKe.png" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Camilla Sharman)</span></figcaption></figure><p>The Halo Core spiral mixer, like its older sibling, is designed specifically for bread making. Instead of the planetary stand mixers home bakers are used to, Ooni’s design brings professional-grade spiral mixing into our kitchens.</p><p>How does it work? The dough hook and bowl rotate around a breaker bar — a stationary vertical metal rod that sits in the mixing bowl. Although watching the rotating bowl is fun to watch, it’s not a gimmick.  </p><p>The breaker bar removes dough from the hook as it spins during mixing, preventing it from climbing up the dough hook and stopping you from pausing the mix to remove the dough. It also stretches the dough for a stronger gluten structure.</p><p>I’ve been experimenting with making bread and pizza dough, and although the pizza dough is currently proving in my kitchen, the bread tasted exceptional. In fact, my husband didn’t realize it was homemade. </p><p>I also found that the kneading process was smooth. The usual mixers I test move around my countertop when the dough hook is in action, and it almost seems like too much for the appliance’s motor. There was a clear difference when using the Ooni Halo Core. The mixer stayed steady, and there was no hint of any electric smell or the motor burning out. </p><h2 id="2-pause-and-go-again">2. Pause and go again</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="xvxCmZ72M4HgX76QvbkzgJ" name="Ooni Halo Core control" alt="Ooni Halo Core stand mixer control" src="https://cdn.mos.cms.futurecdn.net/xvxCmZ72M4HgX76QvbkzgJ.png" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Camilla Sharman)</span></figcaption></figure><p>The controls of the Halo Core work differently from any stand mixer I’ve previously tested, but in a good way. The control knob is positioned on top of the appliance, so it’s easy to access whether you’re right- or left-handed. What’s more, it works in percentages, with 20 speeds. Turn it clockwise once for 5% at 60 rpm, and turn it up to 100% for 300 rpm. </p><p>The control lights up in sections, so you can clearly see which speed setting you're on. This is quite clever in itself, but what impressed me more was that you can simply press the knob and the appliance will pause. Press it again, and it will start from where it left off. It may seem like a small thing, but I found it took away the hassle of turning down the speed when you want to pause the mix.</p><h2 id="3-double-whisk">3. Double whisk </h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="meZBSQFjrR6TbefkE39twD" name="Ooni Halo Core stand mixer" alt="Ooni Halo Core stand mixer" src="https://cdn.mos.cms.futurecdn.net/meZBSQFjrR6TbefkE39twD.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Camilla Sharman)</span></figcaption></figure><p>I’ve never made butter before, but since my colleague made butter with the Halo Pro, I followed suit. I started by attaching the dual-geared whisk attachment — it even has a built-in gearbox for rapid whipping! </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="3WnNedwWrnXHs2HuURMsVU" name="Ooni Halo Core stand mixer buttermilk separating" alt="Ooni Halo Core stand mixer buttermilk separating" src="https://cdn.mos.cms.futurecdn.net/3WnNedwWrnXHs2HuURMsVU.png" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Camilla Sharman)</span></figcaption></figure><p>The whisk really came into its own, whipping the heavy cream into what looked like scrambled eggs until the fat and buttermilk separated. Apart from the speed, it’s fascinating to watch, and if you’ve never made butter before, I recommend giving it a go. </p><p>The whisk attachment proved that the Halo Core isn’t just good at making dough; it has a firm place in the kitchen for other baking tasks. </p><h3 class="article-body__section" id="section-ooni-halo-core-spiral-mixer-what-i-don-t-like"><span>Ooni Halo Core spiral mixer: What I don't like</span></h3><h2 id="it-wasn-39-t-great-at-mixing-cake-batter">It wasn't great at mixing cake batter</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="ubR55uboGghEWXDKiHxLhD" name="Ooni Halo Core stand mixer" alt="Ooni Halo Core stand mixer" src="https://cdn.mos.cms.futurecdn.net/ubR55uboGghEWXDKiHxLhD.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Camilla Sharman)</span></figcaption></figure><p>After the whisk's success, I was excited to try the angled silicone-edge beater to make an all-in-one cake batter. I love the silicone beater I’ve used with the KitchenAid Artisan Plus, as it swipes around the edge of the bowl, incorporating the whole mixture — so you don’t need to stop midway through to scrape the ingredients off the side.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="kToJx2jJvD2CzLkw74AwjJ" name="Ooni Halo Core stand mixer cake batter" alt="Ooni Halo Core stand mixer making cake batter" src="https://cdn.mos.cms.futurecdn.net/kToJx2jJvD2CzLkw74AwjJ.png" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Camilla Sharman)</span></figcaption></figure><p>The Halo Core did the same, but it seemed to struggle to incorporate the butter into the mixture, even though it was soft when I added it to the bowl. Then, when I raised the mixer’s head, I noticed a large clump of butter was still attached to the beater. </p><p>I’m going to keep testing its cake-making ability, since other reviews have given it more positive results. So keep an eye out for my full review.</p><p><strong>Over to you</strong></p><p>Are you thinking about buying an Ooni mixer, or have you already invested in one? I’d love to read your thoughts and experiences in the comments below.</p><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h3><ul><li><a href="https://www.tomsguide.com/home/kitchenaid-vs-cuisinart-which-stand-mixer-is-best">KitchenAid vs Cuisinart: Which stand mixer is best?</a></li><li><a href="https://www.tomsguide.com/home/smegs-newest-stand-mixer-gives-kitchenaid-a-run-for-its-money-heres-why-it-won-me-over">Smeg’s newest retro stand mixer gives KitchenAid a run for its money — here’s why it won me over</a></li><li><a href="https://www.tomsguide.com/home/home-appliances/i-tested-oonis-new-rotating-stone-and-its-your-ticket-to-perfect-pizza-at-home">I tested Ooni's new Rotating Stone — and it's your ticket to perfect pizza at home</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ Are You Storing Summer Foods in the Right Place? ]]></title>
                                                                                                <dc:content><![CDATA[ <p>Summer brings backyard barbecues, farmers market hauls and refrigerators packed with everything from fresh produce to leftover cookout essentials. But while most people know milk belongs in the fridge and ice cream belongs in the freezer, many seasonal foods fall into a gray area.</p><p>Should tomatoes be refrigerated? Does bread stay fresher in the fridge or freezer? And how long can leftover hot dogs really last?</p><p>We all know that proper food storage can help ingredients stay fresh longer, reduce waste, and make meal planning easier. Yet crowded refrigerators, forgotten leftovers and misplaced ingredients remain a common challenge, especially at the hottest time of the year. </p><p>Here's a practical guide to where some of summer's most popular foods should actually be stored — and how <a href="https://sr.studiostack.com/c/link?l=2420846&s=2420844" target="_blank" rel="nofollow"><u>Bespoke AI Refrigerator Family Hub</u></a>’s smart technology can help keep track of what you have before they are forgotten.<sup>1</sup></p><h2 id="foods-that-belong-in-the-refrigerator">Foods that belong in the refrigerator</h2><p>When temperatures climb, the refrigerator becomes the most important food storage zone in the kitchen. While some items are obvious candidates, others may surprise you.</p><p><strong>Cut watermelon</strong></p><p>An uncut watermelon can stay at room temperature, but once sliced, it should be refrigerated immediately. Leaving cut watermelon out for extended periods can encourage bacterial growth and affect both texture and flavor.</p><p>Store slices in a sealed container or tightly wrapped on a shelf rather than in the refrigerator door, where the contents are exposed to outside temperature more frequently.</p><iframe src="https://content.jwplatform.com/players/uLhtjQ37.html" id="uLhtjQ37" title="Watermelon" width="1920" height="1080" frameborder="0" scrolling="auto" allowfullscreen></iframe><p><strong>Fresh corn on the cob</strong></p><p>One of summer's most popular vegetables is often stored incorrectly. Fresh corn starts losing sweetness shortly after harvest, and refrigeration helps slow that process.</p><p>For its flavor, keep corn in the refrigerator’s Crisper+ Drawer and cook it within a few days of purchase. And don’t forget, it should only be husked just before cooking, so it should go into the fridge in its natural case. Storing it at room temperature may cause sugars to convert to starch more quickly, and husking it before storage will lead to that same conversion of sugars to starch, as well as rapid moisture loss and oxidation.</p><iframe src="https://content.jwplatform.com/players/CiY6ZTuO.html" id="CiY6ZTuO" title="Corn On The Cob" width="1920" height="1080" frameborder="0" scrolling="auto" allowfullscreen></iframe><p><strong>Barbecue ribs and cooked leftovers</strong></p><p>Whether it's burgers, grilled chicken or ribs, cooked foods should be refrigerated within two hours of serving — and even sooner during extreme heat.</p><p>Leftovers often get pushed to the back of crowded shelves and forgotten. That's where organization becomes important. With Samsung Family Hub’s latest update, AI Vision<sup>2</sup> technology can identify and track many packaged foods and labeled containers placed inside compatible refrigerators, helping households see what's available and reducing the chances of leftovers being overlooked until it's too late.</p><iframe src="https://content.jwplatform.com/players/IJbpB7fv.html" id="IJbpB7fv" title="BBQ Ribs" width="1920" height="1080" frameborder="0" scrolling="auto" allowfullscreen></iframe><p><strong>Open condiments and sauces</strong></p><p>Barbecue sauce, mayonnaise-based dressings and many opened condiment containers belong in the refrigerator after opening. During cookout season, these items are often moved in and out of coolers and outdoor tables, making proper storage even more important.</p><p>For households juggling tens of bottles and jars, the updated AI Food Manager’s food list can be a game changer, since it helps prevent duplicate purchases and unnecessary waste.</p><iframe src="https://content.jwplatform.com/players/FJdfNgbC.html" id="FJdfNgbC" title="Jam" width="1536" height="1920" frameborder="0" scrolling="auto" allowfullscreen></iframe><p><strong>Berries</strong></p><p>Strawberries, blueberries and raspberries should be refrigerated soon after purchase. Summer berries are particularly delicate and can spoil quickly on the countertop.</p><p>To extend freshness, wait to wash berries until you're ready to eat them. Excess moisture can accelerate spoilage.</p><p><strong>Eggs</strong></p><p>Although eggs are displayed unrefrigerated in some countries, they should remain refrigerated in the United States. Consistent cold temperatures help maintain freshness, so, contrary to popular belief, they should be stored on a shelf inside the refrigerator, not in the door.</p><h2 id="foods-that-belong-in-the-freezer">Foods that belong in the freezer</h2><p>The freezer can do more than store ice cream and frozen vegetables. It can also help extend the life of foods that might otherwise go unused.</p><p><strong>Bread</strong></p><p>Many people automatically refrigerate bread, but that can actually make it stale faster.</p><p>If you plan to eat a loaf within a few days, keep it at room temperature. If not, freeze it. Bread freezes well and can be thawed slice by slice as needed.</p><p><strong>Avocados</strong></p><p>If you've ever watched an avocado go from perfectly ripe to overripe in what feels like a day, the freezer can help. Ripe avocados freeze surprisingly well and can be stored as halves, slices or mashed. </p><p>While they won't keep the same texture for salads or toast after thawing, they're ideal for smoothies, guacamole and baking.</p><p><strong>Excess herbs</strong></p><p>Fresh herbs such as basil, parsley and cilantro can spoil quickly. Freezing chopped herbs in ice cube trays with a small amount of water or olive oil creates ready-to-use portions for future meals.</p><h2 id="foods-that-should-stay-at-room-temperature">Foods that should stay at room temperature</h2><p>Not everything benefits from refrigeration. In fact, some foods lose flavor or texture when stored too cold.</p><p><strong>Tomatoes</strong></p><p>This is one of the most common storage mistakes.</p><p>Refrigeration can make tomatoes mealy and dull their flavor. Whole tomatoes are generally best kept on the countertop and away from direct sunlight until ripe and ready to eat.</p><p>Once cut, however, they should be refrigerated.</p><p><strong>Peaches, nectarines and plums</strong></p><p>Stone fruits continue ripening after purchase. Refrigerating them too early can slow that process and affect texture.</p><p>Leave them on the counter until ripe, then move them to the refrigerator if you need a few extra days before eating them.</p><p><strong>Onions</strong></p><p>Whole onions prefer a cool, dry and well-ventilated location rather than the refrigerator. Moisture can encourage spoilage and soften texture.</p><p>Just don't store them directly next to potatoes, which can shorten their shelf life.</p><h2 id="a-smarter-way-to-manage-summer-food-storage">A smarter way to manage summer food storage</h2><p>Knowing where foods belong is the first step toward keeping them fresher longer. The second is staying aware of what you already have.</p><p>As refrigerators fill up with produce, leftovers and barbecue essentials throughout the summer, it's easy for items to get lost or forgotten. As shown in the clips above, Samsung's upgraded AI Vision technology helps simplify food management by broadening its spectrum of recognized items – like your favorite breakfast jam and labeled food container with your leftovers – making it easier to keep track of ingredients and reduce unnecessary waste.</p><iframe src="https://content.jwplatform.com/players/xpkXFGCQ.html" id="xpkXFGCQ" title="AI Vision" width="1920" height="1080" frameborder="0" scrolling="auto" allowfullscreen></iframe><p>Learn more about Samsung’s Bespoke AI Refrigerator Family Hub <a href="https://sr.studiostack.com/c/link?l=2420848&s=2420844" target="_blank" rel="nofollow"><u>here</u></a>. </p><p><sup>1</sup> Features and availability may vary by model and market.<sup>2</sup> A Wi-Fi connection and a Samsung account are required. If a food item is not recognizable, it may be listed as an unknown item. AI Vision cannot identify or list any food items in the freezer. Recognition uses AI models that may be updated periodically to help improve performance. The user may need to manually check and adjust the list to ensure its accuracy.</p> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/home/kitchen-dining/are-you-storing-summer-foods-in-the-right-place</link>
                                                                            <description>
                            <![CDATA[ Here are some tips for better storage ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">YSEzYXAA72Xst8gwCmD4EW</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/9AkR8iiQzLNMT5yXF5ahoe-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Tue, 08 Sep 2026 16:00:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Kitchen & Dining]]></category>
                                                    <category><![CDATA[Tech]]></category>
                                                    <category><![CDATA[Home]]></category>
                                                    <category><![CDATA[Home Appliances]]></category>
                                                                                                                    <dc:creator><![CDATA[ Sponsored ]]></dc:creator>                                                                                                        <dc:description><![CDATA[ null ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/9AkR8iiQzLNMT5yXF5ahoe-1280-80.jpg">
                                                            <media:credit><![CDATA[Samsung]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Samsung Fridge in a kitchen]]></media:description>                                                            <media:text><![CDATA[Samsung Fridge in a kitchen]]></media:text>
                                <media:title type="plain"><![CDATA[Samsung Fridge in a kitchen]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/9AkR8iiQzLNMT5yXF5ahoe-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Summer brings backyard barbecues, farmers market hauls and refrigerators packed with everything from fresh produce to leftover cookout essentials. But while most people know milk belongs in the fridge and ice cream belongs in the freezer, many seasonal foods fall into a gray area.</p><p>Should tomatoes be refrigerated? Does bread stay fresher in the fridge or freezer? And how long can leftover hot dogs really last?</p><p>We all know that proper food storage can help ingredients stay fresh longer, reduce waste, and make meal planning easier. Yet crowded refrigerators, forgotten leftovers and misplaced ingredients remain a common challenge, especially at the hottest time of the year. </p><p>Here's a practical guide to where some of summer's most popular foods should actually be stored — and how <a href="https://sr.studiostack.com/c/link?l=2420846&s=2420844" target="_blank" rel="nofollow"><u>Bespoke AI Refrigerator Family Hub</u></a>’s smart technology can help keep track of what you have before they are forgotten.<sup>1</sup></p><h2 id="foods-that-belong-in-the-refrigerator">Foods that belong in the refrigerator</h2><p>When temperatures climb, the refrigerator becomes the most important food storage zone in the kitchen. While some items are obvious candidates, others may surprise you.</p><p><strong>Cut watermelon</strong></p><p>An uncut watermelon can stay at room temperature, but once sliced, it should be refrigerated immediately. Leaving cut watermelon out for extended periods can encourage bacterial growth and affect both texture and flavor.</p><p>Store slices in a sealed container or tightly wrapped on a shelf rather than in the refrigerator door, where the contents are exposed to outside temperature more frequently.</p><iframe src="https://content.jwplatform.com/players/uLhtjQ37.html" id="uLhtjQ37" title="Watermelon" width="1920" height="1080" frameborder="0" scrolling="auto" allowfullscreen></iframe><p><strong>Fresh corn on the cob</strong></p><p>One of summer's most popular vegetables is often stored incorrectly. Fresh corn starts losing sweetness shortly after harvest, and refrigeration helps slow that process.</p><p>For its flavor, keep corn in the refrigerator’s Crisper+ Drawer and cook it within a few days of purchase. And don’t forget, it should only be husked just before cooking, so it should go into the fridge in its natural case. Storing it at room temperature may cause sugars to convert to starch more quickly, and husking it before storage will lead to that same conversion of sugars to starch, as well as rapid moisture loss and oxidation.</p><iframe src="https://content.jwplatform.com/players/CiY6ZTuO.html" id="CiY6ZTuO" title="Corn On The Cob" width="1920" height="1080" frameborder="0" scrolling="auto" allowfullscreen></iframe><p><strong>Barbecue ribs and cooked leftovers</strong></p><p>Whether it's burgers, grilled chicken or ribs, cooked foods should be refrigerated within two hours of serving — and even sooner during extreme heat.</p><p>Leftovers often get pushed to the back of crowded shelves and forgotten. That's where organization becomes important. With Samsung Family Hub’s latest update, AI Vision<sup>2</sup> technology can identify and track many packaged foods and labeled containers placed inside compatible refrigerators, helping households see what's available and reducing the chances of leftovers being overlooked until it's too late.</p><iframe src="https://content.jwplatform.com/players/IJbpB7fv.html" id="IJbpB7fv" title="BBQ Ribs" width="1920" height="1080" frameborder="0" scrolling="auto" allowfullscreen></iframe><p><strong>Open condiments and sauces</strong></p><p>Barbecue sauce, mayonnaise-based dressings and many opened condiment containers belong in the refrigerator after opening. During cookout season, these items are often moved in and out of coolers and outdoor tables, making proper storage even more important.</p><p>For households juggling tens of bottles and jars, the updated AI Food Manager’s food list can be a game changer, since it helps prevent duplicate purchases and unnecessary waste.</p><iframe src="https://content.jwplatform.com/players/FJdfNgbC.html" id="FJdfNgbC" title="Jam" width="1536" height="1920" frameborder="0" scrolling="auto" allowfullscreen></iframe><p><strong>Berries</strong></p><p>Strawberries, blueberries and raspberries should be refrigerated soon after purchase. Summer berries are particularly delicate and can spoil quickly on the countertop.</p><p>To extend freshness, wait to wash berries until you're ready to eat them. Excess moisture can accelerate spoilage.</p><p><strong>Eggs</strong></p><p>Although eggs are displayed unrefrigerated in some countries, they should remain refrigerated in the United States. Consistent cold temperatures help maintain freshness, so, contrary to popular belief, they should be stored on a shelf inside the refrigerator, not in the door.</p><h2 id="foods-that-belong-in-the-freezer">Foods that belong in the freezer</h2><p>The freezer can do more than store ice cream and frozen vegetables. It can also help extend the life of foods that might otherwise go unused.</p><p><strong>Bread</strong></p><p>Many people automatically refrigerate bread, but that can actually make it stale faster.</p><p>If you plan to eat a loaf within a few days, keep it at room temperature. If not, freeze it. Bread freezes well and can be thawed slice by slice as needed.</p><p><strong>Avocados</strong></p><p>If you've ever watched an avocado go from perfectly ripe to overripe in what feels like a day, the freezer can help. Ripe avocados freeze surprisingly well and can be stored as halves, slices or mashed. </p><p>While they won't keep the same texture for salads or toast after thawing, they're ideal for smoothies, guacamole and baking.</p><p><strong>Excess herbs</strong></p><p>Fresh herbs such as basil, parsley and cilantro can spoil quickly. Freezing chopped herbs in ice cube trays with a small amount of water or olive oil creates ready-to-use portions for future meals.</p><h2 id="foods-that-should-stay-at-room-temperature">Foods that should stay at room temperature</h2><p>Not everything benefits from refrigeration. In fact, some foods lose flavor or texture when stored too cold.</p><p><strong>Tomatoes</strong></p><p>This is one of the most common storage mistakes.</p><p>Refrigeration can make tomatoes mealy and dull their flavor. Whole tomatoes are generally best kept on the countertop and away from direct sunlight until ripe and ready to eat.</p><p>Once cut, however, they should be refrigerated.</p><p><strong>Peaches, nectarines and plums</strong></p><p>Stone fruits continue ripening after purchase. Refrigerating them too early can slow that process and affect texture.</p><p>Leave them on the counter until ripe, then move them to the refrigerator if you need a few extra days before eating them.</p><p><strong>Onions</strong></p><p>Whole onions prefer a cool, dry and well-ventilated location rather than the refrigerator. Moisture can encourage spoilage and soften texture.</p><p>Just don't store them directly next to potatoes, which can shorten their shelf life.</p><h2 id="a-smarter-way-to-manage-summer-food-storage">A smarter way to manage summer food storage</h2><p>Knowing where foods belong is the first step toward keeping them fresher longer. The second is staying aware of what you already have.</p><p>As refrigerators fill up with produce, leftovers and barbecue essentials throughout the summer, it's easy for items to get lost or forgotten. As shown in the clips above, Samsung's upgraded AI Vision technology helps simplify food management by broadening its spectrum of recognized items – like your favorite breakfast jam and labeled food container with your leftovers – making it easier to keep track of ingredients and reduce unnecessary waste.</p><iframe src="https://content.jwplatform.com/players/xpkXFGCQ.html" id="xpkXFGCQ" title="AI Vision" width="1920" height="1080" frameborder="0" scrolling="auto" allowfullscreen></iframe><p>Learn more about Samsung’s Bespoke AI Refrigerator Family Hub <a href="https://sr.studiostack.com/c/link?l=2420848&s=2420844" target="_blank" rel="nofollow"><u>here</u></a>. </p><p><sup>1</sup> Features and availability may vary by model and market.<sup>2</sup> A Wi-Fi connection and a Samsung account are required. If a food item is not recognizable, it may be listed as an unknown item. AI Vision cannot identify or list any food items in the freezer. Recognition uses AI models that may be updated periodically to help improve performance. The user may need to manually check and adjust the list to ensure its accuracy.</p>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ Le Creuset just dropped an entire Star Trek collection — and I can't decide which item I like the most ]]></title>
                                                                                                <dc:content><![CDATA[ <p>Le Creuset is an iconic kitchen brand. <a href="https://www.tomsguide.com/entertainment/movies/how-to-watch-the-star-trek-movies-in-order">Star Trek is an iconic franchise</a>. And what happens when you take two icons, put them in a bowl and mix them together? Well, a 12-piece kitchenware collection that'll turn your kitchen into a culinary command center.</p><p>To celebrate 60 years of "Star Trek", the cookware brand has lovingly crafted a limited-edition collection for fans of the franchise. Or, maybe you're just a fan of Spock (don't worry, there's a mug for that). </p><p>Christopher Scinto, Chief Marketing Officer at Le Creuset says: "With the Le Creuset x Star Trek Collection, we set out to commemorate some of the franchise's most beloved symbols with our signature craftsmanship and iconic colors and designs."</p><p>While there's 12 pieces in the collection that you can check out for a limited time only at Le Creuset stores, <a href="http://LeCreuset.com" target="_blank" rel="nofollow">LeCreuset.com</a>, and <a href="https://www.williams-sonoma.com/" target="_blank" rel="nofollow">Williams-Sonoma.com</a>, I've highlighted my five top picks below.</p><h2 id="what-39-s-in-my-basket">What's in my basket</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="VenG82ejhYRyErJC2Qj59Q" name="Le Creuset x Star Treck Collection 2" alt="The Le Creuset and Star Trek Collection" src="https://cdn.mos.cms.futurecdn.net/VenG82ejhYRyErJC2Qj59Q.jpg" mos="" align="middle" fullscreen="" width="1920" height="1080" attribution="" endorsement="" class=""></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Le Creuset/CBS)</span></figcaption></figure><p>The full Le Creuset x "Star Trek" collection ranges from $35 to $500, but with 12 items there's hopefully something for every price range. Before we jump into my basket, I want to give a special mention to the Mini Cocottes for Balok, Gorn and Talosian. While they're not in my basket right now, they're certainly worth checking out if you're a fan.</p><div class="product"><a data-dimension112="433de4a6-aaba-11f1-b35b-5b7496d67c8f" data-action="Deal Block" data-label="Spock Mug" data-dimension48="Spock Mug" data-dimension25="$35" href="https://www.lecreuset.com/round-dutch-oven/21177US.html" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:535px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="CCp3WkA7DwRqzDscYBz35T" name="lecreuset_spockmug" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/CCp3WkA7DwRqzDscYBz35T.jpg" mos="" align="middle" fullscreen="" width="535" height="535" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.lecreuset.com/round-dutch-oven/21177US.html" target="_blank" rel="nofollow" data-dimension112="433de4a6-aaba-11f1-b35b-5b7496d67c8f" data-action="Deal Block" data-label="Spock Mug" data-dimension48="Spock Mug" data-dimension25="$35">Spock Mug: $35</a></strong><br>Le Creuset transforms the everyday mug handle into Spock's infamous ear in this unique design. While missing the usual gap for your fingers in the handle, it replaces it with the fun of gripping onto Spock's most defining feature.<a class="view-deal button" href="https://www.lecreuset.com/round-dutch-oven/21177US.html" target="_blank" rel="nofollow" data-dimension112="433de4a6-aaba-11f1-b35b-5b7496d67c8f" data-action="Deal Block" data-label="Spock Mug" data-dimension48="Spock Mug" data-dimension25="$35">View Deal</a></p></div><div class="product"><a data-dimension112="433de5f0-aaba-11f1-bbcc-932ffe9bbb44" data-action="Deal Block" data-label="Live Long and Prosper Spoon Rest" data-dimension48="Live Long and Prosper Spoon Rest" data-dimension25="$55" href="https://www.lecreuset.com/pepper-mill/44001.html" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:535px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="j3CT7XhbZUE9aXfNvK9Pm8" name="lecreuset_spoonrest" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/j3CT7XhbZUE9aXfNvK9Pm8.jpg" mos="" align="middle" fullscreen="" width="535" height="535" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.lecreuset.com/pepper-mill/44001.html" target="_blank" rel="nofollow" data-dimension112="433de5f0-aaba-11f1-bbcc-932ffe9bbb44" data-action="Deal Block" data-label="Live Long and Prosper Spoon Rest" data-dimension48="Live Long and Prosper Spoon Rest" data-dimension25="$55">Live Long and Prosper Spoon Rest: $55</a></strong><br>It wouldn't be <em>Star Trek</em> without the emblematic four-finger split. The Vulcan salute can become a kitchen staple instead taking on new life as a spoon rest that'll subtly tell your friends and family that you're a Trekkie – and a chef.<a class="view-deal button" href="https://www.lecreuset.com/pepper-mill/44001.html" target="_blank" rel="nofollow" data-dimension112="433de5f0-aaba-11f1-bbcc-932ffe9bbb44" data-action="Deal Block" data-label="Live Long and Prosper Spoon Rest" data-dimension48="Live Long and Prosper Spoon Rest" data-dimension25="$55">View Deal</a></p></div><div class="product"><a data-dimension112="433de514-aaba-11f1-840f-63fa391c57df" data-action="Deal Block" data-label="Communi-Grater" data-dimension48="Communi-Grater" data-dimension25="$68" href="https://www.lecreuset.com/signature-skillet/20182US.html" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:535px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="yM3UkLRCCQPiTnkkfysh8T" name="lecreuset_communigrater" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/yM3UkLRCCQPiTnkkfysh8T.jpg" mos="" align="middle" fullscreen="" width="535" height="535" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.lecreuset.com/signature-skillet/20182US.html" target="_blank" rel="nofollow" data-dimension112="433de514-aaba-11f1-840f-63fa391c57df" data-action="Deal Block" data-label="Communi-Grater" data-dimension48="Communi-Grater" data-dimension25="$68">Communi-Grater: $68</a></strong><br>Le Creuset are known more for cookware than they are for kitchen accessories, but there's something extra special about this one. This greater plays on the Communicator with a quirky pun and a unique design to desire.<a class="view-deal button" href="https://www.lecreuset.com/signature-skillet/20182US.html" target="_blank" rel="nofollow" data-dimension112="433de514-aaba-11f1-840f-63fa391c57df" data-action="Deal Block" data-label="Communi-Grater" data-dimension48="Communi-Grater" data-dimension25="$68">View Deal</a></p></div><div class="product"><a data-dimension112="433de668-aaba-11f1-868d-fb080f159d20" data-action="Deal Block" data-label="Galileo Shuttlecraft Rectangular Casserole" data-dimension48="Galileo Shuttlecraft Rectangular Casserole" data-dimension25="$150" href="https://www.lecreuset.com/vancouver-mug/70317US.html" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:535px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="8QvQF6LU5t8Fto3vLjoDn8" name="lecreuset_galileocasserole" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/8QvQF6LU5t8Fto3vLjoDn8.jpg" mos="" align="middle" fullscreen="" width="535" height="535" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.lecreuset.com/vancouver-mug/70317US.html" target="_blank" rel="nofollow" data-dimension112="433de668-aaba-11f1-868d-fb080f159d20" data-action="Deal Block" data-label="Galileo Shuttlecraft Rectangular Casserole" data-dimension48="Galileo Shuttlecraft Rectangular Casserole" data-dimension25="$150">Galileo Shuttlecraft Rectangular Casserole: $150</a></strong><br>My favorite piece from the collection is this retro <em>Star Trek</em> twist on Le Creuset's iconic rectangular casserole dishes. A nod to the 1960s Galileo Shuttlecraft, it's equal parts nostalgia and cookware goodness.<a class="view-deal button" href="https://www.lecreuset.com/vancouver-mug/70317US.html" target="_blank" rel="nofollow" data-dimension112="433de668-aaba-11f1-868d-fb080f159d20" data-action="Deal Block" data-label="Galileo Shuttlecraft Rectangular Casserole" data-dimension48="Galileo Shuttlecraft Rectangular Casserole" data-dimension25="$150">View Deal</a></p></div><div class="product"><a data-dimension112="433de582-aaba-11f1-8881-0ddce702c4bc" data-action="Deal Block" data-label="Klingon Braiser with Klingon Trefoil Knob" data-dimension48="Klingon Braiser with Klingon Trefoil Knob" data-dimension25="$450" href="https://www.lecreuset.com/heritage-3-piece-rectangular-baking-dish-set/ST0098.html" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:535px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="SU5y49orWDCp43mFjBrG6T" name="lecreuset_klingonbraiser" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/SU5y49orWDCp43mFjBrG6T.jpg" mos="" align="middle" fullscreen="" width="535" height="535" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.lecreuset.com/heritage-3-piece-rectangular-baking-dish-set/ST0098.html" target="_blank" rel="nofollow" data-dimension112="433de582-aaba-11f1-8881-0ddce702c4bc" data-action="Deal Block" data-label="Klingon Braiser with Klingon Trefoil Knob" data-dimension48="Klingon Braiser with Klingon Trefoil Knob" data-dimension25="$450">Klingon Braiser with Klingon Trefoil Knob: $450</a></strong><br>And Le Creuset have given another iconic cookware item, the Braiser, a "Star Trek" twist. To commemorate 60 years, it has replaced the trefoil knob with a Klingon emblem whilst embossing a Klingon starship on the lid – all in a striking dark blue.<a class="view-deal button" href="https://www.lecreuset.com/heritage-3-piece-rectangular-baking-dish-set/ST0098.html" target="_blank" rel="nofollow" data-dimension112="433de582-aaba-11f1-8881-0ddce702c4bc" data-action="Deal Block" data-label="Klingon Braiser with Klingon Trefoil Knob" data-dimension48="Klingon Braiser with Klingon Trefoil Knob" data-dimension25="$450">View Deal</a></p></div><ul><li><a href="https://www.tomsguide.com/home/revolutionary-for-homemade-bread-why-i-cant-wait-to-try-le-creusets-new-oval-bread-oven">'Revolutionary for homemade bread': Why I can't wait to try Le Creuset's new oval bread oven</a></li><li><a href="https://www.tomsguide.com/home/cast-iron-skillet-vs-dutch-oven-which-is-better">Cast iron skillet vs Dutch oven — which is better?</a></li><li><a href="https://www.tomsguide.com/home/home-appliances/what-is-a-dutch-oven-everything-you-need-to-know-about-this-kitchen-essential">What is a Dutch oven — everything you need to know about this kitchen essential</a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/home/kitchen-dining/le-creuset-just-dropped-an-entire-star-trek-collection-and-i-cant-decide-which-item-i-like-the-most</link>
                                                                            <description>
                            <![CDATA[ In an unexpected collab, Le Creuset has teamed up with Paramount to celebrate 60 years of Star Trek with kitchenware that's sure to live long and prosper. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">bBZw6JfeqxmyuRJMyv53yD</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/wfxRUph98kwvpRwDGtveGQ-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Tue, 08 Sep 2026 13:00:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Kitchen & Dining]]></category>
                                                    <category><![CDATA[Home]]></category>
                                                    <category><![CDATA[Home Appliances]]></category>
                                                                                                                    <dc:creator><![CDATA[ Grace Dean ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/oxXqkks7wgxZkPiyYY2n6H.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ null ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/wfxRUph98kwvpRwDGtveGQ-1280-80.jpg">
                                                            <media:credit><![CDATA[Le Creuset/CBS]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[The Le Creuset and Star Trek Collection]]></media:description>                                                            <media:text><![CDATA[The Le Creuset and Star Trek Collection]]></media:text>
                                <media:title type="plain"><![CDATA[The Le Creuset and Star Trek Collection]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/wfxRUph98kwvpRwDGtveGQ-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Le Creuset is an iconic kitchen brand. <a href="https://www.tomsguide.com/entertainment/movies/how-to-watch-the-star-trek-movies-in-order">Star Trek is an iconic franchise</a>. And what happens when you take two icons, put them in a bowl and mix them together? Well, a 12-piece kitchenware collection that'll turn your kitchen into a culinary command center.</p><p>To celebrate 60 years of "Star Trek", the cookware brand has lovingly crafted a limited-edition collection for fans of the franchise. Or, maybe you're just a fan of Spock (don't worry, there's a mug for that). </p><p>Christopher Scinto, Chief Marketing Officer at Le Creuset says: "With the Le Creuset x Star Trek Collection, we set out to commemorate some of the franchise's most beloved symbols with our signature craftsmanship and iconic colors and designs."</p><p>While there's 12 pieces in the collection that you can check out for a limited time only at Le Creuset stores, <a href="http://LeCreuset.com" target="_blank" rel="nofollow">LeCreuset.com</a>, and <a href="https://www.williams-sonoma.com/" target="_blank" rel="nofollow">Williams-Sonoma.com</a>, I've highlighted my five top picks below.</p><h2 id="what-39-s-in-my-basket">What's in my basket</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="VenG82ejhYRyErJC2Qj59Q" name="Le Creuset x Star Treck Collection 2" alt="The Le Creuset and Star Trek Collection" src="https://cdn.mos.cms.futurecdn.net/VenG82ejhYRyErJC2Qj59Q.jpg" mos="" align="middle" fullscreen="" width="1920" height="1080" attribution="" endorsement="" class=""></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Le Creuset/CBS)</span></figcaption></figure><p>The full Le Creuset x "Star Trek" collection ranges from $35 to $500, but with 12 items there's hopefully something for every price range. Before we jump into my basket, I want to give a special mention to the Mini Cocottes for Balok, Gorn and Talosian. While they're not in my basket right now, they're certainly worth checking out if you're a fan.</p><div class="product"><a data-dimension112="433de4a6-aaba-11f1-b35b-5b7496d67c8f" data-action="Deal Block" data-label="Spock Mug" data-dimension48="Spock Mug" data-dimension25="$35" href="https://www.lecreuset.com/round-dutch-oven/21177US.html" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:535px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="CCp3WkA7DwRqzDscYBz35T" name="lecreuset_spockmug" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/CCp3WkA7DwRqzDscYBz35T.jpg" mos="" align="middle" fullscreen="" width="535" height="535" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.lecreuset.com/round-dutch-oven/21177US.html" target="_blank" rel="nofollow" data-dimension112="433de4a6-aaba-11f1-b35b-5b7496d67c8f" data-action="Deal Block" data-label="Spock Mug" data-dimension48="Spock Mug" data-dimension25="$35">Spock Mug: $35</a></strong><br>Le Creuset transforms the everyday mug handle into Spock's infamous ear in this unique design. While missing the usual gap for your fingers in the handle, it replaces it with the fun of gripping onto Spock's most defining feature.<a class="view-deal button" href="https://www.lecreuset.com/round-dutch-oven/21177US.html" target="_blank" rel="nofollow" data-dimension112="433de4a6-aaba-11f1-b35b-5b7496d67c8f" data-action="Deal Block" data-label="Spock Mug" data-dimension48="Spock Mug" data-dimension25="$35">View Deal</a></p></div><div class="product"><a data-dimension112="433de5f0-aaba-11f1-bbcc-932ffe9bbb44" data-action="Deal Block" data-label="Live Long and Prosper Spoon Rest" data-dimension48="Live Long and Prosper Spoon Rest" data-dimension25="$55" href="https://www.lecreuset.com/pepper-mill/44001.html" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:535px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="j3CT7XhbZUE9aXfNvK9Pm8" name="lecreuset_spoonrest" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/j3CT7XhbZUE9aXfNvK9Pm8.jpg" mos="" align="middle" fullscreen="" width="535" height="535" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.lecreuset.com/pepper-mill/44001.html" target="_blank" rel="nofollow" data-dimension112="433de5f0-aaba-11f1-bbcc-932ffe9bbb44" data-action="Deal Block" data-label="Live Long and Prosper Spoon Rest" data-dimension48="Live Long and Prosper Spoon Rest" data-dimension25="$55">Live Long and Prosper Spoon Rest: $55</a></strong><br>It wouldn't be <em>Star Trek</em> without the emblematic four-finger split. The Vulcan salute can become a kitchen staple instead taking on new life as a spoon rest that'll subtly tell your friends and family that you're a Trekkie – and a chef.<a class="view-deal button" href="https://www.lecreuset.com/pepper-mill/44001.html" target="_blank" rel="nofollow" data-dimension112="433de5f0-aaba-11f1-bbcc-932ffe9bbb44" data-action="Deal Block" data-label="Live Long and Prosper Spoon Rest" data-dimension48="Live Long and Prosper Spoon Rest" data-dimension25="$55">View Deal</a></p></div><div class="product"><a data-dimension112="433de514-aaba-11f1-840f-63fa391c57df" data-action="Deal Block" data-label="Communi-Grater" data-dimension48="Communi-Grater" data-dimension25="$68" href="https://www.lecreuset.com/signature-skillet/20182US.html" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:535px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="yM3UkLRCCQPiTnkkfysh8T" name="lecreuset_communigrater" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/yM3UkLRCCQPiTnkkfysh8T.jpg" mos="" align="middle" fullscreen="" width="535" height="535" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.lecreuset.com/signature-skillet/20182US.html" target="_blank" rel="nofollow" data-dimension112="433de514-aaba-11f1-840f-63fa391c57df" data-action="Deal Block" data-label="Communi-Grater" data-dimension48="Communi-Grater" data-dimension25="$68">Communi-Grater: $68</a></strong><br>Le Creuset are known more for cookware than they are for kitchen accessories, but there's something extra special about this one. This greater plays on the Communicator with a quirky pun and a unique design to desire.<a class="view-deal button" href="https://www.lecreuset.com/signature-skillet/20182US.html" target="_blank" rel="nofollow" data-dimension112="433de514-aaba-11f1-840f-63fa391c57df" data-action="Deal Block" data-label="Communi-Grater" data-dimension48="Communi-Grater" data-dimension25="$68">View Deal</a></p></div><div class="product"><a data-dimension112="433de668-aaba-11f1-868d-fb080f159d20" data-action="Deal Block" data-label="Galileo Shuttlecraft Rectangular Casserole" data-dimension48="Galileo Shuttlecraft Rectangular Casserole" data-dimension25="$150" href="https://www.lecreuset.com/vancouver-mug/70317US.html" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:535px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="8QvQF6LU5t8Fto3vLjoDn8" name="lecreuset_galileocasserole" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/8QvQF6LU5t8Fto3vLjoDn8.jpg" mos="" align="middle" fullscreen="" width="535" height="535" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.lecreuset.com/vancouver-mug/70317US.html" target="_blank" rel="nofollow" data-dimension112="433de668-aaba-11f1-868d-fb080f159d20" data-action="Deal Block" data-label="Galileo Shuttlecraft Rectangular Casserole" data-dimension48="Galileo Shuttlecraft Rectangular Casserole" data-dimension25="$150">Galileo Shuttlecraft Rectangular Casserole: $150</a></strong><br>My favorite piece from the collection is this retro <em>Star Trek</em> twist on Le Creuset's iconic rectangular casserole dishes. A nod to the 1960s Galileo Shuttlecraft, it's equal parts nostalgia and cookware goodness.<a class="view-deal button" href="https://www.lecreuset.com/vancouver-mug/70317US.html" target="_blank" rel="nofollow" data-dimension112="433de668-aaba-11f1-868d-fb080f159d20" data-action="Deal Block" data-label="Galileo Shuttlecraft Rectangular Casserole" data-dimension48="Galileo Shuttlecraft Rectangular Casserole" data-dimension25="$150">View Deal</a></p></div><div class="product"><a data-dimension112="433de582-aaba-11f1-8881-0ddce702c4bc" data-action="Deal Block" data-label="Klingon Braiser with Klingon Trefoil Knob" data-dimension48="Klingon Braiser with Klingon Trefoil Knob" data-dimension25="$450" href="https://www.lecreuset.com/heritage-3-piece-rectangular-baking-dish-set/ST0098.html" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:535px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="SU5y49orWDCp43mFjBrG6T" name="lecreuset_klingonbraiser" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/SU5y49orWDCp43mFjBrG6T.jpg" mos="" align="middle" fullscreen="" width="535" height="535" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.lecreuset.com/heritage-3-piece-rectangular-baking-dish-set/ST0098.html" target="_blank" rel="nofollow" data-dimension112="433de582-aaba-11f1-8881-0ddce702c4bc" data-action="Deal Block" data-label="Klingon Braiser with Klingon Trefoil Knob" data-dimension48="Klingon Braiser with Klingon Trefoil Knob" data-dimension25="$450">Klingon Braiser with Klingon Trefoil Knob: $450</a></strong><br>And Le Creuset have given another iconic cookware item, the Braiser, a "Star Trek" twist. To commemorate 60 years, it has replaced the trefoil knob with a Klingon emblem whilst embossing a Klingon starship on the lid – all in a striking dark blue.<a class="view-deal button" href="https://www.lecreuset.com/heritage-3-piece-rectangular-baking-dish-set/ST0098.html" target="_blank" rel="nofollow" data-dimension112="433de582-aaba-11f1-8881-0ddce702c4bc" data-action="Deal Block" data-label="Klingon Braiser with Klingon Trefoil Knob" data-dimension48="Klingon Braiser with Klingon Trefoil Knob" data-dimension25="$450">View Deal</a></p></div><ul><li><a href="https://www.tomsguide.com/home/revolutionary-for-homemade-bread-why-i-cant-wait-to-try-le-creusets-new-oval-bread-oven">'Revolutionary for homemade bread': Why I can't wait to try Le Creuset's new oval bread oven</a></li><li><a href="https://www.tomsguide.com/home/cast-iron-skillet-vs-dutch-oven-which-is-better">Cast iron skillet vs Dutch oven — which is better?</a></li><li><a href="https://www.tomsguide.com/home/home-appliances/what-is-a-dutch-oven-everything-you-need-to-know-about-this-kitchen-essential">What is a Dutch oven — everything you need to know about this kitchen essential</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ The aluminum foil refrigerator hack: Does it really cut down on mess? ]]></title>
                                                                                                <dc:content><![CDATA[ <p><a href="https://www.tomsguide.com/how-to/7-surprising-uses-for-aluminum-foil">Aluminum foil</a> is one of the regular kitchen items that gets used in viral hacks, just like <a href="https://www.tomsguide.com/home/i-revived-my-stained-cutlery-with-just-baking-soda-and-aluminium-foil-heres-how">baking soda</a>. Just when you think every possible use has been discovered, another genius trick pops up on your feed. </p><p>It turns out that, apart from <a href="https://www.tomsguide.com/home/gardening/gardeners-are-being-urged-to-put-aluminum-foil-in-their-yard-right-now-and-you-might-be-surprised-why">scaring away pests</a>, <a href="https://www.tomsguide.com/opinion/i-just-beat-the-heat-with-a-dollar2-roll-of-aluminum-foil-heres-how">cooling your home</a>, and even <a href="https://www.tomsguide.com/us/aluminum-foil-wi-fi-extension,news-26097.html">boosting your Wi-Fi signal</a>, foil can play yet another a role in the kitchen — keeping your <a href="https://www.tomsguide.com/us/best-refrigerators,review-6181.html">refrigerator</a> clean and preventing odors. </p><p>Cleaning the refrigerator is an important kitchen task, but while it’s necessary to keep food hygienic, it’s also laborious. So, when I heard about the aluminum foil hack to reduce clean-up time, I was keen to discover more. </p><h2 id="how-aluminum-foil-can-help-in-your-refrigerator">How aluminum foil can help in your refrigerator</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="GMtXHLrsxYo9wwVjUc9rPP" name="aluminum foil" alt="Aluminum foil" src="https://cdn.mos.cms.futurecdn.net/GMtXHLrsxYo9wwVjUc9rPP.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>If you don’t clean out your refrigerator regularly, over time food crumbs and spills create a mess and also encourage mold and bacteria. This is where the aluminum foil hack comes in. </p><p>By placing aluminum foil on your refrigerator shelves, you create an extra layer of protection that helps reduce residue buildup and bad odors. The foil itself won’t stop those spills, splashes and smells, but it does make your refrigerator easier to clean. </p><p>So when your pasta sauce splashes out of its container or your milk spills, the mess lands on the aluminum foil rather than your shelf and doesn’t collect in any awkward-to-clean crevices that trap odors.</p><p>Then, instead of scrubbing your refrigerator shelves, you can remove and replace the aluminum foil.</p><div class="product"><a data-dimension112="990e3ac6-aaaf-11f1-9f3e-a1a0d7ddbae9" data-action="Deal Block" data-label="36-inch Smart Freestanding French Door Refrigerator" data-dimension48="36-inch Smart Freestanding French Door Refrigerator" data-dimension25="$1895" href="https://www.ajmadison.com/cgi-bin/ajmadison/LRFLC2706S.html?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:804px;"><p class="vanilla-image-block" style="padding-top:100.12%;"><img id="nZfPtAQXgav2cTgb8uCbCP" name="Screenshot-2024-09-18-104059edit.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/nZfPtAQXgav2cTgb8uCbCP.jpg" mos="" align="middle" fullscreen="" width="804" height="805" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.ajmadison.com/cgi-bin/ajmadison/LRFLC2706S.html?" target="_blank" rel="nofollow" data-dimension112="990e3ac6-aaaf-11f1-9f3e-a1a0d7ddbae9" data-action="Deal Block" data-label="36-inch Smart Freestanding French Door Refrigerator" data-dimension48="36-inch Smart Freestanding French Door Refrigerator" data-dimension25="$1895">36-inch Smart Freestanding French Door Refrigerator: was $3199 now $1895</a></strong><br>This elegant French-door refrigerator offers the convenience of a water dispenser hidden inside the appliance to keep the external look sleek. It also features a smudge-resistant finish and smart pull handles to make getting in and out of the freezer easy. What’s more, connecting this appliance to the ThinQ app allows you to get notifications about usage and maintenance.<a class="view-deal button" href="https://www.ajmadison.com/cgi-bin/ajmadison/LRFLC2706S.html?" target="_blank" rel="nofollow" data-dimension112="990e3ac6-aaaf-11f1-9f3e-a1a0d7ddbae9" data-action="Deal Block" data-label="36-inch Smart Freestanding French Door Refrigerator" data-dimension48="36-inch Smart Freestanding French Door Refrigerator" data-dimension25="$1895">View Deal</a></p></div><h2 id="how-to-use-the-aluminum-foil-in-your-refrigerator">How to use the aluminum foil in your refrigerator</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="HQ9VmtJRmv4HNiWUpJTAU" name="Aluminum foil on shelf in refrigerator" alt="Aluminum foil on shelf in refrigerator" src="https://cdn.mos.cms.futurecdn.net/HQ9VmtJRmv4HNiWUpJTAU.png" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Camilla Sharman)</span></figcaption></figure><p>Start by giving your <a href="https://www.tomsguide.com/how-to/how-to-clean-a-refrigerator">refrigerator a deep clean</a> to ensure all residue is removed before covering the shelves with the foil. Then take your foil and cut it to size so it covers your shelves neatly, with minimal overhang. Just make sure you are not obstructing any ventilation areas.</p><p>I tried it out on one of my refrigerator shelves (see above), and found the foil surprisingly easy to fix. The cold shelf almost invited the foil to sit snugly against it.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-W0EMkO"></div>                            </div>                            <script src="https://kwizly.com/embed/W0EMkO.js" async></script><h2 id="what-do-i-think-of-this-aluminum-foil-hack">What do I think of this aluminum foil hack?</h2><p><strong>Your refrigerator still needs cleaning</strong><br>Covering your refrigerator shelves with aluminum foil certainly shouldn’t replace cleaning your refrigerator regularly, but if there are areas prone to spills, I can see it would prevent those in-between cleanups. </p><p>For me, it’s the milk spills that quickly turn into bad odors, so I would be happy to use aluminum foil where I store my milk.</p><p><strong>It doesn't look cool</strong><br>I’ve recently purchased a new integrated refrigerator as part of a kitchen renovation, so I’m not too sure about the aesthetics of this hack. I enjoy seeing my brand-new shelves without the foil covering them up.</p><p><strong>Does it really save time?</strong><br>While one of the reasons behind the hack is to prevent odors from food spills and reduce cleanup time, you still need to replace the foil. To me, it would be quicker to clean up the mess than to fiddle about cutting out pieces of aluminum foil.</p><p><strong>Over to you</strong><br>I’d love to know your thoughts on this refrigerator hack. Will you be trying it out, or do you think it’s a waste of time and aluminum foil? Please leave your thoughts in the comments below.</p><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h3><ul><li><a href="https://proof.vanilla.tools/tomsguide/articles/edit/FXB83FEaoNVc7idsisps2k">People are putting aluminum foil in their washing machines — I asked an appliance expert if it’s safe</a></li><li><a href="https://www.tomsguide.com/how-to/how-often-should-you-clean-your-refrigerator-heres-what-the-experts-say">How often should you clean your refrigerator? Here’s what the experts say</a></li><li><a href="https://www.tomsguide.com/how-to/7-refrigerator-mistakes-you-never-knew-you-were-making">Don’t make these 7 refrigerator mistakes</a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/home/home-appliances/the-aluminum-foil-refrigerator-hack-does-it-really-cut-down-on-mess</link>
                                                                            <description>
                            <![CDATA[ Putting aluminum foil to use in your fridge can apparently stop the build-up of mold and bacteria. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">vy32j9VC5NqMHbYtsyQ6FC</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/8qY6pbEzHU9H37LtUDVvDi-1280-80.png" type="image/png" length="0"></enclosure>
                                                                        <pubDate>Mon, 07 Sep 2026 16:34:47 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Home Appliances]]></category>
                                                    <category><![CDATA[Home]]></category>
                                                                                                <author><![CDATA[ camilla.sharman@futurenet.com (Camilla Sharman) ]]></author>                    <dc:creator><![CDATA[ Camilla Sharman ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/nY4nvWzofHKHpvzAqN5LVH.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Camilla is the Homes Staff Writer and covers everything to do with homes and gardens. She has a wealth of editorial experience, mounting over 30 years, and covers news and features, tests products for reviews and compiles buying guides.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;p&gt;Her work has appeared in business and consumer titles, including Ideal Home, Real Homes, House Beautiful, Homebuilding &amp;amp; Renovation, and Kitchen &amp;amp; Bathroom Business. She’s even appeared on the cover of Your Home, writing about her own house renovation.&lt;/p&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;p&gt;Although she’s obsessed with decorating her home, she also enjoys baking and trying out the latest kitchen appliances. But when she’s not inside, you’ll find her pottering about in her yard, tending to her vegetable patch or taking in her prized hydrangeas. She also enjoys keeping fit, and if she&#039;s not on a spin bike trying to keep up with the class, she&#039;ll be in the pool, or trying to perfect her headstand in a yoga class.&lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                <media:content type="image/png" url="https://cdn.mos.cms.futurecdn.net/8qY6pbEzHU9H37LtUDVvDi-1280-80.png">
                                                            <media:credit><![CDATA[Tom&amp;#39;s Guide / Created with Gemini AI]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Fridge shelves covered in aluminum foil]]></media:description>                                                            <media:text><![CDATA[Fridge shelves covered in aluminum foil]]></media:text>
                                <media:title type="plain"><![CDATA[Fridge shelves covered in aluminum foil]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/8qY6pbEzHU9H37LtUDVvDi-1280-80.png" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p><a href="https://www.tomsguide.com/how-to/7-surprising-uses-for-aluminum-foil">Aluminum foil</a> is one of the regular kitchen items that gets used in viral hacks, just like <a href="https://www.tomsguide.com/home/i-revived-my-stained-cutlery-with-just-baking-soda-and-aluminium-foil-heres-how">baking soda</a>. Just when you think every possible use has been discovered, another genius trick pops up on your feed. </p><p>It turns out that, apart from <a href="https://www.tomsguide.com/home/gardening/gardeners-are-being-urged-to-put-aluminum-foil-in-their-yard-right-now-and-you-might-be-surprised-why">scaring away pests</a>, <a href="https://www.tomsguide.com/opinion/i-just-beat-the-heat-with-a-dollar2-roll-of-aluminum-foil-heres-how">cooling your home</a>, and even <a href="https://www.tomsguide.com/us/aluminum-foil-wi-fi-extension,news-26097.html">boosting your Wi-Fi signal</a>, foil can play yet another a role in the kitchen — keeping your <a href="https://www.tomsguide.com/us/best-refrigerators,review-6181.html">refrigerator</a> clean and preventing odors. </p><p>Cleaning the refrigerator is an important kitchen task, but while it’s necessary to keep food hygienic, it’s also laborious. So, when I heard about the aluminum foil hack to reduce clean-up time, I was keen to discover more. </p><h2 id="how-aluminum-foil-can-help-in-your-refrigerator">How aluminum foil can help in your refrigerator</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="GMtXHLrsxYo9wwVjUc9rPP" name="aluminum foil" alt="Aluminum foil" src="https://cdn.mos.cms.futurecdn.net/GMtXHLrsxYo9wwVjUc9rPP.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>If you don’t clean out your refrigerator regularly, over time food crumbs and spills create a mess and also encourage mold and bacteria. This is where the aluminum foil hack comes in. </p><p>By placing aluminum foil on your refrigerator shelves, you create an extra layer of protection that helps reduce residue buildup and bad odors. The foil itself won’t stop those spills, splashes and smells, but it does make your refrigerator easier to clean. </p><p>So when your pasta sauce splashes out of its container or your milk spills, the mess lands on the aluminum foil rather than your shelf and doesn’t collect in any awkward-to-clean crevices that trap odors.</p><p>Then, instead of scrubbing your refrigerator shelves, you can remove and replace the aluminum foil.</p><div class="product"><a data-dimension112="990e3ac6-aaaf-11f1-9f3e-a1a0d7ddbae9" data-action="Deal Block" data-label="36-inch Smart Freestanding French Door Refrigerator" data-dimension48="36-inch Smart Freestanding French Door Refrigerator" data-dimension25="$1895" href="https://www.ajmadison.com/cgi-bin/ajmadison/LRFLC2706S.html?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:804px;"><p class="vanilla-image-block" style="padding-top:100.12%;"><img id="nZfPtAQXgav2cTgb8uCbCP" name="Screenshot-2024-09-18-104059edit.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/nZfPtAQXgav2cTgb8uCbCP.jpg" mos="" align="middle" fullscreen="" width="804" height="805" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.ajmadison.com/cgi-bin/ajmadison/LRFLC2706S.html?" target="_blank" rel="nofollow" data-dimension112="990e3ac6-aaaf-11f1-9f3e-a1a0d7ddbae9" data-action="Deal Block" data-label="36-inch Smart Freestanding French Door Refrigerator" data-dimension48="36-inch Smart Freestanding French Door Refrigerator" data-dimension25="$1895">36-inch Smart Freestanding French Door Refrigerator: was $3199 now $1895</a></strong><br>This elegant French-door refrigerator offers the convenience of a water dispenser hidden inside the appliance to keep the external look sleek. It also features a smudge-resistant finish and smart pull handles to make getting in and out of the freezer easy. What’s more, connecting this appliance to the ThinQ app allows you to get notifications about usage and maintenance.<a class="view-deal button" href="https://www.ajmadison.com/cgi-bin/ajmadison/LRFLC2706S.html?" target="_blank" rel="nofollow" data-dimension112="990e3ac6-aaaf-11f1-9f3e-a1a0d7ddbae9" data-action="Deal Block" data-label="36-inch Smart Freestanding French Door Refrigerator" data-dimension48="36-inch Smart Freestanding French Door Refrigerator" data-dimension25="$1895">View Deal</a></p></div><h2 id="how-to-use-the-aluminum-foil-in-your-refrigerator">How to use the aluminum foil in your refrigerator</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="HQ9VmtJRmv4HNiWUpJTAU" name="Aluminum foil on shelf in refrigerator" alt="Aluminum foil on shelf in refrigerator" src="https://cdn.mos.cms.futurecdn.net/HQ9VmtJRmv4HNiWUpJTAU.png" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Camilla Sharman)</span></figcaption></figure><p>Start by giving your <a href="https://www.tomsguide.com/how-to/how-to-clean-a-refrigerator">refrigerator a deep clean</a> to ensure all residue is removed before covering the shelves with the foil. Then take your foil and cut it to size so it covers your shelves neatly, with minimal overhang. Just make sure you are not obstructing any ventilation areas.</p><p>I tried it out on one of my refrigerator shelves (see above), and found the foil surprisingly easy to fix. The cold shelf almost invited the foil to sit snugly against it.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-W0EMkO"></div>                            </div>                            <script src="https://kwizly.com/embed/W0EMkO.js" async></script><h2 id="what-do-i-think-of-this-aluminum-foil-hack">What do I think of this aluminum foil hack?</h2><p><strong>Your refrigerator still needs cleaning</strong><br>Covering your refrigerator shelves with aluminum foil certainly shouldn’t replace cleaning your refrigerator regularly, but if there are areas prone to spills, I can see it would prevent those in-between cleanups. </p><p>For me, it’s the milk spills that quickly turn into bad odors, so I would be happy to use aluminum foil where I store my milk.</p><p><strong>It doesn't look cool</strong><br>I’ve recently purchased a new integrated refrigerator as part of a kitchen renovation, so I’m not too sure about the aesthetics of this hack. I enjoy seeing my brand-new shelves without the foil covering them up.</p><p><strong>Does it really save time?</strong><br>While one of the reasons behind the hack is to prevent odors from food spills and reduce cleanup time, you still need to replace the foil. To me, it would be quicker to clean up the mess than to fiddle about cutting out pieces of aluminum foil.</p><p><strong>Over to you</strong><br>I’d love to know your thoughts on this refrigerator hack. Will you be trying it out, or do you think it’s a waste of time and aluminum foil? Please leave your thoughts in the comments below.</p><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h3><ul><li><a href="https://proof.vanilla.tools/tomsguide/articles/edit/FXB83FEaoNVc7idsisps2k">People are putting aluminum foil in their washing machines — I asked an appliance expert if it’s safe</a></li><li><a href="https://www.tomsguide.com/how-to/how-often-should-you-clean-your-refrigerator-heres-what-the-experts-say">How often should you clean your refrigerator? Here’s what the experts say</a></li><li><a href="https://www.tomsguide.com/how-to/7-refrigerator-mistakes-you-never-knew-you-were-making">Don’t make these 7 refrigerator mistakes</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ I just tried Ecovacs' robot vacuum of the future — and as a pet owner, I'm beyond floored ]]></title>
                                                                                                <dc:content><![CDATA[ <p>As the joyful caregiver for an 18-pound Long-haired Chihuahua-Dachshund-Miniature Pinscher mix, I know a thing or two about dirty floors. Belvedere, mensch that he is, sheds like a madman. He’s also known to be a bit messy when it comes to wolfing down delicacies like raspberries, his favorite treat.</p><p>As a result, my partner and I spend countless hours a week vacuuming and swiffering to keep the dog-hair tumbleweeds and sticky floors to a minimum. If only there were a robot that could actually handle cleaning up after my all-time best pal. </p><p>Enter: The Ecovacs Deebot X12S OmniCycle.</p><h2 id="1-it-s-a-high-power-vacuum-and-wet-mop-in-one">1. It’s a high-power vacuum and wet mop in one</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="tX3t9wGKJp5B6xkFpwg8YX" name="EcoVacs-X12S-03" alt="close-up of the Ecovacs Deebot X12S robotm vacuum at IFA 2026 in Berlin" src="https://cdn.mos.cms.futurecdn.net/tX3t9wGKJp5B6xkFpwg8YX.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Dan Bracaglia/Tom's Guide)</span></figcaption></figure><p>I just got my hands on the new Ecovacs Deebot X12S OmniCycle robot vacuum at the <a href="https://www.tomsguide.com/tech-events/best-of-ifa-2026-we-found-the-26-top-new-gadgets">IFA show in Berlin</a>, and dear readers, I am floored (some pun intended) by all its features and specs. </p><p>It’s been nearly a decade since I seriously considered purchasing a robot vacuum to assist around the house, and now I’m questioning why; they've really come a long way! </p><p>Make no mistake: the Deebot X12S OmniCycle is Ecovacs’ creme de la creme of consumer robot vacuums, but it’s honestly so much more than that. Sure, it’s got enough power to suck a bad joke right out of the air (or 27,000 Pa of suction), but it’s also a full-blown, automated wet mop with automatic spray action. </p><p>Translation: the grime on your hardwood floors and carpets stands no chance against this bad boy. For sticky messes, built-in sprayers soak down the gunk, while a plush, wet/dry roller underneath soaks up all the nastiness, leaving a floor so shiny, you’ll be seeing your own reflection. </p><h2 id="2-auto-cleaning-eliminates-the-yuck-factor">2. Auto-cleaning eliminates the ‘yuck’ factor</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="DJjK9QyTHufLePYAdruyFX" name="EcoVacs-X12S-06" alt="close-up of the Ecovacs Deebot X12S robotm vacuum at IFA 2026 in Berlin" src="https://cdn.mos.cms.futurecdn.net/DJjK9QyTHufLePYAdruyFX.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Dan Bracaglia/Tom's Guide)</span></figcaption></figure><p>But wait, a robot vacuum that doubles as a robot mop must require all sorts of regular maintenance? No, sir. Ecovacs sells a couple of different docks for the X12S, but all of them feature a thorough auto-clean function that uses pressure washing to thoroughly sanitize the robot’s roller and other mopping components. </p><h2 id="3-rapid-charging-limits-cleaning-downtime">3. Rapid-charging limits cleaning downtime </h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="9viaVWXWJ7DH7AYpKCLzNo" name="Ecovacs-DEEBOT-X12S-b" alt="Close-up of the new Ecovacs Deebot X12S robot vacuum at IFA 2026 in Berlin" src="https://cdn.mos.cms.futurecdn.net/9viaVWXWJ7DH7AYpKCLzNo.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Dan Bracaglia/Tom's Guide)</span></figcaption></figure><p>Need a lot of rooms cleaned? No problem. The Ecovacs Deebot X12S OmniCycle supports rapid charging while docked. So, in the five or so minutes it takes to run the mop auto-clean function, your robot vac is also topping up the battery to power ahead cleaning the next room.</p><p>Moreover, thanks to rapid charging, the Ecovacs Deebot X12S OmniCycle sports a less bulky battery than the robot vacuums of yore, while also being able to clean more rooms back-to-back. </p><h2 id="4-extra-attention-for-edges-and-baseboards">4. Extra attention for edges and baseboards</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="QzK8sJFUrPvFgkTpLqXhQX" name="EcoVacs-X12S-01" alt="close-up of the Ecovacs Deebot X12S robotm vacuum at IFA 2026 in Berlin" src="https://cdn.mos.cms.futurecdn.net/QzK8sJFUrPvFgkTpLqXhQX.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Dan Bracaglia/Tom's Guide)</span></figcaption></figure><p>I’m a bit of a neat freak, and scuzzy baseboards are my Achilles' heel. Fortunately, the Ecovacs Deebot X12S OmniCycle is designed to pay particular attention to baseboards and floor/carpet edges. But how? An admittedly cute yet highly effective little sweeper arm uses onboard sensors to determine where the floor ends and then scoops any/all debris into the robot’s suction mouth as it makes its rounds.</p><h2 id="will-the-ecovacs-deebot-x12s-be-belvedere-approved">Will the Ecovacs Deebot X12S be Belvedere-approved?</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="kMoaAMDyV87Fabzktem9Bo" name="Belvedere" alt="A handsome, 18-lb mixed pup named Belvedere looking dapper as heck" src="https://cdn.mos.cms.futurecdn.net/kMoaAMDyV87Fabzktem9Bo.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Dan Bracaglia)</span></figcaption></figure><p>Ultimately, there’s only one way to know for sure whether or not Ecovacs' latest 2-in-1 robot vacuum will <em>actually</em> be up to the task of tidying up after my rambunctious lil furry monster. </p><p>With that in mind, stay tuned for my full Ecovacs Deebot X12S review, coming soon. </p><h2 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h2><ul><li><a href="https://www.tomsguide.com/wellness/smart-rings/i-just-went-hands-on-with-the-new-circular-ring-3-and-it-beats-the-oura-ring-5-in-3-big-ways">I just went hands-on with the new Circular Ring 3 — and it beats the Oura Ring 5 in 3 big ways</a></li><li><a href="https://www.tomsguide.com/home/smart-home/forget-robot-vacuums-ecovacs-most-exciting-product-at-ces-2026-was-its-upcoming-ai-powered-pet-companion">Forget robot vacuums — Ecovacs' most exciting product at CES 2026 was its upcoming AI-powered pet companion</a></li><li><a href="https://www.tomsguide.com/home/ecovacs-deebot-n20-review">'Cleaning up after my pet has never been easier': I just tested this sub-$200 robot vacuum that's perfect for beginners</a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/home/home-appliances/i-just-tried-ecovacs-robot-vacuum-of-the-future-and-as-a-pet-owner-im-beyond-floored</link>
                                                                            <description>
                            <![CDATA[ The Ecovacs Deebot X12S OmniCycle is a turbo-charged, self-cleaning robot that doubles as both a vacuum and a wet mop. But can it actually keep up with my furball of a dog? ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">5r2AtvGRVqA98gkWNqhk3N</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/W5HyjGZP4mgnc59BmbSGMX-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Sat, 05 Sep 2026 10:38:57 +0000</pubDate>                                                                                                                                <updated>Sat, 05 Sep 2026 10:46:06 +0000</updated>
                                                                                                                                            <category><![CDATA[Home Appliances]]></category>
                                                    <category><![CDATA[Home]]></category>
                                                                                                <author><![CDATA[ dan.bracaglia@futurenet.com (Dan Bracaglia) ]]></author>                    <dc:creator><![CDATA[ Dan Bracaglia ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/3Ev8EFrheNxPemMWSBaKcK.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;&lt;br&gt;&lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/W5HyjGZP4mgnc59BmbSGMX-1280-80.jpg">
                                                            <media:credit><![CDATA[Dan Bracaglia/Tom&amp;#39;s Guide]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[close-up of the Ecovacs Deebot X12S robotm vacuum at IFA 2026 in Berlin]]></media:description>                                                            <media:text><![CDATA[close-up of the Ecovacs Deebot X12S robotm vacuum at IFA 2026 in Berlin]]></media:text>
                                <media:title type="plain"><![CDATA[close-up of the Ecovacs Deebot X12S robotm vacuum at IFA 2026 in Berlin]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/W5HyjGZP4mgnc59BmbSGMX-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>As the joyful caregiver for an 18-pound Long-haired Chihuahua-Dachshund-Miniature Pinscher mix, I know a thing or two about dirty floors. Belvedere, mensch that he is, sheds like a madman. He’s also known to be a bit messy when it comes to wolfing down delicacies like raspberries, his favorite treat.</p><p>As a result, my partner and I spend countless hours a week vacuuming and swiffering to keep the dog-hair tumbleweeds and sticky floors to a minimum. If only there were a robot that could actually handle cleaning up after my all-time best pal. </p><p>Enter: The Ecovacs Deebot X12S OmniCycle.</p><h2 id="1-it-s-a-high-power-vacuum-and-wet-mop-in-one">1. It’s a high-power vacuum and wet mop in one</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="tX3t9wGKJp5B6xkFpwg8YX" name="EcoVacs-X12S-03" alt="close-up of the Ecovacs Deebot X12S robotm vacuum at IFA 2026 in Berlin" src="https://cdn.mos.cms.futurecdn.net/tX3t9wGKJp5B6xkFpwg8YX.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Dan Bracaglia/Tom's Guide)</span></figcaption></figure><p>I just got my hands on the new Ecovacs Deebot X12S OmniCycle robot vacuum at the <a href="https://www.tomsguide.com/tech-events/best-of-ifa-2026-we-found-the-26-top-new-gadgets">IFA show in Berlin</a>, and dear readers, I am floored (some pun intended) by all its features and specs. </p><p>It’s been nearly a decade since I seriously considered purchasing a robot vacuum to assist around the house, and now I’m questioning why; they've really come a long way! </p><p>Make no mistake: the Deebot X12S OmniCycle is Ecovacs’ creme de la creme of consumer robot vacuums, but it’s honestly so much more than that. Sure, it’s got enough power to suck a bad joke right out of the air (or 27,000 Pa of suction), but it’s also a full-blown, automated wet mop with automatic spray action. </p><p>Translation: the grime on your hardwood floors and carpets stands no chance against this bad boy. For sticky messes, built-in sprayers soak down the gunk, while a plush, wet/dry roller underneath soaks up all the nastiness, leaving a floor so shiny, you’ll be seeing your own reflection. </p><h2 id="2-auto-cleaning-eliminates-the-yuck-factor">2. Auto-cleaning eliminates the ‘yuck’ factor</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="DJjK9QyTHufLePYAdruyFX" name="EcoVacs-X12S-06" alt="close-up of the Ecovacs Deebot X12S robotm vacuum at IFA 2026 in Berlin" src="https://cdn.mos.cms.futurecdn.net/DJjK9QyTHufLePYAdruyFX.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Dan Bracaglia/Tom's Guide)</span></figcaption></figure><p>But wait, a robot vacuum that doubles as a robot mop must require all sorts of regular maintenance? No, sir. Ecovacs sells a couple of different docks for the X12S, but all of them feature a thorough auto-clean function that uses pressure washing to thoroughly sanitize the robot’s roller and other mopping components. </p><h2 id="3-rapid-charging-limits-cleaning-downtime">3. Rapid-charging limits cleaning downtime </h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="9viaVWXWJ7DH7AYpKCLzNo" name="Ecovacs-DEEBOT-X12S-b" alt="Close-up of the new Ecovacs Deebot X12S robot vacuum at IFA 2026 in Berlin" src="https://cdn.mos.cms.futurecdn.net/9viaVWXWJ7DH7AYpKCLzNo.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Dan Bracaglia/Tom's Guide)</span></figcaption></figure><p>Need a lot of rooms cleaned? No problem. The Ecovacs Deebot X12S OmniCycle supports rapid charging while docked. So, in the five or so minutes it takes to run the mop auto-clean function, your robot vac is also topping up the battery to power ahead cleaning the next room.</p><p>Moreover, thanks to rapid charging, the Ecovacs Deebot X12S OmniCycle sports a less bulky battery than the robot vacuums of yore, while also being able to clean more rooms back-to-back. </p><h2 id="4-extra-attention-for-edges-and-baseboards">4. Extra attention for edges and baseboards</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="QzK8sJFUrPvFgkTpLqXhQX" name="EcoVacs-X12S-01" alt="close-up of the Ecovacs Deebot X12S robotm vacuum at IFA 2026 in Berlin" src="https://cdn.mos.cms.futurecdn.net/QzK8sJFUrPvFgkTpLqXhQX.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Dan Bracaglia/Tom's Guide)</span></figcaption></figure><p>I’m a bit of a neat freak, and scuzzy baseboards are my Achilles' heel. Fortunately, the Ecovacs Deebot X12S OmniCycle is designed to pay particular attention to baseboards and floor/carpet edges. But how? An admittedly cute yet highly effective little sweeper arm uses onboard sensors to determine where the floor ends and then scoops any/all debris into the robot’s suction mouth as it makes its rounds.</p><h2 id="will-the-ecovacs-deebot-x12s-be-belvedere-approved">Will the Ecovacs Deebot X12S be Belvedere-approved?</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="kMoaAMDyV87Fabzktem9Bo" name="Belvedere" alt="A handsome, 18-lb mixed pup named Belvedere looking dapper as heck" src="https://cdn.mos.cms.futurecdn.net/kMoaAMDyV87Fabzktem9Bo.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Dan Bracaglia)</span></figcaption></figure><p>Ultimately, there’s only one way to know for sure whether or not Ecovacs' latest 2-in-1 robot vacuum will <em>actually</em> be up to the task of tidying up after my rambunctious lil furry monster. </p><p>With that in mind, stay tuned for my full Ecovacs Deebot X12S review, coming soon. </p><h2 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h2><ul><li><a href="https://www.tomsguide.com/wellness/smart-rings/i-just-went-hands-on-with-the-new-circular-ring-3-and-it-beats-the-oura-ring-5-in-3-big-ways">I just went hands-on with the new Circular Ring 3 — and it beats the Oura Ring 5 in 3 big ways</a></li><li><a href="https://www.tomsguide.com/home/smart-home/forget-robot-vacuums-ecovacs-most-exciting-product-at-ces-2026-was-its-upcoming-ai-powered-pet-companion">Forget robot vacuums — Ecovacs' most exciting product at CES 2026 was its upcoming AI-powered pet companion</a></li><li><a href="https://www.tomsguide.com/home/ecovacs-deebot-n20-review">'Cleaning up after my pet has never been easier': I just tested this sub-$200 robot vacuum that's perfect for beginners</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ I just tried the world’s first AI espresso machine — I'm a coffee snob, and it was surprisingly... good? ]]></title>
                                                                                                <dc:content><![CDATA[ <p>As a self-confessed coffee snob and director of Tom's Guide's <a href="https://www.tomsguide.com/tag/the-coffee-lab">The Coffee Lab</a>, I'm always testing out new espresso products. At <a href="https://www.tomsguide.com/tag/ifa-2026">IFA 2026</a>, I tried nunc., an AI-assisted espresso machine. Yes, an AI espresso machine. </p><p>So what does the AI in nunc. actually do? Instead of having to manually dial in your beans, nunc. uses an NFC code to analyze pre-packaged, nunc.-branded beans (you can also use your own beans). Then, the machine analyzes humidity, heat, bean size, and basically every other variable to grind to the perfect particle size. As someone who loves espresso but <em>hates</em> dialing in (why does it take so long sometimes?), I was excited to try this out. But as someone skeptical of AI at best, I had my reservations. </p><p>I didn't want nunc. to take away the art of making coffee. That's so human and personalized that it's impossible for AI to copy. Luckily, though, nunc. proved me wrong. Here's what happened when I tried it.</p><h2 id="how-does-nunc-work">How does nunc. work?</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="kF8Kb6n2kBm3dGRVNXZRxn" name="nunc coffee 3" alt="the nunc. espresso machine with AI assisted dialling in" src="https://cdn.mos.cms.futurecdn.net/kF8Kb6n2kBm3dGRVNXZRxn.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Erin Bashford)</span></figcaption></figure><p>As I mentioned above, every nunc.-branded bean hopper has an NFC code, exactly like a <a href="https://www.tomsguide.com/home/coffee-makers/nespresso-vertuo-up-review">Nespresso Vertuo</a> pod. The machine reads this NFC code to analyze the roast date, roast type, bean type, and processing type, and work out precisely how to grind those specific beans. Then, it analyzes the environment — heat, humidity — to finalize the optimal grind. </p><p>This means the grind size will change from morning to evening, or even hour to hour. If you have an espresso at 6 a.m., when the air in your house is dewy and humid, the grind size will be different from your 1 p.m. espresso, sun shining overhead, A/C running. </p><p>Of course, if you have the companion app, you can input information about any beans. </p><h2 id="how-is-nunc-different-from-a-normal-espresso-machine">How is nunc. different from a normal espresso machine?</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="82wdT3Q2NSfh74EGRmjRun" name="nunc coffee 4" alt="the nunc. espresso machine with AI assisted dialling in" src="https://cdn.mos.cms.futurecdn.net/82wdT3Q2NSfh74EGRmjRun.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Erin Bashford)</span></figcaption></figure><p>In terms of functionality, nunc. works just like any other espresso machine. Think about it like this: it's almost like a superautomatic — <a href="https://www.tomsguide.com/home/coffee-makers/jura-c8-coffee-machine-review">Jura</a>, <a href="https://www.tomsguide.com/home/home-appliances/delonghi-rivelia-review">De'Longhi Rivelia</a> — but a totally manual machine. All it does <em>for you</em> is choose the ideal grind size. Honestly, dialling in beans is the worst part of espresso making for me, so I'm completely on board. </p><p>You tamp, insert the portafilter into the grouphead, and can pre-infuse the beans yourself. You can either steam the milk automatically (like the <a href="https://www.tomsguide.com/home/home-appliances/breville-sage-bambino-plus-review">Breville Bambino Plus</a>), or do it manually (any other manual espresso machine). </p><p>You dispose of the spent grounds yourself; you empty the drip tray yourself. The only part that is "AI" is the grinder. </p><h2 id="how-does-nunc-39-s-quot-ai-quot-coffee-taste">How does nunc.'s "AI" coffee taste?</h2><p>nunc. doesn't make "different" coffee. You won't have one sip and go, "Woah, I can totally taste the AI, dude!" It honestly tastes like a human barista was there every step of the way... because there was. <em>You </em>make the coffee. </p><p>Here's a shot of my oat flat white. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="kxPZGdF7Adk8JTzFPLspmn" name="nunc coffee 1" alt="the nunc. espresso machine with AI assisted dialling in" src="https://cdn.mos.cms.futurecdn.net/kxPZGdF7Adk8JTzFPLspmn.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Erin Bashford)</span></figcaption></figure><p>It looks like a normal coffee. The taste was clean, polished, with a soft, dark-chocolate-like bitterness rounding it out. I wanted a little more fruit, acid, and funk — I like a funky coffee — but this was likely because I didn't choose my beans. </p><p>The milk texture was a little too bubbly for me; I like mine more velvety. Like any other espresso machine, though, you can adjust milk texture easily. Just don't aerate it as much.</p><p>I expected to dislike it because I'm extremely particular about my coffee, but this went down a treat. </p><h2 id="where-can-i-get-nunc">Where can I get nunc.?</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="dhd4u4TNfBnADXJFWus9rn" name="nunc coffee 2" alt="the nunc. espresso machine with AI assisted dialling in" src="https://cdn.mos.cms.futurecdn.net/dhd4u4TNfBnADXJFWus9rn.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Erin Bashford)</span></figcaption></figure><p>So, now's the time for the bad news. As I'm writing this, nunc. is only available in Germany. If you happen to be in Germany, <a href="https://nunc.coffee/en/pages/nunc-espresso-machine-buy" target="_blank" rel="nofollow">nunc. costs €2,699</a>. For an extra €149, you get a grinder, the machine, a spring-loaded tamper, a milk jug, a brush, and a tamping mat. </p><p>That price equates to around $3,135, which makes this one of the most expensive home espresso machines I've ever seen. There's the $3,000 <a href="https://www.tomsguide.com/home/coffee-makers/breville-oracle-dual-boiler-review">Breville Dual Boiler</a>, but the nunc. out-prices many of the prosumer models like the Lelit Bianca ($2,999) and <a href="https://www.tomsguide.com/home/coffee-makers/fellow-espresso-series-1-review">Fellow Espresso Series 1</a> ($1,499).</p><p>nunc.'s representative informed me there is no release date for the U.S., U.K., E.U., Canada, Australia — basically any non-German markets. Hopefully, it won't be five years before we're seeing nunc. in our kitchens. I would love to play around with this machine myself. </p><figure class="inline-layout"><div style="min-height: 400px;"><fw-embed-feed channel="toms_guide" playlist="ojE0pK" mode="row" player_placement="bottom-right"></fw-embed-feed></div></figure><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h3><ul><li><a href="https://www.tomsguide.com/home/kitchen-dining/canoly-c16-cold-press-juicer-review"><strong>I’ve been testing the Canoly C16 Cold Press Juicer — it somehow makes juicing complicated</strong></a></li><li><a href="https://www.tomsguide.com/home/home-appliances/i-just-watched-a-robot-vacuum-actually-climb-stairs-it-took-3-minutes-but-those-steps-were-sparkling-after"><strong>I just watched a robot vacuum actually climb stairs — it took 3 minutes but those steps were sparkling after</strong></a></li><li><a href="https://www.tomsguide.com/home/irobots-new-flagship-roomba-creates-an-airtight-seal-with-your-carpet-the-competition-should-be-worried"><strong>iRobot's new flagship Roomba creates an airtight seal with your carpet — the competition should be worried</strong></a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/home/coffee-makers/i-just-tried-the-worlds-first-ai-espresso-machine-im-a-coffee-snob-and-it-was-surprisingly-good</link>
                                                                            <description>
                            <![CDATA[ I tried nunc., the world's first espresso machine that dials in your beans using AI. Is it actually good, or just a gimmick? ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">5V67MkSkyDoVQGsvB7tyXU</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/BXq2XNtTgqcS8bLM7WeWWV-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Fri, 04 Sep 2026 15:57:14 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Coffee Makers]]></category>
                                                    <category><![CDATA[AI]]></category>
                                                    <category><![CDATA[Home]]></category>
                                                    <category><![CDATA[Home Appliances]]></category>
                                                    <category><![CDATA[Kitchen & Dining]]></category>
                                                                                                <author><![CDATA[ erin.bashford@futurenet.com (Erin Bashford) ]]></author>                    <dc:creator><![CDATA[ Erin Bashford ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/rLvJvJVZx43hEzSsJy3BpL.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Erin Bashford is a senior reviews writer at Tom’s Guide. She has a Master’s in Broadcast and Digital Journalism from the University of East Anglia and 7 years of experience reviewing music and events for various publications. She has edited publications such as Outline Magazine’s Guide to Norwich, and she has written for a number of music magazines and websites such as Clash Magazine, Outline Magazine and Dork Magazine. She has a strong interest in audio gear and the music world. &lt;/p&gt;&lt;p&gt;As an ex-barista, Erin is passionate about coffee tech. She also loves finding the best cooking hacks and kitchen appliances, including her beloved Instant Pot. &lt;/p&gt;&lt;p&gt;In her spare time, you can find her reading, practising yoga, hiking, writing fantasy novels, or stressing over NYT Games.&lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/BXq2XNtTgqcS8bLM7WeWWV-1280-80.jpg">
                                                            <media:credit><![CDATA[Erin Bashford]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[a photo of a coffee made on the nunc. ai espresso machine]]></media:description>                                                            <media:text><![CDATA[a photo of a coffee made on the nunc. ai espresso machine]]></media:text>
                                <media:title type="plain"><![CDATA[a photo of a coffee made on the nunc. ai espresso machine]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/BXq2XNtTgqcS8bLM7WeWWV-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>As a self-confessed coffee snob and director of Tom's Guide's <a href="https://www.tomsguide.com/tag/the-coffee-lab">The Coffee Lab</a>, I'm always testing out new espresso products. At <a href="https://www.tomsguide.com/tag/ifa-2026">IFA 2026</a>, I tried nunc., an AI-assisted espresso machine. Yes, an AI espresso machine. </p><p>So what does the AI in nunc. actually do? Instead of having to manually dial in your beans, nunc. uses an NFC code to analyze pre-packaged, nunc.-branded beans (you can also use your own beans). Then, the machine analyzes humidity, heat, bean size, and basically every other variable to grind to the perfect particle size. As someone who loves espresso but <em>hates</em> dialing in (why does it take so long sometimes?), I was excited to try this out. But as someone skeptical of AI at best, I had my reservations. </p><p>I didn't want nunc. to take away the art of making coffee. That's so human and personalized that it's impossible for AI to copy. Luckily, though, nunc. proved me wrong. Here's what happened when I tried it.</p><h2 id="how-does-nunc-work">How does nunc. work?</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="kF8Kb6n2kBm3dGRVNXZRxn" name="nunc coffee 3" alt="the nunc. espresso machine with AI assisted dialling in" src="https://cdn.mos.cms.futurecdn.net/kF8Kb6n2kBm3dGRVNXZRxn.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Erin Bashford)</span></figcaption></figure><p>As I mentioned above, every nunc.-branded bean hopper has an NFC code, exactly like a <a href="https://www.tomsguide.com/home/coffee-makers/nespresso-vertuo-up-review">Nespresso Vertuo</a> pod. The machine reads this NFC code to analyze the roast date, roast type, bean type, and processing type, and work out precisely how to grind those specific beans. Then, it analyzes the environment — heat, humidity — to finalize the optimal grind. </p><p>This means the grind size will change from morning to evening, or even hour to hour. If you have an espresso at 6 a.m., when the air in your house is dewy and humid, the grind size will be different from your 1 p.m. espresso, sun shining overhead, A/C running. </p><p>Of course, if you have the companion app, you can input information about any beans. </p><h2 id="how-is-nunc-different-from-a-normal-espresso-machine">How is nunc. different from a normal espresso machine?</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="82wdT3Q2NSfh74EGRmjRun" name="nunc coffee 4" alt="the nunc. espresso machine with AI assisted dialling in" src="https://cdn.mos.cms.futurecdn.net/82wdT3Q2NSfh74EGRmjRun.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Erin Bashford)</span></figcaption></figure><p>In terms of functionality, nunc. works just like any other espresso machine. Think about it like this: it's almost like a superautomatic — <a href="https://www.tomsguide.com/home/coffee-makers/jura-c8-coffee-machine-review">Jura</a>, <a href="https://www.tomsguide.com/home/home-appliances/delonghi-rivelia-review">De'Longhi Rivelia</a> — but a totally manual machine. All it does <em>for you</em> is choose the ideal grind size. Honestly, dialling in beans is the worst part of espresso making for me, so I'm completely on board. </p><p>You tamp, insert the portafilter into the grouphead, and can pre-infuse the beans yourself. You can either steam the milk automatically (like the <a href="https://www.tomsguide.com/home/home-appliances/breville-sage-bambino-plus-review">Breville Bambino Plus</a>), or do it manually (any other manual espresso machine). </p><p>You dispose of the spent grounds yourself; you empty the drip tray yourself. The only part that is "AI" is the grinder. </p><h2 id="how-does-nunc-39-s-quot-ai-quot-coffee-taste">How does nunc.'s "AI" coffee taste?</h2><p>nunc. doesn't make "different" coffee. You won't have one sip and go, "Woah, I can totally taste the AI, dude!" It honestly tastes like a human barista was there every step of the way... because there was. <em>You </em>make the coffee. </p><p>Here's a shot of my oat flat white. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="kxPZGdF7Adk8JTzFPLspmn" name="nunc coffee 1" alt="the nunc. espresso machine with AI assisted dialling in" src="https://cdn.mos.cms.futurecdn.net/kxPZGdF7Adk8JTzFPLspmn.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Erin Bashford)</span></figcaption></figure><p>It looks like a normal coffee. The taste was clean, polished, with a soft, dark-chocolate-like bitterness rounding it out. I wanted a little more fruit, acid, and funk — I like a funky coffee — but this was likely because I didn't choose my beans. </p><p>The milk texture was a little too bubbly for me; I like mine more velvety. Like any other espresso machine, though, you can adjust milk texture easily. Just don't aerate it as much.</p><p>I expected to dislike it because I'm extremely particular about my coffee, but this went down a treat. </p><h2 id="where-can-i-get-nunc">Where can I get nunc.?</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="dhd4u4TNfBnADXJFWus9rn" name="nunc coffee 2" alt="the nunc. espresso machine with AI assisted dialling in" src="https://cdn.mos.cms.futurecdn.net/dhd4u4TNfBnADXJFWus9rn.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Erin Bashford)</span></figcaption></figure><p>So, now's the time for the bad news. As I'm writing this, nunc. is only available in Germany. If you happen to be in Germany, <a href="https://nunc.coffee/en/pages/nunc-espresso-machine-buy" target="_blank" rel="nofollow">nunc. costs €2,699</a>. For an extra €149, you get a grinder, the machine, a spring-loaded tamper, a milk jug, a brush, and a tamping mat. </p><p>That price equates to around $3,135, which makes this one of the most expensive home espresso machines I've ever seen. There's the $3,000 <a href="https://www.tomsguide.com/home/coffee-makers/breville-oracle-dual-boiler-review">Breville Dual Boiler</a>, but the nunc. out-prices many of the prosumer models like the Lelit Bianca ($2,999) and <a href="https://www.tomsguide.com/home/coffee-makers/fellow-espresso-series-1-review">Fellow Espresso Series 1</a> ($1,499).</p><p>nunc.'s representative informed me there is no release date for the U.S., U.K., E.U., Canada, Australia — basically any non-German markets. Hopefully, it won't be five years before we're seeing nunc. in our kitchens. I would love to play around with this machine myself. </p><figure class="inline-layout"><div style="min-height: 400px;"><fw-embed-feed channel="toms_guide" playlist="ojE0pK" mode="row" player_placement="bottom-right"></fw-embed-feed></div></figure><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h3><ul><li><a href="https://www.tomsguide.com/home/kitchen-dining/canoly-c16-cold-press-juicer-review"><strong>I’ve been testing the Canoly C16 Cold Press Juicer — it somehow makes juicing complicated</strong></a></li><li><a href="https://www.tomsguide.com/home/home-appliances/i-just-watched-a-robot-vacuum-actually-climb-stairs-it-took-3-minutes-but-those-steps-were-sparkling-after"><strong>I just watched a robot vacuum actually climb stairs — it took 3 minutes but those steps were sparkling after</strong></a></li><li><a href="https://www.tomsguide.com/home/irobots-new-flagship-roomba-creates-an-airtight-seal-with-your-carpet-the-competition-should-be-worried"><strong>iRobot's new flagship Roomba creates an airtight seal with your carpet — the competition should be worried</strong></a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ I’ve been testing the Canoly C16 Cold Press Juicer — it somehow makes juicing complicated ]]></title>
                                                                                                <dc:content><![CDATA[ <p>The Canoly C16 Cold Press Juicer promises a convenient way to make juice, nut milk and sorbet. But if anything, it proved to me once and for all that if you want a smooth-sailing juicing experience, you need to spend a little more money. </p><p>The machine is very quiet when operating and has a large hopper, meaning you can load up your ingredients in bulk. It’s also very simple to use with just one switch to control everything. However, I’m not sure any of that makes it worth the hassle. </p><p>It regularly overheats, is incredibly difficult to clean, and clogs frequently. To find out more about my experience with the machine, you can keep reading this full Canoly C16 Cold Press Juicer review.</p><h2 class="article-body__section" id="section-canoly-c16-cold-press-juicer-review-specs"><span>Canoly C16 Cold Press Juicer review: Specs</span></h2><div ><table><tbody><tr><td class="firstcol " ><p><strong>Price</strong></p></td><td  ><p><a href="https://www.canoly.com/products/c16-cold-press-juicer" target="_blank" rel="nofollow">$299</a> / <a href="https://www.amazon.co.uk/Canoly-Press-Juicer-Machines-150mm/dp/B0H1KQNVL3" target="_blank" rel="nofollow">£93</a></p></td></tr><tr><td class="firstcol " ><p><strong>Dimensions</strong></p></td><td  ><p>17.3 x 9.7 x 6.7 inches</p></td></tr><tr><td class="firstcol " ><p><strong>Weight</strong></p></td><td  ><p>13.2 pounds</p></td></tr><tr><td class="firstcol " ><p><strong>Functions</strong></p></td><td  ><p>Juice, Nut milk, sorbet</p></td></tr><tr><td class="firstcol " ><p><strong>Material</strong></p></td><td  ><p>PC and stainless steel</p></td></tr><tr><td class="firstcol " ><p><strong>Capacity</strong></p></td><td  ><p>90 ounces</p></td></tr><tr><td class="firstcol " ><p><strong>Power</strong></p></td><td  ><p>250W</p></td></tr><tr><td class="firstcol " ><p><strong>Dishwasher safe</strong></p></td><td  ><p>Yes</p></td></tr><tr><td class="firstcol " ><p><strong>Warranty</strong></p></td><td  ><p>1-year</p></td></tr></tbody></table></div><h2 class="article-body__section" id="section-canoly-c16-cold-press-juicer-review-price-availability"><span>Canoly C16 Cold Press Juicer review: Price & availability</span></h2><p>The Canoly C16 Cold Press Juicer is available to purchase in the U.S. for <a href="https://www.canoly.com/products/c16-cold-press-juicer" target="_blank" rel="nofollow">$299 directly from the Canoly online store</a>, but it’s often on sale for as low as $199. In the U.K., you can pick it up for <a href="https://www.amazon.co.uk/Canoly-Press-Juicer-Machines-150mm/dp/B0H1KQNVL3" target="_blank" rel="nofollow">£93 from Amazon</a>. </p><p>This is very cheap for a cold press juicer, especially a 3-in-1 machine, as you need a <em>lot</em> of power to make nut milk. For example, the <a href="https://www.tomsguide.com/home/home-appliances/nama-c2-cold-press-juicer-and-blender-review">Nama C2 Cold Press Juicer and Blender</a> can make nut milk with ease, but it retails for $800 — ouch!</p><p>Primarily, the Canoly is a juicer and sits in the market alongside the <a href="https://www.tomsguide.com/home/home-appliances/amzchef-cold-press-juicer-zm1902-review">AMZCHEF Cold Press Juicer</a>, which is priced at $199. This juicer is the same size as the Canoly but is far more controlled and user-friendly whilst remaining a budget option. </p><p>If you’re short on space, you could pick up the Ninja NeverClog Cold Press Juicer for $149, but it’s not the strongest and the process is very fiddly, so I would recommend a model with a hopper, but not the Canoly. Instead, the AMZCHEF would be the best option. </p><h2 class="article-body__section" id="section-canoly-c16-cold-press-juicer-review-design"><span>Canoly C16 Cold Press Juicer review: Design </span></h2><p>The Canoly C16 Cold Press Juicer looks like any other juicer with a hopper. It’s striking and catches your attention immediately because of its size and almost futuristic design — the handle’s shape is almost spaceship-like — although it doesn’t have a flurry of touchscreen buttons like the <a href="https://www.tomsguide.com/home/home-appliances/tribest-slowstar-ai-vertical-hopper-juicer-review">Tribest Slowstar AI Vertical Hopper Juicer</a> ($599).</p><p>The machine measures 17.3 x 9.7 x 6.7 inches, so it’s very tall. It didn’t fit under my kitchen cabinets, so storing it on the countertop wasn't an option. However, it’s easy to dismantle so it can be stored away in the cupboard. The Canoly C16 weighs 13.2 pounds, and I was able to carry it around easily while setting it up. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="iMvfwrEcDn64YsuhH2G4iV" name="Canoly C16 Cold Press Juicer" alt="Canoly C16 Cold Press Juicer photographed in front of a blue background" src="https://cdn.mos.cms.futurecdn.net/iMvfwrEcDn64YsuhH2G4iV.jpg" mos="" align="middle" fullscreen="" width="1920" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>Inside the hopper, there’s a pre-cutting blade, and this made light work of tough ingredients, so I didn’t have to spend time chopping before adding them to the hopper. That said, the small feed chute on top measures six inches in diameter, so if you want to continuously feed ingredients, you’ll need to spend time chopping. I’d recommend simply lifting the lid and adding ingredients that way.  </p><p>There are two different filters with the machine, so you can make milk, sorbet or juice, meaning you're not limited in what you can do. There are two spouts on either side of the machine. On the left is the pulp and on the right is the juice. You can open and close these as needed. I didn’t experience any drips or spills, so I was happy with these.  </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="D976oddxaPAUkJ9pca6fMW" name="Canoly C16 Cold Press Juicer" alt="Canoly C16 Cold Press Juicer photographed in front of a blue background" src="https://cdn.mos.cms.futurecdn.net/D976oddxaPAUkJ9pca6fMW.jpg" mos="" align="middle" fullscreen="" width="1920" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The juicer comes with two containers, one for collecting pulp and one for collecting juice. The juice container has a small lip to reduce spills and measurements denoted on the side. My only issue is that the measurements are very faint, and I found myself searching around the container for them. I found it easier to use my own measuring jug to see exactly how much liquid I was getting. </p><h3 id="controls">Controls</h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="4pB6fDsGKRTvKRSniNHKBW" name="Canoly C16 Cold Press Juicer" alt="Canoly C16 Cold Press Juicer photographed in front of a blue background" src="https://cdn.mos.cms.futurecdn.net/4pB6fDsGKRTvKRSniNHKBW.jpg" mos="" align="middle" fullscreen="" width="1920" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The Canoly C16 couldn’t be easier to use because it has one switch. Flip it one way for juice and the other for reverse. Annoyingly, this button is placed at the back of the juicer, so it’s a bit out of the way when you’re using it. When the hopper is open, the juicer stops for safety, like any other juicer. </p><h2 class="article-body__section" id="section-canoly-c16-cold-press-juicer-review-performance"><span>Canoly C16 Cold Press Juicer review: Performance</span></h2><p>The Canoly C16 Cold Press Juicer can do a lot. It’s a 3-in-1 machine, so it can make juice, nut milk, and sorbet. It sounds good on the packaging, but using it let me down. During operation, the machine was continuously overheating, despite the Canoly website stating it can handle 30 minutes of continuous operation. It also smells like burnt plastic after about 10 minutes of use. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="iwot5zrj4w3TRGMiFiuqHW" name="Canoly C16 Cold Press Juicer" alt="Canoly C16 Cold Press Juicer photographed in front of a blue background" src="https://cdn.mos.cms.futurecdn.net/iwot5zrj4w3TRGMiFiuqHW.jpg" mos="" align="middle" fullscreen="" width="1920" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The machine clogs often, so I had to reverse the juicing a couple of times, and it is extremely hard to clean as the pulp gets stuck throughout the machine rather than being pushed out. That said, it’s very quiet, operating at around 40 decibels thanks to the brushless motor. </p><p>To get an idea of what the C16 is capable of, I carried out my usual juicing tests and made nut milk and sorbet. </p><p><strong>Apple juice:</strong></p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="8hbjwhZ9YaUxDD9xxKVMCW" name="Canoly C16 Cold Press Juicer" alt="apple juice made using the Canoly C16 Cold Press Juicer" src="https://cdn.mos.cms.futurecdn.net/8hbjwhZ9YaUxDD9xxKVMCW.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>Firstly, I juiced four apples, which gave me 700ml of juice. I cut the apples in half and put them straight into the hopper, which could fit two and a half apples at a time. </p><p>I was surprised by how long the apples took to juice. It looked as though they were being mulched in the hopper by the chopping blade. After all of the juice was extracted, there was still a lot of the apple stuck to the side walls of the hopper. </p><p>The fiber took a long time to come out, but it was mostly dry, indicating that most of the moisture had been extracted from the fruit. There was foam on the top of the apple juice but not much, meaning there wasn’t much air in the machine. This meant the juice had a sweeter taste, which is what you want. The juice was a little bitty, but felt mostly smooth in my mouth while drinking. </p><p><strong>Orange juice:</strong></p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="n445zcTkbAFeQnpm4QoeKW" name="Canoly C16 Cold Press Juicer" alt="orange juice made using the Canoly C16 Cold Press Juicer" src="https://cdn.mos.cms.futurecdn.net/n445zcTkbAFeQnpm4QoeKW.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>Next up, I made a batch of orange juice using four oranges, which gave me a yield of 400ml. Before putting them in the hopper, they were peeled to avoid the bitter taste of the pith making its way into the final product. </p><p>This was a lot faster than the apple, but the pulp that came out of the machine was very moist, so it didn’t do a great job of getting all the juice out. The juice itself was thick in texture but not exactly bitty. </p><p>After juicing the four oranges without the peel, the juicer overheated. I left it for around half an hour and it came back to life, but four oranges should be a very easy ask. </p><p><strong>Carrot and Celery juice:</strong></p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="KhrQ3NTYB9RSZfVNmJjYQW" name="Canoly C16 Cold Press Juicer" alt="carrot and celery made using the Canoly C16 Cold Press Juicer" src="https://cdn.mos.cms.futurecdn.net/KhrQ3NTYB9RSZfVNmJjYQW.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>I then made carrot and celery juice. I juiced 2.2 pounds of carrots and a whole bunch of celery, which gave me 500ml of juice. The chopping blade in the hopper was able to easily break down the carrot into manageable pieces for the auger, which was impressive to watch, but it was so strong that some small pieces of carrots came flying out at me through the six-inch feed chute. </p><p>The ingredients moved through the hopper quickly, but the celery stalks became very tangled, and there was a lot of carrot pulp remaining throughout the machine. A lot of the pulp made it into the juice too, unfortunately resulting in a very thick texture. </p><p><strong>Cashew milk:</strong></p><figure role="gallery"><figure><img src="https://cdn.mos.cms.futurecdn.net/pXLDiYvri8ZzSecZm4tPUW.jpg" alt="cashew nut milk made using the Canoly C16 Cold Press Juicer" /><figcaption><small role="credit">Tom's Guide</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/ZXrSSj4uDgSXpwNKsiUafW.jpg" alt="cashew nut milk made using the Canoly C16 Cold Press Juicer" /><figcaption><small role="credit">Tom's Guide</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/bn9Bht7urDYXPEFprBnhXW.jpg" alt="cashew nut milk made using the Canoly C16 Cold Press Juicer" /><figcaption><small role="credit">Tom's Guide</small></figcaption></figure></figure><p>Moving on from classic juices, I made some nut milk. I opted for cashews and soaked two cups in water overnight in the refrigerator. After rinsing the nuts the next day, I slowly fed them into the juicer with filtered water. </p><p>As the milk was coming out of the juicer, I used the included sieve over the cup to catch any rogue lumps… and there were a lot. That said, the milk tasted good. I would just recommend using a cheesecloth to strain the milk after juicing to ensure there are no lumps. </p><p>The pulp was effectively pushed out of the machine, although there wasn’t much of it. But when I cleaned the juicer, all of the pulp was stuck in the hollow auger. This was annoying to clean out. </p><p><strong>Sorbet:</strong></p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="QP97YbpWKMVoMDwn9FiupW" name="Canoly C16 Cold Press Juicer" alt="berry sorbet made using the Canoly C16 Cold Press Juicer" src="https://cdn.mos.cms.futurecdn.net/QP97YbpWKMVoMDwn9FiupW.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>Finally, I made sorbet using the included sorbet strainer. I added a mixture of frozen berries and cherries to the machine and simply pressed the on button. </p><p>The machine stopped a few times and had to be reversed. This isn’t something I’ve had to deal with when using any other juicer, but it just meant I had to be on hand to hit the reverse button when needed. </p><p>It quickly made spirals of sorbet, giving me a sweet treat that was ready in minutes. This clean-up was also a lot more straightforward than the juices with their messy pulp. </p><h2 class="article-body__section" id="section-canoly-c16-cold-press-juicer-review-cleaning"><span>Canoly C16 Cold Press Juicer review: Cleaning</span></h2><p>The Canoly C16 Cold Press Juicer is a nightmare to maintain. Juicers are notoriously difficult to keep clean because all of the small pieces of fruit and vegetables are being pushed through small gaps to get the most liquid possible. So everything gets trapped. But the Canoly is especially bad. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="YBTGyEyzuu6vQxE6h47SpV" name="Canoly C16 Cold Press Juicer" alt="Canoly C16 Cold Press Juicer photographed in front of a blue background" src="https://cdn.mos.cms.futurecdn.net/YBTGyEyzuu6vQxE6h47SpV.jpg" mos="" align="middle" fullscreen="" width="1920" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>All of the parts are dishwasher safe apart from the motor base. Before I loaded it into the dishwasher, I rinsed off as much pulp as possible, but there was still some residue after the wash cycle. I went in with the provided cleaning brush to get the final bits out, but it took me about half an hour of scrubbing to be happy with the cleanliness of the machine. Tiny bits of pulp get stuck in the smallest crevices you’ve ever seen — nightmare.</p><h2 class="article-body__section" id="section-canoly-c16-cold-press-juicer-review-verdict"><span>Canoly C16 Cold Press Juicer review: Verdict</span></h2><p>The Canoly C16 Cold Press is a 3-in-1 machine, so I was able to make milk, sorbet and juice. It’s very useful that all of the necessary attachments are included when you purchase the juicer. It’s very quiet when operating too, so it doesn’t cause too much of a commotion in the home. </p><p>The large hopper makes it easy to juice in batches if you need to, and it couldn’t be easier to use, with just one switch that controls everything. </p><p>However, this juice wastes a lot of your time through cleaning and waiting for it to stop overheating. Cleaning is incredibly difficult, with pulp getting caught up in every crevice you can think of, the machine frequently clogs, meaning you have to be on hand to hit the reverse switch. And it overheats when juicing fruits that should be easy, like oranges. </p><p>If you seriously want to get into juicing, I would recommend spending more money on a Nama juicer like the <a href="https://www.tomsguide.com/home/nama-j3-cold-press-juicer-review">Nama J3</a>.</p> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/home/kitchen-dining/canoly-c16-cold-press-juicer-review</link>
                                                                            <description>
                            <![CDATA[ The Canoly C16 Cold Press Juicer is a cheap option, but overheating and clogging may put you off. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">iaJs3iNAsdcyFuNFGmN655</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/xtMhjtvX8jF75vgULxzLXV-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Fri, 04 Sep 2026 14:05:52 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Kitchen & Dining]]></category>
                                                    <category><![CDATA[Home]]></category>
                                                    <category><![CDATA[Home Appliances]]></category>
                                                                                                <author><![CDATA[ ashley.thieme@futurenet.com (Ashley Thieme) ]]></author>                    <dc:creator><![CDATA[ Ashley Thieme ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/3AWovHjApwuNrSGRS6WBcL.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Ashley Thieme is a staff writer on the Reviews team at Tom’s Guide where she tests out the latest tech so you can know what’s going to be worth your time and money. She has a master’s degree in Magazine Journalism and a bachelor’s degree in Journalism, Media and Sociology from Cardiff University. She has bylines in titles including Women’s Health UK, sharing the latest health and wellness news stories, and Virgin Radio UK, providing the latest entertainment news and working on celebrity interviews. She has experience reporting on a variety of topics including music, literature, motorsport, entertainment and health. In previously published work, she has reviewed live music events, books, and wellness products. She values the importance of tech enhancing your life rather than taking over, and as a music fanatic, she is always looking for the best way to listen to new music releases. Discovering the top audio equipment that enhances sound quality and provides optimum comfort is what Ashley does best. In her spare time, Ashley enjoys hitting her reading goals on Goodreads by getting into the latest novels with a cup of tea as well as getting out in the Welsh mountains for a good hike on the weekend.&lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/xtMhjtvX8jF75vgULxzLXV-1280-80.jpg">
                                                            <media:credit><![CDATA[Tom&amp;#39;s Guide]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Canoly C16 Cold Press Juicer photographed in front of a blue background]]></media:description>                                                            <media:text><![CDATA[Canoly C16 Cold Press Juicer photographed in front of a blue background]]></media:text>
                                <media:title type="plain"><![CDATA[Canoly C16 Cold Press Juicer photographed in front of a blue background]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/xtMhjtvX8jF75vgULxzLXV-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>The Canoly C16 Cold Press Juicer promises a convenient way to make juice, nut milk and sorbet. But if anything, it proved to me once and for all that if you want a smooth-sailing juicing experience, you need to spend a little more money. </p><p>The machine is very quiet when operating and has a large hopper, meaning you can load up your ingredients in bulk. It’s also very simple to use with just one switch to control everything. However, I’m not sure any of that makes it worth the hassle. </p><p>It regularly overheats, is incredibly difficult to clean, and clogs frequently. To find out more about my experience with the machine, you can keep reading this full Canoly C16 Cold Press Juicer review.</p><h2 class="article-body__section" id="section-canoly-c16-cold-press-juicer-review-specs"><span>Canoly C16 Cold Press Juicer review: Specs</span></h2><div ><table><tbody><tr><td class="firstcol " ><p><strong>Price</strong></p></td><td  ><p><a href="https://www.canoly.com/products/c16-cold-press-juicer" target="_blank" rel="nofollow">$299</a> / <a href="https://www.amazon.co.uk/Canoly-Press-Juicer-Machines-150mm/dp/B0H1KQNVL3" target="_blank" rel="nofollow">£93</a></p></td></tr><tr><td class="firstcol " ><p><strong>Dimensions</strong></p></td><td  ><p>17.3 x 9.7 x 6.7 inches</p></td></tr><tr><td class="firstcol " ><p><strong>Weight</strong></p></td><td  ><p>13.2 pounds</p></td></tr><tr><td class="firstcol " ><p><strong>Functions</strong></p></td><td  ><p>Juice, Nut milk, sorbet</p></td></tr><tr><td class="firstcol " ><p><strong>Material</strong></p></td><td  ><p>PC and stainless steel</p></td></tr><tr><td class="firstcol " ><p><strong>Capacity</strong></p></td><td  ><p>90 ounces</p></td></tr><tr><td class="firstcol " ><p><strong>Power</strong></p></td><td  ><p>250W</p></td></tr><tr><td class="firstcol " ><p><strong>Dishwasher safe</strong></p></td><td  ><p>Yes</p></td></tr><tr><td class="firstcol " ><p><strong>Warranty</strong></p></td><td  ><p>1-year</p></td></tr></tbody></table></div><h2 class="article-body__section" id="section-canoly-c16-cold-press-juicer-review-price-availability"><span>Canoly C16 Cold Press Juicer review: Price & availability</span></h2><p>The Canoly C16 Cold Press Juicer is available to purchase in the U.S. for <a href="https://www.canoly.com/products/c16-cold-press-juicer" target="_blank" rel="nofollow">$299 directly from the Canoly online store</a>, but it’s often on sale for as low as $199. In the U.K., you can pick it up for <a href="https://www.amazon.co.uk/Canoly-Press-Juicer-Machines-150mm/dp/B0H1KQNVL3" target="_blank" rel="nofollow">£93 from Amazon</a>. </p><p>This is very cheap for a cold press juicer, especially a 3-in-1 machine, as you need a <em>lot</em> of power to make nut milk. For example, the <a href="https://www.tomsguide.com/home/home-appliances/nama-c2-cold-press-juicer-and-blender-review">Nama C2 Cold Press Juicer and Blender</a> can make nut milk with ease, but it retails for $800 — ouch!</p><p>Primarily, the Canoly is a juicer and sits in the market alongside the <a href="https://www.tomsguide.com/home/home-appliances/amzchef-cold-press-juicer-zm1902-review">AMZCHEF Cold Press Juicer</a>, which is priced at $199. This juicer is the same size as the Canoly but is far more controlled and user-friendly whilst remaining a budget option. </p><p>If you’re short on space, you could pick up the Ninja NeverClog Cold Press Juicer for $149, but it’s not the strongest and the process is very fiddly, so I would recommend a model with a hopper, but not the Canoly. Instead, the AMZCHEF would be the best option. </p><h2 class="article-body__section" id="section-canoly-c16-cold-press-juicer-review-design"><span>Canoly C16 Cold Press Juicer review: Design </span></h2><p>The Canoly C16 Cold Press Juicer looks like any other juicer with a hopper. It’s striking and catches your attention immediately because of its size and almost futuristic design — the handle’s shape is almost spaceship-like — although it doesn’t have a flurry of touchscreen buttons like the <a href="https://www.tomsguide.com/home/home-appliances/tribest-slowstar-ai-vertical-hopper-juicer-review">Tribest Slowstar AI Vertical Hopper Juicer</a> ($599).</p><p>The machine measures 17.3 x 9.7 x 6.7 inches, so it’s very tall. It didn’t fit under my kitchen cabinets, so storing it on the countertop wasn't an option. However, it’s easy to dismantle so it can be stored away in the cupboard. The Canoly C16 weighs 13.2 pounds, and I was able to carry it around easily while setting it up. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="iMvfwrEcDn64YsuhH2G4iV" name="Canoly C16 Cold Press Juicer" alt="Canoly C16 Cold Press Juicer photographed in front of a blue background" src="https://cdn.mos.cms.futurecdn.net/iMvfwrEcDn64YsuhH2G4iV.jpg" mos="" align="middle" fullscreen="" width="1920" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>Inside the hopper, there’s a pre-cutting blade, and this made light work of tough ingredients, so I didn’t have to spend time chopping before adding them to the hopper. That said, the small feed chute on top measures six inches in diameter, so if you want to continuously feed ingredients, you’ll need to spend time chopping. I’d recommend simply lifting the lid and adding ingredients that way.  </p><p>There are two different filters with the machine, so you can make milk, sorbet or juice, meaning you're not limited in what you can do. There are two spouts on either side of the machine. On the left is the pulp and on the right is the juice. You can open and close these as needed. I didn’t experience any drips or spills, so I was happy with these.  </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="D976oddxaPAUkJ9pca6fMW" name="Canoly C16 Cold Press Juicer" alt="Canoly C16 Cold Press Juicer photographed in front of a blue background" src="https://cdn.mos.cms.futurecdn.net/D976oddxaPAUkJ9pca6fMW.jpg" mos="" align="middle" fullscreen="" width="1920" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The juicer comes with two containers, one for collecting pulp and one for collecting juice. The juice container has a small lip to reduce spills and measurements denoted on the side. My only issue is that the measurements are very faint, and I found myself searching around the container for them. I found it easier to use my own measuring jug to see exactly how much liquid I was getting. </p><h3 id="controls">Controls</h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="4pB6fDsGKRTvKRSniNHKBW" name="Canoly C16 Cold Press Juicer" alt="Canoly C16 Cold Press Juicer photographed in front of a blue background" src="https://cdn.mos.cms.futurecdn.net/4pB6fDsGKRTvKRSniNHKBW.jpg" mos="" align="middle" fullscreen="" width="1920" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The Canoly C16 couldn’t be easier to use because it has one switch. Flip it one way for juice and the other for reverse. Annoyingly, this button is placed at the back of the juicer, so it’s a bit out of the way when you’re using it. When the hopper is open, the juicer stops for safety, like any other juicer. </p><h2 class="article-body__section" id="section-canoly-c16-cold-press-juicer-review-performance"><span>Canoly C16 Cold Press Juicer review: Performance</span></h2><p>The Canoly C16 Cold Press Juicer can do a lot. It’s a 3-in-1 machine, so it can make juice, nut milk, and sorbet. It sounds good on the packaging, but using it let me down. During operation, the machine was continuously overheating, despite the Canoly website stating it can handle 30 minutes of continuous operation. It also smells like burnt plastic after about 10 minutes of use. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="iwot5zrj4w3TRGMiFiuqHW" name="Canoly C16 Cold Press Juicer" alt="Canoly C16 Cold Press Juicer photographed in front of a blue background" src="https://cdn.mos.cms.futurecdn.net/iwot5zrj4w3TRGMiFiuqHW.jpg" mos="" align="middle" fullscreen="" width="1920" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The machine clogs often, so I had to reverse the juicing a couple of times, and it is extremely hard to clean as the pulp gets stuck throughout the machine rather than being pushed out. That said, it’s very quiet, operating at around 40 decibels thanks to the brushless motor. </p><p>To get an idea of what the C16 is capable of, I carried out my usual juicing tests and made nut milk and sorbet. </p><p><strong>Apple juice:</strong></p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="8hbjwhZ9YaUxDD9xxKVMCW" name="Canoly C16 Cold Press Juicer" alt="apple juice made using the Canoly C16 Cold Press Juicer" src="https://cdn.mos.cms.futurecdn.net/8hbjwhZ9YaUxDD9xxKVMCW.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>Firstly, I juiced four apples, which gave me 700ml of juice. I cut the apples in half and put them straight into the hopper, which could fit two and a half apples at a time. </p><p>I was surprised by how long the apples took to juice. It looked as though they were being mulched in the hopper by the chopping blade. After all of the juice was extracted, there was still a lot of the apple stuck to the side walls of the hopper. </p><p>The fiber took a long time to come out, but it was mostly dry, indicating that most of the moisture had been extracted from the fruit. There was foam on the top of the apple juice but not much, meaning there wasn’t much air in the machine. This meant the juice had a sweeter taste, which is what you want. The juice was a little bitty, but felt mostly smooth in my mouth while drinking. </p><p><strong>Orange juice:</strong></p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="n445zcTkbAFeQnpm4QoeKW" name="Canoly C16 Cold Press Juicer" alt="orange juice made using the Canoly C16 Cold Press Juicer" src="https://cdn.mos.cms.futurecdn.net/n445zcTkbAFeQnpm4QoeKW.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>Next up, I made a batch of orange juice using four oranges, which gave me a yield of 400ml. Before putting them in the hopper, they were peeled to avoid the bitter taste of the pith making its way into the final product. </p><p>This was a lot faster than the apple, but the pulp that came out of the machine was very moist, so it didn’t do a great job of getting all the juice out. The juice itself was thick in texture but not exactly bitty. </p><p>After juicing the four oranges without the peel, the juicer overheated. I left it for around half an hour and it came back to life, but four oranges should be a very easy ask. </p><p><strong>Carrot and Celery juice:</strong></p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="KhrQ3NTYB9RSZfVNmJjYQW" name="Canoly C16 Cold Press Juicer" alt="carrot and celery made using the Canoly C16 Cold Press Juicer" src="https://cdn.mos.cms.futurecdn.net/KhrQ3NTYB9RSZfVNmJjYQW.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>I then made carrot and celery juice. I juiced 2.2 pounds of carrots and a whole bunch of celery, which gave me 500ml of juice. The chopping blade in the hopper was able to easily break down the carrot into manageable pieces for the auger, which was impressive to watch, but it was so strong that some small pieces of carrots came flying out at me through the six-inch feed chute. </p><p>The ingredients moved through the hopper quickly, but the celery stalks became very tangled, and there was a lot of carrot pulp remaining throughout the machine. A lot of the pulp made it into the juice too, unfortunately resulting in a very thick texture. </p><p><strong>Cashew milk:</strong></p><figure role="gallery"><figure><img src="https://cdn.mos.cms.futurecdn.net/pXLDiYvri8ZzSecZm4tPUW.jpg" alt="cashew nut milk made using the Canoly C16 Cold Press Juicer" /><figcaption><small role="credit">Tom's Guide</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/ZXrSSj4uDgSXpwNKsiUafW.jpg" alt="cashew nut milk made using the Canoly C16 Cold Press Juicer" /><figcaption><small role="credit">Tom's Guide</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/bn9Bht7urDYXPEFprBnhXW.jpg" alt="cashew nut milk made using the Canoly C16 Cold Press Juicer" /><figcaption><small role="credit">Tom's Guide</small></figcaption></figure></figure><p>Moving on from classic juices, I made some nut milk. I opted for cashews and soaked two cups in water overnight in the refrigerator. After rinsing the nuts the next day, I slowly fed them into the juicer with filtered water. </p><p>As the milk was coming out of the juicer, I used the included sieve over the cup to catch any rogue lumps… and there were a lot. That said, the milk tasted good. I would just recommend using a cheesecloth to strain the milk after juicing to ensure there are no lumps. </p><p>The pulp was effectively pushed out of the machine, although there wasn’t much of it. But when I cleaned the juicer, all of the pulp was stuck in the hollow auger. This was annoying to clean out. </p><p><strong>Sorbet:</strong></p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="QP97YbpWKMVoMDwn9FiupW" name="Canoly C16 Cold Press Juicer" alt="berry sorbet made using the Canoly C16 Cold Press Juicer" src="https://cdn.mos.cms.futurecdn.net/QP97YbpWKMVoMDwn9FiupW.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>Finally, I made sorbet using the included sorbet strainer. I added a mixture of frozen berries and cherries to the machine and simply pressed the on button. </p><p>The machine stopped a few times and had to be reversed. This isn’t something I’ve had to deal with when using any other juicer, but it just meant I had to be on hand to hit the reverse button when needed. </p><p>It quickly made spirals of sorbet, giving me a sweet treat that was ready in minutes. This clean-up was also a lot more straightforward than the juices with their messy pulp. </p><h2 class="article-body__section" id="section-canoly-c16-cold-press-juicer-review-cleaning"><span>Canoly C16 Cold Press Juicer review: Cleaning</span></h2><p>The Canoly C16 Cold Press Juicer is a nightmare to maintain. Juicers are notoriously difficult to keep clean because all of the small pieces of fruit and vegetables are being pushed through small gaps to get the most liquid possible. So everything gets trapped. But the Canoly is especially bad. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="YBTGyEyzuu6vQxE6h47SpV" name="Canoly C16 Cold Press Juicer" alt="Canoly C16 Cold Press Juicer photographed in front of a blue background" src="https://cdn.mos.cms.futurecdn.net/YBTGyEyzuu6vQxE6h47SpV.jpg" mos="" align="middle" fullscreen="" width="1920" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>All of the parts are dishwasher safe apart from the motor base. Before I loaded it into the dishwasher, I rinsed off as much pulp as possible, but there was still some residue after the wash cycle. I went in with the provided cleaning brush to get the final bits out, but it took me about half an hour of scrubbing to be happy with the cleanliness of the machine. Tiny bits of pulp get stuck in the smallest crevices you’ve ever seen — nightmare.</p><h2 class="article-body__section" id="section-canoly-c16-cold-press-juicer-review-verdict"><span>Canoly C16 Cold Press Juicer review: Verdict</span></h2><p>The Canoly C16 Cold Press is a 3-in-1 machine, so I was able to make milk, sorbet and juice. It’s very useful that all of the necessary attachments are included when you purchase the juicer. It’s very quiet when operating too, so it doesn’t cause too much of a commotion in the home. </p><p>The large hopper makes it easy to juice in batches if you need to, and it couldn’t be easier to use, with just one switch that controls everything. </p><p>However, this juice wastes a lot of your time through cleaning and waiting for it to stop overheating. Cleaning is incredibly difficult, with pulp getting caught up in every crevice you can think of, the machine frequently clogs, meaning you have to be on hand to hit the reverse switch. And it overheats when juicing fruits that should be easy, like oranges. </p><p>If you seriously want to get into juicing, I would recommend spending more money on a Nama juicer like the <a href="https://www.tomsguide.com/home/nama-j3-cold-press-juicer-review">Nama J3</a>.</p>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ I tested the Traeger Flatrock 2 Zone Griddle, and it will make you want to cook outside more often ]]></title>
                                                                                                <dc:content><![CDATA[ <div  class="fancy-box"><div class="fancy_box-title">Traeger Flatrock 2 Zone Griddle: Specs</div><div class="fancy_box_body"><p class="fancy-box__body-text"><strong>Price: </strong>$800<br><strong>Weight: </strong>120 pounds<br><strong>Cooktop dimensions: </strong>26 x 18 inches<br><strong>Cooking space: </strong>468 square inches<br><strong>Dimensions: </strong>59 x 36 x 35 inches (to top of cooking surface)</p></div></div><p>I have a garage full of tools because I have far too many hobbies. And as anyone with complex hobbies can attest, the right tool for the job goes a long way toward making your life easier. Traeger’s Flatrock 2 Zone Griddle is one such tool. As experienced grillers can attest, some foods cook wonderfully over open flames, while others require a flat, even surface.</p><p>That distinction means a griddle needs to function differently than the best grill, and it’s vital to have even heat over your cooking surface. And even then, it can be difficult to cook multiple foods at one time, since different foods require different cooking temperatures. </p><p>Traeger has come up with a clever solution with the Flatrock 2 Zone Griddle, and overall, I found this griddle to outperform its peers, thanks in part to its two-chamber heating system and high-quality build. Here’s what happened.</p><h3 class="article-body__section" id="section-traeger-flatrock-2-zone-griddle-review-price-and-availability"><span>Traeger Flatrock 2 Zone Griddle review: Price and availability</span></h3><p>The Flatrock 2 Zone Griddle is available for $800 on <a href="https://www.traeger.com/">Traeger’s website</a>. Additionally, you can finance the purchase using Affirm at checkout. Traeger includes a 5-year warranty with purchase.</p><p>You can also buy the Flatrock 2 at other retailers such as The Home Depot, though availability may be limited. Traeger includes a SHOP LOCAL button on its website so you can find a retailer near you. </p><h3 class="article-body__section" id="section-traeger-flatrock-2-zone-griddle-review-design"><span>Traeger Flatrock 2 Zone Griddle review: Design</span></h3><p>The Flatrock 2 Zone Griddle took about an hour and a half to build, although most of that time was spent unboxing and laying out the parts. The rest of the assembly process goes very quickly and the instructions are rock-solid, as was my experience with other Traeger products. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="p9qUMa8HvrUDYaBrJL7Jni" name="Traeger-Flatrock-2-Zone-2" alt="Traeger Flatrock 2 Zone Griddle in a back yard" src="https://cdn.mos.cms.futurecdn.net/p9qUMa8HvrUDYaBrJL7Jni.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>Once it’s all together, the Flatrock 2 feels stable and well built. The materials feel high-quality, and overall the unit looks great. I did have one small issue with the wire shelf that sits on the low shelf next to the propane bottle. One of the screw holes did not line up properly — as a result, that wire shelf tends to sway a bit. </p><p>Nevertheless, the Flatrock 2 comes packed with nifty features. For starters, the TruZone temperature control design allows for two very distinct cooking zones on each side of the griddle. In other words, the left burner is completely isolated from the right burner. Each one gets its own chamber, so you can really tailor the temperatures on different parts of the griddle. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="4SnNR7dHz9YiTo4m8JYzC3" name="Traeger-Flatrock-2-Zone-4" alt="Traeger Flatrock 2 Zone Griddle in a back yard" src="https://cdn.mos.cms.futurecdn.net/4SnNR7dHz9YiTo4m8JYzC3.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>Within those chambers, Traeger includes U-shaped burners — one for each side. Traeger says this helps eliminate cold spots on the cooking surface. And the FlameLock construction keeps wind out by using a recessed cooktop. That means wind won’t get in and blow at your burners while you’re cooking. Traeger says this also improves fuel efficiency. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="BUi9dtJ9T3zxGhoHH3R7Di" name="Traeger-Flatrock-2-Zone-6" alt="Traeger Flatrock 2 Zone Griddle in a back yard" src="https://cdn.mos.cms.futurecdn.net/BUi9dtJ9T3zxGhoHH3R7Di.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The lid features folding hinges that keep the lid upright during cooking. Traeger says you should never cook with the lid closed, as this creates an excessively hot cooking surface that could pose a danger. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="uBRoyg9eDhB6moKKhUr6cd" name="Traeger-Flatrock-2-Zone-5" alt="Traeger Flatrock 2 Zone Griddle in a back yard" src="https://cdn.mos.cms.futurecdn.net/uBRoyg9eDhB6moKKhUr6cd.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>On the outside, the Flatrock features a folding prep shelf on each side, both equipped with P.A.L. accessory rails. Traeger makes a whole host of “Pop and Lock” accessories to work with these rails. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="PEb5juKixqJkE5uNCfGka4" name="Traeger-Flatrock-2-Zone-7" alt="Cooking on the Traeger Flatrock 2 Zone griddle" src="https://cdn.mos.cms.futurecdn.net/PEb5juKixqJkE5uNCfGka4.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The carbon steel cooking surface is heavy-duty. It offers 486 square inches of cooking surface area, and a grease trap on the near side of the cooktop. That feeds into Traeger’s EZ-Clean Keg grease trap, which pulls out of the front of the unit for easy cleaning.</p><p>As is the case with any cast iron or carbon steel cooktop, you’ll want to season the cooking surface before your first use. This helps create a nice, non-stick surface, and it also burns off any residues or debris that may have accumulated during manufacturing and shipping. </p><h3 class="article-body__section" id="section-traeger-flatrock-2-zone-griddle-review-cooking-performance"><span>Traeger Flatrock 2 Zone Griddle review: Cooking performance </span></h3><p>Getting the Flatrock 2 Zone Griddle in for testing seemed like a great excuse for a burger night in the backyard. Griddles are a great choice for burgers because they cook the patties more evenly and help the burger retain moisture better. On top of that, you’ll get a nice sear all around. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="cFBKWabphHemNtMmu59xY4" name="Traeger-Flatrock-2-Zone-8" alt="Cooking on the Traeger Flatrock 2 Zone griddle" src="https://cdn.mos.cms.futurecdn.net/cFBKWabphHemNtMmu59xY4.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The fold-out shelves are pretty spacious, and I was able to pack them full of everything I needed. I had already seasoned the cooking surface, so I simply fired up the Flatrock and let it heat up.</p><p>My infrared thermometer read 450 degrees in most regions of the cooking surface after about 10 minutes of warm-up time. The edges of the griddle registered cooler temperatures, and the corners the coolest of all. This isn’t too surprising, and it’s an issue I’ve faced in most griddles I’ve tested. It’s largely the result of a rectangular cooking surface and the rounded heating elements beneath.</p><p>Still, the Flatrock registered more consistent temperatures across the cooking surface, enough that I wasn’t worried too much about uneven cooking overall. Once the cooking surface had reached around 500 degrees, I lowered one side so I could caramelize some onions and slow-cook some bacon.</p><p>The Flatrock truly does allow for 2-zone cooking. The dual “chambers” around the individual burners work like a charm. The left side continued to register between 450 and 500 degrees, while the right side was consistent between 275 and 325 degrees. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="dhhHD52ryBcUHCSPEACY93" name="Traeger-Flatrock-2-Zone-9" alt="Cooking on the Traeger Flatrock 2 Zone Griddle" src="https://cdn.mos.cms.futurecdn.net/dhhHD52ryBcUHCSPEACY93.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>I was very glad to see the temperature on the hot side reach 500 degrees, which is something that other griddles I’ve tested have struggled with. If the cooking surface doesn’t get hot enough, you’ll struggle to get a good sear on meats. So kudos to Traeger here.</p><p>That said, be sure to heed Traeger’s advice not to cook with the lid lowered. The lid gets super hot, and the handle does, too. I found that out the hard way when I left the lid closed during pre-heating. </p><p>On the first burger, I used Traeger’s steam dome to ensure a nice, juicy, medium-rare finish. I got an excellent sear on both sides without burning or losing any moisture. The burger ended up better than anything I’ve been served at a restaurant in recent memory.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="F76YxgMgAJydqicYRGYML4" name="Traeger-Flatrock-2-Zone-10" alt="Cooking on the Traeger Flatrock 2 Zone Griddle" src="https://cdn.mos.cms.futurecdn.net/F76YxgMgAJydqicYRGYML4.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>For the second burger, I used Traeger’s Weighted Grill Press. This burger also came out very good, though the press does make more moisture seep out of the patty. Use this one if you’re after that “Smashburger” style. There was no sticking on the cook surface using either method. </p><p>On the other side of the grill, the onions caramelized perfectly at a lower temperature. When I wasn’t using the steam dome for the burgers, I put this over the onions so they didn’t dry out and start to burn. A bit of cowboy butter, sliced onions, and patience led to an excellent finish. Even at lower temperatures, none of the food stuck to the cooking surface.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="2G3ud5E7ryNxaEy3Qu6L44" name="Traeger-Flatrock-2-Zone-12" alt="Cooking on the Traeger Flatrock 2 Zone Griddle" src="https://cdn.mos.cms.futurecdn.net/2G3ud5E7ryNxaEy3Qu6L44.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>It was so incredibly handy to be able to cook the onions and bacon at the same time as the burgers. The dual-zone heating really is a treat since it works so well. Everything I cooked came out perfectly. </p><p>And the cooking surface feels high-quality, rugged, and ready for years of use. You’ll need to care for it, and seasoning isn’t a difficult process — I recommend doing it frequently. When I was done cooking, I scraped off any debris and then added a light coating of grapeseed oil to the still-hot cooking surface. I spread it around, then wiped off the excess once the griddle cooled. Easy peasy. </p><h3 class="article-body__section" id="section-traeger-flatrock-2-zone-griddle-review-accessories"><span>Traeger Flatrock 2 Zone Griddle review: Accessories</span></h3><p>Traeger offers a ton of accessories that work with its Pop and Lock system. One of the more relevant ones for this use is the Flat Top Grill Essentials Kit ($100), which includes two spatulas, a cooking surface scraper, and two squirt bottles. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="C2f7Qasz9VpoAX8rqcijx3" name="Traeger-Flatrock-2-Zone-11" alt="Cooking on the Traeger Flatrock 2 Zone Griddle" src="https://cdn.mos.cms.futurecdn.net/C2f7Qasz9VpoAX8rqcijx3.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The Ultimate Smashed Burger Kit ($130) is another great option for use with the Flatrock 2. It includes a weighted grill press, a spatula, and a steam dome that help you make delicious burgers.</p><h3 class="article-body__section" id="section-traeger-flatrock-2-zone-griddle-review-competition"><span>Traeger Flatrock 2 Zone Griddle review: Competition </span></h3><p>The outdoor griddle market is a big one, with brands like Traeger and Blackstone leading the way. There are more entry-level options like Nexgrill as well as fancier options like Solo Stove’s Steelfire 30, a clad stainless steel griddle option different from most other offerings.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="Qa6ajGkv65ffWh3WwMXURk" name="Traeger-Flatrock-2-Zone-3" alt="Traeger Flatrock 2 Zone Griddle in a back yard" src="https://cdn.mos.cms.futurecdn.net/Qa6ajGkv65ffWh3WwMXURk.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The Flatrock 2 Zone Griddle offers plenty of nifty features that set it apart from the competition. Traeger bests Blackstone and Nexgrill in terms of build quality, though Nexgrill is the most economical offering if you just want to give griddles a try without a big commitment.</p><p>The Solo Stove Steelfire is an interesting competitor. It’s more expensive than the Flatrock, but it also offers a stainless steel cooktop, which heats faster and requires no seasoning. </p><p>Both the Flatrock and the Steelfire are excellent griddle options, though they’re very different experiences. If you want your griddle to be as low-maintenance as possible, choose the Solo Stove. If a more traditional, carbon-steel or cast-iron cooktop is what you’re after for durability and an easily-non-stick surface, the Flatrock 2 is the solid choice.</p><h3 class="article-body__section" id="section-traeger-flatrock-2-zone-griddle-review-verdict"><span>Traeger Flatrock 2 Zone Griddle review: Verdict</span></h3><p>Traeger really shines thanks to its build quality, wide selection of accessories, and functionality — and the Flatrock 2 Zone Griddle is no exception. </p><p>Traeger has done a wonderful job of ensuring you get true 2-zone cooking out of this unit. While it suffers from the same issues as many griddles out there — namely, dead spots in the corners and edges of the cooking surface — the overall heating capabilities far outshine the downsides. It’s an excellent choice for outdoor griddle cooking that will make you want to cook outside more often. </p> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/home/home-appliances/traeger-flatrock-2-zone-griddle-review</link>
                                                                            <description>
                            <![CDATA[ The Traeger Flatrock 2 Zone Griddle will change how you cook outside. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">LqDeUZhV4pTC2YWe7Px7h6</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/hGRju8kpmXoVfbPMAforbg-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Fri, 04 Sep 2026 12:30:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Home Appliances]]></category>
                                                    <category><![CDATA[Home]]></category>
                                                                                                                    <dc:creator><![CDATA[ Dan Cavallari ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/RzBY7zZLXQ8jdC6dtzKdxZ.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ null ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/hGRju8kpmXoVfbPMAforbg-1280-80.jpg">
                                                            <media:credit><![CDATA[Tom&amp;#39;s Guide]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Traeger Flatrock 2 Zone griddle in a back yard]]></media:description>                                                            <media:text><![CDATA[Traeger Flatrock 2 Zone griddle in a back yard]]></media:text>
                                <media:title type="plain"><![CDATA[Traeger Flatrock 2 Zone griddle in a back yard]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/hGRju8kpmXoVfbPMAforbg-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <div  class="fancy-box"><div class="fancy_box-title">Traeger Flatrock 2 Zone Griddle: Specs</div><div class="fancy_box_body"><p class="fancy-box__body-text"><strong>Price: </strong>$800<br><strong>Weight: </strong>120 pounds<br><strong>Cooktop dimensions: </strong>26 x 18 inches<br><strong>Cooking space: </strong>468 square inches<br><strong>Dimensions: </strong>59 x 36 x 35 inches (to top of cooking surface)</p></div></div><p>I have a garage full of tools because I have far too many hobbies. And as anyone with complex hobbies can attest, the right tool for the job goes a long way toward making your life easier. Traeger’s Flatrock 2 Zone Griddle is one such tool. As experienced grillers can attest, some foods cook wonderfully over open flames, while others require a flat, even surface.</p><p>That distinction means a griddle needs to function differently than the best grill, and it’s vital to have even heat over your cooking surface. And even then, it can be difficult to cook multiple foods at one time, since different foods require different cooking temperatures. </p><p>Traeger has come up with a clever solution with the Flatrock 2 Zone Griddle, and overall, I found this griddle to outperform its peers, thanks in part to its two-chamber heating system and high-quality build. Here’s what happened.</p><h3 class="article-body__section" id="section-traeger-flatrock-2-zone-griddle-review-price-and-availability"><span>Traeger Flatrock 2 Zone Griddle review: Price and availability</span></h3><p>The Flatrock 2 Zone Griddle is available for $800 on <a href="https://www.traeger.com/">Traeger’s website</a>. Additionally, you can finance the purchase using Affirm at checkout. Traeger includes a 5-year warranty with purchase.</p><p>You can also buy the Flatrock 2 at other retailers such as The Home Depot, though availability may be limited. Traeger includes a SHOP LOCAL button on its website so you can find a retailer near you. </p><h3 class="article-body__section" id="section-traeger-flatrock-2-zone-griddle-review-design"><span>Traeger Flatrock 2 Zone Griddle review: Design</span></h3><p>The Flatrock 2 Zone Griddle took about an hour and a half to build, although most of that time was spent unboxing and laying out the parts. The rest of the assembly process goes very quickly and the instructions are rock-solid, as was my experience with other Traeger products. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="p9qUMa8HvrUDYaBrJL7Jni" name="Traeger-Flatrock-2-Zone-2" alt="Traeger Flatrock 2 Zone Griddle in a back yard" src="https://cdn.mos.cms.futurecdn.net/p9qUMa8HvrUDYaBrJL7Jni.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>Once it’s all together, the Flatrock 2 feels stable and well built. The materials feel high-quality, and overall the unit looks great. I did have one small issue with the wire shelf that sits on the low shelf next to the propane bottle. One of the screw holes did not line up properly — as a result, that wire shelf tends to sway a bit. </p><p>Nevertheless, the Flatrock 2 comes packed with nifty features. For starters, the TruZone temperature control design allows for two very distinct cooking zones on each side of the griddle. In other words, the left burner is completely isolated from the right burner. Each one gets its own chamber, so you can really tailor the temperatures on different parts of the griddle. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="4SnNR7dHz9YiTo4m8JYzC3" name="Traeger-Flatrock-2-Zone-4" alt="Traeger Flatrock 2 Zone Griddle in a back yard" src="https://cdn.mos.cms.futurecdn.net/4SnNR7dHz9YiTo4m8JYzC3.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>Within those chambers, Traeger includes U-shaped burners — one for each side. Traeger says this helps eliminate cold spots on the cooking surface. And the FlameLock construction keeps wind out by using a recessed cooktop. That means wind won’t get in and blow at your burners while you’re cooking. Traeger says this also improves fuel efficiency. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="BUi9dtJ9T3zxGhoHH3R7Di" name="Traeger-Flatrock-2-Zone-6" alt="Traeger Flatrock 2 Zone Griddle in a back yard" src="https://cdn.mos.cms.futurecdn.net/BUi9dtJ9T3zxGhoHH3R7Di.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The lid features folding hinges that keep the lid upright during cooking. Traeger says you should never cook with the lid closed, as this creates an excessively hot cooking surface that could pose a danger. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="uBRoyg9eDhB6moKKhUr6cd" name="Traeger-Flatrock-2-Zone-5" alt="Traeger Flatrock 2 Zone Griddle in a back yard" src="https://cdn.mos.cms.futurecdn.net/uBRoyg9eDhB6moKKhUr6cd.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>On the outside, the Flatrock features a folding prep shelf on each side, both equipped with P.A.L. accessory rails. Traeger makes a whole host of “Pop and Lock” accessories to work with these rails. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="PEb5juKixqJkE5uNCfGka4" name="Traeger-Flatrock-2-Zone-7" alt="Cooking on the Traeger Flatrock 2 Zone griddle" src="https://cdn.mos.cms.futurecdn.net/PEb5juKixqJkE5uNCfGka4.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The carbon steel cooking surface is heavy-duty. It offers 486 square inches of cooking surface area, and a grease trap on the near side of the cooktop. That feeds into Traeger’s EZ-Clean Keg grease trap, which pulls out of the front of the unit for easy cleaning.</p><p>As is the case with any cast iron or carbon steel cooktop, you’ll want to season the cooking surface before your first use. This helps create a nice, non-stick surface, and it also burns off any residues or debris that may have accumulated during manufacturing and shipping. </p><h3 class="article-body__section" id="section-traeger-flatrock-2-zone-griddle-review-cooking-performance"><span>Traeger Flatrock 2 Zone Griddle review: Cooking performance </span></h3><p>Getting the Flatrock 2 Zone Griddle in for testing seemed like a great excuse for a burger night in the backyard. Griddles are a great choice for burgers because they cook the patties more evenly and help the burger retain moisture better. On top of that, you’ll get a nice sear all around. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="cFBKWabphHemNtMmu59xY4" name="Traeger-Flatrock-2-Zone-8" alt="Cooking on the Traeger Flatrock 2 Zone griddle" src="https://cdn.mos.cms.futurecdn.net/cFBKWabphHemNtMmu59xY4.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The fold-out shelves are pretty spacious, and I was able to pack them full of everything I needed. I had already seasoned the cooking surface, so I simply fired up the Flatrock and let it heat up.</p><p>My infrared thermometer read 450 degrees in most regions of the cooking surface after about 10 minutes of warm-up time. The edges of the griddle registered cooler temperatures, and the corners the coolest of all. This isn’t too surprising, and it’s an issue I’ve faced in most griddles I’ve tested. It’s largely the result of a rectangular cooking surface and the rounded heating elements beneath.</p><p>Still, the Flatrock registered more consistent temperatures across the cooking surface, enough that I wasn’t worried too much about uneven cooking overall. Once the cooking surface had reached around 500 degrees, I lowered one side so I could caramelize some onions and slow-cook some bacon.</p><p>The Flatrock truly does allow for 2-zone cooking. The dual “chambers” around the individual burners work like a charm. The left side continued to register between 450 and 500 degrees, while the right side was consistent between 275 and 325 degrees. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="dhhHD52ryBcUHCSPEACY93" name="Traeger-Flatrock-2-Zone-9" alt="Cooking on the Traeger Flatrock 2 Zone Griddle" src="https://cdn.mos.cms.futurecdn.net/dhhHD52ryBcUHCSPEACY93.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>I was very glad to see the temperature on the hot side reach 500 degrees, which is something that other griddles I’ve tested have struggled with. If the cooking surface doesn’t get hot enough, you’ll struggle to get a good sear on meats. So kudos to Traeger here.</p><p>That said, be sure to heed Traeger’s advice not to cook with the lid lowered. The lid gets super hot, and the handle does, too. I found that out the hard way when I left the lid closed during pre-heating. </p><p>On the first burger, I used Traeger’s steam dome to ensure a nice, juicy, medium-rare finish. I got an excellent sear on both sides without burning or losing any moisture. The burger ended up better than anything I’ve been served at a restaurant in recent memory.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="F76YxgMgAJydqicYRGYML4" name="Traeger-Flatrock-2-Zone-10" alt="Cooking on the Traeger Flatrock 2 Zone Griddle" src="https://cdn.mos.cms.futurecdn.net/F76YxgMgAJydqicYRGYML4.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>For the second burger, I used Traeger’s Weighted Grill Press. This burger also came out very good, though the press does make more moisture seep out of the patty. Use this one if you’re after that “Smashburger” style. There was no sticking on the cook surface using either method. </p><p>On the other side of the grill, the onions caramelized perfectly at a lower temperature. When I wasn’t using the steam dome for the burgers, I put this over the onions so they didn’t dry out and start to burn. A bit of cowboy butter, sliced onions, and patience led to an excellent finish. Even at lower temperatures, none of the food stuck to the cooking surface.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="2G3ud5E7ryNxaEy3Qu6L44" name="Traeger-Flatrock-2-Zone-12" alt="Cooking on the Traeger Flatrock 2 Zone Griddle" src="https://cdn.mos.cms.futurecdn.net/2G3ud5E7ryNxaEy3Qu6L44.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>It was so incredibly handy to be able to cook the onions and bacon at the same time as the burgers. The dual-zone heating really is a treat since it works so well. Everything I cooked came out perfectly. </p><p>And the cooking surface feels high-quality, rugged, and ready for years of use. You’ll need to care for it, and seasoning isn’t a difficult process — I recommend doing it frequently. When I was done cooking, I scraped off any debris and then added a light coating of grapeseed oil to the still-hot cooking surface. I spread it around, then wiped off the excess once the griddle cooled. Easy peasy. </p><h3 class="article-body__section" id="section-traeger-flatrock-2-zone-griddle-review-accessories"><span>Traeger Flatrock 2 Zone Griddle review: Accessories</span></h3><p>Traeger offers a ton of accessories that work with its Pop and Lock system. One of the more relevant ones for this use is the Flat Top Grill Essentials Kit ($100), which includes two spatulas, a cooking surface scraper, and two squirt bottles. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="C2f7Qasz9VpoAX8rqcijx3" name="Traeger-Flatrock-2-Zone-11" alt="Cooking on the Traeger Flatrock 2 Zone Griddle" src="https://cdn.mos.cms.futurecdn.net/C2f7Qasz9VpoAX8rqcijx3.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The Ultimate Smashed Burger Kit ($130) is another great option for use with the Flatrock 2. It includes a weighted grill press, a spatula, and a steam dome that help you make delicious burgers.</p><h3 class="article-body__section" id="section-traeger-flatrock-2-zone-griddle-review-competition"><span>Traeger Flatrock 2 Zone Griddle review: Competition </span></h3><p>The outdoor griddle market is a big one, with brands like Traeger and Blackstone leading the way. There are more entry-level options like Nexgrill as well as fancier options like Solo Stove’s Steelfire 30, a clad stainless steel griddle option different from most other offerings.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="Qa6ajGkv65ffWh3WwMXURk" name="Traeger-Flatrock-2-Zone-3" alt="Traeger Flatrock 2 Zone Griddle in a back yard" src="https://cdn.mos.cms.futurecdn.net/Qa6ajGkv65ffWh3WwMXURk.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The Flatrock 2 Zone Griddle offers plenty of nifty features that set it apart from the competition. Traeger bests Blackstone and Nexgrill in terms of build quality, though Nexgrill is the most economical offering if you just want to give griddles a try without a big commitment.</p><p>The Solo Stove Steelfire is an interesting competitor. It’s more expensive than the Flatrock, but it also offers a stainless steel cooktop, which heats faster and requires no seasoning. </p><p>Both the Flatrock and the Steelfire are excellent griddle options, though they’re very different experiences. If you want your griddle to be as low-maintenance as possible, choose the Solo Stove. If a more traditional, carbon-steel or cast-iron cooktop is what you’re after for durability and an easily-non-stick surface, the Flatrock 2 is the solid choice.</p><h3 class="article-body__section" id="section-traeger-flatrock-2-zone-griddle-review-verdict"><span>Traeger Flatrock 2 Zone Griddle review: Verdict</span></h3><p>Traeger really shines thanks to its build quality, wide selection of accessories, and functionality — and the Flatrock 2 Zone Griddle is no exception. </p><p>Traeger has done a wonderful job of ensuring you get true 2-zone cooking out of this unit. While it suffers from the same issues as many griddles out there — namely, dead spots in the corners and edges of the cooking surface — the overall heating capabilities far outshine the downsides. It’s an excellent choice for outdoor griddle cooking that will make you want to cook outside more often. </p>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ I just watched a robot vacuum actually climb stairs — it took 3 minutes but those steps were sparkling after ]]></title>
                                                                                                <dc:content><![CDATA[ <p>Stair-climbing <a href="https://www.tomsguide.com/us/best-robot-vacuums,review-2000.html">robot vacuums</a> aren't necessarily a <em>new</em> thing. Last year at IFA 2025, I watched <a href="https://www.tomsguide.com/home/home-appliances/yes-this-robot-vacuum-has-legs-and-can-climb-stairs-this-is-a-game-changer-for-easy-cleaning">Dreame's Cyber X</a> climb stairs (super quickly, may I add), but I was disappointed with the bulk of the product — and that it's been a whole year and you still can't buy the Cyber X. </p><p>Now I'm at <a href="http://tomsguide.com/tag/ifa">IFA 2026</a> in Berlin, and I've just seen Roborock's stair-climbing contraption — the Rover. While this isn't available yet, you can get the new Qrevo Edge 3 Pro — for <a href="https://www.amazon.com/dp/B0H1WCKGPX" target="_blank" rel="nofollow">$1,499 from Amazon</a>.</p><p>Unfortunately, Roborock's representative was unable to confirm a release date or more specs. It was initially unveiled at CES in January — eight months ago. In the meantime, though, let's see it in action.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-Xk8nke"></div>                            </div>                            <script src="https://kwizly.com/embed/Xk8nke.js" async></script><h2 id="so-what-can-the-roborock-rover-actually-do">So what can the Roborock Rover actually do?</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="HzGDa5GJiTcYr9KGqNg9BV" name="roborock ifa 4" alt="the roborock rover climbing stairs at IFA 2026" src="https://cdn.mos.cms.futurecdn.net/HzGDa5GJiTcYr9KGqNg9BV.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Erin Bashford)</span></figcaption></figure><p>Unfortunately, as Roborock's representative was unable to confirm additional information, I know very little. What I <em>do</em> know, though, is that the Rover does climb stairs, and it can manoeuvre down slopes. I saw it with my own two eyes.</p><p>As it has two retractable, wheel-based legs, the Rover can climb and clean at the same time. Yes, it took around three minutes to climb the stairs you see in the photos — and get back down again — but the stairs were sparkling after.</p><p>Even though it took a while to climb the stairs, if you're simply working from home or out running errands, you won't notice how long it takes. That's the whole point of a robot vacuum — clean so you don't have to!</p><h2 id="but-i-have-some-major-reservations">But I have some major reservations</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.21%;"><img id="S3hhrbjg3KayoDdLJJHzyU" name="roborock IFA 3" alt="the roborock rover climbing stairs at IFA 2026" src="https://cdn.mos.cms.futurecdn.net/S3hhrbjg3KayoDdLJJHzyU.jpg" mos="" align="middle" fullscreen="" width="2560" height="1439" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Erin Bashford)</span></figcaption></figure><p>The Roborock Rover was first unveiled at CES in Las Vegas this past January. It was shown off again in Berlin in September. </p><p>And there is still no release date in sight. No specs. No pricing. What is Roborock cooking up behind the scenes? Are there some major issues we're not privy to? Or is it simply waiting for the right time to release it?</p><p>Roborock confirmed that they may have more information by CES 2027, but there's no release timeline yet. Why show off a product so far out from release?</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="dzs5MCXnu9FLShSxPr3vm" name="roborock 6" alt="the roborock rover climbing stairs at IFA" src="https://cdn.mos.cms.futurecdn.net/dzs5MCXnu9FLShSxPr3vm.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Erin Bashford)</span></figcaption></figure><p>I could spend all day speculating, but the long and short of it is this: Roborock has "unveiled" this stair-climbing robot vacuum twice now, but we're still no closer to being able to actually make use of it. Forget watching it at tech shows — I want it in my house! </p><div class="youtube-video" data-nosnippet ><div class="video-aspect-box"><iframe data-lazy-priority="high" data-lazy-src="https://www.youtube-nocookie.com/embed/SuyBti4YC-Y" allowfullscreen></iframe></div></div><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h3><ul><li><a href="https://www.tomsguide.com/home/gardening/ive-just-found-the-perfect-hummingbird-house-for-my-yard-on-amazon-and-it-has-the-perfect-rustic-cozy-vibe">I've just found the perfect hummingbird house for my yard on Amazon — and it has a rustic-cozy vibe</a></li><li><a href="https://www.tomsguide.com/home/anker-just-launched-a-ton-of-new-products-at-ifa-2026-including-an-ai-powered-home-hub">Anker just launched a ton of new products at IFA 2026 — including an AI-powered home hub</a></li><li><a href="https://www.tomsguide.com/home/irobots-new-flagship-roomba-creates-an-airtight-seal-with-your-carpet-the-competition-should-be-worried">iRobot's new flagship Roomba creates an airtight seal with your carpet — the competition should be worried</a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/home/home-appliances/i-just-watched-a-robot-vacuum-actually-climb-stairs-it-took-3-minutes-but-those-steps-were-sparkling-after</link>
                                                                            <description>
                            <![CDATA[ The Roborock Rover is a stair-climbing robot vacuum, and it actually works... but there's a catch. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">d4fkoutT7HU8FH5HvD2Buc</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/uuBKgHRNDDcB8SJs5zbSFV-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Thu, 03 Sep 2026 14:42:31 +0000</pubDate>                                                                                                                                <updated>Thu, 03 Sep 2026 21:55:11 +0000</updated>
                                                                                                                                            <category><![CDATA[Home Appliances]]></category>
                                                    <category><![CDATA[Home]]></category>
                                                                                                <author><![CDATA[ erin.bashford@futurenet.com (Erin Bashford) ]]></author>                    <dc:creator><![CDATA[ Erin Bashford ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/rLvJvJVZx43hEzSsJy3BpL.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Erin Bashford is a senior reviews writer at Tom’s Guide. She has a Master’s in Broadcast and Digital Journalism from the University of East Anglia and 7 years of experience reviewing music and events for various publications. She has edited publications such as Outline Magazine’s Guide to Norwich, and she has written for a number of music magazines and websites such as Clash Magazine, Outline Magazine and Dork Magazine. She has a strong interest in audio gear and the music world. &lt;/p&gt;&lt;p&gt;As an ex-barista, Erin is passionate about coffee tech. She also loves finding the best cooking hacks and kitchen appliances, including her beloved Instant Pot. &lt;/p&gt;&lt;p&gt;In her spare time, you can find her reading, practising yoga, hiking, writing fantasy novels, or stressing over NYT Games.&lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/uuBKgHRNDDcB8SJs5zbSFV-1280-80.jpg">
                                                            <media:credit><![CDATA[Erin Bashford]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[the roborock saros 20 flow complete climbing stairs at IFA 2026]]></media:description>                                                            <media:text><![CDATA[the roborock saros 20 flow complete climbing stairs at IFA 2026]]></media:text>
                                <media:title type="plain"><![CDATA[the roborock saros 20 flow complete climbing stairs at IFA 2026]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/uuBKgHRNDDcB8SJs5zbSFV-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Stair-climbing <a href="https://www.tomsguide.com/us/best-robot-vacuums,review-2000.html">robot vacuums</a> aren't necessarily a <em>new</em> thing. Last year at IFA 2025, I watched <a href="https://www.tomsguide.com/home/home-appliances/yes-this-robot-vacuum-has-legs-and-can-climb-stairs-this-is-a-game-changer-for-easy-cleaning">Dreame's Cyber X</a> climb stairs (super quickly, may I add), but I was disappointed with the bulk of the product — and that it's been a whole year and you still can't buy the Cyber X. </p><p>Now I'm at <a href="http://tomsguide.com/tag/ifa">IFA 2026</a> in Berlin, and I've just seen Roborock's stair-climbing contraption — the Rover. While this isn't available yet, you can get the new Qrevo Edge 3 Pro — for <a href="https://www.amazon.com/dp/B0H1WCKGPX" target="_blank" rel="nofollow">$1,499 from Amazon</a>.</p><p>Unfortunately, Roborock's representative was unable to confirm a release date or more specs. It was initially unveiled at CES in January — eight months ago. In the meantime, though, let's see it in action.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-Xk8nke"></div>                            </div>                            <script src="https://kwizly.com/embed/Xk8nke.js" async></script><h2 id="so-what-can-the-roborock-rover-actually-do">So what can the Roborock Rover actually do?</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="HzGDa5GJiTcYr9KGqNg9BV" name="roborock ifa 4" alt="the roborock rover climbing stairs at IFA 2026" src="https://cdn.mos.cms.futurecdn.net/HzGDa5GJiTcYr9KGqNg9BV.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Erin Bashford)</span></figcaption></figure><p>Unfortunately, as Roborock's representative was unable to confirm additional information, I know very little. What I <em>do</em> know, though, is that the Rover does climb stairs, and it can manoeuvre down slopes. I saw it with my own two eyes.</p><p>As it has two retractable, wheel-based legs, the Rover can climb and clean at the same time. Yes, it took around three minutes to climb the stairs you see in the photos — and get back down again — but the stairs were sparkling after.</p><p>Even though it took a while to climb the stairs, if you're simply working from home or out running errands, you won't notice how long it takes. That's the whole point of a robot vacuum — clean so you don't have to!</p><h2 id="but-i-have-some-major-reservations">But I have some major reservations</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.21%;"><img id="S3hhrbjg3KayoDdLJJHzyU" name="roborock IFA 3" alt="the roborock rover climbing stairs at IFA 2026" src="https://cdn.mos.cms.futurecdn.net/S3hhrbjg3KayoDdLJJHzyU.jpg" mos="" align="middle" fullscreen="" width="2560" height="1439" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Erin Bashford)</span></figcaption></figure><p>The Roborock Rover was first unveiled at CES in Las Vegas this past January. It was shown off again in Berlin in September. </p><p>And there is still no release date in sight. No specs. No pricing. What is Roborock cooking up behind the scenes? Are there some major issues we're not privy to? Or is it simply waiting for the right time to release it?</p><p>Roborock confirmed that they may have more information by CES 2027, but there's no release timeline yet. Why show off a product so far out from release?</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="dzs5MCXnu9FLShSxPr3vm" name="roborock 6" alt="the roborock rover climbing stairs at IFA" src="https://cdn.mos.cms.futurecdn.net/dzs5MCXnu9FLShSxPr3vm.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Erin Bashford)</span></figcaption></figure><p>I could spend all day speculating, but the long and short of it is this: Roborock has "unveiled" this stair-climbing robot vacuum twice now, but we're still no closer to being able to actually make use of it. Forget watching it at tech shows — I want it in my house! </p><div class="youtube-video" data-nosnippet ><div class="video-aspect-box"><iframe data-lazy-priority="high" data-lazy-src="https://www.youtube-nocookie.com/embed/SuyBti4YC-Y" allowfullscreen></iframe></div></div><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h3><ul><li><a href="https://www.tomsguide.com/home/gardening/ive-just-found-the-perfect-hummingbird-house-for-my-yard-on-amazon-and-it-has-the-perfect-rustic-cozy-vibe">I've just found the perfect hummingbird house for my yard on Amazon — and it has a rustic-cozy vibe</a></li><li><a href="https://www.tomsguide.com/home/anker-just-launched-a-ton-of-new-products-at-ifa-2026-including-an-ai-powered-home-hub">Anker just launched a ton of new products at IFA 2026 — including an AI-powered home hub</a></li><li><a href="https://www.tomsguide.com/home/irobots-new-flagship-roomba-creates-an-airtight-seal-with-your-carpet-the-competition-should-be-worried">iRobot's new flagship Roomba creates an airtight seal with your carpet — the competition should be worried</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ iRobot's new flagship Roomba creates an airtight seal with your carpet — the competition should be worried ]]></title>
                                                                                                <dc:content><![CDATA[ <p>It’s been a busy year for iRobot. March brought the Roomba Mini — a new compact bot available in bold, playful colorways rarely seen in the category. May saw a massive release of eight new models, ranging from the entry-level 115 to the flagship 775. </p><p>Now, just in time for IFA and as we roll into September, the company has dropped another heavyweight. Enter the Roomba Max 875 Combo, pushing the 775 off the top spot. </p><p>With so many new models on the market, you’ve got to ask whether the world needs yet another robot vacuum? Apparently so.</p><p>Could the Roomba Max 875 Combo be the ultimate floor cleaning tool? At <a href="https://www.irobot.com/en_US/roomba-max-875-combo-robot-plus-autowash-dock/Z185020.html" target="_blank" rel="nofollow">$1,119 at iRobot</a>, I’ll let you decide if the features justify the price tag. I can’t wait to see how it compares to the <a href="https://www.tomsguide.com/home/dreame-x60-max-ultra-complete-review">Dreame X60 Max Ultra Complete</a>, which currently ranks as the<a href="https://www.tomsguide.com/us/best-robot-vacuums,review-2000.html"> best robot vacuum</a> in our buying guide.</p><h2 id="hard-floors-and-carpet-no-problem">Hard floors and carpet: No problem</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="dS2ykywVQWbg4ZnAMyhdqV" name="Roomba Max 875" alt="Roomba Max 875" src="https://cdn.mos.cms.futurecdn.net/dS2ykywVQWbg4ZnAMyhdqV.png" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: iRobot)</span></figcaption></figure><p>I spoke to Reena Paatel, Floorcare Category Manager at iRobot, to learn more about iRobot’s flagship model. She says it was engineered to tackle the full spectrum of household messes, from deeply embedded debris to everyday dust and pet hair.  </p><p>“It combines serious cleaning power with smart automation, so customers can spend less time managing their floors and more time enjoying their homes and experiences outside their home, too,” Patel says. “It’s not just a smarter clean; it’s a stronger, deeper, and more effortless clean," which she adds is all handled through the app. </p><p>She explains that the Roomba Max 875 was designed around clear feedback iRobot repeatedly sees. “Customers continually want to experience a robot to deliver a tough stain clean. So if you’ve got debris locked into your carpets or liquid stains that are dried on your hard floors, you want the robot to be able to clean those away effectively.” </p><h2 id="what-does-the-roomba-max-875-combo-deliver">What does the Roomba Max 875 Combo deliver?</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="UsDxpmJh5NQ9mPaSx45s56" name="Roomba Max 875" alt="Roomba Max 875" src="https://cdn.mos.cms.futurecdn.net/UsDxpmJh5NQ9mPaSx45s56.png" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: iRobot)</span></figcaption></figure><p>So, what does iRobot’s latest model actually bring to the table? According to the company, the robot pairs proprietary <strong>SealForce vacuuming technology</strong> with a <strong>dual-action heated mopping system</strong>. The result is deep carpet cleaning, target stain removal on hard floors, and automated rug protection during mopping. </p><p><strong>Deep cleaning on carpets</strong><br>Let’s look at that more closely. SealForce does not rely on suction power alone; instead, the chassis lowers a dedicated skirt to create a tight seal against carpet fibers, concentrating vacuuming force directly where debris hides. </p><p>Paired with 20 L/s of tornado-like airflow and 35,000 Pa of suction, iRobot claims this delivers three times deeper carpet cleaning than systems without SealForce, making it their best pickup performance to date.  </p><p><strong>Tough on hard floor stains</strong><br>On hard surfaces, the vacuuming pairs with an advanced mopping system. iRobot’s ultrasonic <strong>ThermaMist technology</strong> continuously sprays a heated mist to soften and loosen dried-on spills so tough stains lift in a single pass — eliminating the need for manual scrubbing.  It could be a game-changer in the kitchen.</p><p>What’s more, this intelligent floor cleaner boasts a continuously self-cleaning <strong>PowerSpin Max roller mop </strong>— the industry’s largest according to iRobot. It scrubs with heated water at 300 RPM under 18 Newtons of downward pressure, delivering 3.75 times deeper scrubbing power and 1.2 times wider coverage per pass, compared to a standard PowerSpin roller mop.  </p><p><strong>Rug-safe mopping</strong> <br>When returning to carpets, the patented <strong>DriLift technology</strong> automatically detects carpeted areas, raises the mop roller, and lowers a protective shield to guarantee rugs remain completely dry throughout the run. That puts an end to stopping the robot mid-clean to remove a rug.  </p><p><strong>Sharp on edges</strong><br>The 875 also addresses the common pain point of robots not reaching the edges by delivering <strong>PerfectEdge cleaning</strong>, with an outward-expanding brush for corners.</p><p>However, despite all the tech, this model still can't climb stairs.</p><div class="product"><a data-dimension112="ec31572e-a6bd-11f1-9a0c-f1fd724aae38" data-action="Deal Block" data-label="Roomba Max 875 Combo robot + AutoWash dock" data-dimension48="Roomba Max 875 Combo robot + AutoWash dock" data-dimension25="$1199" href="https://www.irobot.com/en_US/roomba-max-875-combo-robot-plus-autowash-dock/Z185020.html" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="YWA5uyNArvwkBsPw8UVGuQ" name="Roomba Max 875" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/YWA5uyNArvwkBsPw8UVGuQ.png" mos="" align="middle" fullscreen="" width="2000" height="2000" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.irobot.com/en_US/roomba-max-875-combo-robot-plus-autowash-dock/Z185020.html" target="_blank" rel="nofollow" data-dimension112="ec31572e-a6bd-11f1-9a0c-f1fd724aae38" data-action="Deal Block" data-label="Roomba Max 875 Combo robot + AutoWash dock" data-dimension48="Roomba Max 875 Combo robot + AutoWash dock" data-dimension25="$1199">Roomba Max 875 Combo robot + AutoWash dock: $1199</a></strong><br>Designed for pro-level cleaning, this robot vacuum and mop combines powerful suction and SealForce Technology, with ultrasonic ThermaMist and a PowerSpin roller mop. <a class="view-deal button" href="https://www.irobot.com/en_US/roomba-max-875-combo-robot-plus-autowash-dock/Z185020.html" target="_blank" rel="nofollow" data-dimension112="ec31572e-a6bd-11f1-9a0c-f1fd724aae38" data-action="Deal Block" data-label="Roomba Max 875 Combo robot + AutoWash dock" data-dimension48="Roomba Max 875 Combo robot + AutoWash dock" data-dimension25="$1199">View Deal</a></p></div><h2 id="smart-cleaning-from-irobot">Smart cleaning from iRobot</h2><p>When paired with the Roomba app, you can make the most of personalized cleaning schedules, target specific rooms with heavier footfall like hallways and prioritize pet areas. You can even define whether you require a light, medium or deep clean.</p><p>And with Precision Vision AI, you shouldn’t have to worry about common floor hazards, such as pet bowls and children’s toys, as it recognizes over 300 common household objects. </p><p>We can't recommend iRobot’s latest flagship model without testing it, but it sure sounds impressive. Would you consider purchasing the 875 to clean your floors? Let me know in the comments below.</p><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h3><ul><li><a href="https://www.tomsguide.com/home/home-appliances/best-robot-vacuums-of-ces-2026">The top robot vacuums we saw at CES 2026</a></li><li><a href="https://www.tomsguide.com/home/home-appliances/best-robot-vacuums-for-pet-hair">We fought fur and mopped paw prints with the best robot vacuums for pet hair in 2026 — these 5 came out on top</a></li><li><a href="https://www.tomsguide.com/best-picks/best-vacuum-cleaners">Best vacuum cleaners 2026: Top picks for spotless floors</a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/home/irobots-new-flagship-roomba-creates-an-airtight-seal-with-your-carpet-the-competition-should-be-worried</link>
                                                                            <description>
                            <![CDATA[ iRobot unveils the Roomba Max 875 Combo: Is it the ultimate floor cleaning tool? ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">vXGQpNwoCjaqnApdx7qHA5</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/yyBPERs5wVRPE9yP72cBzH-1280-80.png" type="image/png" length="0"></enclosure>
                                                                        <pubDate>Wed, 02 Sep 2026 13:12:14 +0000</pubDate>                                                                                                                                <updated>Wed, 02 Sep 2026 14:00:06 +0000</updated>
                                                                                                                                            <category><![CDATA[Home]]></category>
                                                    <category><![CDATA[Home Appliances]]></category>
                                                                                                <author><![CDATA[ camilla.sharman@futurenet.com (Camilla Sharman) ]]></author>                    <dc:creator><![CDATA[ Camilla Sharman ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/nY4nvWzofHKHpvzAqN5LVH.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Camilla is the Homes Staff Writer and covers everything to do with homes and gardens. She has a wealth of editorial experience, mounting over 30 years, and covers news and features, tests products for reviews and compiles buying guides.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;p&gt;Her work has appeared in business and consumer titles, including Ideal Home, Real Homes, House Beautiful, Homebuilding &amp;amp; Renovation, and Kitchen &amp;amp; Bathroom Business. She’s even appeared on the cover of Your Home, writing about her own house renovation.&lt;/p&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;p&gt;Although she’s obsessed with decorating her home, she also enjoys baking and trying out the latest kitchen appliances. But when she’s not inside, you’ll find her pottering about in her yard, tending to her vegetable patch or taking in her prized hydrangeas. She also enjoys keeping fit, and if she&#039;s not on a spin bike trying to keep up with the class, she&#039;ll be in the pool, or trying to perfect her headstand in a yoga class.&lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                <media:content type="image/png" url="https://cdn.mos.cms.futurecdn.net/yyBPERs5wVRPE9yP72cBzH-1280-80.png">
                                                            <media:credit><![CDATA[iRobot]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Roomba Max 875]]></media:description>                                                            <media:text><![CDATA[Roomba Max 875]]></media:text>
                                <media:title type="plain"><![CDATA[Roomba Max 875]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/yyBPERs5wVRPE9yP72cBzH-1280-80.png" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>It’s been a busy year for iRobot. March brought the Roomba Mini — a new compact bot available in bold, playful colorways rarely seen in the category. May saw a massive release of eight new models, ranging from the entry-level 115 to the flagship 775. </p><p>Now, just in time for IFA and as we roll into September, the company has dropped another heavyweight. Enter the Roomba Max 875 Combo, pushing the 775 off the top spot. </p><p>With so many new models on the market, you’ve got to ask whether the world needs yet another robot vacuum? Apparently so.</p><p>Could the Roomba Max 875 Combo be the ultimate floor cleaning tool? At <a href="https://www.irobot.com/en_US/roomba-max-875-combo-robot-plus-autowash-dock/Z185020.html" target="_blank" rel="nofollow">$1,119 at iRobot</a>, I’ll let you decide if the features justify the price tag. I can’t wait to see how it compares to the <a href="https://www.tomsguide.com/home/dreame-x60-max-ultra-complete-review">Dreame X60 Max Ultra Complete</a>, which currently ranks as the<a href="https://www.tomsguide.com/us/best-robot-vacuums,review-2000.html"> best robot vacuum</a> in our buying guide.</p><h2 id="hard-floors-and-carpet-no-problem">Hard floors and carpet: No problem</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="dS2ykywVQWbg4ZnAMyhdqV" name="Roomba Max 875" alt="Roomba Max 875" src="https://cdn.mos.cms.futurecdn.net/dS2ykywVQWbg4ZnAMyhdqV.png" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: iRobot)</span></figcaption></figure><p>I spoke to Reena Paatel, Floorcare Category Manager at iRobot, to learn more about iRobot’s flagship model. She says it was engineered to tackle the full spectrum of household messes, from deeply embedded debris to everyday dust and pet hair.  </p><p>“It combines serious cleaning power with smart automation, so customers can spend less time managing their floors and more time enjoying their homes and experiences outside their home, too,” Patel says. “It’s not just a smarter clean; it’s a stronger, deeper, and more effortless clean," which she adds is all handled through the app. </p><p>She explains that the Roomba Max 875 was designed around clear feedback iRobot repeatedly sees. “Customers continually want to experience a robot to deliver a tough stain clean. So if you’ve got debris locked into your carpets or liquid stains that are dried on your hard floors, you want the robot to be able to clean those away effectively.” </p><h2 id="what-does-the-roomba-max-875-combo-deliver">What does the Roomba Max 875 Combo deliver?</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="UsDxpmJh5NQ9mPaSx45s56" name="Roomba Max 875" alt="Roomba Max 875" src="https://cdn.mos.cms.futurecdn.net/UsDxpmJh5NQ9mPaSx45s56.png" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: iRobot)</span></figcaption></figure><p>So, what does iRobot’s latest model actually bring to the table? According to the company, the robot pairs proprietary <strong>SealForce vacuuming technology</strong> with a <strong>dual-action heated mopping system</strong>. The result is deep carpet cleaning, target stain removal on hard floors, and automated rug protection during mopping. </p><p><strong>Deep cleaning on carpets</strong><br>Let’s look at that more closely. SealForce does not rely on suction power alone; instead, the chassis lowers a dedicated skirt to create a tight seal against carpet fibers, concentrating vacuuming force directly where debris hides. </p><p>Paired with 20 L/s of tornado-like airflow and 35,000 Pa of suction, iRobot claims this delivers three times deeper carpet cleaning than systems without SealForce, making it their best pickup performance to date.  </p><p><strong>Tough on hard floor stains</strong><br>On hard surfaces, the vacuuming pairs with an advanced mopping system. iRobot’s ultrasonic <strong>ThermaMist technology</strong> continuously sprays a heated mist to soften and loosen dried-on spills so tough stains lift in a single pass — eliminating the need for manual scrubbing.  It could be a game-changer in the kitchen.</p><p>What’s more, this intelligent floor cleaner boasts a continuously self-cleaning <strong>PowerSpin Max roller mop </strong>— the industry’s largest according to iRobot. It scrubs with heated water at 300 RPM under 18 Newtons of downward pressure, delivering 3.75 times deeper scrubbing power and 1.2 times wider coverage per pass, compared to a standard PowerSpin roller mop.  </p><p><strong>Rug-safe mopping</strong> <br>When returning to carpets, the patented <strong>DriLift technology</strong> automatically detects carpeted areas, raises the mop roller, and lowers a protective shield to guarantee rugs remain completely dry throughout the run. That puts an end to stopping the robot mid-clean to remove a rug.  </p><p><strong>Sharp on edges</strong><br>The 875 also addresses the common pain point of robots not reaching the edges by delivering <strong>PerfectEdge cleaning</strong>, with an outward-expanding brush for corners.</p><p>However, despite all the tech, this model still can't climb stairs.</p><div class="product"><a data-dimension112="ec31572e-a6bd-11f1-9a0c-f1fd724aae38" data-action="Deal Block" data-label="Roomba Max 875 Combo robot + AutoWash dock" data-dimension48="Roomba Max 875 Combo robot + AutoWash dock" data-dimension25="$1199" href="https://www.irobot.com/en_US/roomba-max-875-combo-robot-plus-autowash-dock/Z185020.html" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="YWA5uyNArvwkBsPw8UVGuQ" name="Roomba Max 875" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/YWA5uyNArvwkBsPw8UVGuQ.png" mos="" align="middle" fullscreen="" width="2000" height="2000" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.irobot.com/en_US/roomba-max-875-combo-robot-plus-autowash-dock/Z185020.html" target="_blank" rel="nofollow" data-dimension112="ec31572e-a6bd-11f1-9a0c-f1fd724aae38" data-action="Deal Block" data-label="Roomba Max 875 Combo robot + AutoWash dock" data-dimension48="Roomba Max 875 Combo robot + AutoWash dock" data-dimension25="$1199">Roomba Max 875 Combo robot + AutoWash dock: $1199</a></strong><br>Designed for pro-level cleaning, this robot vacuum and mop combines powerful suction and SealForce Technology, with ultrasonic ThermaMist and a PowerSpin roller mop. <a class="view-deal button" href="https://www.irobot.com/en_US/roomba-max-875-combo-robot-plus-autowash-dock/Z185020.html" target="_blank" rel="nofollow" data-dimension112="ec31572e-a6bd-11f1-9a0c-f1fd724aae38" data-action="Deal Block" data-label="Roomba Max 875 Combo robot + AutoWash dock" data-dimension48="Roomba Max 875 Combo robot + AutoWash dock" data-dimension25="$1199">View Deal</a></p></div><h2 id="smart-cleaning-from-irobot">Smart cleaning from iRobot</h2><p>When paired with the Roomba app, you can make the most of personalized cleaning schedules, target specific rooms with heavier footfall like hallways and prioritize pet areas. You can even define whether you require a light, medium or deep clean.</p><p>And with Precision Vision AI, you shouldn’t have to worry about common floor hazards, such as pet bowls and children’s toys, as it recognizes over 300 common household objects. </p><p>We can't recommend iRobot’s latest flagship model without testing it, but it sure sounds impressive. Would you consider purchasing the 875 to clean your floors? Let me know in the comments below.</p><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h3><ul><li><a href="https://www.tomsguide.com/home/home-appliances/best-robot-vacuums-of-ces-2026">The top robot vacuums we saw at CES 2026</a></li><li><a href="https://www.tomsguide.com/home/home-appliances/best-robot-vacuums-for-pet-hair">We fought fur and mopped paw prints with the best robot vacuums for pet hair in 2026 — these 5 came out on top</a></li><li><a href="https://www.tomsguide.com/best-picks/best-vacuum-cleaners">Best vacuum cleaners 2026: Top picks for spotless floors</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ People are seriously spending $300 on a handheld coffee grinder, and here's why I'm completely on their side ]]></title>
                                                                                                <dc:content><![CDATA[ <div  class="fancy-box"><div class="fancy_box-title">The Coffee Lab</div><div class="fancy_box_body"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' ><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="UwFdgr6xkNzHUWjapZThcN" name="smeg edited2" caption="" alt="the smeg emc02 mini pro manual espresso machine in jade green" src="https://cdn.mos.cms.futurecdn.net/UwFdgr6xkNzHUWjapZThcN.jpg" mos="" link="" align="" fullscreen="" width="" height="" attribution="" endorsement="" class="pinterest-pin-exclude"></p></div></div><figcaption itemprop="caption description" class=""><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p class="fancy-box__body-text">I'm Erin, and welcome to the twenty-second episode of <a data-analytics-id="inline-link" href="https://www.tomsguide.com/tag/the-coffee-lab">The Coffee Lab</a>, the series where we forget coffee snobbery. The Coffee Lab is all about making coffee fun. Join me as I help you kickstart your coffee journey!</p></div></div><p>In the coffee sphere, a select few brands are so well-respected that they elicit a revered gasp when mentioned. Moccamaster is one, as is Lelit, Acaia, and La Marzocco. Of course, this isn't an exhaustive list, and you've also got the universally adored Mazzer and Comandante, which make the <a href="https://www.tomsguide.com/best-picks/best-coffee-grinder">best coffee grinders</a>.</p><p>Comandante is what I'm going to discuss today. You may have heard of the <a href="https://www.tomsguide.com/home/home-appliances/comandante-c40-mk4-review">Comandante C40 MK4</a>, the Comandante C60 Baracuda, or the Comandante X25 Trailmaster. The C60 Baracuda is the priciest option, at around $500-$650 depending on finish, and the X25 Trailmaster is the closest Comandante gets to "budget" — $250. But let's focus on the midrange option, the C40 MK4. </p>                    <div class= "tiktok-wrapper" style="min-height: 750px;"><blockquote class="tiktok-embed" cite="https://www.tiktok.com/@tomsguide/video/7680226127113243918" data-video-id="7680226127113243918" style="max-width: 605px; min-width: 325px;">                        <section>                            <a target="_blank" title="@tomsguide" href="https://www.tiktok.com/@tomsguide">@tomsguide</a>                            <p></p><a target="_blank" title="♬ Heartwarming, everyday, funny BGM(1194980) - K's note" href="https://www.tiktok.com/music/Heartwarming-everyday-funny-BGM-1194980-7065431325666183169">♬ Heartwarming, everyday, funny BGM(1194980) - K's note</a></section>                    </blockquote></div>                <p>I've owned this coffee grinder for about 18 months now, and I'm seriously obsessed. I use it every day, multiple times a day, and it's simply perfection. While pricey, ranging from <a href="https://www.amazon.com/Comandante-4260113435663-Nitro-Blade-Black/dp/B07JQ4P976" target="_blank" rel="nofollow">$289-$325 at Amazon</a>, I'd seriously pay it for this performance. </p><div class="product"><a data-dimension112="21205f64-a2d3-11f1-aae5-a3cf0dca9955" data-action="Deal Block" data-label="C40 MK4" data-dimension48="C40 MK4" data-dimension25="$275" href="https://www.amazon.com/Comandante-4260113435663-Nitro-Blade-Black/dp/B07JQ4P976" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1500px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="CZ2VbSvqAbjXtZwv5d62A8" name="Comandante C40 MK4" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/CZ2VbSvqAbjXtZwv5d62A8.jpg" mos="" align="middle" fullscreen="" width="1500" height="1500" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>While pricey, the Comandante C40 MK4 earns its keep — the Martensitic steel burrs have a lifetime warranty and it's constructed from high-quality metals or wood (depending on your chosen finish). I have the pictured walnut version.<a class="view-deal button" href="https://www.amazon.com/Comandante-4260113435663-Nitro-Blade-Black/dp/B07JQ4P976" target="_blank" rel="nofollow" data-dimension112="21205f64-a2d3-11f1-aae5-a3cf0dca9955" data-action="Deal Block" data-label="C40 MK4" data-dimension48="C40 MK4" data-dimension25="$275">View Deal</a></p></div><h2 id="what-actually-is-the-comandante-c40-mk4">What actually is the Comandante C40 MK4? </h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="wXomSExhKizcfgBFv5Jk4B" name="Comandante_C40_Mk4_grinder_ 4.JPG" alt="the comandante c40 mk4 hand coffee grinder with a glass catch chamber and high nitrogen steel burrs" src="https://cdn.mos.cms.futurecdn.net/wXomSExhKizcfgBFv5Jk4B.jpg" mos="" align="middle" fullscreen="" width="1920" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The Comandante C40 MK4 is a handheld coffee grinder. This means you have to turn the burrs yourself. The hand crank is easy to grip and it comes with a rubber band you can put around the canister to secure your hold. The rubber band is "supposed" to be a wristband but I use it for holding the grinder steady (I'm weak). </p><p>So while other coffee grinders are powered by an electric motor, like the <a href="https://www.tomsguide.com/home/home-appliances/baratza-encore-esp-review">Baratza Encore ESP</a> or the <a href="https://www.tomsguide.com/home/coffee-makers/mazzer-philos-review">Mazzer Philos</a>, the Comandante C40 MK4 is all you, baby. </p><p>Hand grinders are generally cheaper than electric grinders. I've tested some as cheap as $60 —like the <a href="https://www.tomsguide.com/home/kitchen-dining/timemore-chestnut-c2s-review">Timemore Chestnut C2s</a> — but the Comandante is by far the priciest (and best). Naturally, electric grinders can set you back much, much more than the C40 MK4. The Eureka Mignon Specialita is $699, and the Mazzer Philos is $1,500.</p><p>As a hand grinder, its maximum capacity is around 50g, but I would only recommend grinding enough for one or two espressos (so 36g) at once. When the bottom canister gets full, you can't grind any more. </p><h2 id="why-is-a-hand-grinder-worth-300">Why is a hand grinder worth $300? </h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="sZoB6aKU56X5auqv5K2y4B" name="Comandante_C40_Mk4_grinder_.JPG" alt="the comandante c40 mk4 hand coffee grinder with a glass catch chamber and high nitrogen steel burrs" src="https://cdn.mos.cms.futurecdn.net/sZoB6aKU56X5auqv5K2y4B.jpg" mos="" align="middle" fullscreen="" width="1920" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The Comandante C40 MK4 is worth $300 because of one reason: materials. The grinder uses Martensitic steel burrs, which is the same material used in sharp surgical instruments. Oh, and the burrs also come with a lifetime warranty. No biggie. </p><p>Naturally, this quality material results in excellent uniformity, minimal retention, and low static. These are the three touchstones of a great grinder. You want all your coffee grounds to be the same size, you want the grinder to retain as little coffee as possible, and you don't want your worktop to be covered in sticky coffee granules post-grind. </p><p>Thankfully, the grinder excels in all three. Here's a little insight into the grinder's uniformity. Here, I'm checking if all the coffee grounds are the same size. You want big jumps: 0% 300um to 100% 500um, for example.</p><div ><table><thead><tr><th class="firstcol " ><p><strong>Grind size</strong></p></th><th  ><p><strong>300μm</strong></p></th><th  ><p><strong>500μm</strong></p></th><th  ><p><strong>800μm</strong></p></th><th  ><p><strong>1100μm</strong></p></th><th  ><p><strong>1400μm</strong></p></th></tr></thead><tbody><tr><td class="firstcol " ><p>1 click (min/finest)</p></td><td  ><p>100%</p></td><td  ><p>100%</p></td><td  ><p>100%</p></td><td  ><p>100%</p></td><td  ><p>100%</p></td></tr><tr><td class="firstcol " ><p>4 clicks</p></td><td  ><p>99%</p></td><td  ><p>100%</p></td><td  ><p>100%</p></td><td  ><p>100%</p></td><td  ><p>100%</p></td></tr><tr><td class="firstcol " ><p>8 clicks</p></td><td  ><p>90%</p></td><td  ><p>99%</p></td><td  ><p>100%</p></td><td  ><p>100%</p></td><td  ><p>100%</p></td></tr><tr><td class="firstcol " ><p>12 clicks</p></td><td  ><p>1%</p></td><td  ><p>95%</p></td><td  ><p>99%</p></td><td  ><p>100%</p></td><td  ><p>100%</p></td></tr><tr><td class="firstcol " ><p>20 clicks</p></td><td  ><p>1%</p></td><td  ><p>80%</p></td><td  ><p>100%</p></td><td  ><p>100%</p></td><td  ><p>100%</p></td></tr><tr><td class="firstcol " ><p>24 clicks</p></td><td  ><p>0%</p></td><td  ><p>20%</p></td><td  ><p>90%</p></td><td  ><p>100%</p></td><td  ><p>100%</p></td></tr><tr><td class="firstcol " ><p>32 clicks</p></td><td  ><p>0%</p></td><td  ><p>30%</p></td><td  ><p>95%</p></td><td  ><p>100%</p></td><td  ><p>100%</p></td></tr><tr><td class="firstcol " ><p>36 clicks</p></td><td  ><p>0%</p></td><td  ><p>0%</p></td><td  ><p>1%</p></td><td  ><p>30%</p></td><td  ><p>50%</p></td></tr><tr><td class="firstcol " ><p>40 clicks (max/coarsest)</p></td><td  ><p>0%</p></td><td  ><p>0%</p></td><td  ><p>0%</p></td><td  ><p>0%</p></td><td  ><p>10%</p></td></tr></tbody></table></div><p>As you can see, the consistency is excellent. Most granules are the same size, which will result in a better-tasting coffee. If you've got some grains at >300um, but some at 1400um>, this means the coffee will be half over- and half under-extracted. Ergo, no thank you, I'll just drink my water. </p><h2 id="should-i-spend-300-on-a-coffee-grinder">Should I spend $300 on a coffee grinder? </h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="yczfdS2GVsvYrwKUgMU65B" name="Comandante_C40_Mk4_grinder_ 7.JPG" alt="the comandante c40 mk4 hand coffee grinder with a glass catch chamber and high nitrogen steel burrs" src="https://cdn.mos.cms.futurecdn.net/yczfdS2GVsvYrwKUgMU65B.jpg" mos="" align="middle" fullscreen="" width="1920" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>If you have $300 to spare and you're into coffee, yes, you should buy this grinder. All that being said, though, if you don't have $300 lying around, then please don't buy an objectively expensive piece of coffee tech. You can still get a good coffee with a cheaper grinder, like the aforementioned Timemore Chestnut C2s. </p><p>I love my Comandante C40 MK4, but it's not for everyone. In this economy, I think there are more important things to invest in. Save your dollars for a rainy day! </p><p>But if you've got loads of cash spare, then of course you won't be disappointed by this incredible coffee grinder. It's my favorite grinder of all time... I just wish the military branding wasn't so cringe. </p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-OaLgwW"></div>                            </div>                            <script src="https://kwizly.com/embed/OaLgwW.js" async></script><figure class="inline-layout"><div style="min-height: 400px;"><fw-embed-feed channel="toms_guide" playlist="ojE0pK" mode="row" player_placement="bottom-right"></fw-embed-feed></div></figure><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h3><ul><li><a href="https://www.tomsguide.com/home/coffee-makers/overwhelmed-by-coffee-jargon-here-are-the-5-key-espresso-terms-you-need-to-know"><strong>Overwhelmed by coffee jargon? Here are the 5 key espresso terms you need to know</strong></a></li><li><a href="https://www.tomsguide.com/home/coffee-makers/im-an-ex-starbucks-barista-you-can-make-the-iced-brown-sugar-oatmilk-shaken-espresso-at-home-for-a-fraction-of-the-cost"><strong>I'm an ex-Starbucks barista — you can make the Iced Brown Sugar Oatmilk Shaken Espresso at home for a fraction of the cost</strong></a></li><li><a href="https://www.tomsguide.com/home/coffee-makers/people-are-mixing-coffee-with-diet-coke-yes-really-im-an-ex-barista-and-i-tried-the-viral-fridge-cigarette"><strong>People are mixing coffee with Diet Coke (yes, really) — I'm an ex-barista, and I tried the viral 'fridge cigarette'</strong></a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/home/coffee-makers/people-are-seriously-spending-usd300-on-a-handheld-coffee-grinder-and-heres-why-im-completely-on-their-side</link>
                                                                            <description>
                            <![CDATA[ On episode 22 of The Coffee Lab, I'm diving deep into the Comandante C40 MK4: Why does this pricey coffee grinder have a cult following? ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">H3B7qrJtKRFZBD9tsBKfvW</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/oWcc46QcegZzZbfbugKkWj-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Mon, 31 Aug 2026 11:30:00 +0000</pubDate>                                                                                                                                <updated>Mon, 31 Aug 2026 16:08:10 +0000</updated>
                                                                                                                                            <category><![CDATA[Coffee Makers]]></category>
                                                    <category><![CDATA[Home]]></category>
                                                    <category><![CDATA[Home Appliances]]></category>
                                                    <category><![CDATA[Kitchen & Dining]]></category>
                                                                                                <author><![CDATA[ erin.bashford@futurenet.com (Erin Bashford) ]]></author>                    <dc:creator><![CDATA[ Erin Bashford ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/rLvJvJVZx43hEzSsJy3BpL.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Erin Bashford is a senior reviews writer at Tom’s Guide. She has a Master’s in Broadcast and Digital Journalism from the University of East Anglia and 7 years of experience reviewing music and events for various publications. She has edited publications such as Outline Magazine’s Guide to Norwich, and she has written for a number of music magazines and websites such as Clash Magazine, Outline Magazine and Dork Magazine. She has a strong interest in audio gear and the music world. &lt;/p&gt;&lt;p&gt;As an ex-barista, Erin is passionate about coffee tech. She also loves finding the best cooking hacks and kitchen appliances, including her beloved Instant Pot. &lt;/p&gt;&lt;p&gt;In her spare time, you can find her reading, practising yoga, hiking, writing fantasy novels, or stressing over NYT Games.&lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/oWcc46QcegZzZbfbugKkWj-1280-80.jpg">
                                                            <media:credit><![CDATA[Tom&amp;#39;s Guide]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[the comandante c40 mk4 with the coffee lab logo]]></media:description>                                                            <media:text><![CDATA[the comandante c40 mk4 with the coffee lab logo]]></media:text>
                                <media:title type="plain"><![CDATA[the comandante c40 mk4 with the coffee lab logo]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/oWcc46QcegZzZbfbugKkWj-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <div  class="fancy-box"><div class="fancy_box-title">The Coffee Lab</div><div class="fancy_box_body"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' ><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="UwFdgr6xkNzHUWjapZThcN" name="smeg edited2" caption="" alt="the smeg emc02 mini pro manual espresso machine in jade green" src="https://cdn.mos.cms.futurecdn.net/UwFdgr6xkNzHUWjapZThcN.jpg" mos="" link="" align="" fullscreen="" width="" height="" attribution="" endorsement="" class="pinterest-pin-exclude"></p></div></div><figcaption itemprop="caption description" class=""><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p class="fancy-box__body-text">I'm Erin, and welcome to the twenty-second episode of <a data-analytics-id="inline-link" href="https://www.tomsguide.com/tag/the-coffee-lab">The Coffee Lab</a>, the series where we forget coffee snobbery. The Coffee Lab is all about making coffee fun. Join me as I help you kickstart your coffee journey!</p></div></div><p>In the coffee sphere, a select few brands are so well-respected that they elicit a revered gasp when mentioned. Moccamaster is one, as is Lelit, Acaia, and La Marzocco. Of course, this isn't an exhaustive list, and you've also got the universally adored Mazzer and Comandante, which make the <a href="https://www.tomsguide.com/best-picks/best-coffee-grinder">best coffee grinders</a>.</p><p>Comandante is what I'm going to discuss today. You may have heard of the <a href="https://www.tomsguide.com/home/home-appliances/comandante-c40-mk4-review">Comandante C40 MK4</a>, the Comandante C60 Baracuda, or the Comandante X25 Trailmaster. The C60 Baracuda is the priciest option, at around $500-$650 depending on finish, and the X25 Trailmaster is the closest Comandante gets to "budget" — $250. But let's focus on the midrange option, the C40 MK4. </p>                    <div class= "tiktok-wrapper" style="min-height: 750px;"><blockquote class="tiktok-embed" cite="https://www.tiktok.com/@tomsguide/video/7680226127113243918" data-video-id="7680226127113243918" style="max-width: 605px; min-width: 325px;">                        <section>                            <a target="_blank" title="@tomsguide" href="https://www.tiktok.com/@tomsguide">@tomsguide</a>                            <p></p><a target="_blank" title="♬ Heartwarming, everyday, funny BGM(1194980) - K's note" href="https://www.tiktok.com/music/Heartwarming-everyday-funny-BGM-1194980-7065431325666183169">♬ Heartwarming, everyday, funny BGM(1194980) - K's note</a></section>                    </blockquote></div>                <p>I've owned this coffee grinder for about 18 months now, and I'm seriously obsessed. I use it every day, multiple times a day, and it's simply perfection. While pricey, ranging from <a href="https://www.amazon.com/Comandante-4260113435663-Nitro-Blade-Black/dp/B07JQ4P976" target="_blank" rel="nofollow">$289-$325 at Amazon</a>, I'd seriously pay it for this performance. </p><div class="product"><a data-dimension112="21205f64-a2d3-11f1-aae5-a3cf0dca9955" data-action="Deal Block" data-label="C40 MK4" data-dimension48="C40 MK4" data-dimension25="$275" href="https://www.amazon.com/Comandante-4260113435663-Nitro-Blade-Black/dp/B07JQ4P976" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1500px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="CZ2VbSvqAbjXtZwv5d62A8" name="Comandante C40 MK4" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/CZ2VbSvqAbjXtZwv5d62A8.jpg" mos="" align="middle" fullscreen="" width="1500" height="1500" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>While pricey, the Comandante C40 MK4 earns its keep — the Martensitic steel burrs have a lifetime warranty and it's constructed from high-quality metals or wood (depending on your chosen finish). I have the pictured walnut version.<a class="view-deal button" href="https://www.amazon.com/Comandante-4260113435663-Nitro-Blade-Black/dp/B07JQ4P976" target="_blank" rel="nofollow" data-dimension112="21205f64-a2d3-11f1-aae5-a3cf0dca9955" data-action="Deal Block" data-label="C40 MK4" data-dimension48="C40 MK4" data-dimension25="$275">View Deal</a></p></div><h2 id="what-actually-is-the-comandante-c40-mk4">What actually is the Comandante C40 MK4? </h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="wXomSExhKizcfgBFv5Jk4B" name="Comandante_C40_Mk4_grinder_ 4.JPG" alt="the comandante c40 mk4 hand coffee grinder with a glass catch chamber and high nitrogen steel burrs" src="https://cdn.mos.cms.futurecdn.net/wXomSExhKizcfgBFv5Jk4B.jpg" mos="" align="middle" fullscreen="" width="1920" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The Comandante C40 MK4 is a handheld coffee grinder. This means you have to turn the burrs yourself. The hand crank is easy to grip and it comes with a rubber band you can put around the canister to secure your hold. The rubber band is "supposed" to be a wristband but I use it for holding the grinder steady (I'm weak). </p><p>So while other coffee grinders are powered by an electric motor, like the <a href="https://www.tomsguide.com/home/home-appliances/baratza-encore-esp-review">Baratza Encore ESP</a> or the <a href="https://www.tomsguide.com/home/coffee-makers/mazzer-philos-review">Mazzer Philos</a>, the Comandante C40 MK4 is all you, baby. </p><p>Hand grinders are generally cheaper than electric grinders. I've tested some as cheap as $60 —like the <a href="https://www.tomsguide.com/home/kitchen-dining/timemore-chestnut-c2s-review">Timemore Chestnut C2s</a> — but the Comandante is by far the priciest (and best). Naturally, electric grinders can set you back much, much more than the C40 MK4. The Eureka Mignon Specialita is $699, and the Mazzer Philos is $1,500.</p><p>As a hand grinder, its maximum capacity is around 50g, but I would only recommend grinding enough for one or two espressos (so 36g) at once. When the bottom canister gets full, you can't grind any more. </p><h2 id="why-is-a-hand-grinder-worth-300">Why is a hand grinder worth $300? </h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="sZoB6aKU56X5auqv5K2y4B" name="Comandante_C40_Mk4_grinder_.JPG" alt="the comandante c40 mk4 hand coffee grinder with a glass catch chamber and high nitrogen steel burrs" src="https://cdn.mos.cms.futurecdn.net/sZoB6aKU56X5auqv5K2y4B.jpg" mos="" align="middle" fullscreen="" width="1920" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The Comandante C40 MK4 is worth $300 because of one reason: materials. The grinder uses Martensitic steel burrs, which is the same material used in sharp surgical instruments. Oh, and the burrs also come with a lifetime warranty. No biggie. </p><p>Naturally, this quality material results in excellent uniformity, minimal retention, and low static. These are the three touchstones of a great grinder. You want all your coffee grounds to be the same size, you want the grinder to retain as little coffee as possible, and you don't want your worktop to be covered in sticky coffee granules post-grind. </p><p>Thankfully, the grinder excels in all three. Here's a little insight into the grinder's uniformity. Here, I'm checking if all the coffee grounds are the same size. You want big jumps: 0% 300um to 100% 500um, for example.</p><div ><table><thead><tr><th class="firstcol " ><p><strong>Grind size</strong></p></th><th  ><p><strong>300μm</strong></p></th><th  ><p><strong>500μm</strong></p></th><th  ><p><strong>800μm</strong></p></th><th  ><p><strong>1100μm</strong></p></th><th  ><p><strong>1400μm</strong></p></th></tr></thead><tbody><tr><td class="firstcol " ><p>1 click (min/finest)</p></td><td  ><p>100%</p></td><td  ><p>100%</p></td><td  ><p>100%</p></td><td  ><p>100%</p></td><td  ><p>100%</p></td></tr><tr><td class="firstcol " ><p>4 clicks</p></td><td  ><p>99%</p></td><td  ><p>100%</p></td><td  ><p>100%</p></td><td  ><p>100%</p></td><td  ><p>100%</p></td></tr><tr><td class="firstcol " ><p>8 clicks</p></td><td  ><p>90%</p></td><td  ><p>99%</p></td><td  ><p>100%</p></td><td  ><p>100%</p></td><td  ><p>100%</p></td></tr><tr><td class="firstcol " ><p>12 clicks</p></td><td  ><p>1%</p></td><td  ><p>95%</p></td><td  ><p>99%</p></td><td  ><p>100%</p></td><td  ><p>100%</p></td></tr><tr><td class="firstcol " ><p>20 clicks</p></td><td  ><p>1%</p></td><td  ><p>80%</p></td><td  ><p>100%</p></td><td  ><p>100%</p></td><td  ><p>100%</p></td></tr><tr><td class="firstcol " ><p>24 clicks</p></td><td  ><p>0%</p></td><td  ><p>20%</p></td><td  ><p>90%</p></td><td  ><p>100%</p></td><td  ><p>100%</p></td></tr><tr><td class="firstcol " ><p>32 clicks</p></td><td  ><p>0%</p></td><td  ><p>30%</p></td><td  ><p>95%</p></td><td  ><p>100%</p></td><td  ><p>100%</p></td></tr><tr><td class="firstcol " ><p>36 clicks</p></td><td  ><p>0%</p></td><td  ><p>0%</p></td><td  ><p>1%</p></td><td  ><p>30%</p></td><td  ><p>50%</p></td></tr><tr><td class="firstcol " ><p>40 clicks (max/coarsest)</p></td><td  ><p>0%</p></td><td  ><p>0%</p></td><td  ><p>0%</p></td><td  ><p>0%</p></td><td  ><p>10%</p></td></tr></tbody></table></div><p>As you can see, the consistency is excellent. Most granules are the same size, which will result in a better-tasting coffee. If you've got some grains at >300um, but some at 1400um>, this means the coffee will be half over- and half under-extracted. Ergo, no thank you, I'll just drink my water. </p><h2 id="should-i-spend-300-on-a-coffee-grinder">Should I spend $300 on a coffee grinder? </h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="yczfdS2GVsvYrwKUgMU65B" name="Comandante_C40_Mk4_grinder_ 7.JPG" alt="the comandante c40 mk4 hand coffee grinder with a glass catch chamber and high nitrogen steel burrs" src="https://cdn.mos.cms.futurecdn.net/yczfdS2GVsvYrwKUgMU65B.jpg" mos="" align="middle" fullscreen="" width="1920" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>If you have $300 to spare and you're into coffee, yes, you should buy this grinder. All that being said, though, if you don't have $300 lying around, then please don't buy an objectively expensive piece of coffee tech. You can still get a good coffee with a cheaper grinder, like the aforementioned Timemore Chestnut C2s. </p><p>I love my Comandante C40 MK4, but it's not for everyone. In this economy, I think there are more important things to invest in. Save your dollars for a rainy day! </p><p>But if you've got loads of cash spare, then of course you won't be disappointed by this incredible coffee grinder. It's my favorite grinder of all time... I just wish the military branding wasn't so cringe. </p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-OaLgwW"></div>                            </div>                            <script src="https://kwizly.com/embed/OaLgwW.js" async></script><figure class="inline-layout"><div style="min-height: 400px;"><fw-embed-feed channel="toms_guide" playlist="ojE0pK" mode="row" player_placement="bottom-right"></fw-embed-feed></div></figure><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h3><ul><li><a href="https://www.tomsguide.com/home/coffee-makers/overwhelmed-by-coffee-jargon-here-are-the-5-key-espresso-terms-you-need-to-know"><strong>Overwhelmed by coffee jargon? Here are the 5 key espresso terms you need to know</strong></a></li><li><a href="https://www.tomsguide.com/home/coffee-makers/im-an-ex-starbucks-barista-you-can-make-the-iced-brown-sugar-oatmilk-shaken-espresso-at-home-for-a-fraction-of-the-cost"><strong>I'm an ex-Starbucks barista — you can make the Iced Brown Sugar Oatmilk Shaken Espresso at home for a fraction of the cost</strong></a></li><li><a href="https://www.tomsguide.com/home/coffee-makers/people-are-mixing-coffee-with-diet-coke-yes-really-im-an-ex-barista-and-i-tried-the-viral-fridge-cigarette"><strong>People are mixing coffee with Diet Coke (yes, really) — I'm an ex-barista, and I tried the viral 'fridge cigarette'</strong></a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ I tested Subminimal’s newest handheld milk frother — and it’s so much more than a coffee accessory ]]></title>
                                                                                                <dc:content><![CDATA[ <p>Subminimal is one of the most “Oooh! Aaah!”-inducing names in the coffee world, and the new Subminimal Nanofoamer Go is no different. Ever looked at a milk frother and thought, “Damn, I wish that came with a carry case?” Well, your calls have been answered — the Nanofoamer Go comes with three impellers, ten color options, and, yes, a carry case. </p><p>If you’re the kind of coffee drinker who takes your whole setup to a campsite, Airbnb, or simply to the office, this will be ideal for you. While I struggled to achieve the same velvety microfoam I can make on the Subminimal Nanofoamer Pro, the Go can also whisk cream and eggs, so I guess it wins there. </p><p>So, is this the handheld milk frother for you? If you value affordability, fancy colors, and portability, I’m leaning towards yes. Are you a coffee snob? Hm… you might want to splurge on the $159 Nanofoamer Pro instead. To find out the full story, keep reading this Subminimal Nanofoamer Go review. </p><h2 class="article-body__section" id="section-subminimal-nanofoamer-go-review-specs"><span>Subminimal Nanofoamer Go review: Specs</span></h2><div ><table><tbody><tr><td class="firstcol " ><p><strong>Price</strong></p></td><td  ><p><a href="https://www.amazon.com/Subminimal-NanoFoamer-Rechargeable-Handheld-Cabernet/dp/B0GXMW21BP/" target="_blank" rel="nofollow">$34</a> / <a href="https://subminimal.com/products/nanofoamer-go" target="_blank" rel="nofollow">£34</a></p></td></tr><tr><td class="firstcol " ><p><strong>Weight</strong></p></td><td  ><p>2.68 oz</p></td></tr><tr><td class="firstcol " ><p><strong>Dimensions</strong></p></td><td  ><p>1 x 1 x 8.1 inches</p></td></tr><tr><td class="firstcol " ><p><strong>Impellers</strong></p></td><td  ><p>3: whisk, mixer, microfoam mesh</p></td></tr><tr><td class="firstcol " ><p><strong>RPM</strong></p></td><td  ><p>5,300</p></td></tr><tr><td class="firstcol " ><p><strong>Power</strong></p></td><td  ><p>Rechargeable USB-C</p></td></tr></tbody></table></div><h2 class="article-body__section" id="section-subminimal-nanofoamer-go-review-price-availability"><span>Subminimal Nanofoamer Go review: Price & availability</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="nkCWVCgG4VFKVB8fYxstEF" name="Subminimal Nanofoamer Go_003.JPG" alt="the subminimal nanofoamer go in sky blue photographed against the blue tom's guide background" src="https://cdn.mos.cms.futurecdn.net/nkCWVCgG4VFKVB8fYxstEF.jpg" mos="" align="middle" fullscreen="" width="1920" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The Subminimal Nanofoamer Go is considerably cheaper than the brand’s other milk frothers — just <a href="https://subminimal.com/products/nanofoamer-go" target="_blank" rel="nofollow">$37 from Subminimal U.S.</a> and <a href="https://subminimal.com/products/nanofoamer-go" target="_blank" rel="nofollow">£34 from Subminimal U.K.</a> On <a href="https://www.amazon.com/Subminimal-NanoFoamer-Rechargeable-Handheld-Cabernet/dp/B0GXMW21BP/" target="_blank" rel="nofollow">Amazon, it's $34</a>.</p><p>Subminimal’s Nanofoamer Lithium is $57, while the Subminimal Nanofoamer Pro (my personal milk frother) is $159. While both of these models are better at making straight-up cold foam and microfoam, if you prioritize budget and portability over pure functionality, you’d likely be better off with the Nanofoamer Go. Personally, I prefer the Nanofoamer Pro — it’s much better at making honest-to-God microfoam than the Go, as I’ll get into later.</p><h2 class="article-body__section" id="section-subminimal-nanofoamer-go-review-design"><span>Subminimal Nanofoamer Go review: Design </span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="kXVr7XRmpeEGveJmNrqXGE" name="Subminimal Nanofoamer Go_006.JPG" alt="the subminimal nanofoamer go in sky blue photographed against the blue tom's guide background" src="https://cdn.mos.cms.futurecdn.net/kXVr7XRmpeEGveJmNrqXGE.jpg" mos="" align="middle" fullscreen="" width="1920" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>As with everything else made by Subminimal, the Nanofoamer Go looks and feels awesome. Alright, the body is quite plasticky, but I don’t mind because it means it’s relatively lightweight and affordable. </p><p>But the best part? The colors. While the Subminimal Nanofoamer Lithium and Pro are both available solely in minimalist black, the Go comes in a huge ten colors. And every single one of them looks gorgeous. As you can see from the images in this review, I tested the sky blue version. Had I chosen the color for myself, I would have picked the terracotta or sage shades. Both are pretty enough to win a beauty pageant. </p><p>You also get a carry case! The clue’s in the name, but the Nanofoamer Go is intended to be portable. You’re supposed to take it on trips with you. AeroPress with foamed milk at the campsite? Yes, please. As expected, the carry case is the same lovely blue shade, and all the attachments click nicely into place. It’s satisfying to hold and use. I have nothing bad to say about the design here. </p><p>Of course, you get three impeller attachments. One is a whisk for thicker ingredients like cream and eggs. One is for mix-ins, like hot chocolate powder, matcha, so on and so forth, and the third is Subminimal’s patent-pending nanofoam mesh. Now, this is supposed to be the “secret” to barista-quality microfoam… but more on that later.</p><h2 class="article-body__section" id="section-subminimal-nanofoamer-go-review-performance"><span>Subminimal Nanofoamer Go review: Performance</span></h2><p>I’m just going to rip the Band-Aid off: I didn’t get microfoam with the Nanofoamer Go at all. I tried with dairy and non-dairy milk, heated to varying temperatures, frothed in various ways. I tried on full power, low power; I tried for ten seconds, thirty seconds, two minutes, five minutes, one minute, everything. Did I achieve microfoam? No. No, I did not. Here’s a photo of the closest I got. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:4032px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="gYVUX7NjZChwMnj2e5Ns9S" name="subminimal microfoam" alt="a milk drink made by the subminimal nanofoamer go" src="https://cdn.mos.cms.futurecdn.net/gYVUX7NjZChwMnj2e5Ns9S.jpg" mos="" align="middle" fullscreen="" width="4032" height="2268" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Erin Bashford)</span></figcaption></figure><p>As you can see, there are some relatively large bubbles. This is after banging and swirling the milk as you’re supposed to. I was quite disappointed by this. As mentioned earlier, my Subminimal Nanofoamer Pro <em>can</em> make microfoam, so I expected the same of the Go.</p><p>I also struggled to achieve velvety cold foam. I frothed this milk for over two minutes and this is the thickest it got. Of course, I was using the microfoam attachment. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:3463px;"><p class="vanilla-image-block" style="padding-top:56.22%;"><img id="dyudfhzQX99YGRKGewCMxR" name="subminimal cold foam" alt="a milk drink made by the subminimal nanofoamer go" src="https://cdn.mos.cms.futurecdn.net/dyudfhzQX99YGRKGewCMxR.jpg" mos="" align="middle" fullscreen="" width="3463" height="1947" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Erin Bashford)</span></figcaption></figure><p>However, I was able to get delicious, perfect sweet cream cold foam in just forty seconds. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:4933px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="LEo7BjYAhUxA7bqmhhrKdS" name="subminimal whip topping" alt="a milk drink made by the subminimal nanofoamer go" src="https://cdn.mos.cms.futurecdn.net/LEo7BjYAhUxA7bqmhhrKdS.jpg" mos="" align="middle" fullscreen="" width="4933" height="2775" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Erin Bashford)</span></figcaption></figure><p>As you can see, the texture is thick, fluffy, and creamy. This is perfect, Starbucks-approved sweet cream cold foam. My colleagues and I literally ate this with a spoon. </p><p>According to Subminimal’s website, you can actually whisk eggs with the Nanofoamer Go… so of course I had to try it out. For science. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:4459px;"><p class="vanilla-image-block" style="padding-top:56.27%;"><img id="QUZF5J5VeaBsXfrcMzcDYS" name="subminimal egg" alt="a milk drink made by the subminimal nanofoamer go" src="https://cdn.mos.cms.futurecdn.net/QUZF5J5VeaBsXfrcMzcDYS.jpg" mos="" align="middle" fullscreen="" width="4459" height="2509" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Erin Bashford)</span></figcaption></figure><p>Yes, that’s an egg whisked by a milk frother. I don’t eat eggs, so this is a little gross to me, but great if you’re a regular egg whipper. </p><h2 class="article-body__section" id="section-subminimal-nanofoamer-go-review-storage-maintenance"><span>Subminimal Nanofoamer Go review: Storage & maintenance</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="SbD356xxGfjtLLyxaDVLFF" name="Subminimal Nanofoamer Go_009.JPG" alt="the subminimal nanofoamer go in sky blue photographed against the blue tom's guide background" src="https://cdn.mos.cms.futurecdn.net/SbD356xxGfjtLLyxaDVLFF.jpg" mos="" align="middle" fullscreen="" width="1920" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>As it’s a tiny milk frother — 1 inch by 8 inches — you’ll have no trouble fitting it in your cutlery drawer. This model comes with a handy carry case, which measures 2.1 x 6 x 1.3 inches, perfect for throwing in a camping backpack or keeping in a cupboard. If you’re short on space, I’d go for this model over the Nanofoamer Pro, which is shaped like a jug. </p><p>The Go is <em>not</em> dishwasher safe, and you obviously shouldn’t get the body wet. I cleaned it by simply rinsing it under warm water. </p><p>Of course, should your cleaning be sub-minimal (see what I did there? No?), you can buy <a href="https://subminimal.com/products/nanofoamer-go-nanoscreen-kit" target="_blank" rel="nofollow">replacement impellers directly from Subminimal for $6</a>.  </p><p>In terms of longevity, Subminimal offers a standard warranty of one year, which is a little shorter than I’d like. However, this is pretty standard with other $10-$20 milk frothers on Amazon.</p><h2 class="article-body__section" id="section-subminimal-nanofoamer-go-review-verdict"><span>Subminimal Nanofoamer Go review: Verdict</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="Z3oqoZaSEoZS9zNGaUB8EF" name="Subminimal Nanofoamer Go_002.JPG" alt="the subminimal nanofoamer go in sky blue photographed against the blue tom's guide background" src="https://cdn.mos.cms.futurecdn.net/Z3oqoZaSEoZS9zNGaUB8EF.jpg" mos="" align="middle" fullscreen="" width="1920" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The Nanofoamer Go is more than just a milk frother — it can be a pretty little kitchen assistant, too. While this makes it more versatile than the Subminimal Nanofoamer Pro, it’s also not as coffee-snob-friendly. Even though it uses the same micro-mesh as other Nanofoamer products, it doesn’t seem to be able to achieve the same barista-smooth microfoam. </p><p>For $37, this is a neat little frother. I’d recommend it for casual coffee drinkers rather than those practising for the World Barista Championships. I would personally save up for the Subminimal Nanofoamer Pro or Lithium over the Go, but that’s because I take my cold foam seriously — and the Pro is much better at making it. </p><p>For generic froth, though, the Nanofoamer Go is great. Obviously, you have to heat your milk separately — microwave, stovetop — but if you want a one-stop for whisking eggs, cream cold foam, and milk, I’d go for the Go. </p> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/home/coffee-makers/subminimal-nanofoamer-go-review</link>
                                                                            <description>
                            <![CDATA[ The Subminimal Nanofoamer Go isn’t quite barista-worthy yet, but it’s a veritable sous chef in the kitchen department. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">B9JBG5bbGo6ADKMqRnE7fU</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/EcXasfu4pR4YCJkLv9ChDF-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Mon, 31 Aug 2026 07:00:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Coffee Makers]]></category>
                                                    <category><![CDATA[Home]]></category>
                                                    <category><![CDATA[Home Appliances]]></category>
                                                    <category><![CDATA[Kitchen & Dining]]></category>
                                                                                                <author><![CDATA[ erin.bashford@futurenet.com (Erin Bashford) ]]></author>                    <dc:creator><![CDATA[ Erin Bashford ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/rLvJvJVZx43hEzSsJy3BpL.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Erin Bashford is a senior reviews writer at Tom’s Guide. She has a Master’s in Broadcast and Digital Journalism from the University of East Anglia and 7 years of experience reviewing music and events for various publications. She has edited publications such as Outline Magazine’s Guide to Norwich, and she has written for a number of music magazines and websites such as Clash Magazine, Outline Magazine and Dork Magazine. She has a strong interest in audio gear and the music world. &lt;/p&gt;&lt;p&gt;As an ex-barista, Erin is passionate about coffee tech. She also loves finding the best cooking hacks and kitchen appliances, including her beloved Instant Pot. &lt;/p&gt;&lt;p&gt;In her spare time, you can find her reading, practising yoga, hiking, writing fantasy novels, or stressing over NYT Games.&lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/EcXasfu4pR4YCJkLv9ChDF-1280-80.jpg">
                                                            <media:credit><![CDATA[Tom&amp;#39;s Guide]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[the subminimal nanofoamer go in sky blue photographed against the blue tom&#039;s guide background]]></media:description>                                                            <media:text><![CDATA[the subminimal nanofoamer go in sky blue photographed against the blue tom&#039;s guide background]]></media:text>
                                <media:title type="plain"><![CDATA[the subminimal nanofoamer go in sky blue photographed against the blue tom&#039;s guide background]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/EcXasfu4pR4YCJkLv9ChDF-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Subminimal is one of the most “Oooh! Aaah!”-inducing names in the coffee world, and the new Subminimal Nanofoamer Go is no different. Ever looked at a milk frother and thought, “Damn, I wish that came with a carry case?” Well, your calls have been answered — the Nanofoamer Go comes with three impellers, ten color options, and, yes, a carry case. </p><p>If you’re the kind of coffee drinker who takes your whole setup to a campsite, Airbnb, or simply to the office, this will be ideal for you. While I struggled to achieve the same velvety microfoam I can make on the Subminimal Nanofoamer Pro, the Go can also whisk cream and eggs, so I guess it wins there. </p><p>So, is this the handheld milk frother for you? If you value affordability, fancy colors, and portability, I’m leaning towards yes. Are you a coffee snob? Hm… you might want to splurge on the $159 Nanofoamer Pro instead. To find out the full story, keep reading this Subminimal Nanofoamer Go review. </p><h2 class="article-body__section" id="section-subminimal-nanofoamer-go-review-specs"><span>Subminimal Nanofoamer Go review: Specs</span></h2><div ><table><tbody><tr><td class="firstcol " ><p><strong>Price</strong></p></td><td  ><p><a href="https://www.amazon.com/Subminimal-NanoFoamer-Rechargeable-Handheld-Cabernet/dp/B0GXMW21BP/" target="_blank" rel="nofollow">$34</a> / <a href="https://subminimal.com/products/nanofoamer-go" target="_blank" rel="nofollow">£34</a></p></td></tr><tr><td class="firstcol " ><p><strong>Weight</strong></p></td><td  ><p>2.68 oz</p></td></tr><tr><td class="firstcol " ><p><strong>Dimensions</strong></p></td><td  ><p>1 x 1 x 8.1 inches</p></td></tr><tr><td class="firstcol " ><p><strong>Impellers</strong></p></td><td  ><p>3: whisk, mixer, microfoam mesh</p></td></tr><tr><td class="firstcol " ><p><strong>RPM</strong></p></td><td  ><p>5,300</p></td></tr><tr><td class="firstcol " ><p><strong>Power</strong></p></td><td  ><p>Rechargeable USB-C</p></td></tr></tbody></table></div><h2 class="article-body__section" id="section-subminimal-nanofoamer-go-review-price-availability"><span>Subminimal Nanofoamer Go review: Price & availability</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="nkCWVCgG4VFKVB8fYxstEF" name="Subminimal Nanofoamer Go_003.JPG" alt="the subminimal nanofoamer go in sky blue photographed against the blue tom's guide background" src="https://cdn.mos.cms.futurecdn.net/nkCWVCgG4VFKVB8fYxstEF.jpg" mos="" align="middle" fullscreen="" width="1920" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The Subminimal Nanofoamer Go is considerably cheaper than the brand’s other milk frothers — just <a href="https://subminimal.com/products/nanofoamer-go" target="_blank" rel="nofollow">$37 from Subminimal U.S.</a> and <a href="https://subminimal.com/products/nanofoamer-go" target="_blank" rel="nofollow">£34 from Subminimal U.K.</a> On <a href="https://www.amazon.com/Subminimal-NanoFoamer-Rechargeable-Handheld-Cabernet/dp/B0GXMW21BP/" target="_blank" rel="nofollow">Amazon, it's $34</a>.</p><p>Subminimal’s Nanofoamer Lithium is $57, while the Subminimal Nanofoamer Pro (my personal milk frother) is $159. While both of these models are better at making straight-up cold foam and microfoam, if you prioritize budget and portability over pure functionality, you’d likely be better off with the Nanofoamer Go. Personally, I prefer the Nanofoamer Pro — it’s much better at making honest-to-God microfoam than the Go, as I’ll get into later.</p><h2 class="article-body__section" id="section-subminimal-nanofoamer-go-review-design"><span>Subminimal Nanofoamer Go review: Design </span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="kXVr7XRmpeEGveJmNrqXGE" name="Subminimal Nanofoamer Go_006.JPG" alt="the subminimal nanofoamer go in sky blue photographed against the blue tom's guide background" src="https://cdn.mos.cms.futurecdn.net/kXVr7XRmpeEGveJmNrqXGE.jpg" mos="" align="middle" fullscreen="" width="1920" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>As with everything else made by Subminimal, the Nanofoamer Go looks and feels awesome. Alright, the body is quite plasticky, but I don’t mind because it means it’s relatively lightweight and affordable. </p><p>But the best part? The colors. While the Subminimal Nanofoamer Lithium and Pro are both available solely in minimalist black, the Go comes in a huge ten colors. And every single one of them looks gorgeous. As you can see from the images in this review, I tested the sky blue version. Had I chosen the color for myself, I would have picked the terracotta or sage shades. Both are pretty enough to win a beauty pageant. </p><p>You also get a carry case! The clue’s in the name, but the Nanofoamer Go is intended to be portable. You’re supposed to take it on trips with you. AeroPress with foamed milk at the campsite? Yes, please. As expected, the carry case is the same lovely blue shade, and all the attachments click nicely into place. It’s satisfying to hold and use. I have nothing bad to say about the design here. </p><p>Of course, you get three impeller attachments. One is a whisk for thicker ingredients like cream and eggs. One is for mix-ins, like hot chocolate powder, matcha, so on and so forth, and the third is Subminimal’s patent-pending nanofoam mesh. Now, this is supposed to be the “secret” to barista-quality microfoam… but more on that later.</p><h2 class="article-body__section" id="section-subminimal-nanofoamer-go-review-performance"><span>Subminimal Nanofoamer Go review: Performance</span></h2><p>I’m just going to rip the Band-Aid off: I didn’t get microfoam with the Nanofoamer Go at all. I tried with dairy and non-dairy milk, heated to varying temperatures, frothed in various ways. I tried on full power, low power; I tried for ten seconds, thirty seconds, two minutes, five minutes, one minute, everything. Did I achieve microfoam? No. No, I did not. Here’s a photo of the closest I got. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:4032px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="gYVUX7NjZChwMnj2e5Ns9S" name="subminimal microfoam" alt="a milk drink made by the subminimal nanofoamer go" src="https://cdn.mos.cms.futurecdn.net/gYVUX7NjZChwMnj2e5Ns9S.jpg" mos="" align="middle" fullscreen="" width="4032" height="2268" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Erin Bashford)</span></figcaption></figure><p>As you can see, there are some relatively large bubbles. This is after banging and swirling the milk as you’re supposed to. I was quite disappointed by this. As mentioned earlier, my Subminimal Nanofoamer Pro <em>can</em> make microfoam, so I expected the same of the Go.</p><p>I also struggled to achieve velvety cold foam. I frothed this milk for over two minutes and this is the thickest it got. Of course, I was using the microfoam attachment. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:3463px;"><p class="vanilla-image-block" style="padding-top:56.22%;"><img id="dyudfhzQX99YGRKGewCMxR" name="subminimal cold foam" alt="a milk drink made by the subminimal nanofoamer go" src="https://cdn.mos.cms.futurecdn.net/dyudfhzQX99YGRKGewCMxR.jpg" mos="" align="middle" fullscreen="" width="3463" height="1947" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Erin Bashford)</span></figcaption></figure><p>However, I was able to get delicious, perfect sweet cream cold foam in just forty seconds. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:4933px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="LEo7BjYAhUxA7bqmhhrKdS" name="subminimal whip topping" alt="a milk drink made by the subminimal nanofoamer go" src="https://cdn.mos.cms.futurecdn.net/LEo7BjYAhUxA7bqmhhrKdS.jpg" mos="" align="middle" fullscreen="" width="4933" height="2775" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Erin Bashford)</span></figcaption></figure><p>As you can see, the texture is thick, fluffy, and creamy. This is perfect, Starbucks-approved sweet cream cold foam. My colleagues and I literally ate this with a spoon. </p><p>According to Subminimal’s website, you can actually whisk eggs with the Nanofoamer Go… so of course I had to try it out. For science. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:4459px;"><p class="vanilla-image-block" style="padding-top:56.27%;"><img id="QUZF5J5VeaBsXfrcMzcDYS" name="subminimal egg" alt="a milk drink made by the subminimal nanofoamer go" src="https://cdn.mos.cms.futurecdn.net/QUZF5J5VeaBsXfrcMzcDYS.jpg" mos="" align="middle" fullscreen="" width="4459" height="2509" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Erin Bashford)</span></figcaption></figure><p>Yes, that’s an egg whisked by a milk frother. I don’t eat eggs, so this is a little gross to me, but great if you’re a regular egg whipper. </p><h2 class="article-body__section" id="section-subminimal-nanofoamer-go-review-storage-maintenance"><span>Subminimal Nanofoamer Go review: Storage & maintenance</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="SbD356xxGfjtLLyxaDVLFF" name="Subminimal Nanofoamer Go_009.JPG" alt="the subminimal nanofoamer go in sky blue photographed against the blue tom's guide background" src="https://cdn.mos.cms.futurecdn.net/SbD356xxGfjtLLyxaDVLFF.jpg" mos="" align="middle" fullscreen="" width="1920" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>As it’s a tiny milk frother — 1 inch by 8 inches — you’ll have no trouble fitting it in your cutlery drawer. This model comes with a handy carry case, which measures 2.1 x 6 x 1.3 inches, perfect for throwing in a camping backpack or keeping in a cupboard. If you’re short on space, I’d go for this model over the Nanofoamer Pro, which is shaped like a jug. </p><p>The Go is <em>not</em> dishwasher safe, and you obviously shouldn’t get the body wet. I cleaned it by simply rinsing it under warm water. </p><p>Of course, should your cleaning be sub-minimal (see what I did there? No?), you can buy <a href="https://subminimal.com/products/nanofoamer-go-nanoscreen-kit" target="_blank" rel="nofollow">replacement impellers directly from Subminimal for $6</a>.  </p><p>In terms of longevity, Subminimal offers a standard warranty of one year, which is a little shorter than I’d like. However, this is pretty standard with other $10-$20 milk frothers on Amazon.</p><h2 class="article-body__section" id="section-subminimal-nanofoamer-go-review-verdict"><span>Subminimal Nanofoamer Go review: Verdict</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="Z3oqoZaSEoZS9zNGaUB8EF" name="Subminimal Nanofoamer Go_002.JPG" alt="the subminimal nanofoamer go in sky blue photographed against the blue tom's guide background" src="https://cdn.mos.cms.futurecdn.net/Z3oqoZaSEoZS9zNGaUB8EF.jpg" mos="" align="middle" fullscreen="" width="1920" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The Nanofoamer Go is more than just a milk frother — it can be a pretty little kitchen assistant, too. While this makes it more versatile than the Subminimal Nanofoamer Pro, it’s also not as coffee-snob-friendly. Even though it uses the same micro-mesh as other Nanofoamer products, it doesn’t seem to be able to achieve the same barista-smooth microfoam. </p><p>For $37, this is a neat little frother. I’d recommend it for casual coffee drinkers rather than those practising for the World Barista Championships. I would personally save up for the Subminimal Nanofoamer Pro or Lithium over the Go, but that’s because I take my cold foam seriously — and the Pro is much better at making it. </p><p>For generic froth, though, the Nanofoamer Go is great. Obviously, you have to heat your milk separately — microwave, stovetop — but if you want a one-stop for whisking eggs, cream cold foam, and milk, I’d go for the Go. </p>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ I've been using this Momcozy baby bottle cleaner for the past month — and now I wish I hadn't spent nine months washing them by hand ]]></title>
                                                                                                <dc:content><![CDATA[ <p>As any parent will no doubt confirm, one of the things that comes with having children is the need to spend a lot more of your time cleaning. Kids make a lot of mess, and I've found myself spending a bunch more time washing clothes, cleaning floors and sterilizing baby bottles.</p><p>You would not believe how much time and effort goes into cleaning those bottles. Like kids themselves, it's shocking to see just how dirty they actually get — and I'm not just talking about the leftover formula they contain. After 9 months of deep cleaning milk bottles, inside and out, I finally caved and got hold of an appliance to do the job for me.</p><p>The machine in question is the MomCozy DeepClean Baby Bottle Washer (D8), and it's been such a help that I can't believe I was too cheap to buy something like this a year ago.</p><div class="product"><a data-dimension112="171c99be-a2c5-11f1-899a-731f56d5cacb" data-action="Deal Block" data-label="DeepClean Baby Bottle Cleaner (D8)" data-dimension48="DeepClean Baby Bottle Cleaner (D8)" data-dimension25="$329" href="https://www.amazon.com/Momcozy-DeepClean-Bottle-Washer-Sterilizer/dp/B0H6Q2G76Z" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1500px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="ETBsCG4nA5MWQTae9ZQumY" name="DeepClean Baby Bottle Cleaner (D8)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/ETBsCG4nA5MWQTae9ZQumY.png" mos="" align="middle" fullscreen="" width="1500" height="1500" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Momcozy-DeepClean-Bottle-Washer-Sterilizer/dp/B0H6Q2G76Z" target="_blank" rel="nofollow" data-dimension112="171c99be-a2c5-11f1-899a-731f56d5cacb" data-action="Deal Block" data-label="DeepClean Baby Bottle Cleaner (D8)" data-dimension48="DeepClean Baby Bottle Cleaner (D8)" data-dimension25="$329">DeepClean Baby Bottle Cleaner (D8): was $359 now $329</a></strong><br>Clean up to eight baby bottles at a time with this combination bottle cleaner and sterilizer from Momcozy. It supports bottles, nipples, breast pump parts and other baby-centric accessories that need almost constant cleaning. Oh, and it can keep the freshly cleaned contents sterile for up to 72 hours, should you need to leave them that long.<a class="view-deal button" href="https://www.amazon.com/Momcozy-DeepClean-Bottle-Washer-Sterilizer/dp/B0H6Q2G76Z" target="_blank" rel="nofollow" data-dimension112="171c99be-a2c5-11f1-899a-731f56d5cacb" data-action="Deal Block" data-label="DeepClean Baby Bottle Cleaner (D8)" data-dimension48="DeepClean Baby Bottle Cleaner (D8)" data-dimension25="$329">View Deal</a></p></div><h2 id="how-the-deepclean-bottle-cleaner-works">How the DeepClean Bottle Cleaner works</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:800px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="W6sCo8DxnEvJJ3wHrN7WSn" name="ezgif-23f997c4c5e354eb" alt="momcozy deepclean baby bottle cleaner" src="https://cdn.mos.cms.futurecdn.net/W6sCo8DxnEvJJ3wHrN7WSn.gif" mos="" align="middle" fullscreen="" width="800" height="450" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>The Momcozy DeepClean Baby Bottle Cleaner is exactly what the name suggests. It's a countertop appliance that washes used baby bottles, removing all traces of leftover milk or formula, and then sterilizes them ready to be used later on. It retails for $359, and comes bundles with 60 detergent blocks and four limescale removal tablets.</p><p>The appliance has room for up to eight bottles at a time, with a two-tier rack system that lets you wash bottles and nipples simultaneously — aided by 64 water jets capable of spraying 154.4ºF water to help break through whatever leftovers are left on your baby's bottles after use. </p><p>The DeepClean also has a built-in 212º F sterilization mode, a 55-minute bottle drying cycle and an integrated fan (complete with HEPA filter) to keep the newly cleaned bottles sterile for up to 72 hours. The general idea is that you slot the bottles in, and let the appliance do all the hard work for you — something that I have grown incredibly grateful for.</p><p>Oh, and you don't have to worry about keeping the DeepClean itself clean, since it has a dedicated self-cleaning mode. This 30-minute process can even reduce any built-up limescale — provided that you use one of Momcozy's limescale removal tablets.</p><p>Oh, and you don't need to use Momcozy bottles to take advantage of the DeepClean, either. All my baby bottles come from different brands, and they fit into the cleaning rack without issue. However, some of the weird and wonderful shaped bottles you can buy may not slide in quite so smoothly.</p><h2 id="it-39-s-not-just-for-cleaning-bottles">It's not just for cleaning bottles</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:4032px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="4FhKZiTuxfMgUXHt2f67ef" name="PXL_20260828_101624592" alt="momcozy deepclean baby bottle cleaner" src="https://cdn.mos.cms.futurecdn.net/4FhKZiTuxfMgUXHt2f67ef.jpg" mos="" align="middle" fullscreen="" width="4032" height="2268" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>The main benefit is that the DeepClean is not just for washing and sterilizing milk bottles. It's also suitable for all kinds of baby accessories, including gravity bottles and breast pump parts. While Momcozy doesn't specifically approve this, I've also used the machine to clean things like pacifiers and those syringes you use to feed babies medicine without ill effect.</p><p>We don't use breast pumps anymore, but there was a point where my wife was using them pretty regularly — and a machine like the DeepClean could have saved us a lot of trouble. </p><p>The thing about breast pump parts is that you're not supposed to sterilize them in a microwave, as you can with milk bottles. That's in the manual, but the sleep deprived state new parents find themselves in may gloss over this fact and leave you with a bunch of melted chunks of plastic. That happened to us, and sourcing the appropriate replacement parts was a pretty miserable experience.</p><p>Worse is the fact that we had to source a very large pot that was big enough to boil the replacement parts over the stove. Oh and you need to continuously stir the part to stop the plastic melting against the hot metal. The process technically only takes five minutes, but the sheer size of those plastic pieces meant we had to repeat the process multiple times.</p><p>Or you can just stick them into a cleaner like the DeepClean and leave them for half an hour as a machine does all the hard work for you. It certainly would have saved us a lot of headaches during one of the most exhaustive periods of our lives.</p><h2 id="you-39-re-saving-more-than-just-time-too">You're saving more than just time too</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:4032px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="CbuSwEs3Yb9KSRW5hSPbJg" name="PXL_20260828_134837473" alt="momcozy deepclean baby bottle cleaner" src="https://cdn.mos.cms.futurecdn.net/CbuSwEs3Yb9KSRW5hSPbJg.jpg" mos="" align="middle" fullscreen="" width="4032" height="2268" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>The thing about using appliances is that they generally help save you time by doing all the hard work for you. The DeepClean Bottle Cleaner is effectively a miniature dishwasher, or something very close to it, which means it has slashed the amount of time it takes to actually clean my used milk bottles.</p><p>The old system of cleaning by hand meant that I had to rinse the bottles, clean them with (fragrance free) dish soap and a brush, rinsing out the suds and then sterilizing them in my 700W microwave for at least seven minutes. The DeepClean does all of that for you; the only thing I need to do to the bottles before cleaning is empty out any leftover formula. In fact, the most time-consuming part of the whole process is filling up the 96-ounce water tank.</p><p>The actual cleaning cycle takes at least 28 minutes for the low-powered mode, or 38 minutes for the more intensive clean. That's a lot longer than my old system of hand-washing bottles, but unless you need a clean bottle ASAP, it's not really a big deal. It's not as though you have to stand there and watch the entire cleaning cycle unfold.</p><p>Time is only part of the equation, and the 96-oz. water tank is a perfect example of this. </p><p>96 ounces feels like a lot of water, and I was admittedly shocked when I saw that almost the entire tank was used in the DeepClean's washing cycle — with the rest being saved to make sterilizing steam. But after that initial outrage, I started to wonder whether it was actually a lot of water. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:4032px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="jbWydcGSTq9ZzfZAASS2qf" name="PXL_20260828_135112815" alt="momcozy deepclean baby bottle cleaner" src="https://cdn.mos.cms.futurecdn.net/jbWydcGSTq9ZzfZAASS2qf.jpg" mos="" align="middle" fullscreen="" width="4032" height="2268" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="caption-text">This was the old way of doing things </span><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>Frankly, I had no idea how much water I use hand washing baby bottles, and had to find out. It turns out, even if I wash super-conservatively, I could use up around 35oz of water washing a single bottle. So, in the same way that <a href="https://www.tomsguide.com/face-off/dishwasher-vs-washing-by-hand-which-is-cheaper">running a full dishwasher might save more water than hand washing</a>, it seems as though the DeepClean might actually reduce your water consumption. More so when you remember that it can clean up to eight bottles (and their respective nipples) at a time without any change in water consumption.</p><p>Energy is a little more complicated. Momcozy says that the DeepClean uses 500W of power during the water heating and sterilizing parts of the cycle, which seemed accurate when I tracked by energy usage. Meanwhile the actual cleaning takes up about 55W, and the dryer uses 200W. Meanwhile, my microwave uses around 1,600W, but also only runs for a third of the time.</p><p>I'm not good at physics or math, so I know I will mess up the calculations if I try and figure it out. Needless to say, the DeepClean is far from the biggest power draw in your kitchen, and it shouldn't affect your energy bills too much.</p><p>It's also worth noting that you should be using the DeepClean with Momcozy's detergent blocks. They cost $20 for 120, working out at around 16.7 cents per cycle. How much that compares to handwashing with dish soap is going to depend on what brand you buy and how much you actually use, but I'd wager that even the fanciest dish soap is going to come in cheaper.</p><h2 id="there-are-some-downsides">There are some downsides</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:4032px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="PJRofYjqHejYgBk4MCihcf" name="PXL_20260828_101713764" alt="momcozy deepclean baby bottle cleaner" src="https://cdn.mos.cms.futurecdn.net/PJRofYjqHejYgBk4MCihcf.jpg" mos="" align="middle" fullscreen="" width="4032" height="2268" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>The first thing I actually noticed about the DeepClean unit is that it's big. 10.6 x 13.78 x 15.35 inches, to be exact, which means it takes up roughly 1.3 cubic feet of space on whichever counter top you've set aside. The only thing I have that comes close is my vertical air fryer, which is so tall it has to be tucked away in the corner.</p><p>Placement on the counter matters a lot as well, since the DeepClean doesn't have a tank to store used water. There's a hose at the back of the unit, and that means you need to make sure it drains somewhere appropriate — such as the sink or a bucket. Otherwise you're just going to end up with a very wet floor.</p><p>The $359 price tag is also a lot to take in, especially when a microwave bottle sterilizer can be bought for as little as $20. But I have to tell myself that you're buying convenience, and potentially lower bills, which could make that investment worth it — especially if you're still expecting or have a newborn. But if your kid is already moving onto solid food, it's a much tougher sell.</p><p>I have found a few other downsides to using the DeepClean at home, though some of these are more about what's going on in my brain than a flaw with the product itself. The big one is that I find it kind of gross to imagine dirty bottles left lying around, waiting for enough of their comrades to justify switching the DeepClean on. </p><p>Leftover milk in the height of the hottest summer most people can remember is not a very good mix, after all. Though I will be the first to admit that this is just something I personally need to wrap my head around, and retrain myself to think slightly differently in the face of new technology.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:4032px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="erc9635EpA7MsdCHjUaC9f" name="PXL_20260828_134828976" alt="momcozy deepclean baby bottle cleaner" src="https://cdn.mos.cms.futurecdn.net/erc9635EpA7MsdCHjUaC9f.jpg" mos="" align="middle" fullscreen="" width="4032" height="2268" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>The fact you need to buy extra detergent tablets is also worth bearing in mind, since the DeepClean is not compatible with the usual soaps or detergents you'd use to hand wash dishes. They're not expensive, and you get 60 included with the DeepClean, but it means you will be on the hook to keep buying those blocks for the duration of the appliance's lifespan.</p><p>I'll admit I forgot to use the detergent blocks on more than one occasion with no apparent ill effect. But obviously you'll want to make sure your baby's bottles are actually clean, and the detergent is the best way to ensure that.</p><p>Limescale is also going to be an issue with any machine that requires water, especially if your local water is as hard as it is in my area. I can't think of a single part of my bathroom or kitchen sink that isn't coated with that pesky layer of white deposit. Momcozy recommends using distilled water, rather than tap water, but to that I say "who has the time for that?" </p><p>I've taken to using filtered water instead, and while not perfectly free of excess minerals, it generally extends the amount of time my water-based appliances have between descaling cycles. Momcozy does include descaling tablets in the box, which are compatible with the DeepClean's self-cleaning mode.</p><p>Finally, the system that keeps clean bottles sterile for up to 72 hours is all down to a built-in air circulation system. This requires power to run, around 190-200W based on my energy meter, and turning it off means Momcozy can't guarantee the bottles will remain sterile. Such a feature could potentially be useful, especially if you need to clean bottles before going away for the weekend, but it does feel a little like overkill. So if you're anything like me, you'll have the bottles out and packed away safely pretty soon after the cleaning cycle is over.</p><h2 id="verdict">Verdict</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:4032px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="kAL987MKqZvVsKuxqop8bf" name="PXL_20260828_134822885" alt="momcozy deepclean baby bottle cleaner" src="https://cdn.mos.cms.futurecdn.net/kAL987MKqZvVsKuxqop8bf.jpg" mos="" align="middle" fullscreen="" width="4032" height="2268" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>I like using the Momcozy DeepClean Baby Bottle Washer, for the simple fact that it takes all the extra stress and hassle out of the whole bottle-cleaning process. All you need to do is fill the tank, slot the bottles in and turn the machine on. It's an extremely convenient tool to have, and it's something I wish I had back before my son started eating solid food and needed a bottle every couple of hours.</p><p>Having handwashed bottles for 9 months does mean that switching to an appliance does take an adjustment. My wife in particular is finding it hard to get out of the habit of washing milk bottles as soon as they're finished. Asking her not to clean up is like asking her not to breathe, so I'm not sure if she's actually used the DeepClean yet. </p><p>As for me, I'm coming around to the idea of being much lazier, and not scrubbing used bottles clean. Even if my math is totally wrong, and the DeepClean doesn't end up saving me money on my water or energy bills, I'm at least regaining a little bit more of my time — which is a luxury when you have young kids. </p><p>I just wish it wasn't quite so big, because it does take up a lot of space. But I guess that's the price you pay for cleaning up to eight bottles at once.</p><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h3><ul><li><a href="https://www.tomsguide.com/home/forget-weekend-deep-cleaning-this-30-second-daily-bathroom-hack-saved-my-schedule">Forget weekend deep cleaning: This 30-second daily bathroom hack saved my schedule</a></li><li><a href="https://www.tomsguide.com/home/expert-warns-against-pouring-boiling-water-down-sinks-heres-why">Expert warns against pouring boiling water down sinks — here's why</a></li><li><a href="https://www.tomsguide.com/home/home-appliances/sharkninjas-new-aquareach-wet-dry-vacuum-cleans-up">SharkNinja’s AquaReach just reinvented wet-dry vacs with an extendable wand</a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/home/home-appliances/ive-been-using-this-momcozy-baby-bottle-cleaner-for-the-past-month-and-now-i-wish-i-hadnt-spent-nine-months-washing-them-by-hand</link>
                                                                            <description>
                            <![CDATA[ Momcozy's DeepClean Baby Bottle Washer has been a huge timesaver for keeping my baby son's milk bottles clean and ready to go. But it is taking some getting used to. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">uVe9Cips8tFoxhc6AypdtH</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/2c2Z2t9TvdcfWEuQQhPDGg-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Sun, 30 Aug 2026 10:00:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Home Appliances]]></category>
                                                    <category><![CDATA[Home]]></category>
                                                                                                <author><![CDATA[ tom.pritchard@futurenet.com (Tom Pritchard) ]]></author>                    <dc:creator><![CDATA[ Tom Pritchard ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/biCewUkKfSA6QnT2HxVc3f.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ null ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/2c2Z2t9TvdcfWEuQQhPDGg-1280-80.jpg">
                                                            <media:credit><![CDATA[Future]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[momcozy deepclean baby bottle cleaner]]></media:description>                                                            <media:text><![CDATA[momcozy deepclean baby bottle cleaner]]></media:text>
                                <media:title type="plain"><![CDATA[momcozy deepclean baby bottle cleaner]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/2c2Z2t9TvdcfWEuQQhPDGg-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>As any parent will no doubt confirm, one of the things that comes with having children is the need to spend a lot more of your time cleaning. Kids make a lot of mess, and I've found myself spending a bunch more time washing clothes, cleaning floors and sterilizing baby bottles.</p><p>You would not believe how much time and effort goes into cleaning those bottles. Like kids themselves, it's shocking to see just how dirty they actually get — and I'm not just talking about the leftover formula they contain. After 9 months of deep cleaning milk bottles, inside and out, I finally caved and got hold of an appliance to do the job for me.</p><p>The machine in question is the MomCozy DeepClean Baby Bottle Washer (D8), and it's been such a help that I can't believe I was too cheap to buy something like this a year ago.</p><div class="product"><a data-dimension112="171c99be-a2c5-11f1-899a-731f56d5cacb" data-action="Deal Block" data-label="DeepClean Baby Bottle Cleaner (D8)" data-dimension48="DeepClean Baby Bottle Cleaner (D8)" data-dimension25="$329" href="https://www.amazon.com/Momcozy-DeepClean-Bottle-Washer-Sterilizer/dp/B0H6Q2G76Z" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1500px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="ETBsCG4nA5MWQTae9ZQumY" name="DeepClean Baby Bottle Cleaner (D8)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/ETBsCG4nA5MWQTae9ZQumY.png" mos="" align="middle" fullscreen="" width="1500" height="1500" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Momcozy-DeepClean-Bottle-Washer-Sterilizer/dp/B0H6Q2G76Z" target="_blank" rel="nofollow" data-dimension112="171c99be-a2c5-11f1-899a-731f56d5cacb" data-action="Deal Block" data-label="DeepClean Baby Bottle Cleaner (D8)" data-dimension48="DeepClean Baby Bottle Cleaner (D8)" data-dimension25="$329">DeepClean Baby Bottle Cleaner (D8): was $359 now $329</a></strong><br>Clean up to eight baby bottles at a time with this combination bottle cleaner and sterilizer from Momcozy. It supports bottles, nipples, breast pump parts and other baby-centric accessories that need almost constant cleaning. Oh, and it can keep the freshly cleaned contents sterile for up to 72 hours, should you need to leave them that long.<a class="view-deal button" href="https://www.amazon.com/Momcozy-DeepClean-Bottle-Washer-Sterilizer/dp/B0H6Q2G76Z" target="_blank" rel="nofollow" data-dimension112="171c99be-a2c5-11f1-899a-731f56d5cacb" data-action="Deal Block" data-label="DeepClean Baby Bottle Cleaner (D8)" data-dimension48="DeepClean Baby Bottle Cleaner (D8)" data-dimension25="$329">View Deal</a></p></div><h2 id="how-the-deepclean-bottle-cleaner-works">How the DeepClean Bottle Cleaner works</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:800px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="W6sCo8DxnEvJJ3wHrN7WSn" name="ezgif-23f997c4c5e354eb" alt="momcozy deepclean baby bottle cleaner" src="https://cdn.mos.cms.futurecdn.net/W6sCo8DxnEvJJ3wHrN7WSn.gif" mos="" align="middle" fullscreen="" width="800" height="450" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>The Momcozy DeepClean Baby Bottle Cleaner is exactly what the name suggests. It's a countertop appliance that washes used baby bottles, removing all traces of leftover milk or formula, and then sterilizes them ready to be used later on. It retails for $359, and comes bundles with 60 detergent blocks and four limescale removal tablets.</p><p>The appliance has room for up to eight bottles at a time, with a two-tier rack system that lets you wash bottles and nipples simultaneously — aided by 64 water jets capable of spraying 154.4ºF water to help break through whatever leftovers are left on your baby's bottles after use. </p><p>The DeepClean also has a built-in 212º F sterilization mode, a 55-minute bottle drying cycle and an integrated fan (complete with HEPA filter) to keep the newly cleaned bottles sterile for up to 72 hours. The general idea is that you slot the bottles in, and let the appliance do all the hard work for you — something that I have grown incredibly grateful for.</p><p>Oh, and you don't have to worry about keeping the DeepClean itself clean, since it has a dedicated self-cleaning mode. This 30-minute process can even reduce any built-up limescale — provided that you use one of Momcozy's limescale removal tablets.</p><p>Oh, and you don't need to use Momcozy bottles to take advantage of the DeepClean, either. All my baby bottles come from different brands, and they fit into the cleaning rack without issue. However, some of the weird and wonderful shaped bottles you can buy may not slide in quite so smoothly.</p><h2 id="it-39-s-not-just-for-cleaning-bottles">It's not just for cleaning bottles</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:4032px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="4FhKZiTuxfMgUXHt2f67ef" name="PXL_20260828_101624592" alt="momcozy deepclean baby bottle cleaner" src="https://cdn.mos.cms.futurecdn.net/4FhKZiTuxfMgUXHt2f67ef.jpg" mos="" align="middle" fullscreen="" width="4032" height="2268" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>The main benefit is that the DeepClean is not just for washing and sterilizing milk bottles. It's also suitable for all kinds of baby accessories, including gravity bottles and breast pump parts. While Momcozy doesn't specifically approve this, I've also used the machine to clean things like pacifiers and those syringes you use to feed babies medicine without ill effect.</p><p>We don't use breast pumps anymore, but there was a point where my wife was using them pretty regularly — and a machine like the DeepClean could have saved us a lot of trouble. </p><p>The thing about breast pump parts is that you're not supposed to sterilize them in a microwave, as you can with milk bottles. That's in the manual, but the sleep deprived state new parents find themselves in may gloss over this fact and leave you with a bunch of melted chunks of plastic. That happened to us, and sourcing the appropriate replacement parts was a pretty miserable experience.</p><p>Worse is the fact that we had to source a very large pot that was big enough to boil the replacement parts over the stove. Oh and you need to continuously stir the part to stop the plastic melting against the hot metal. The process technically only takes five minutes, but the sheer size of those plastic pieces meant we had to repeat the process multiple times.</p><p>Or you can just stick them into a cleaner like the DeepClean and leave them for half an hour as a machine does all the hard work for you. It certainly would have saved us a lot of headaches during one of the most exhaustive periods of our lives.</p><h2 id="you-39-re-saving-more-than-just-time-too">You're saving more than just time too</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:4032px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="CbuSwEs3Yb9KSRW5hSPbJg" name="PXL_20260828_134837473" alt="momcozy deepclean baby bottle cleaner" src="https://cdn.mos.cms.futurecdn.net/CbuSwEs3Yb9KSRW5hSPbJg.jpg" mos="" align="middle" fullscreen="" width="4032" height="2268" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>The thing about using appliances is that they generally help save you time by doing all the hard work for you. The DeepClean Bottle Cleaner is effectively a miniature dishwasher, or something very close to it, which means it has slashed the amount of time it takes to actually clean my used milk bottles.</p><p>The old system of cleaning by hand meant that I had to rinse the bottles, clean them with (fragrance free) dish soap and a brush, rinsing out the suds and then sterilizing them in my 700W microwave for at least seven minutes. The DeepClean does all of that for you; the only thing I need to do to the bottles before cleaning is empty out any leftover formula. In fact, the most time-consuming part of the whole process is filling up the 96-ounce water tank.</p><p>The actual cleaning cycle takes at least 28 minutes for the low-powered mode, or 38 minutes for the more intensive clean. That's a lot longer than my old system of hand-washing bottles, but unless you need a clean bottle ASAP, it's not really a big deal. It's not as though you have to stand there and watch the entire cleaning cycle unfold.</p><p>Time is only part of the equation, and the 96-oz. water tank is a perfect example of this. </p><p>96 ounces feels like a lot of water, and I was admittedly shocked when I saw that almost the entire tank was used in the DeepClean's washing cycle — with the rest being saved to make sterilizing steam. But after that initial outrage, I started to wonder whether it was actually a lot of water. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:4032px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="jbWydcGSTq9ZzfZAASS2qf" name="PXL_20260828_135112815" alt="momcozy deepclean baby bottle cleaner" src="https://cdn.mos.cms.futurecdn.net/jbWydcGSTq9ZzfZAASS2qf.jpg" mos="" align="middle" fullscreen="" width="4032" height="2268" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="caption-text">This was the old way of doing things </span><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>Frankly, I had no idea how much water I use hand washing baby bottles, and had to find out. It turns out, even if I wash super-conservatively, I could use up around 35oz of water washing a single bottle. So, in the same way that <a href="https://www.tomsguide.com/face-off/dishwasher-vs-washing-by-hand-which-is-cheaper">running a full dishwasher might save more water than hand washing</a>, it seems as though the DeepClean might actually reduce your water consumption. More so when you remember that it can clean up to eight bottles (and their respective nipples) at a time without any change in water consumption.</p><p>Energy is a little more complicated. Momcozy says that the DeepClean uses 500W of power during the water heating and sterilizing parts of the cycle, which seemed accurate when I tracked by energy usage. Meanwhile the actual cleaning takes up about 55W, and the dryer uses 200W. Meanwhile, my microwave uses around 1,600W, but also only runs for a third of the time.</p><p>I'm not good at physics or math, so I know I will mess up the calculations if I try and figure it out. Needless to say, the DeepClean is far from the biggest power draw in your kitchen, and it shouldn't affect your energy bills too much.</p><p>It's also worth noting that you should be using the DeepClean with Momcozy's detergent blocks. They cost $20 for 120, working out at around 16.7 cents per cycle. How much that compares to handwashing with dish soap is going to depend on what brand you buy and how much you actually use, but I'd wager that even the fanciest dish soap is going to come in cheaper.</p><h2 id="there-are-some-downsides">There are some downsides</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:4032px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="PJRofYjqHejYgBk4MCihcf" name="PXL_20260828_101713764" alt="momcozy deepclean baby bottle cleaner" src="https://cdn.mos.cms.futurecdn.net/PJRofYjqHejYgBk4MCihcf.jpg" mos="" align="middle" fullscreen="" width="4032" height="2268" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>The first thing I actually noticed about the DeepClean unit is that it's big. 10.6 x 13.78 x 15.35 inches, to be exact, which means it takes up roughly 1.3 cubic feet of space on whichever counter top you've set aside. The only thing I have that comes close is my vertical air fryer, which is so tall it has to be tucked away in the corner.</p><p>Placement on the counter matters a lot as well, since the DeepClean doesn't have a tank to store used water. There's a hose at the back of the unit, and that means you need to make sure it drains somewhere appropriate — such as the sink or a bucket. Otherwise you're just going to end up with a very wet floor.</p><p>The $359 price tag is also a lot to take in, especially when a microwave bottle sterilizer can be bought for as little as $20. But I have to tell myself that you're buying convenience, and potentially lower bills, which could make that investment worth it — especially if you're still expecting or have a newborn. But if your kid is already moving onto solid food, it's a much tougher sell.</p><p>I have found a few other downsides to using the DeepClean at home, though some of these are more about what's going on in my brain than a flaw with the product itself. The big one is that I find it kind of gross to imagine dirty bottles left lying around, waiting for enough of their comrades to justify switching the DeepClean on. </p><p>Leftover milk in the height of the hottest summer most people can remember is not a very good mix, after all. Though I will be the first to admit that this is just something I personally need to wrap my head around, and retrain myself to think slightly differently in the face of new technology.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:4032px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="erc9635EpA7MsdCHjUaC9f" name="PXL_20260828_134828976" alt="momcozy deepclean baby bottle cleaner" src="https://cdn.mos.cms.futurecdn.net/erc9635EpA7MsdCHjUaC9f.jpg" mos="" align="middle" fullscreen="" width="4032" height="2268" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>The fact you need to buy extra detergent tablets is also worth bearing in mind, since the DeepClean is not compatible with the usual soaps or detergents you'd use to hand wash dishes. They're not expensive, and you get 60 included with the DeepClean, but it means you will be on the hook to keep buying those blocks for the duration of the appliance's lifespan.</p><p>I'll admit I forgot to use the detergent blocks on more than one occasion with no apparent ill effect. But obviously you'll want to make sure your baby's bottles are actually clean, and the detergent is the best way to ensure that.</p><p>Limescale is also going to be an issue with any machine that requires water, especially if your local water is as hard as it is in my area. I can't think of a single part of my bathroom or kitchen sink that isn't coated with that pesky layer of white deposit. Momcozy recommends using distilled water, rather than tap water, but to that I say "who has the time for that?" </p><p>I've taken to using filtered water instead, and while not perfectly free of excess minerals, it generally extends the amount of time my water-based appliances have between descaling cycles. Momcozy does include descaling tablets in the box, which are compatible with the DeepClean's self-cleaning mode.</p><p>Finally, the system that keeps clean bottles sterile for up to 72 hours is all down to a built-in air circulation system. This requires power to run, around 190-200W based on my energy meter, and turning it off means Momcozy can't guarantee the bottles will remain sterile. Such a feature could potentially be useful, especially if you need to clean bottles before going away for the weekend, but it does feel a little like overkill. So if you're anything like me, you'll have the bottles out and packed away safely pretty soon after the cleaning cycle is over.</p><h2 id="verdict">Verdict</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:4032px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="kAL987MKqZvVsKuxqop8bf" name="PXL_20260828_134822885" alt="momcozy deepclean baby bottle cleaner" src="https://cdn.mos.cms.futurecdn.net/kAL987MKqZvVsKuxqop8bf.jpg" mos="" align="middle" fullscreen="" width="4032" height="2268" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>I like using the Momcozy DeepClean Baby Bottle Washer, for the simple fact that it takes all the extra stress and hassle out of the whole bottle-cleaning process. All you need to do is fill the tank, slot the bottles in and turn the machine on. It's an extremely convenient tool to have, and it's something I wish I had back before my son started eating solid food and needed a bottle every couple of hours.</p><p>Having handwashed bottles for 9 months does mean that switching to an appliance does take an adjustment. My wife in particular is finding it hard to get out of the habit of washing milk bottles as soon as they're finished. Asking her not to clean up is like asking her not to breathe, so I'm not sure if she's actually used the DeepClean yet. </p><p>As for me, I'm coming around to the idea of being much lazier, and not scrubbing used bottles clean. Even if my math is totally wrong, and the DeepClean doesn't end up saving me money on my water or energy bills, I'm at least regaining a little bit more of my time — which is a luxury when you have young kids. </p><p>I just wish it wasn't quite so big, because it does take up a lot of space. But I guess that's the price you pay for cleaning up to eight bottles at once.</p><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h3><ul><li><a href="https://www.tomsguide.com/home/forget-weekend-deep-cleaning-this-30-second-daily-bathroom-hack-saved-my-schedule">Forget weekend deep cleaning: This 30-second daily bathroom hack saved my schedule</a></li><li><a href="https://www.tomsguide.com/home/expert-warns-against-pouring-boiling-water-down-sinks-heres-why">Expert warns against pouring boiling water down sinks — here's why</a></li><li><a href="https://www.tomsguide.com/home/home-appliances/sharkninjas-new-aquareach-wet-dry-vacuum-cleans-up">SharkNinja’s AquaReach just reinvented wet-dry vacs with an extendable wand</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ Yes, chef — shop these 21 hot kitchen appliances and cookware items for your foodie dad this Father's Day ]]></title>
                                                                                                <dc:content><![CDATA[ <p>Only seven days left before <a href="https://www.tomsguide.com/sales-events/fathers-day-gift-ideas-au">Father's Day 2026</a>, which falls on Sunday, September 6 in Australia.</p><p>If dad enjoys cooking up a feast, or maybe hosting the occasional dinner party, there's no better way to celebrate him than nabbing a kitchen-inspired gift this year. From small appliances to cookware and drinkware, there's plenty to consider here, as I've spotted 21 of the best kitchen and dining Father's Day gifts below. </p><p>All of these items have 4-star reviews on <a href="https://www.amazon.com.au/b/?_encoding=UTF8&node=222081923051&pd_rd_w=FBhNx&content-id=amzn1.sym.c75f719b-9ab0-435d-b82c-dec893d0af07&pf_rd_p=c75f719b-9ab0-435d-b82c-dec893d0af07&pf_rd_r=PFYM99CHZD98Q1J4GKH2&pd_rd_wg=EuT2g&pd_rd_r=f88e13df-cee3-4e46-a377-4ee7cc0d9fc6&ref_=pd_hp_d_r_stg_unk" target="_blank">Amazon</a>, <a href="https://kitchenaid.com.au/collections/sale" target="_blank">KitchenAid</a>, and <a href="https://www.davidjones.com/gifts/fathers-day" target="_blank">David Jones</a>, plus they offer same-day or fast delivery, so your preferred gift will arrive just in time for the big day. </p><p>I'll stop with the fuss about now — here are the best kitchen-inspired Father's Day gifts available right now. </p>        <div class="featured_product_block featured_block_hero" data-id="c1a88b3a-a294-11f1-ad60-0b5c83491949">            <a href="https://www.amazon.com.au/Breville-Toast-4-Slice-Sandwich-Press/dp/B0DB4FBBN8" data-model-name="the Toast and Melt 4-Slice Sandwich Press, Black Truffle" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:150%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/K6fcFkU8ABMKyZMqoGW3UF.jpg" alt="Breville the Toast and Melt 4-Slice Sandwich Press, Black Truffle, Lsg545btr"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Breville</div>                                        <div class="featured__title">the Toast and Melt 4-Slice Sandwich Press, Black Truffle</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="c1a88bc6-a294-11f1-ae98-c520c23c781d">            <a href="https://www.amazon.com.au/Ninja-CleanCrispTM-Functionality-Leak-Proof-FN101SGANZ" data-model-name="Crispi Air fryer" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/ji967wLx3MW4p5HDTHCYr.jpg" alt="Ninja Crispi 4-In-1 Glass Air Fryer | With Non-Toxic 4qt & 6-Cup Glass Containers & Lids | Microwave, Freezer, Dishwasher Safe | 450°f Max Temp |1500 Watt | Green | Fn101sg"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Ninja</div>                                        <div class="featured__title">Crispi Air fryer</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="c1a88c48-a294-11f1-87e1-937bd3e660f0">            <a href="https://www.amazon.com.au/DeLonghi-Nespresso-Single-Serve-Centrifusion-Technology/dp/B0BSV6MRM6" data-model-name="Vertuo Pop, Pacific Blue" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/AXJpc6UQSuFnqkTzxfZxME.jpg" alt="De'longhi Nespresso Vertuo Pop Env90.a, Capsule Coffee Machine, Single-Serve Pod Coffee Machine, 4 Cup Sizes, Nespresso Starter Pack, Centrifusion Technology, Smart Connectivity, Pacific Blue"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Nespresso</div>                                        <div class="featured__title">Vertuo Pop, Pacific Blue</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="c1a88cc0-a294-11f1-8678-0fd4b4f2a7aa">            <a href="https://www.amazon.com.au/Russell-Hobbs-21670-70-red-21670-70-Stainless/dp/B01J1RWURS" data-model-name="Kettle 1.7L" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/DYC8nLQgckrFk6ZqZreo4F.jpg" alt="Russell Hobbs Kettle [1.7 L, 2400 W] Retro Red and Polished Stainless Steel (quick Boil Function, Water Temperature Display in Retro Design, External Water Level Indicator) Vintage Tea Maker 21670-70"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Russell Hobbs</div>                                        <div class="featured__title">Kettle 1.7L</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="c1a88d42-a294-11f1-8b98-fde935f6a04c">            <a href="https://www.amazon.com.au/dreame-Portable-Blender-BPA-Free-Self-Cleaning/dp/B0H1C1FWS1" data-model-name="Portable Blender" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/jLMNZRNpYRLB3GiFgnzsBE.jpg" alt="Dreame Portable Blender, 880 Ml Bpa-Free Cup, 5 Presets Self-Cleaning Green"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Dreame</div>                                        <div class="featured__title">Portable Blender</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="c1a88dba-a294-11f1-8111-27021b787040">            <a href="https://kitchenaid.com.au/products/kitchenaid-3-5-cup-mini-food-chopper-kfc3516a-1" data-model-name="3.5 Cup Mini Food Chopper" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:70.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/hFuK2rRP3Y3Ek6BVK3YqMF.jpg" alt="3.5 Cup Mini Food Chopper Kfc3516a"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>KitchenAid</div>                                        <div class="featured__title">3.5 Cup Mini Food Chopper</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="c1a88e32-a294-11f1-a8af-8379444a3035">            <a href="https://www.amazon.com.au/CERA-Self-Heating-Portable-Espresso-CERApresso/dp/B0FHPS5LXC/ref=sr_1_14" data-model-name="Self Heating Portable Espresso Machine" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/mQsroLpQbkgbC3ZVaNnyEE.jpg" alt="Cera+ Self Heating Portable Espresso Machine, 20 Bar Coffee Maker"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>CERA+</div>                                        <div class="featured__title">Self Heating Portable Espresso Machine</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="c1a88eaa-a294-11f1-b705-2d95cbfa0d87">            <a href="https://www.amazon.com.au/Bialetti-Express-Espresso-Maker-06799/dp/B0000AN3QI" data-model-name="Moka Express Stovetop Espresso Maker" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/pFjtYdEq7g76bnKM5hL4xD.jpg" alt="Bialetti - Moka Express Stovetop Espresso Maker, 3 Cups (130 Ml) Capacity – Makes Real Italian Coffee – Iconic Moka Pot With Patented Safety Valve, Ergonomic Handle, Aluminium, Silver"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Bialetti</div>                                        <div class="featured__title">Moka Express Stovetop Espresso Maker</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="c1a88f2c-a294-11f1-9343-c196cabfbec0">            <a href="https://www.amazon.com.au/Wirefree-Thermometer-INT-11I-B-Bluetooth-Waterproof/dp/B0GSQ6JPN7" data-model-name="Mini Wirefree Meat BBQ Thermometer" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/FhqiRzkT8m3hz3D37XkvYF.jpg" alt="Inkbird Mini Wirefree Meat Bbq Thermometer Int-11i-B, Bluetooth 305m Wide Distance, 1s Fast Readout,built-In 500mah Lithium Battery Ip67 Waterproof 25 Min Fast Charge for Kitchen Bbq Grill Oven Smoker"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Inkbird</div>                                        <div class="featured__title">Mini Wirefree Meat BBQ Thermometer</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="c1a88fa4-a294-11f1-88d2-1fc9e87d2cfd">            <a href="https://www.amazon.com.au/Russell-Hobbs-Slow-Cooker-Black/dp/B07D8RNVP1" data-model-name="7L Slow Cooker" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/YmDaRNLqgrZpbrjVETCi4E.jpg" alt="Russell Hobbs 7l Slow Cooker, Rhsc7, 3 Heat Settings (low, High and Keep Warm), Dishwasher-Safe Ceramic Pot, Built-In Lid Holder, Cooks 8 Servings - Matte Black"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Russell Hobbs</div>                                        <div class="featured__title">7L Slow Cooker</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="c1a8901c-a294-11f1-b893-77ad33e72ad8">            <a href="https://www.amazon.com.au/Scanpan-Impact-Frypan-20cm-28cm/dp/B077P2X216" data-model-name="Impact Stainless Steel Fry Pan Set 2pk" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:67.80%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/NL6AZoyN5KcXPvJHF5dY7E.jpg" alt="Scanpan Impact 2-Piece Stainless Steel Fry Pan Set, 20 Cm & 28 Cm"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Scanpan</div>                                        <div class="featured__title">Impact Stainless Steel Fry Pan Set 2pk</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="c1a89094-a294-11f1-b0f7-917703e79ee4">            <a href="https://www.amazon.com.au/Tefal-Non-Stick-C2893802-Aluminium-Technology/dp/B0CKJ98P83" data-model-name="Daily Expert Red Non-Stick Pancake Pan" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/UYrtuasmjhDnXm9ijbYy7F.jpg" alt="Tefal Daily Expert Red Non-Stick Pancake Pan, 25cm, C2893802, Fixed Handle Aluminium, Titanium Non-Stick Coating, Thermo Signal Technology for Easier Cooking, Suitable for All Cooktops, Oven Safe"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Tefal</div>                                        <div class="featured__title">Daily Expert Red Non-Stick Pancake Pan</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="c1a8910c-a294-11f1-960a-85c111315b52">            <a href="https://www.amazon.com.au/Tefal-H912S217-Induction-Non-Stick-Anodised/dp/B08F5FHFHZ/" data-model-name="Jamie Oliver by Tefal Cooks Classic Non-Stick Frypan 2pk" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/vMoYTpu9ZP3QZZQ6FuDTJE.jpg" alt="Tefal Jamie Oliver by Tefal Cooks Classic Non-Stick Induction Hard Anodised Twinpack Frypan 24/28cm, H912s217"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Tefal</div>                                        <div class="featured__title">Jamie Oliver by Tefal Cooks Classic Non-Stick Frypan 2pk</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="c1a8918e-a294-11f1-8f94-8166f1c5d089">            <a href="https://www.amazon.com.au/Corelle-Livingware-18-Piece-Dinnerware-1088609/dp/B00F39GFUW/ref=sr_1_1" data-model-name="Winter Frost White Dinnerware Set, 18-Piece" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/xmi2LzHp76FSPcQk4oh3BF.jpg" alt="Corelle Winter Frost White Dinnerware Set, 18-Piece – Chip-Resistant Triple-Layer Glass – Stackable Design for Everyday Dining, 6 Dinner Plates, 6 Bread & Butter Plates, 4 Soup/cereal Bowls"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Corelle</div>                                        <div class="featured__title">Winter Frost White Dinnerware Set, 18-Piece</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="c1a89206-a294-11f1-8352-b516830da536">            <a href="https://www.amazon.com.au/Multi-Prep-Compact-4pc-Prep-Mcolor/dp/B0CF6B979W/" data-model-name="Multi-Prep Compact 4-In-1 Multifunctional Set" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:81.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/aH9quCbNdCBLushj2sREWE.jpg" alt="Joseph Joseph Multi-Prep Compact 4-In-1 Multifunctional Set, Kitchen Vegetable Chopper & Dicer, Cheese Grater, Mandoline Veggie Slicer, Food Julienne Cutter With Container, Stainless Steel Blades"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Joseph Joseph</div>                                        <div class="featured__title">Multi-Prep Compact 4-In-1 Multifunctional Set</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="c1a8927e-a294-11f1-b0e6-e53adc173fd2">            <a href="https://www.amazon.com.au/Joseph-Colander-Strainer-Vegetable-Space-Saving/dp/B0DPG6JG3K" data-model-name="Droplet Mini Colander With Folding Handles" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:81.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/CeYv85aBMMtAFpuDZSCzdF.jpg" alt="Joseph Joseph Droplet Mini Colander With Folding Handles, Kitchen Strainer for Small Vegetable, Fruits & Berries, Space-Saving"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Joseph Joseph</div>                                        <div class="featured__title">Droplet Mini Colander With Folding Handles</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="c1a89300-a294-11f1-96c6-9b95201bdf3c">            <a href="https://www.amazon.com.au/Whiskey-Smoker-Kit-Torch-Fashioned/dp/B0BJV68C17" data-model-name="Whiskey Smoker Kit With Torch" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/rTmtej8Z2JJXuFp3sXAWSE.jpg" alt="Whiskey Smoker Kit With Torch - 6 Flavors Wood Chips, 2 Glasses, 2 Ice Ball Molds - Cocktail Smoker Infuser Kit, Old Fashioned Drink Smoker Kit, Birthday Bourbon Whiskey Gifts for Men,dad(no Butane)"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>ComboJoy</div>                                        <div class="featured__title">Whiskey Smoker Kit With Torch</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="c1a89378-a294-11f1-93b1-cbe5dc88828b">            <a href="https://www.amazon.com.au/JoyJolt-Decanter-Lead-free-Crystal-Carafe/dp/B073NXQWBV/" data-model-name="Cigno Wine Decanter" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/qNmdy9ESusQDw9wfdYBe2F.jpg" alt="Joyjolt Cigno Wine Decanter Hand Blown Lead-Free Crystal Glass Red Wine Carafe 50.72 Fl. Oz."></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>JoyJolt</div>                                        <div class="featured__title">Cigno Wine Decanter</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="c1a893f0-a294-11f1-952c-99681b5b87c9">            <a href="https://www.davidjones.com/product/gentlemens-hardware-top-hat-bottle-stoppers-set-of-2-28768167" data-model-name="Top Hat Bottle Stoppers - Set of 2" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:128.79%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/fXbMJwjuvpEfhYjyHxLhfU.png" alt="Top hat bottle tops"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Gentleman's Hardware</div>                                        <div class="featured__title">Top Hat Bottle Stoppers - Set of 2</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="c1a89468-a294-11f1-b9db-b9707d1bf769">            <a href="https://www.davidjones.com/product/gentlemens-hardware-golf-ball-bottle-opener-28768171" data-model-name="Golf Ball Bottle Opener" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:128.79%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/AdgBT6PdKyFY9GZQFH82zP.png" alt="Gentleman's Hardware golf ball"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Gentleman's Hardware</div>                                        <div class="featured__title">Golf Ball Bottle Opener</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="c1a894ea-a294-11f1-934b-31590118f811">            <a href="https://www.davidjones.com/product/gentlemens-hardware-fish-hip-flask-26067577" data-model-name="Fish Hip Flask" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:130.18%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/9gTVk8dqEaztEfXZzonhE7.png" alt="Gentleman's hardware fish flask"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Gentleman's Hardware</div>                                        <div class="featured__title">Fish Hip Flask</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h3><ul><li><a href="https://www.tomsguide.com/wellness/forget-socks-shop-these-30-expert-picked-skincare-and-haircare-buys-for-dad-this-fathers-day">Forget socks — shop these 30 expert-picked skincare and haircare buys for dad this Father's Day</a></li><li><a href="https://www.tomsguide.com/tech/forget-a-new-tie-ive-found-15-of-the-best-fathers-day-tech-gifts-that-will-make-you-his-favourite-child">Forget a new tie — I've found 15 of the best Father's Day tech gifts that will make you his favourite child</a></li><li><a href="https://www.tomsguide.com/gaming/gaming-peripherals/gamer-dad-ive-found-11-winning-fathers-day-gaming-ideas-to-level-up-your-gifting">Gamer dad? I've found 11 winning Father's Day gaming ideas to level up your gifting</a></li><li><a href="https://www.tomsguide.com/wellness/fitness/run-dont-walk-ive-spotted-9-of-the-best-fitness-fathers-day-gifts-thatll-help-dad-work-on-his-dadbod">Run, don't walk — I've spotted 9 of the best fitness Father's Day gifts that'll help dad work on his #DadBod</a></li><li><a href="https://www.tomsguide.com/home/gardening/got-an-outdoorsy-or-garden-loving-dad-ive-compiled-12-of-the-best-fathers-day-gifts-that-your-green-thumbed-dad-would-enjoy">Got an outdoorsy or garden-loving dad? I've compiled 12 of the best Father's Day gifts that your green-thumbed dad would enjoy</a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/home/kitchen-dining/yes-chef-shop-these-21-hot-kitchen-appliances-and-cookware-items-for-your-foodie-dad-this-fathers-day</link>
                                                                            <description>
                            <![CDATA[ Give your head chef-dad one of these great kitchen-related gifts this Father's Day. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">fc4r3Z8GCHnReox2h2nCUc</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/KexY8jZGHNutJaacVxKDe4-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Sat, 29 Aug 2026 23:00:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Kitchen & Dining]]></category>
                                                    <category><![CDATA[Home]]></category>
                                                    <category><![CDATA[Home Appliances]]></category>
                                                                                                <author><![CDATA[ lucy.scotting@futurenet.com (Lucy Scotting) ]]></author>                    <dc:creator><![CDATA[ Lucy Scotting ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/UC9ncAYxkmJ5ipHEyX44ri.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Lucy Scotting is a staff writer for Tom’s Guide Australia, primarily covering lifestyle, streaming and internet-related news. Lucy started her career writing for HR and staffing industry publications, with articles covering emerging tech, business and finance.&lt;/p&gt;&lt;p&gt;In her spare time, Lucy can be found watching sci-fi movies, working on her dystopian fiction novel (in progress since 2017) or hanging out with her dog, Fletcher. If she’s not found doing any of the above, she’s likely on her next adventure to a new city, country, or continent. &lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/KexY8jZGHNutJaacVxKDe4-1280-80.jpg">
                                                            <media:credit><![CDATA[Future / Edited with Gemini]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Kitchen appliances on gradient background]]></media:description>                                                            <media:text><![CDATA[Kitchen appliances on gradient background]]></media:text>
                                <media:title type="plain"><![CDATA[Kitchen appliances on gradient background]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/KexY8jZGHNutJaacVxKDe4-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Only seven days left before <a href="https://www.tomsguide.com/sales-events/fathers-day-gift-ideas-au">Father's Day 2026</a>, which falls on Sunday, September 6 in Australia.</p><p>If dad enjoys cooking up a feast, or maybe hosting the occasional dinner party, there's no better way to celebrate him than nabbing a kitchen-inspired gift this year. From small appliances to cookware and drinkware, there's plenty to consider here, as I've spotted 21 of the best kitchen and dining Father's Day gifts below. </p><p>All of these items have 4-star reviews on <a href="https://www.amazon.com.au/b/?_encoding=UTF8&node=222081923051&pd_rd_w=FBhNx&content-id=amzn1.sym.c75f719b-9ab0-435d-b82c-dec893d0af07&pf_rd_p=c75f719b-9ab0-435d-b82c-dec893d0af07&pf_rd_r=PFYM99CHZD98Q1J4GKH2&pd_rd_wg=EuT2g&pd_rd_r=f88e13df-cee3-4e46-a377-4ee7cc0d9fc6&ref_=pd_hp_d_r_stg_unk" target="_blank">Amazon</a>, <a href="https://kitchenaid.com.au/collections/sale" target="_blank">KitchenAid</a>, and <a href="https://www.davidjones.com/gifts/fathers-day" target="_blank">David Jones</a>, plus they offer same-day or fast delivery, so your preferred gift will arrive just in time for the big day. </p><p>I'll stop with the fuss about now — here are the best kitchen-inspired Father's Day gifts available right now. </p>        <div class="featured_product_block featured_block_hero" data-id="c1a88b3a-a294-11f1-ad60-0b5c83491949">            <a href="https://www.amazon.com.au/Breville-Toast-4-Slice-Sandwich-Press/dp/B0DB4FBBN8" data-model-name="the Toast and Melt 4-Slice Sandwich Press, Black Truffle" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:150%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/K6fcFkU8ABMKyZMqoGW3UF.jpg" alt="Breville the Toast and Melt 4-Slice Sandwich Press, Black Truffle, Lsg545btr"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Breville</div>                                        <div class="featured__title">the Toast and Melt 4-Slice Sandwich Press, Black Truffle</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="c1a88bc6-a294-11f1-ae98-c520c23c781d">            <a href="https://www.amazon.com.au/Ninja-CleanCrispTM-Functionality-Leak-Proof-FN101SGANZ" data-model-name="Crispi Air fryer" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/ji967wLx3MW4p5HDTHCYr.jpg" alt="Ninja Crispi 4-In-1 Glass Air Fryer | With Non-Toxic 4qt & 6-Cup Glass Containers & Lids | Microwave, Freezer, Dishwasher Safe | 450°f Max Temp |1500 Watt | Green | Fn101sg"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Ninja</div>                                        <div class="featured__title">Crispi Air fryer</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="c1a88c48-a294-11f1-87e1-937bd3e660f0">            <a href="https://www.amazon.com.au/DeLonghi-Nespresso-Single-Serve-Centrifusion-Technology/dp/B0BSV6MRM6" data-model-name="Vertuo Pop, Pacific Blue" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/AXJpc6UQSuFnqkTzxfZxME.jpg" alt="De'longhi Nespresso Vertuo Pop Env90.a, Capsule Coffee Machine, Single-Serve Pod Coffee Machine, 4 Cup Sizes, Nespresso Starter Pack, Centrifusion Technology, Smart Connectivity, Pacific Blue"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Nespresso</div>                                        <div class="featured__title">Vertuo Pop, Pacific Blue</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="c1a88cc0-a294-11f1-8678-0fd4b4f2a7aa">            <a href="https://www.amazon.com.au/Russell-Hobbs-21670-70-red-21670-70-Stainless/dp/B01J1RWURS" data-model-name="Kettle 1.7L" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/DYC8nLQgckrFk6ZqZreo4F.jpg" alt="Russell Hobbs Kettle [1.7 L, 2400 W] Retro Red and Polished Stainless Steel (quick Boil Function, Water Temperature Display in Retro Design, External Water Level Indicator) Vintage Tea Maker 21670-70"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Russell Hobbs</div>                                        <div class="featured__title">Kettle 1.7L</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="c1a88d42-a294-11f1-8b98-fde935f6a04c">            <a href="https://www.amazon.com.au/dreame-Portable-Blender-BPA-Free-Self-Cleaning/dp/B0H1C1FWS1" data-model-name="Portable Blender" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/jLMNZRNpYRLB3GiFgnzsBE.jpg" alt="Dreame Portable Blender, 880 Ml Bpa-Free Cup, 5 Presets Self-Cleaning Green"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Dreame</div>                                        <div class="featured__title">Portable Blender</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="c1a88dba-a294-11f1-8111-27021b787040">            <a href="https://kitchenaid.com.au/products/kitchenaid-3-5-cup-mini-food-chopper-kfc3516a-1" data-model-name="3.5 Cup Mini Food Chopper" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:70.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/hFuK2rRP3Y3Ek6BVK3YqMF.jpg" alt="3.5 Cup Mini Food Chopper Kfc3516a"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>KitchenAid</div>                                        <div class="featured__title">3.5 Cup Mini Food Chopper</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="c1a88e32-a294-11f1-a8af-8379444a3035">            <a href="https://www.amazon.com.au/CERA-Self-Heating-Portable-Espresso-CERApresso/dp/B0FHPS5LXC/ref=sr_1_14" data-model-name="Self Heating Portable Espresso Machine" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/mQsroLpQbkgbC3ZVaNnyEE.jpg" alt="Cera+ Self Heating Portable Espresso Machine, 20 Bar Coffee Maker"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>CERA+</div>                                        <div class="featured__title">Self Heating Portable Espresso Machine</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="c1a88eaa-a294-11f1-b705-2d95cbfa0d87">            <a href="https://www.amazon.com.au/Bialetti-Express-Espresso-Maker-06799/dp/B0000AN3QI" data-model-name="Moka Express Stovetop Espresso Maker" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/pFjtYdEq7g76bnKM5hL4xD.jpg" alt="Bialetti - Moka Express Stovetop Espresso Maker, 3 Cups (130 Ml) Capacity – Makes Real Italian Coffee – Iconic Moka Pot With Patented Safety Valve, Ergonomic Handle, Aluminium, Silver"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Bialetti</div>                                        <div class="featured__title">Moka Express Stovetop Espresso Maker</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="c1a88f2c-a294-11f1-9343-c196cabfbec0">            <a href="https://www.amazon.com.au/Wirefree-Thermometer-INT-11I-B-Bluetooth-Waterproof/dp/B0GSQ6JPN7" data-model-name="Mini Wirefree Meat BBQ Thermometer" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/FhqiRzkT8m3hz3D37XkvYF.jpg" alt="Inkbird Mini Wirefree Meat Bbq Thermometer Int-11i-B, Bluetooth 305m Wide Distance, 1s Fast Readout,built-In 500mah Lithium Battery Ip67 Waterproof 25 Min Fast Charge for Kitchen Bbq Grill Oven Smoker"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Inkbird</div>                                        <div class="featured__title">Mini Wirefree Meat BBQ Thermometer</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="c1a88fa4-a294-11f1-88d2-1fc9e87d2cfd">            <a href="https://www.amazon.com.au/Russell-Hobbs-Slow-Cooker-Black/dp/B07D8RNVP1" data-model-name="7L Slow Cooker" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/YmDaRNLqgrZpbrjVETCi4E.jpg" alt="Russell Hobbs 7l Slow Cooker, Rhsc7, 3 Heat Settings (low, High and Keep Warm), Dishwasher-Safe Ceramic Pot, Built-In Lid Holder, Cooks 8 Servings - Matte Black"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Russell Hobbs</div>                                        <div class="featured__title">7L Slow Cooker</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="c1a8901c-a294-11f1-b893-77ad33e72ad8">            <a href="https://www.amazon.com.au/Scanpan-Impact-Frypan-20cm-28cm/dp/B077P2X216" data-model-name="Impact Stainless Steel Fry Pan Set 2pk" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:67.80%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/NL6AZoyN5KcXPvJHF5dY7E.jpg" alt="Scanpan Impact 2-Piece Stainless Steel Fry Pan Set, 20 Cm & 28 Cm"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Scanpan</div>                                        <div class="featured__title">Impact Stainless Steel Fry Pan Set 2pk</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="c1a89094-a294-11f1-b0f7-917703e79ee4">            <a href="https://www.amazon.com.au/Tefal-Non-Stick-C2893802-Aluminium-Technology/dp/B0CKJ98P83" data-model-name="Daily Expert Red Non-Stick Pancake Pan" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/UYrtuasmjhDnXm9ijbYy7F.jpg" alt="Tefal Daily Expert Red Non-Stick Pancake Pan, 25cm, C2893802, Fixed Handle Aluminium, Titanium Non-Stick Coating, Thermo Signal Technology for Easier Cooking, Suitable for All Cooktops, Oven Safe"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Tefal</div>                                        <div class="featured__title">Daily Expert Red Non-Stick Pancake Pan</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="c1a8910c-a294-11f1-960a-85c111315b52">            <a href="https://www.amazon.com.au/Tefal-H912S217-Induction-Non-Stick-Anodised/dp/B08F5FHFHZ/" data-model-name="Jamie Oliver by Tefal Cooks Classic Non-Stick Frypan 2pk" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/vMoYTpu9ZP3QZZQ6FuDTJE.jpg" alt="Tefal Jamie Oliver by Tefal Cooks Classic Non-Stick Induction Hard Anodised Twinpack Frypan 24/28cm, H912s217"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Tefal</div>                                        <div class="featured__title">Jamie Oliver by Tefal Cooks Classic Non-Stick Frypan 2pk</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="c1a8918e-a294-11f1-8f94-8166f1c5d089">            <a href="https://www.amazon.com.au/Corelle-Livingware-18-Piece-Dinnerware-1088609/dp/B00F39GFUW/ref=sr_1_1" data-model-name="Winter Frost White Dinnerware Set, 18-Piece" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/xmi2LzHp76FSPcQk4oh3BF.jpg" alt="Corelle Winter Frost White Dinnerware Set, 18-Piece – Chip-Resistant Triple-Layer Glass – Stackable Design for Everyday Dining, 6 Dinner Plates, 6 Bread & Butter Plates, 4 Soup/cereal Bowls"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Corelle</div>                                        <div class="featured__title">Winter Frost White Dinnerware Set, 18-Piece</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="c1a89206-a294-11f1-8352-b516830da536">            <a href="https://www.amazon.com.au/Multi-Prep-Compact-4pc-Prep-Mcolor/dp/B0CF6B979W/" data-model-name="Multi-Prep Compact 4-In-1 Multifunctional Set" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:81.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/aH9quCbNdCBLushj2sREWE.jpg" alt="Joseph Joseph Multi-Prep Compact 4-In-1 Multifunctional Set, Kitchen Vegetable Chopper & Dicer, Cheese Grater, Mandoline Veggie Slicer, Food Julienne Cutter With Container, Stainless Steel Blades"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Joseph Joseph</div>                                        <div class="featured__title">Multi-Prep Compact 4-In-1 Multifunctional Set</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="c1a8927e-a294-11f1-b0e6-e53adc173fd2">            <a href="https://www.amazon.com.au/Joseph-Colander-Strainer-Vegetable-Space-Saving/dp/B0DPG6JG3K" data-model-name="Droplet Mini Colander With Folding Handles" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:81.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/CeYv85aBMMtAFpuDZSCzdF.jpg" alt="Joseph Joseph Droplet Mini Colander With Folding Handles, Kitchen Strainer for Small Vegetable, Fruits & Berries, Space-Saving"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Joseph Joseph</div>                                        <div class="featured__title">Droplet Mini Colander With Folding Handles</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="c1a89300-a294-11f1-96c6-9b95201bdf3c">            <a href="https://www.amazon.com.au/Whiskey-Smoker-Kit-Torch-Fashioned/dp/B0BJV68C17" data-model-name="Whiskey Smoker Kit With Torch" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/rTmtej8Z2JJXuFp3sXAWSE.jpg" alt="Whiskey Smoker Kit With Torch - 6 Flavors Wood Chips, 2 Glasses, 2 Ice Ball Molds - Cocktail Smoker Infuser Kit, Old Fashioned Drink Smoker Kit, Birthday Bourbon Whiskey Gifts for Men,dad(no Butane)"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>ComboJoy</div>                                        <div class="featured__title">Whiskey Smoker Kit With Torch</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="c1a89378-a294-11f1-93b1-cbe5dc88828b">            <a href="https://www.amazon.com.au/JoyJolt-Decanter-Lead-free-Crystal-Carafe/dp/B073NXQWBV/" data-model-name="Cigno Wine Decanter" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/qNmdy9ESusQDw9wfdYBe2F.jpg" alt="Joyjolt Cigno Wine Decanter Hand Blown Lead-Free Crystal Glass Red Wine Carafe 50.72 Fl. Oz."></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>JoyJolt</div>                                        <div class="featured__title">Cigno Wine Decanter</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="c1a893f0-a294-11f1-952c-99681b5b87c9">            <a href="https://www.davidjones.com/product/gentlemens-hardware-top-hat-bottle-stoppers-set-of-2-28768167" data-model-name="Top Hat Bottle Stoppers - Set of 2" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:128.79%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/fXbMJwjuvpEfhYjyHxLhfU.png" alt="Top hat bottle tops"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Gentleman's Hardware</div>                                        <div class="featured__title">Top Hat Bottle Stoppers - Set of 2</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="c1a89468-a294-11f1-b9db-b9707d1bf769">            <a href="https://www.davidjones.com/product/gentlemens-hardware-golf-ball-bottle-opener-28768171" data-model-name="Golf Ball Bottle Opener" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:128.79%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/AdgBT6PdKyFY9GZQFH82zP.png" alt="Gentleman's Hardware golf ball"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Gentleman's Hardware</div>                                        <div class="featured__title">Golf Ball Bottle Opener</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="c1a894ea-a294-11f1-934b-31590118f811">            <a href="https://www.davidjones.com/product/gentlemens-hardware-fish-hip-flask-26067577" data-model-name="Fish Hip Flask" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:130.18%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/9gTVk8dqEaztEfXZzonhE7.png" alt="Gentleman's hardware fish flask"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Gentleman's Hardware</div>                                        <div class="featured__title">Fish Hip Flask</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h3><ul><li><a href="https://www.tomsguide.com/wellness/forget-socks-shop-these-30-expert-picked-skincare-and-haircare-buys-for-dad-this-fathers-day">Forget socks — shop these 30 expert-picked skincare and haircare buys for dad this Father's Day</a></li><li><a href="https://www.tomsguide.com/tech/forget-a-new-tie-ive-found-15-of-the-best-fathers-day-tech-gifts-that-will-make-you-his-favourite-child">Forget a new tie — I've found 15 of the best Father's Day tech gifts that will make you his favourite child</a></li><li><a href="https://www.tomsguide.com/gaming/gaming-peripherals/gamer-dad-ive-found-11-winning-fathers-day-gaming-ideas-to-level-up-your-gifting">Gamer dad? I've found 11 winning Father's Day gaming ideas to level up your gifting</a></li><li><a href="https://www.tomsguide.com/wellness/fitness/run-dont-walk-ive-spotted-9-of-the-best-fitness-fathers-day-gifts-thatll-help-dad-work-on-his-dadbod">Run, don't walk — I've spotted 9 of the best fitness Father's Day gifts that'll help dad work on his #DadBod</a></li><li><a href="https://www.tomsguide.com/home/gardening/got-an-outdoorsy-or-garden-loving-dad-ive-compiled-12-of-the-best-fathers-day-gifts-that-your-green-thumbed-dad-would-enjoy">Got an outdoorsy or garden-loving dad? I've compiled 12 of the best Father's Day gifts that your green-thumbed dad would enjoy</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ I tested Philips’s new ‘budget’ Baristina espresso machine — but I’m more confused than impressed ]]></title>
                                                                                                <dc:content><![CDATA[ <p>The Philips Baristina is an interesting espresso machine. It’s an automatic, but also not quite an automatic. How does that work, I hear you ask? Let me explain. </p><p>So, while it grinds, doses, tamps, and brews without any input from you (aside from you clicking the shot button), you also have to empty the portafilter. Isn’t that the worst part of any manual machine? The coffee grounds always get stuck to my hands. Anyway, if you’re after an espresso machine that does <em>most</em> of the hard work for you, the Baristina could be ideal. </p><p>However, the espresso does taste pretty mid, and the price is about $200 more than I’d expect. So, could it be one of the <a href="https://www.tomsguide.com/home/coffee-makers/best-espresso-machines">best espresso machines</a>? Hm. I don’t think so. But want to find out the full story? Keep reading this Philips Baristina review.</p><h2 class="article-body__section" id="section-philips-baristina-review-specs"><span>Philips Baristina review: Specs</span></h2><div ><table><tbody><tr><td class="firstcol " ><p><strong>Price</strong></p></td><td  ><p><a href="https://www.amazon.com/Baristina-Espresso-Automatic-Portafilter-BAR302/dp/B0F6TQYRJV" target="_blank" rel="nofollow">$449-$529</a> / <a href="https://www.amazon.co.uk/Baristina-Automatic-Portafilter-BAR300-60/dp/B0GX61DZGS" target="_blank" rel="nofollow">£299-£379</a></p></td></tr><tr><td class="firstcol " ><p><strong>Weight</strong></p></td><td  ><p>11 pounds</p></td></tr><tr><td class="firstcol " ><p><strong>Dimensions</strong></p></td><td  ><p>15 x 7 x 13.6 inches</p></td></tr><tr><td class="firstcol " ><p><strong>Grinder</strong></p></td><td  ><p>Yes</p></td></tr><tr><td class="firstcol " ><p><strong>Heating system </strong></p></td><td  ><p>Unspecified </p></td></tr><tr><td class="firstcol " ><p><strong>Pressure </strong></p></td><td  ><p>16 bar</p></td></tr><tr><td class="firstcol " ><p><strong>Water tank capacity</strong></p></td><td  ><p>40.6 fluid ounces</p></td></tr><tr><td class="firstcol " ><p><strong>Accessories</strong></p></td><td  ><p>None</p></td></tr></tbody></table></div><h2 class="article-body__section" id="section-philips-baristina-review-price-availability"><span>Philips Baristina review: Price & availability</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.20%;"><img id="Ckgfg6oQ5wGpZnuVfNrcSW" name="Philips_Baristina_10" alt="the philips baristina photographed against the blue tom's guide background" src="https://cdn.mos.cms.futurecdn.net/Ckgfg6oQ5wGpZnuVfNrcSW.jpg" mos="" align="middle" fullscreen="" width="1920" height="1079" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The Philips Baristina is <a href="https://www.amazon.com/Baristina-Espresso-Automatic-Portafilter-BAR302/dp/B0F6TQYRJV" target="_blank" rel="nofollow">$449-$529 from Amazon U.S.</a> and <a href="https://www.amazon.co.uk/Baristina-Automatic-Portafilter-BAR300-60/dp/B0GX61DZGS" target="_blank" rel="nofollow">£299-£379 from Amazon U.K</a>. While this price is reasonable enough in the U.K., I would not recommend paying $529 if you’re in the U.S. You don’t even get a built-in milk frother — it looks and feels like a Nespresso Aeroccino standalone milk heater/frother. You can’t customize milk texture at all. </p><p>Even though I think the Baristina is overpriced, it’s an automatic machine, which means it’s always going to be pricier than manuals. However, I would wholeheartedly recommend spending just a little more for a genuinely decent machine. </p><p>Instead of spending $529 on what is effectively an espresso maker and a separate (cheap-feeling, one-trick-pony) milk frother, I’d spend $699 on the <a href="https://www.amazon.com/PHILIPS-Automatic-Espresso-Machine-LatteGo/dp/B0GZW8QCGM" target="_blank" rel="nofollow">Philips 2300 Series</a>, $799 on the <a href="https://www.tomsguide.com/home/coffee-makers/kitchenaid-kf2-review-this-fully-automatic-coffee-machine-effortlessly-takes-the-guesswork-out-of-your-morning-brew" target="_blank">KitchenAid KF2</a>, or, heck, even $379 on the <a href="https://www.tomsguide.com/home/coffee-makers/nespresso-citiz-aeroccino-review">Nespresso CitiZ + Aeroccino</a>. It’s a pod machine, sure, but honestly? It makes a better brew. </p><h2 class="article-body__section" id="section-philips-baristina-review-design"><span>Philips Baristina review: Design</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.20%;"><img id="y7T39v8dU9cq7iCocsQvLW" name="Philips_Baristina_9" alt="the philips baristina photographed against the blue tom's guide background" src="https://cdn.mos.cms.futurecdn.net/y7T39v8dU9cq7iCocsQvLW.jpg" mos="" align="middle" fullscreen="" width="1920" height="1079" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>So, I’m not a huge fan of how the Baristina looks. I think it looks incredibly cheap, like something that costs $200 rather than $530. When I found out how much it costs, I actually gasped. </p><p>While it doesn’t look <em>bad</em>, it does look <em>cheap</em>. Whether this is a dealbreaker will depend on your preferences. For me, I’d rather spend a little extra on the KitchenAid KF2 or just get a bog-standard manual like the $300 <a href="https://www.tomsguide.com/home/coffee-makers/sage-breville-bambino-review">Breville Bambino</a>. </p><p>You get a “portafilter”. I say “portafilter” because, yes, it’s technically a portafilter in that it has a handle and a basket where the coffee goes. But you can’t use it like a traditional portafilter — you don’t dose and tamp manually. All you have to do is push the portafilter over to the grinder side at the start of the brew and then sit back and relax. </p><p>While, yes, I <em>loved </em>watching the portafilter snap back into place after the grinder finished (it’s the simple things), I think this is more of a style gimmick than actual function. If you’re after a truly automatic machine, it might even be a major con. Yes, you have to empty and clean out the portafilter yourself. </p><h2 class="article-body__section" id="section-philips-baristina-review-espresso"><span>Philips Baristina review: Espresso</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.20%;"><img id="4aBpHB3mhJV5FmajBR7VjV" name="Philips_Baristina_6" alt="the philips baristina photographed against the blue tom's guide background" src="https://cdn.mos.cms.futurecdn.net/4aBpHB3mhJV5FmajBR7VjV.jpg" mos="" align="middle" fullscreen="" width="1920" height="1079" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>If you’re an espresso aficionado, you won’t want to read this. However, if you’re someone who prioritizes speed, ease of use, and simplicity, you’re the perfect candidate for a Baristina. </p><p>As it’s a bean-to-cup automatic — despite having a “portafilter” — you have very little input. Pour your beans in, press the espresso button, slide the portafilter to the grinder side (which is super fun), and you’ve done all the work. The machine snaps the portafilter into place hands-free, and, yes, this is mesmerizing to watch. I don’t care how lame that makes me; I enjoy watching a portafilter careen across a coffee machine like a stone from a slingshot. It’s novel. Sue me. </p><p>In terms of espresso flavor… it’s okay. It tastes incredibly average. I tried the machine with both artisan Ethiopian beans and your generic “strong” dark roast, and it tasted better with the latter. I’d recommend using cheaper, darker beans on this machine, as the excessive 16-bar pressure and the tiny (40mm) pressurized portafilter destroys any nuance anyway. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:3256px;"><p class="vanilla-image-block" style="padding-top:56.27%;"><img id="rtiKZ2LC6EDh7AA5Dtja4Y" name="philpis baristina espresso" alt="a photo of a drink made on the philips baristina espresso machine" src="https://cdn.mos.cms.futurecdn.net/rtiKZ2LC6EDh7AA5Dtja4Y.jpg" mos="" align="middle" fullscreen="" width="3256" height="1832" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Erin Bashford)</span></figcaption></figure><p>As you can see, this espresso shot is foamy and aerated, which means it was extracted under too much pressure. The crema is fluffy, but it dissipated within seconds. The first Ethiopian beans (which usually taste divine) were overly sour and astringent. However, the second generic Illy-brand beans resulted in a stronger, more palatable coffee taste. Of course, this won’t impress coffee nerds, but this isn’t a machine for coffee nerds. </p><p>Even so, I struggle to recommend this machine wholeheartedly considering you can get much better machines for just a little extra. The <a href="https://www.amazon.com/PHILIPS-Automatic-Espresso-Machine-LatteGo/dp/B0GZW8QCGM">Philips 2300</a> is a modest stretch at $699; the <a href="https://www.tomsguide.com/home/coffee-makers/kitchenaid-kf2-review-this-fully-automatic-coffee-machine-effortlessly-takes-the-guesswork-out-of-your-morning-brew">KitchenAid KF2</a> is $799. Considering these machines have built-in milk preparation and zero user input, I’d recommend them if you’re after a totally automatic machine. The espresso tastes much nicer. </p><h2 class="article-body__section" id="section-philips-baristina-review-grinder"><span>Philips Baristina review: Grinder</span></h2><p>While the Philips Baristina does have a built-in grinder and therefore demands a standalone ‘grinder’ section, this is going to be extremely short. </p><p>The grinder is not adjustable. Yes, you heard me correctly. Not adjustable. The grinder grinds to one size and one size only. Want it finer? Not possible. Coarser? Oh, again, you guessed it, not possible. </p><p>Other automatic machines such as the De’Longhi Rivelia have an adjustable grinder, and also the $699 manual bean-to-cup De’Longhi Arte Evo. If you’re interested in actually playing and experimenting with coffee, I’d recommend the Arte Evo over the Baristina. You’re paying an extra $150, but it’s often discounted to $599 (so just $50 more), and you get all the bonuses of a manual machine with the ease of an assisted tamping system. </p><h2 class="article-body__section" id="section-philips-baristina-review-milk"><span>Philips Baristina review: Milk</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1919px;"><p class="vanilla-image-block" style="padding-top:56.28%;"><img id="MfszB5jgQRneGjDEThJMeV" name="Philips_Baristina_11" alt="the philips baristina photographed against the blue tom's guide background" src="https://cdn.mos.cms.futurecdn.net/MfszB5jgQRneGjDEThJMeV.jpg" mos="" align="middle" fullscreen="" width="1919" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>As mentioned earlier, the Baristina comes in two variants: with milk frother and without milk frother. If you order the cheaper model, it won’t come with the frother. </p><p>Those familiar with something like the Nespresso Aeroccino will recognize this milk frother: the Philips model is essentially just your standard countertop model. It’s not particularly unique or innovative, but damn, it works. If it ain’t broke, don’t fix, right? </p><p>Here’s a photo of a milk drink made. Notice how I said “milk drink” rather than latte or cappuccino — the Baristina can only make one type of milk. No wet lattes or dry cappuccinos here. Milk or no milk only!</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:3464px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="5kq8rRgCmJq6oKjjjKcnxX" name="philpis baristina milk" alt="a photo of a drink made on the philips baristina espresso machine" src="https://cdn.mos.cms.futurecdn.net/5kq8rRgCmJq6oKjjjKcnxX.jpg" mos="" align="middle" fullscreen="" width="3464" height="1948" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Erin Bashford)</span></figcaption></figure><p>As you can see, the milk is extremely thick. Don’t get me wrong, the texture is satisfying, with well-distributed, evenly sized bubbles. However, this isn’t going to impress people who are used to barista-crafted beverages. It cannot make microfoam; therefore, drinks like lattes and flat whites are out of the question. You can only make cappuccinos. </p><h2 class="article-body__section" id="section-philips-baristina-review-storage-maintenance"><span>Philips Baristina review: Storage & maintenance</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1919px;"><p class="vanilla-image-block" style="padding-top:56.28%;"><img id="GXChiJ6pWNhcLoZd4fLDhV" name="Philips_Baristina_7" alt="the philips baristina photographed against the blue tom's guide background" src="https://cdn.mos.cms.futurecdn.net/GXChiJ6pWNhcLoZd4fLDhV.jpg" mos="" align="middle" fullscreen="" width="1919" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>Although 15 inches tall, the Philips Baristina feels a lot smaller. This height is solely due to the grinder hopper — its main body is more compact. Of course, you’d need to ensure you have space under your counters for the hopper, but the machine should take up less space than you think. </p><p>Due to this size, the machine has a teeny-tiny drip tray. I always recommend cleaning out your drip tray after every use, but in this case, it’s definitely a necessity. If you don’t clean it out every day, it’s going to overflow before you know it. </p><p>As with the rest of the machine, the drip tray is incredibly plasticky. This is one of my biggest complaints — a design this plasticky is pretty inexcusable when you’re charging $549 from an aesthetic and longevity perspective. </p><p>Speaking of longevity, you get a 2-year warranty as standard, which is the same as Breville, Ninja, and De’Longhi. </p><h2 class="article-body__section" id="section-philips-baristina-review-verdict"><span>Philips Baristina review: Verdict</span></h2><p>While I don’t think the Philips Baristina is the worst espresso machine I’ve ever used, I can’t recommend it wholeheartedly. Only a very specific user base should get this machine. If you can’t stretch to $699 for a Philips 2300 Series, you don’t mind mid-tasting espresso, you’re happy with one-size-fits-all milk texture, <em>and</em> you’re happy to spend $200 more than I think you should, then yes, this would be the machine for you. </p><p>All other people, though? You’d either be better off with the $699 Philips 2300 Series, the $799 KitchenAid KF2, or even venture into the world of manual bean-to-cups with the fantastic De’Longhi Arte Evo. </p><p>As I said earlier, if you want simplicity and ease of use over anything else, I’d even go as far to say you’re the perfect candidate for a Nespresso CitiZ + Milk. </p> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/home/coffee-makers/philips-baristina-review</link>
                                                                            <description>
                            <![CDATA[ The Philips Baristina is a curious espresso machine, with a handheld portafilter yet a totally automated grinding and dosing system. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">CVW7DNBjaXvgJqB9dECYDK</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/JE2SiR75byHZm6XMWGCq3W-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Fri, 28 Aug 2026 09:52:38 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Coffee Makers]]></category>
                                                    <category><![CDATA[Home]]></category>
                                                    <category><![CDATA[Home Appliances]]></category>
                                                    <category><![CDATA[Kitchen & Dining]]></category>
                                                                                                <author><![CDATA[ erin.bashford@futurenet.com (Erin Bashford) ]]></author>                    <dc:creator><![CDATA[ Erin Bashford ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/rLvJvJVZx43hEzSsJy3BpL.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Erin Bashford is a senior reviews writer at Tom’s Guide. She has a Master’s in Broadcast and Digital Journalism from the University of East Anglia and 7 years of experience reviewing music and events for various publications. She has edited publications such as Outline Magazine’s Guide to Norwich, and she has written for a number of music magazines and websites such as Clash Magazine, Outline Magazine and Dork Magazine. She has a strong interest in audio gear and the music world. &lt;/p&gt;&lt;p&gt;As an ex-barista, Erin is passionate about coffee tech. She also loves finding the best cooking hacks and kitchen appliances, including her beloved Instant Pot. &lt;/p&gt;&lt;p&gt;In her spare time, you can find her reading, practising yoga, hiking, writing fantasy novels, or stressing over NYT Games.&lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/JE2SiR75byHZm6XMWGCq3W-1280-80.jpg">
                                                            <media:credit><![CDATA[Tom&amp;#39;s Guide]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[the philips baristina photographed against the blue tom&#039;s guide background]]></media:description>                                                            <media:text><![CDATA[the philips baristina photographed against the blue tom&#039;s guide background]]></media:text>
                                <media:title type="plain"><![CDATA[the philips baristina photographed against the blue tom&#039;s guide background]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/JE2SiR75byHZm6XMWGCq3W-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>The Philips Baristina is an interesting espresso machine. It’s an automatic, but also not quite an automatic. How does that work, I hear you ask? Let me explain. </p><p>So, while it grinds, doses, tamps, and brews without any input from you (aside from you clicking the shot button), you also have to empty the portafilter. Isn’t that the worst part of any manual machine? The coffee grounds always get stuck to my hands. Anyway, if you’re after an espresso machine that does <em>most</em> of the hard work for you, the Baristina could be ideal. </p><p>However, the espresso does taste pretty mid, and the price is about $200 more than I’d expect. So, could it be one of the <a href="https://www.tomsguide.com/home/coffee-makers/best-espresso-machines">best espresso machines</a>? Hm. I don’t think so. But want to find out the full story? Keep reading this Philips Baristina review.</p><h2 class="article-body__section" id="section-philips-baristina-review-specs"><span>Philips Baristina review: Specs</span></h2><div ><table><tbody><tr><td class="firstcol " ><p><strong>Price</strong></p></td><td  ><p><a href="https://www.amazon.com/Baristina-Espresso-Automatic-Portafilter-BAR302/dp/B0F6TQYRJV" target="_blank" rel="nofollow">$449-$529</a> / <a href="https://www.amazon.co.uk/Baristina-Automatic-Portafilter-BAR300-60/dp/B0GX61DZGS" target="_blank" rel="nofollow">£299-£379</a></p></td></tr><tr><td class="firstcol " ><p><strong>Weight</strong></p></td><td  ><p>11 pounds</p></td></tr><tr><td class="firstcol " ><p><strong>Dimensions</strong></p></td><td  ><p>15 x 7 x 13.6 inches</p></td></tr><tr><td class="firstcol " ><p><strong>Grinder</strong></p></td><td  ><p>Yes</p></td></tr><tr><td class="firstcol " ><p><strong>Heating system </strong></p></td><td  ><p>Unspecified </p></td></tr><tr><td class="firstcol " ><p><strong>Pressure </strong></p></td><td  ><p>16 bar</p></td></tr><tr><td class="firstcol " ><p><strong>Water tank capacity</strong></p></td><td  ><p>40.6 fluid ounces</p></td></tr><tr><td class="firstcol " ><p><strong>Accessories</strong></p></td><td  ><p>None</p></td></tr></tbody></table></div><h2 class="article-body__section" id="section-philips-baristina-review-price-availability"><span>Philips Baristina review: Price & availability</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.20%;"><img id="Ckgfg6oQ5wGpZnuVfNrcSW" name="Philips_Baristina_10" alt="the philips baristina photographed against the blue tom's guide background" src="https://cdn.mos.cms.futurecdn.net/Ckgfg6oQ5wGpZnuVfNrcSW.jpg" mos="" align="middle" fullscreen="" width="1920" height="1079" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The Philips Baristina is <a href="https://www.amazon.com/Baristina-Espresso-Automatic-Portafilter-BAR302/dp/B0F6TQYRJV" target="_blank" rel="nofollow">$449-$529 from Amazon U.S.</a> and <a href="https://www.amazon.co.uk/Baristina-Automatic-Portafilter-BAR300-60/dp/B0GX61DZGS" target="_blank" rel="nofollow">£299-£379 from Amazon U.K</a>. While this price is reasonable enough in the U.K., I would not recommend paying $529 if you’re in the U.S. You don’t even get a built-in milk frother — it looks and feels like a Nespresso Aeroccino standalone milk heater/frother. You can’t customize milk texture at all. </p><p>Even though I think the Baristina is overpriced, it’s an automatic machine, which means it’s always going to be pricier than manuals. However, I would wholeheartedly recommend spending just a little more for a genuinely decent machine. </p><p>Instead of spending $529 on what is effectively an espresso maker and a separate (cheap-feeling, one-trick-pony) milk frother, I’d spend $699 on the <a href="https://www.amazon.com/PHILIPS-Automatic-Espresso-Machine-LatteGo/dp/B0GZW8QCGM" target="_blank" rel="nofollow">Philips 2300 Series</a>, $799 on the <a href="https://www.tomsguide.com/home/coffee-makers/kitchenaid-kf2-review-this-fully-automatic-coffee-machine-effortlessly-takes-the-guesswork-out-of-your-morning-brew" target="_blank">KitchenAid KF2</a>, or, heck, even $379 on the <a href="https://www.tomsguide.com/home/coffee-makers/nespresso-citiz-aeroccino-review">Nespresso CitiZ + Aeroccino</a>. It’s a pod machine, sure, but honestly? It makes a better brew. </p><h2 class="article-body__section" id="section-philips-baristina-review-design"><span>Philips Baristina review: Design</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.20%;"><img id="y7T39v8dU9cq7iCocsQvLW" name="Philips_Baristina_9" alt="the philips baristina photographed against the blue tom's guide background" src="https://cdn.mos.cms.futurecdn.net/y7T39v8dU9cq7iCocsQvLW.jpg" mos="" align="middle" fullscreen="" width="1920" height="1079" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>So, I’m not a huge fan of how the Baristina looks. I think it looks incredibly cheap, like something that costs $200 rather than $530. When I found out how much it costs, I actually gasped. </p><p>While it doesn’t look <em>bad</em>, it does look <em>cheap</em>. Whether this is a dealbreaker will depend on your preferences. For me, I’d rather spend a little extra on the KitchenAid KF2 or just get a bog-standard manual like the $300 <a href="https://www.tomsguide.com/home/coffee-makers/sage-breville-bambino-review">Breville Bambino</a>. </p><p>You get a “portafilter”. I say “portafilter” because, yes, it’s technically a portafilter in that it has a handle and a basket where the coffee goes. But you can’t use it like a traditional portafilter — you don’t dose and tamp manually. All you have to do is push the portafilter over to the grinder side at the start of the brew and then sit back and relax. </p><p>While, yes, I <em>loved </em>watching the portafilter snap back into place after the grinder finished (it’s the simple things), I think this is more of a style gimmick than actual function. If you’re after a truly automatic machine, it might even be a major con. Yes, you have to empty and clean out the portafilter yourself. </p><h2 class="article-body__section" id="section-philips-baristina-review-espresso"><span>Philips Baristina review: Espresso</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.20%;"><img id="4aBpHB3mhJV5FmajBR7VjV" name="Philips_Baristina_6" alt="the philips baristina photographed against the blue tom's guide background" src="https://cdn.mos.cms.futurecdn.net/4aBpHB3mhJV5FmajBR7VjV.jpg" mos="" align="middle" fullscreen="" width="1920" height="1079" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>If you’re an espresso aficionado, you won’t want to read this. However, if you’re someone who prioritizes speed, ease of use, and simplicity, you’re the perfect candidate for a Baristina. </p><p>As it’s a bean-to-cup automatic — despite having a “portafilter” — you have very little input. Pour your beans in, press the espresso button, slide the portafilter to the grinder side (which is super fun), and you’ve done all the work. The machine snaps the portafilter into place hands-free, and, yes, this is mesmerizing to watch. I don’t care how lame that makes me; I enjoy watching a portafilter careen across a coffee machine like a stone from a slingshot. It’s novel. Sue me. </p><p>In terms of espresso flavor… it’s okay. It tastes incredibly average. I tried the machine with both artisan Ethiopian beans and your generic “strong” dark roast, and it tasted better with the latter. I’d recommend using cheaper, darker beans on this machine, as the excessive 16-bar pressure and the tiny (40mm) pressurized portafilter destroys any nuance anyway. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:3256px;"><p class="vanilla-image-block" style="padding-top:56.27%;"><img id="rtiKZ2LC6EDh7AA5Dtja4Y" name="philpis baristina espresso" alt="a photo of a drink made on the philips baristina espresso machine" src="https://cdn.mos.cms.futurecdn.net/rtiKZ2LC6EDh7AA5Dtja4Y.jpg" mos="" align="middle" fullscreen="" width="3256" height="1832" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Erin Bashford)</span></figcaption></figure><p>As you can see, this espresso shot is foamy and aerated, which means it was extracted under too much pressure. The crema is fluffy, but it dissipated within seconds. The first Ethiopian beans (which usually taste divine) were overly sour and astringent. However, the second generic Illy-brand beans resulted in a stronger, more palatable coffee taste. Of course, this won’t impress coffee nerds, but this isn’t a machine for coffee nerds. </p><p>Even so, I struggle to recommend this machine wholeheartedly considering you can get much better machines for just a little extra. The <a href="https://www.amazon.com/PHILIPS-Automatic-Espresso-Machine-LatteGo/dp/B0GZW8QCGM">Philips 2300</a> is a modest stretch at $699; the <a href="https://www.tomsguide.com/home/coffee-makers/kitchenaid-kf2-review-this-fully-automatic-coffee-machine-effortlessly-takes-the-guesswork-out-of-your-morning-brew">KitchenAid KF2</a> is $799. Considering these machines have built-in milk preparation and zero user input, I’d recommend them if you’re after a totally automatic machine. The espresso tastes much nicer. </p><h2 class="article-body__section" id="section-philips-baristina-review-grinder"><span>Philips Baristina review: Grinder</span></h2><p>While the Philips Baristina does have a built-in grinder and therefore demands a standalone ‘grinder’ section, this is going to be extremely short. </p><p>The grinder is not adjustable. Yes, you heard me correctly. Not adjustable. The grinder grinds to one size and one size only. Want it finer? Not possible. Coarser? Oh, again, you guessed it, not possible. </p><p>Other automatic machines such as the De’Longhi Rivelia have an adjustable grinder, and also the $699 manual bean-to-cup De’Longhi Arte Evo. If you’re interested in actually playing and experimenting with coffee, I’d recommend the Arte Evo over the Baristina. You’re paying an extra $150, but it’s often discounted to $599 (so just $50 more), and you get all the bonuses of a manual machine with the ease of an assisted tamping system. </p><h2 class="article-body__section" id="section-philips-baristina-review-milk"><span>Philips Baristina review: Milk</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1919px;"><p class="vanilla-image-block" style="padding-top:56.28%;"><img id="MfszB5jgQRneGjDEThJMeV" name="Philips_Baristina_11" alt="the philips baristina photographed against the blue tom's guide background" src="https://cdn.mos.cms.futurecdn.net/MfszB5jgQRneGjDEThJMeV.jpg" mos="" align="middle" fullscreen="" width="1919" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>As mentioned earlier, the Baristina comes in two variants: with milk frother and without milk frother. If you order the cheaper model, it won’t come with the frother. </p><p>Those familiar with something like the Nespresso Aeroccino will recognize this milk frother: the Philips model is essentially just your standard countertop model. It’s not particularly unique or innovative, but damn, it works. If it ain’t broke, don’t fix, right? </p><p>Here’s a photo of a milk drink made. Notice how I said “milk drink” rather than latte or cappuccino — the Baristina can only make one type of milk. No wet lattes or dry cappuccinos here. Milk or no milk only!</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:3464px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="5kq8rRgCmJq6oKjjjKcnxX" name="philpis baristina milk" alt="a photo of a drink made on the philips baristina espresso machine" src="https://cdn.mos.cms.futurecdn.net/5kq8rRgCmJq6oKjjjKcnxX.jpg" mos="" align="middle" fullscreen="" width="3464" height="1948" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Erin Bashford)</span></figcaption></figure><p>As you can see, the milk is extremely thick. Don’t get me wrong, the texture is satisfying, with well-distributed, evenly sized bubbles. However, this isn’t going to impress people who are used to barista-crafted beverages. It cannot make microfoam; therefore, drinks like lattes and flat whites are out of the question. You can only make cappuccinos. </p><h2 class="article-body__section" id="section-philips-baristina-review-storage-maintenance"><span>Philips Baristina review: Storage & maintenance</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1919px;"><p class="vanilla-image-block" style="padding-top:56.28%;"><img id="GXChiJ6pWNhcLoZd4fLDhV" name="Philips_Baristina_7" alt="the philips baristina photographed against the blue tom's guide background" src="https://cdn.mos.cms.futurecdn.net/GXChiJ6pWNhcLoZd4fLDhV.jpg" mos="" align="middle" fullscreen="" width="1919" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>Although 15 inches tall, the Philips Baristina feels a lot smaller. This height is solely due to the grinder hopper — its main body is more compact. Of course, you’d need to ensure you have space under your counters for the hopper, but the machine should take up less space than you think. </p><p>Due to this size, the machine has a teeny-tiny drip tray. I always recommend cleaning out your drip tray after every use, but in this case, it’s definitely a necessity. If you don’t clean it out every day, it’s going to overflow before you know it. </p><p>As with the rest of the machine, the drip tray is incredibly plasticky. This is one of my biggest complaints — a design this plasticky is pretty inexcusable when you’re charging $549 from an aesthetic and longevity perspective. </p><p>Speaking of longevity, you get a 2-year warranty as standard, which is the same as Breville, Ninja, and De’Longhi. </p><h2 class="article-body__section" id="section-philips-baristina-review-verdict"><span>Philips Baristina review: Verdict</span></h2><p>While I don’t think the Philips Baristina is the worst espresso machine I’ve ever used, I can’t recommend it wholeheartedly. Only a very specific user base should get this machine. If you can’t stretch to $699 for a Philips 2300 Series, you don’t mind mid-tasting espresso, you’re happy with one-size-fits-all milk texture, <em>and</em> you’re happy to spend $200 more than I think you should, then yes, this would be the machine for you. </p><p>All other people, though? You’d either be better off with the $699 Philips 2300 Series, the $799 KitchenAid KF2, or even venture into the world of manual bean-to-cups with the fantastic De’Longhi Arte Evo. </p><p>As I said earlier, if you want simplicity and ease of use over anything else, I’d even go as far to say you’re the perfect candidate for a Nespresso CitiZ + Milk. </p>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ These 15 Ninja deals are too good to miss ahead of Labor Day — save up to 40% on blenders, air fryers and more ]]></title>
                                                                                                <dc:content><![CDATA[ <p>Labor Day is almost here — and if you're hosting any backyard barbecues or celebrations, chances are you could use a little help. That's where Ninja comes into play! The kitchen appliance brand has everything you need to meal prep and get grilling! </p><p>Fortunately, <a href="https://www.amazon.com/stores/page/471F718E-0761-48DF-ABAF-0FC6590C695B" target="_blank" rel="nofollow">Amazon is closing out the summer with a bunch of Ninja appliance deals</a>. From high-quality blenders and air fryers to pizza ovens and grills, there are some discounts here that you definitely don't want to miss — especially since the best deals are currently up to 40% off.</p><p>I've been scouring the sale and have found the best cooking deals to help you in the kitchen this Labor Day and beyond. I've listed all my favorites below, so keep scrolling to check them out.</p><h3 class="article-body__section" id="section-quick-links"><span>Quick Links</span></h3><ul><li><a href="https://www.amazon.com/stores/page/471F718E-0761-48DF-ABAF-0FC6590C695B" target="_blank" rel="nofollow"><strong>shop all Ninja deals at Amazon</strong></a></li><li><strong>Ninja Blast Max: </strong><a href="https://www.amazon.com/dp/B0DB964918?" target="_blank" rel="nofollow"><strong>was $99 now $69</strong></a></li><li><strong>Ninja Iced Coffee Maker: </strong><a href="https://www.amazon.com/Ninja-Specialty-Single-Serve-Compatible-PB055ABL/dp/B0D1LNKN4Z?" target="_blank" rel="nofollow"><strong>was $129 now $99</strong></a></li><li><strong>Ninja Crispi 4-in-1 Portable Glass Air Fryer: </strong><a href="https://www.amazon.com/Ninja-Microwave-Dishwasher-Containers-FN101GY/dp/B0DDDD8WD6?" target="_blank" rel="nofollow"><strong>was $179 now $159</strong></a></li><li><strong>Ninja Double Oven, 12-in-1: </strong><a href="https://www.amazon.com/Ninja-DCT401-FlavorSeal-Convection-Stainless/dp/B0BRQS5BH6" target="_blank" rel="nofollow"><strong>was $379 now $219</strong></a></li><li><strong>Ninja Woodfire Oven & Smoker: </strong><a href="https://www.amazon.com/Ninja-Woodfire-Technology-terracotta-OO101/dp/B0C6BQVDX3/" target="_blank" rel="nofollow"><strong>was $399 now $279</strong></a></li><li><strong>Ninja Luxe Café Premier: </strong><a href="https://www.amazon.com/dp/B0FGDTHY1Y" target="_blank" rel="nofollow"><strong>now $599</strong></a></li><li><strong>Ninja FlexFlame Propane Grill: </strong><a href="https://www.amazon.com/Ninja-FlexFlame-Electric-Stainless-PG301/dp/B0GJ76517J" target="_blank" rel="nofollow"><strong>was $1,119 now $999</strong></a></li></ul><h3 class="article-body__section" id="section-ninja-deals"><span>Ninja Deals</span></h3><div class="product"><a data-dimension112="69b0fedc-a21f-11f1-8a6e-418eb9d3d485" data-action="Deal Block" data-label="Blast Max" data-dimension48="Blast Max" data-dimension25="$69" href="https://www.amazon.com/dp/B0DB964918?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1216px;"><p class="vanilla-image-block" style="padding-top:123.36%;"><img id="9Q4QY399FaozAFUt4j8dTW" name="ninja-blast-max-portable-blender--twist--bb517479-54ce-4a77-974c-58e2f44dde33.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/9Q4QY399FaozAFUt4j8dTW.jpg" mos="" align="middle" fullscreen="" width="1216" height="1500" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>The Ninja Blast Max is capable of taking on any challenge you throw at it, including crushing ice and blitzing berries to make yummy smoothies. It comes with multiple blend settings to make sure your blender is using the right level of power for the task at hand, and the compact size means it’s a great option for anyone with a small kitchen. <a class="view-deal button" href="https://www.amazon.com/dp/B0DB964918?" target="_blank" rel="nofollow" data-dimension112="69b0fedc-a21f-11f1-8a6e-418eb9d3d485" data-action="Deal Block" data-label="Blast Max" data-dimension48="Blast Max" data-dimension25="$69">View Deal</a></p></div><div class="product"><a data-dimension112="69b0ff4a-a21f-11f1-9b87-d7697e968c6e" data-action="Deal Block" data-label="Professional Blender" data-dimension48="Professional Blender" data-dimension25="$79" href="https://www.amazon.com/Ninja-BR201AMZ-Professional-Smoothies-Dishwasher-Safe/dp/B0GH8PVFHS?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:679px;"><p class="vanilla-image-block" style="padding-top:162.30%;"><img id="sFftzctqbej7oaSQLEtBRj" name="Ninja Pro Blender" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/sFftzctqbej7oaSQLEtBRj.jpg" mos="" align="middle" fullscreen="" width="679" height="1102" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Ninja-BR201AMZ-Professional-Smoothies-Dishwasher-Safe/dp/B0GH8PVFHS?" target="_blank" rel="nofollow" data-dimension112="69b0ff4a-a21f-11f1-9b87-d7697e968c6e" data-action="Deal Block" data-label="Professional Blender" data-dimension48="Professional Blender" data-dimension25="$79">Professional Blender: was $109 now $79</a></strong><br>Be it daily smoothies or making ice cream, this blender can tackle it all, at the touch of a button. Also featured on our <a href="https://www.tomsguide.com/best-picks/best-blenders">best blenders</a> guide, this comes with 3 preset Auto-iQ programs that creates smoothies, frozen drinks, and ice cream, and its powerful blades can crush ice in no time. This is a great deal if you want an easy-to-use blender, with professional results.  <a class="view-deal button" href="https://www.amazon.com/Ninja-BR201AMZ-Professional-Smoothies-Dishwasher-Safe/dp/B0GH8PVFHS?" target="_blank" rel="nofollow" data-dimension112="69b0ff4a-a21f-11f1-9b87-d7697e968c6e" data-action="Deal Block" data-label="Professional Blender" data-dimension48="Professional Blender" data-dimension25="$79">View Deal</a></p></div><div class="product"><a data-dimension112="69b0ffc2-a21f-11f1-b219-a33e5661b9bb" data-action="Deal Block" data-label="Air Fryer Pro 4-in-1" data-dimension48="Air Fryer Pro 4-in-1" data-dimension25="$89" href="https://www.amazon.com/dp/B0CSZ7WBYW" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:560px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="f49Q8qGkV5TG2EsuDo3or5" name="Ninja Air Fryer Pro 4 in 1" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/f49Q8qGkV5TG2EsuDo3or5.jpg" mos="" align="middle" fullscreen="" width="560" height="560" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>The Ninja Air Fryer Pro 4-in-1 is a versatile kitchen appliance that air fries, roasts, reheats, and dehydrates. With its 5-quart capacity, it cooks food quickly using hot air circulation, delivering crispy, healthier meals with little to no oil. That makes it <em>perfect </em>for everyday cooking and batch meal prep!<a class="view-deal button" href="https://www.amazon.com/dp/B0CSZ7WBYW" target="_blank" rel="nofollow" data-dimension112="69b0ffc2-a21f-11f1-b219-a33e5661b9bb" data-action="Deal Block" data-label="Air Fryer Pro 4-in-1" data-dimension48="Air Fryer Pro 4-in-1" data-dimension25="$89">View Deal</a></p></div><div class="product"><a data-dimension112="69b10030-a21f-11f1-87c3-c57969611a45" data-action="Deal Block" data-label="Pods & Grounds Specialty Single-Serve Iced Coffee Maker" data-dimension48="Pods & Grounds Specialty Single-Serve Iced Coffee Maker" data-dimension25="$99" href="https://www.amazon.com/Ninja-Specialty-Single-Serve-Compatible-PB055ABL/dp/B0D1LP9SF1?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:679px;"><p class="vanilla-image-block" style="padding-top:99.56%;"><img id="4uiaRXRKY8Go6F4ZpM7UdA" name="Ninja coffee" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/4uiaRXRKY8Go6F4ZpM7UdA.jpg" mos="" align="middle" fullscreen="" width="679" height="676" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Ninja-Specialty-Single-Serve-Compatible-PB055ABL/dp/B0D1LP9SF1?" target="_blank" rel="nofollow" data-dimension112="69b10030-a21f-11f1-87c3-c57969611a45" data-action="Deal Block" data-label="Pods & Grounds Specialty Single-Serve Iced Coffee Maker" data-dimension48="Pods & Grounds Specialty Single-Serve Iced Coffee Maker" data-dimension25="$99">Pods & Grounds Specialty Single-Serve Iced Coffee Maker: was $129 now $99</a></strong><br>This stylish Ninja coffee maker comes in a gorgeous Sage colorway and is now on sale for $30 off. Whether you prefer pods or grounds, this device makes tasty brews in 7 sizes (6-oz. to 24-oz) and has a built-in, fold-away milk frother!<a class="view-deal button" href="https://www.amazon.com/Ninja-Specialty-Single-Serve-Compatible-PB055ABL/dp/B0D1LP9SF1?" target="_blank" rel="nofollow" data-dimension112="69b10030-a21f-11f1-87c3-c57969611a45" data-action="Deal Block" data-label="Pods & Grounds Specialty Single-Serve Iced Coffee Maker" data-dimension48="Pods & Grounds Specialty Single-Serve Iced Coffee Maker" data-dimension25="$99">View Deal</a></p></div><div class="product"><a data-dimension112="69b100a8-a21f-11f1-9e18-95eb917f62af" data-action="Deal Block" data-label="BlendBOSS Blender" data-dimension48="BlendBOSS Blender" data-dimension25="$109" href="https://www.amazon.com/Ninja-BlendbossTM-Detachable-Technology-DB351CY/dp/B0FSGSYF79?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1500px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="JkaewDaMJCoHarzBbjk5u8" name="Ninja BlendBOSS deal block" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/JkaewDaMJCoHarzBbjk5u8.jpg" mos="" align="middle" fullscreen="" width="1500" height="1500" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Ninja-BlendbossTM-Detachable-Technology-DB351CY/dp/B0FSGSYF79?" target="_blank" rel="nofollow" data-dimension112="69b100a8-a21f-11f1-9e18-95eb917f62af" data-action="Deal Block" data-label="BlendBOSS Blender" data-dimension48="BlendBOSS Blender" data-dimension25="$109">BlendBOSS Blender: was $129 now $109</a></strong><br>The Ninja BlendBOSS is one of the best personal blenders we've used. In our <a href="https://www.tomsguide.com/home/home-appliances/ninja-blendboss-review">Ninja BlendBOSS review</a>, we said the Editor's Choice blender is great at everything from making hummus to lump-free smoothies. Its' compact, comes in a range of colors, and it's simply the best personal blender you can buy at this price point. <a class="view-deal button" href="https://www.amazon.com/Ninja-BlendbossTM-Detachable-Technology-DB351CY/dp/B0FSGSYF79?" target="_blank" rel="nofollow" data-dimension112="69b100a8-a21f-11f1-9e18-95eb917f62af" data-action="Deal Block" data-label="BlendBOSS Blender" data-dimension48="BlendBOSS Blender" data-dimension25="$109">View Deal</a></p></div><div class="product"><a data-dimension112="69b10120-a21f-11f1-8d7b-654bb46f6692" data-action="Deal Block" data-label="NeverClog Cold Press Juicer" data-dimension48="NeverClog Cold Press Juicer" data-dimension25="$129" href="https://www.amazon.com/dp/B0BR8HZL9V?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:522px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="pKMqdL3azKMYSNwdTHk4m9" name="Ninja Never Clog" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/pKMqdL3azKMYSNwdTHk4m9.jpg" mos="" align="middle" fullscreen="" width="522" height="522" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0BR8HZL9V?" target="_blank" rel="nofollow" data-dimension112="69b10120-a21f-11f1-8d7b-654bb46f6692" data-action="Deal Block" data-label="NeverClog Cold Press Juicer" data-dimension48="NeverClog Cold Press Juicer" data-dimension25="$129">NeverClog Cold Press Juicer: was $149 now $129</a></strong><br>Create healthy juices from the comforts of your home with the Ninja Cold Press Juicer Pro. It features a powerful high torque motor and includes two one-touch programs that make it easy to operate. We also like that it has a pulp control that allows you to customize your juice with pulp or without.<a class="view-deal button" href="https://www.amazon.com/dp/B0BR8HZL9V?" target="_blank" rel="nofollow" data-dimension112="69b10120-a21f-11f1-8d7b-654bb46f6692" data-action="Deal Block" data-label="NeverClog Cold Press Juicer" data-dimension48="NeverClog Cold Press Juicer" data-dimension25="$129">View Deal</a></p></div><div class="product"><a data-dimension112="69b10198-a21f-11f1-8c60-5be5d32ce5bf" data-action="Deal Block" data-label="Mega Kitchen System" data-dimension48="Mega Kitchen System" data-dimension25="$159" href="https://www.amazon.com/dp/B00939I7EK" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1676px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="sWibiMn9jcqpLxyQRazy6f" name="Ninja Amazon 2.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/sWibiMn9jcqpLxyQRazy6f.jpg" mos="" align="middle" fullscreen="" width="1676" height="1676" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B00939I7EK" target="_blank" rel="nofollow" data-dimension112="69b10198-a21f-11f1-8c60-5be5d32ce5bf" data-action="Deal Block" data-label="Mega Kitchen System" data-dimension48="Mega Kitchen System" data-dimension25="$159">Mega Kitchen System: was $219 now $159</a></strong><br>Leave all the multi-tasking in the kitchen to one appliance with this Ninja blender. With four functions for smoothies, processing, dough, drinks and more it will quickly become your go-to kitchen appliance. With this ultimate appliance, you’ll be enjoying fresh, healthy drinks, homemade bread and sweet bakes.<a class="view-deal button" href="https://www.amazon.com/dp/B00939I7EK" target="_blank" rel="nofollow" data-dimension112="69b10198-a21f-11f1-8c60-5be5d32ce5bf" data-action="Deal Block" data-label="Mega Kitchen System" data-dimension48="Mega Kitchen System" data-dimension25="$159">View Deal</a></p></div><div class="product"><a data-dimension112="69b10206-a21f-11f1-b6d6-d311f0210fc6" data-action="Deal Block" data-label="Crispi 4-in-1 Portable Glass Air Fryer" data-dimension48="Crispi 4-in-1 Portable Glass Air Fryer" data-dimension25="$159" href="https://www.amazon.com/Ninja-Microwave-Dishwasher-Containers-FN101GY/dp/B0DDDD8WD6?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:679px;"><p class="vanilla-image-block" style="padding-top:85.86%;"><img id="zNkXNCVYCubXhCRwjaoGPj" name="Ninjs Crispi" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/zNkXNCVYCubXhCRwjaoGPj.jpg" mos="" align="middle" fullscreen="" width="679" height="583" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Ninja-Microwave-Dishwasher-Containers-FN101GY/dp/B0DDDD8WD6?" target="_blank" rel="nofollow" data-dimension112="69b10206-a21f-11f1-b6d6-d311f0210fc6" data-action="Deal Block" data-label="Crispi 4-in-1 Portable Glass Air Fryer" data-dimension48="Crispi 4-in-1 Portable Glass Air Fryer" data-dimension25="$159">Crispi 4-in-1 Portable Glass Air Fryer: was $179 now $159</a></strong><br>The Ninja Crispi is one of Ninja's most interesting recent releases. It features a removable cooking lid and interchangeable glass containers to cook meals of a range of sizes. In our <a href="https://www.tomsguide.com/home/air-fryers/ninja-crispi-air-fryer-review">Ninja Crispi review</a>, it earned a well-deserved 4.5 stars.  <a class="view-deal button" href="https://www.amazon.com/Ninja-Microwave-Dishwasher-Containers-FN101GY/dp/B0DDDD8WD6?" target="_blank" rel="nofollow" data-dimension112="69b10206-a21f-11f1-b6d6-d311f0210fc6" data-action="Deal Block" data-label="Crispi 4-in-1 Portable Glass Air Fryer" data-dimension48="Crispi 4-in-1 Portable Glass Air Fryer" data-dimension25="$159">View Deal</a></p></div><div class="product"><a data-dimension112="69b1027e-a21f-11f1-b242-23fcfb084303" data-action="Deal Block" data-label="Double Oven, 12-in-1" data-dimension48="Double Oven, 12-in-1" data-dimension25="$219" href="https://www.amazon.com/Ninja-DCT401-FlavorSeal-Convection-Stainless/dp/B0BRQS5BH6" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:875px;"><p class="vanilla-image-block" style="padding-top:85.60%;"><img id="LQBDeKyzWKbLWRQgh54YmA" name="Double Oven, 12-in-1 DCT401" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/LQBDeKyzWKbLWRQgh54YmA.jpg" mos="" align="middle" fullscreen="" width="875" height="749" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Ninja-DCT401-FlavorSeal-Convection-Stainless/dp/B0BRQS5BH6" target="_blank" rel="nofollow" data-dimension112="69b1027e-a21f-11f1-b242-23fcfb084303" data-action="Deal Block" data-label="Double Oven, 12-in-1" data-dimension48="Double Oven, 12-in-1" data-dimension25="$219">Double Oven, 12-in-1: was $379 now $219</a></strong><br>We couldn’t recommend this toaster oven more. Although it has since been replaced by a newer model, the DCT401 is a previous winner on our list of the <a href="https://www.tomsguide.com/best-picks/best-toaster-ovens">best toaster ovens</a>. We love that it divides into two ovens you can access separately via the FlexDoor, so you can cook two things at once. There are 12 functions overall, including toast, bake, whole roast, air fry, convection and pizza — meaning you can cook pretty much anything in there however you like.<a class="view-deal button" href="https://www.amazon.com/Ninja-DCT401-FlavorSeal-Convection-Stainless/dp/B0BRQS5BH6" target="_blank" rel="nofollow" data-dimension112="69b1027e-a21f-11f1-b242-23fcfb084303" data-action="Deal Block" data-label="Double Oven, 12-in-1" data-dimension48="Double Oven, 12-in-1" data-dimension25="$219">View Deal</a></p></div><div class="product"><a data-dimension112="69b102ec-a21f-11f1-9afb-01ba23bf4691" data-action="Deal Block" data-label="Foodi XL Pro Air Fry Oven, 10-in-1" data-dimension48="Foodi XL Pro Air Fry Oven, 10-in-1" data-dimension25="$229" href="https://www.amazon.com/Ninja-DT201-Countertop-Convection-Dehydrate/dp/B08BXX69K4" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1500px;"><p class="vanilla-image-block" style="padding-top:75.80%;"><img id="sFc44K8P9eTgsrZ4Kc25oB" name="Foodi XL Pro Air Fry Oven, 10-in-1" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/sFc44K8P9eTgsrZ4Kc25oB.jpg" mos="" align="middle" fullscreen="" width="1500" height="1137" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Ninja-DT201-Countertop-Convection-Dehydrate/dp/B08BXX69K4" target="_blank" rel="nofollow" data-dimension112="69b102ec-a21f-11f1-9afb-01ba23bf4691" data-action="Deal Block" data-label="Foodi XL Pro Air Fry Oven, 10-in-1" data-dimension48="Foodi XL Pro Air Fry Oven, 10-in-1" data-dimension25="$229">Foodi XL Pro Air Fry Oven, 10-in-1: was $379 now $229</a></strong><br>40% off is one of the biggest Ninja discounts you'll find right now. While this XL air fryer/oven takes up a lot of space, it offers plenty of cooking functions and perfect cooking results every time. <a class="view-deal button" href="https://www.amazon.com/Ninja-DT201-Countertop-Convection-Dehydrate/dp/B08BXX69K4" target="_blank" rel="nofollow" data-dimension112="69b102ec-a21f-11f1-9afb-01ba23bf4691" data-action="Deal Block" data-label="Foodi XL Pro Air Fry Oven, 10-in-1" data-dimension48="Foodi XL Pro Air Fry Oven, 10-in-1" data-dimension25="$229">View Deal</a></p></div><div class="product"><a data-dimension112="69b10364-a21f-11f1-85ce-a5e1ab8f06dc" data-action="Deal Block" data-label="Woodfire ProConnect Premium XL Outdoor 7-in-1 Grill & Smoker" data-dimension48="Woodfire ProConnect Premium XL Outdoor 7-in-1 Grill & Smoker" data-dimension25="$242" href="https://www.amazon.com/Ninja-Woodfire-Functionality-Authentic-OG301/dp/B0DZF2DV3T?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1429px;"><p class="vanilla-image-block" style="padding-top:104.97%;"><img id="zyLJdnsjZA39kWuyNGm55G" name="Woodire outdoor and grill" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/zyLJdnsjZA39kWuyNGm55G.jpg" mos="" align="middle" fullscreen="" width="1429" height="1500" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Ninja-Woodfire-Functionality-Authentic-OG301/dp/B0DZF2DV3T?" target="_blank" rel="nofollow" data-dimension112="69b10364-a21f-11f1-85ce-a5e1ab8f06dc" data-action="Deal Block" data-label="Woodfire ProConnect Premium XL Outdoor 7-in-1 Grill & Smoker" data-dimension48="Woodfire ProConnect Premium XL Outdoor 7-in-1 Grill & Smoker" data-dimension25="$242">Woodfire ProConnect Premium XL Outdoor 7-in-1 Grill & Smoker: was $349 now $242</a></strong><br>You can score almost $100 off this Ninja outdoor grill and smoker right now. This smart grill lets you monitor cooking progress from your phone, which is great if you're juggling multiple dishes at once during a cookout! Be sure to apply the on-page coupon.<a class="view-deal button" href="https://www.amazon.com/Ninja-Woodfire-Functionality-Authentic-OG301/dp/B0DZF2DV3T?" target="_blank" rel="nofollow" data-dimension112="69b10364-a21f-11f1-85ce-a5e1ab8f06dc" data-action="Deal Block" data-label="Woodfire ProConnect Premium XL Outdoor 7-in-1 Grill & Smoker" data-dimension48="Woodfire ProConnect Premium XL Outdoor 7-in-1 Grill & Smoker" data-dimension25="$242">View Deal</a></p></div><div class="product"><a data-dimension112="69b103d2-a21f-11f1-9608-5fa98b37418f" data-action="Deal Block" data-label="Woodfire Oven & Smoker" data-dimension48="Woodfire Oven & Smoker" data-dimension25="$279" href="https://www.amazon.com/Ninja-Woodfire-Technology-terracotta-OO101/dp/B0C6BQVDX3/" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1500px;"><p class="vanilla-image-block" style="padding-top:90.20%;"><img id="C5KWDYUzjspNSP6tT8AAQP" name="81IeXOFExqL._AC_SL1500_.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/C5KWDYUzjspNSP6tT8AAQP.jpg" mos="" align="middle" fullscreen="" width="1500" height="1353" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>The Ninja Woodfire Oven & Smoker is a favorite with the Tom's Guide team. It makes amazing pizzas, smoked wings and many things in between. It's perfect to keep the summer vibes going all year long with delicious dishes.<a class="view-deal button" href="https://www.amazon.com/Ninja-Woodfire-Technology-terracotta-OO101/dp/B0C6BQVDX3/" target="_blank" rel="nofollow" data-dimension112="69b103d2-a21f-11f1-9608-5fa98b37418f" data-action="Deal Block" data-label="Woodfire Oven & Smoker" data-dimension48="Woodfire Oven & Smoker" data-dimension25="$279">View Deal</a></p></div><div class="product"><a data-dimension112="69b1044a-a21f-11f1-8f9c-c9e6b35d6a60" data-action="Deal Block" data-label="Fireside360 Outdoor Heater and Firepit" data-dimension48="Fireside360 Outdoor Heater and Firepit" data-dimension25="$404" href="https://www.amazon.com/Ninja-Fireside360-Fire-Heater-Modes/dp/B0GWFP3T3N?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:889px;"><p class="vanilla-image-block" style="padding-top:168.73%;"><img id="hCnMFizeFWLfCRyTyyFyuc" name="Ninja fireside" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/hCnMFizeFWLfCRyTyyFyuc.jpg" mos="" align="middle" fullscreen="" width="889" height="1500" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Ninja-Fireside360-Fire-Heater-Modes/dp/B0GWFP3T3N?" target="_blank" rel="nofollow" data-dimension112="69b1044a-a21f-11f1-8f9c-c9e6b35d6a60" data-action="Deal Block" data-label="Fireside360 Outdoor Heater and Firepit" data-dimension48="Fireside360 Outdoor Heater and Firepit" data-dimension25="$404">Fireside360 Outdoor Heater and Firepit: was $499 now $404</a></strong><br>The newly-launched Fireside360 is a smokeless firepit and heater in one neat unit. There are three heat modes, you can feel the warmth up to 13ft. away, and since its powered by propane, there's nothing to clean away. Be sure to apply the on-page coupon to get this price.<a class="view-deal button" href="https://www.amazon.com/Ninja-Fireside360-Fire-Heater-Modes/dp/B0GWFP3T3N?" target="_blank" rel="nofollow" data-dimension112="69b1044a-a21f-11f1-8f9c-c9e6b35d6a60" data-action="Deal Block" data-label="Fireside360 Outdoor Heater and Firepit" data-dimension48="Fireside360 Outdoor Heater and Firepit" data-dimension25="$404">View Deal</a></p></div><div class="product"><a data-dimension112="69b104c2-a21f-11f1-a622-75b3da269b63" data-action="Deal Block" data-label="Luxe Café Premier" data-dimension48="Luxe Café Premier" data-dimension25="$599" href="https://www.amazon.com/dp/B0FGDTHY1Y" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:541px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="HcnQ36qmUJg5VJidxsJ76X" name="Ninja Luxe Cafe.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/HcnQ36qmUJg5VJidxsJ76X.jpg" mos="" align="middle" fullscreen="" width="541" height="541" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>It's not on sale, but the Ninja Luxe Café Premier is just that good. This 3-in-1 coffee machine brews quality espresso, drip coffee, and fast cold brew using its Barista Assist technology, an integrated grinder, and weight-based dosing. Plus, it makes creating pro-level microfoam easy, thanks to its Dual Froth system. Our reviewer called it "the best beginner-friendly espresso machine I’ve ever tested" in our <a href="https://www.tomsguide.com/home/ninja-luxe-cafe-premier-series-espresso-machine-review" data-dimension112="69b104c2-a21f-11f1-a622-75b3da269b63" data-action="Deal Block" data-label="Luxe Café Premier" data-dimension48="Luxe Café Premier" data-dimension25="$599">Ninja Luxe Café coffee maker review</a>.<a class="view-deal button" href="https://www.amazon.com/dp/B0FGDTHY1Y" target="_blank" rel="nofollow" data-dimension112="69b104c2-a21f-11f1-a622-75b3da269b63" data-action="Deal Block" data-label="Luxe Café Premier" data-dimension48="Luxe Café Premier" data-dimension25="$599">View Deal</a></p></div><div class="product"><a data-dimension112="69b10530-a21f-11f1-8a88-1d69015b22f5" data-action="Deal Block" data-label="FlexFlame Propane Grill" data-dimension48="FlexFlame Propane Grill" data-dimension25="$999" href="https://www.amazon.com/Ninja-FlexFlame-Electric-Stainless-PG301/dp/B0GJ76517J" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1490px;"><p class="vanilla-image-block" style="padding-top:100.67%;"><img id="anfQB46xz27Fy6KWn9ysqX" name="Ninja Flexflame" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/anfQB46xz27Fy6KWn9ysqX.jpg" mos="" align="middle" fullscreen="" width="1490" height="1500" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Ninja-FlexFlame-Electric-Stainless-PG301/dp/B0GJ76517J" target="_blank" rel="nofollow" data-dimension112="69b10530-a21f-11f1-8a88-1d69015b22f5" data-action="Deal Block" data-label="FlexFlame Propane Grill" data-dimension48="FlexFlame Propane Grill" data-dimension25="$999">FlexFlame Propane Grill: was $1119 now $999</a></strong><br>The Ninja FlexFlame is Ninja's first attempt at a propane grill, and it offers all the ingeniuity you'd expect from a Ninja product. It's got a pellet chamber to infuse your food with an authentic smoked flavor, but can also sear and even be converted to a griddle with the use of add-ons.<a class="view-deal button" href="https://www.amazon.com/Ninja-FlexFlame-Electric-Stainless-PG301/dp/B0GJ76517J" target="_blank" rel="nofollow" data-dimension112="69b10530-a21f-11f1-8a88-1d69015b22f5" data-action="Deal Block" data-label="FlexFlame Propane Grill" data-dimension48="FlexFlame Propane Grill" data-dimension25="$999">View Deal</a></p></div><h3 class="article-body__section" id="section-more-deals"><span>More Deals</span></h3><div class="vizualizer-embed"><div class="tg-df-widget-host" data-widget-config="?search=Home+Appliances&brands=Ninja%2CShark&min_discount_ratio=0.95&offer_type=all&view_mode=carousel&widget_title=Top+Deals+Handpicked+by+Our+Editors&widget_subtitle=Discover+the+best+discounts+currently+available%2C+curated+daily+by+the+Tom%27s+Guide+Savings+Squad.&bg_color=light_blue" data-vizualizer-embed="true"></div>    <script>    /**     * Tom's Guide Deals Finder - Vanilla JS Encapsulated Engine     */    (function() {      // --- Freyr Analytics Adapter ---      function initAnalytics() {        window.dataLayer = window.dataLayer || [];        window.googletag = window.googletag || {};        window.googletag.cmd = window.googletag.cmd || [];        window.hawk = window.hawk || { analytics: { freyr: [] } };        window.hawk.analytics = window.hawk.analytics || { freyr: [] };        window.hawk.analytics.freyr = window.hawk.analytics.freyr || [];        window.freyr = window.freyr || { cmd: [] };        const scriptSrc = 'https://freyr.futurecdn.net/freyr.js';        const hostname = typeof window !== 'undefined' ? window.location.hostname : '';        const isTestEnv = typeof window.navigator !== 'undefined' && (window.navigator.webdriver || window.navigator.userAgent.includes('Headless'));        const shouldSendRealAnalytics = !isTestEnv && hostname && hostname !== 'localhost' && hostname !== '127.0.0.1' && !hostname.includes('run.app');        if (shouldSendRealAnalytics && !document.querySelector(`script[src="${scriptSrc}"]`)) {          const script = document.createElement('script');          script.src = scriptSrc;          script.async = true;          document.head.appendChild(script);        }      }      function storeEventForDebug(name, data) {        if (!window.hawk || !window.hawk.analytics || !window.hawk.analytics.freyr) return;        window.hawk.analytics.freyr.push({ name, data });        try {          if (typeof window !== 'undefined' && window.localStorage) {            window.localStorage.setItem("hawk", JSON.stringify(window.hawk));          }        } catch (e) {          // Ignore storage issues        }        try {          window.dispatchEvent(new CustomEvent("hawk-analytics-update"));        } catch (e) {}      }      function sendToFreyr(eventName, data) {        if (typeof window === 'undefined') return;        window.freyr = window.freyr || { cmd: [] };        window.freyr.cmd.push(() => {          if (window.freyr && window.freyr.pushAndUpdate) {            window.freyr.pushAndUpdate(eventName, data);          }        });      }      function sendEvent(event, skip = false) {        try {          storeEventForDebug(event.name, event.data);          if (!skip) {            sendToFreyr(event.name, event.data);          }        } catch (e) {          // Ensure tracking errors don't surface to the user        }      }      function getCookie(name) {        try {          const match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));          return match ? match[2] : null;        } catch (e) {          return null;        }      }      function normalizeCurrency(symbol) {        const map = {          '£': 'GBP',          '$': 'USD',          'A$': 'AUD',          'CA$': 'CAD',          '€': 'EUR'        };        return map[symbol] || symbol;      }      function trackElementInteraction(props) {        sendEvent({          name: 'elementInteraction',          data: {            element: {              action: props.action || "click",              id: props.id || undefined,              class: props.class || undefined,              name: props.name || undefined,              text: props.text || undefined,              label: props.label || undefined,              container: props.container || undefined,              url: props.url || undefined,              articleId: props.articleId || undefined            }          }        });      }      function generateRevenueId(url, productName, merchantName, modelId) {        const str = `${window.location.href}|${productName}|${merchantName}|${modelId || ''}|${new Date().toDateString()}|tomsguide`;        let hash = 0;        for (let i = 0; i < str.length; i++) {          const char = str.charCodeAt(i);          hash = ((hash << 5) - hash) + char;          hash = hash & hash;        }        let numericStr = Math.abs(hash).toString();        while (numericStr.length < 19) {          numericStr += Math.floor(Math.random() * 10).toString();        }        return numericStr.substring(0, 19);      }      function rewriteAffiliateLink(url, territory, revenueId) {        if (!url) return url;        const t = (territory || 'gb').toLowerCase();        return url.replace(/hawk-custom-tracking/g, `tomsguide-${t}-${revenueId}`);      }      function trackHawkEvent(params) {        const { clickType, widgetId, productCategoryName, product, productsArray, zeroBasedProductIndexOrNull, totalDealsOrProducts, areaClicked, merchant, revenueId, isoCurrencyCode, queryName, widgetTypeName } = params;        const data = {          event: "hawkEvent",          category: "Affiliates",          affiliate: {            action: {              type: clickType,              id: widgetId,              event: clickType === "appeared" ? "viewed" : "Click from",              timestamp: Date.now()            },            component: {              flag: "Editor",              product: productCategoryName || "deals",              category: `Signal Deal Finder ${widgetTypeName || "Carousel"} widget`,              type: clickType === "appeared" ? "review" : "signal product",              label: queryName || (product ? (product.name || "") : ""),              index: zeroBasedProductIndexOrNull === null || zeroBasedProductIndexOrNull === undefined ? -1 : zeroBasedProductIndexOrNull,              linkCount: totalDealsOrProducts || 0,              blockLayout: "",              areaClicked: areaClicked || ""            }          },          products: productsArray || (product && merchant ? [            {              product: {                primary: {                  id: product.id || product.matchId || null,                  name: product.name,                  type: "deal",                  price: product.price,                  previousPrice: product.previousPrice || null,                  currency: isoCurrencyCode || "USD",                  preorder: false,                  labels: [],                  link: product.link,                  originalLink: product.originalLink || null,                  revenueId: revenueId || null,                  startTime: null,                  endTime: null,                  voucherCode: null,                  voucherAudience: null,                  voucherPercentageSaving: null,                  voucherMoneySaving: null,                  voucherType: null,                  offerExclusive: false,                  offerScope: null,                  globalId: product.globalId || null,                  inStock: product.inStock !== false,                  contractProvider: null,                  contractMinutes: null,                  contractTexts: null,                  contractData: null,                  contractLength: null,                  contractMonthlyPrice: null,                  contractCurrency: isoCurrencyCode || "USD"                }              },              merchant: {                id: merchant.id || null,                name: merchant.name,                url: merchant.url || null,                network: merchant.network || null              },              model: {                id: product.modelId || null,                brand: product.brand || null,                name: product.name,                parent: product.parent || null              }            }          ] : []),          reviews: [],          _clear: true,          "gtm.uniqueEventId": Date.now() % 10000        };        sendEvent({ name: 'hawkEvent', data });      }      function trackDealClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Product Card" });      }      function trackViewSimilarClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Product Card View Similar" });      }      function trackPriceComparisonClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Price Comparison" });      }      function trackReviewClick(params) {        trackHawkEvent({ ...params, clickType: "review", areaClicked: "Signal Product Card Review Link" });      }      function trackShare(params) {        trackHawkEvent({ ...params, clickType: "share", areaClicked: "Signal Product Card Share" });      }      function trackDealsAppeared(widgetId, deals, revenueId, currency, queryName, widgetTypeName) {         if (!deals || deals.length === 0) return;                  const productsArray = deals.slice(0, 50).map((deal) => {            let voucherPct = null;            let rawPrice = parseFloat(deal.rawPrice) || parseFloat(deal.price) || null;            let rawMsrp = parseFloat(deal.rawMsrp) || parseFloat(deal.msrp) || null;            if (rawMsrp > rawPrice && rawPrice > 0) {              voucherPct = Math.round((1 - (rawPrice / rawMsrp)) * 100);            }            let numId = null;            if (deal.externalProductId && !isNaN(parseInt(deal.externalProductId))) {              numId = parseInt(deal.externalProductId);            } else if (deal.id && !isNaN(parseInt(deal.id))) {              numId = parseInt(deal.id);            } else {              numId = deal.matchId || null;            }            return {              product: {                primary: {                  id: numId,                  name: deal.productName || deal.title || "",                  type: "deal",                  price: rawPrice,                  previousPrice: rawMsrp,                  currency: currency || 'USD',                  preorder: false,                  labels: deal.modelBrand || deal.brand ? [                     { type: "brand", value: deal.modelBrand || deal.brand }                  ] : [],                  link: deal.url,                  originalLink: deal.url,                  revenueId: revenueId || null,                  startTime: null,                  endTime: null,                  voucherCode: null,                  voucherAudience: null,                  voucherPercentageSaving: voucherPct,                  voucherMoneySaving: null,                  voucherType: null,                  offerExclusive: false,                  offerScope: null,                  globalId: deal.productKey || null,                  inStock: deal.inStock !== false,                  contractProvider: null,                  contractMinutes: null,                  contractTexts: null,                  contractData: null,                  contractLength: null,                  contractMonthlyPrice: null,                  contractCurrency: currency || 'USD'                }              },              merchant: {                id: deal.merchantId ? parseInt(deal.merchantId) : null,                name: deal.merchant || "Retailer",                url: deal.merchantUrl || null,                network: deal.merchantNetwork || null              },              model: {                id: deal.modelId ? parseInt(deal.modelId) : null,                brand: deal.modelBrand || deal.brand || null,                name: deal.productName || deal.title || "",                parent: deal.modelParent || null              }            };         });                  trackHawkEvent({             clickType: "appeared",             widgetId: widgetId,             productCategoryName: "deals",             zeroBasedProductIndexOrNull: null,             totalDealsOrProducts: deals.length,             productsArray: productsArray,             queryName: queryName,             widgetTypeName: widgetTypeName         });      }      // 1. Setup Shadow DOM Sandbox      const currentScript = document.currentScript;      let hostContainer = null;      let template = null;            if (currentScript) {        let prev = currentScript.previousElementSibling;        while (prev) {          if (prev.tagName === 'TEMPLATE' && prev.classList.contains('tg-df-widget-template')) {            template = prev;          } else if (prev.tagName === 'DIV' && prev.classList.contains('tg-df-widget-host') && !prev.hasAttribute('data-initialized')) {            hostContainer = prev;            break;          }          prev = prev.previousElementSibling;        }      }            // Fallbacks in case script is deferred      if (!hostContainer) {        const hosts = document.querySelectorAll('.tg-df-widget-host:not([data-initialized])');        if (hosts.length > 0) hostContainer = hosts[0];      }            // Safely embedded template for CMS environments      const rawTemplate = `  \x3Cstyle>    /* --- Shadow DOM Base Reset --- */    *, *::before, *::after {      box-sizing: border-box;    }    img, picture, svg, video {      max-width: 100%;      height: auto;      display: block;    }    /*       1. Scoped CSS for Tom's Guide Deals Widget       All classes are prefixed with \`tg-df-\` to prevent CMS style leakage.    */    .tg-df-container {      container-type: inline-size;      container-name: tg-df;      --tg-df-blue: #1F69FF;      --tg-df-blue-hover: #004d8c;      --tg-df-text: #222222;      --tg-df-text-muted: #555555;      --tg-df-bg: #ffffff;      --tg-df-bg-secondary: #f4f4f4;      --tg-df-border: #e2e8f0;      font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;      color: var(--tg-df-text);      background-color: transparent;       width: 100%;      max-width: 1200px;      margin: 0 auto;      padding-bottom: 24px;    }    .tg-df-container *, .tg-df-container *::before, .tg-df-container *::after {      margin: 0;      padding: 0;      box-sizing: border-box;    }    .tg-df-container img {      border: none;      margin: 0;      padding: 0;    }    .tg-df-container a {      text-decoration: none;      color: inherit;    }    /*       2. Search & Filter Bar    */    .tg-df-controls {      display: flex;      flex-direction: column;      align-items: center;      gap: 20px;      margin-bottom: 32px;      width: 100%;    }    .tg-df-top-bar {      display: flex;      width: 100%;      max-width: 760px;      gap: 12px;      align-items: center;    }    .tg-df-search-wrapper {      position: relative;      flex: 1;      width: 100%;      box-shadow: 0 8px 24px rgba(0,0,0,0.06);      border-radius: 40px;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      z-index: 100;    }    .tg-df-autocomplete-dropdown {      position: absolute;      top: calc(100% + 4px);      left: 0;      right: 0;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 12px;      box-shadow: 0 8px 32px rgba(0,0,0,0.12);      max-height: 300px;      overflow-y: auto;      z-index: 200;      display: none;    }    .tg-df-autocomplete-dropdown.active {      display: block;    }    .tg-df-autocomplete-item {      padding: 12px 24px;      cursor: pointer;      font-size: 14px;      color: var(--tg-df-text);      transition: background 0.1s ease;    }    .tg-df-autocomplete-item:hover {      background: var(--tg-df-bg-secondary);    }    .tg-df-search-input {      width: 100%;      padding: 16px 64px 16px 24px;      font-size: 16px;      border: 2px solid transparent;      border-radius: 40px;      outline: none;      transition: border-color 0.2s ease, box-shadow 0.2s ease;      color: var(--tg-df-text);      background: transparent;    }    .tg-df-search-input:focus {      border-color: transparent;      box-shadow: 0 0 0 3px rgba(0, 108, 196, 0.15);    }    .tg-df-search-input::placeholder {      color: #999999;    }        .tg-df-search-btn {      position: absolute;      right: 8px;      top: 50%;      transform: translateY(-50%);      width: 40px;      height: 40px;      border-radius: 50%;      background: #222;      border: none;      display: flex;      align-items: center;      justify-content: center;      cursor: pointer;      transition: background 0.2s ease;    }        .tg-df-search-btn:hover {      background: #000;    }    .tg-df-search-icon {      width: 16px;      height: 16px;      fill: #fff;    }    .tg-df-settings-wrapper {      position: relative;    }        .tg-df-settings-btn {      width: 48px;      height: 48px;      border-radius: 50%;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      box-shadow: 0 4px 12px rgba(0,0,0,0.04);      display: flex;      align-items: center;      justify-content: center;      cursor: pointer;      transition: all 0.2s ease;      color: var(--tg-df-text-muted);      flex-shrink: 0;    }    .tg-df-settings-btn:hover {      background: var(--tg-df-bg-secondary);      border-color: #0000ff;      color: var(--tg-df-text);    }    .tg-df-settings-btn svg {      width: 24px;      height: 24px;      fill: currentColor;    }    .tg-df-settings-dropdown {      position: absolute;      top: calc(100% + 8px);      right: 0;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 12px;      box-shadow: 0 8px 32px rgba(0,0,0,0.12);      width: 280px;      padding: 20px;      display: none;      z-index: 100;      flex-direction: column;      gap: 20px;    }    .tg-df-settings-dropdown.active {      display: flex;    }        .tg-df-settings-dropdown-backdrop {      display: none;      position: fixed;      inset: 0;      z-index: 99;    }        .tg-df-settings-dropdown-backdrop.active {      display: block;    }    .tg-df-setting-item {      display: flex;      flex-direction: column;      gap: 10px;    }    .tg-df-setting-label {      font-size: 11px;      font-weight: 700;      color: var(--tg-df-text-muted);      text-transform: uppercase;      letter-spacing: 0.5px;    }        .tg-df-region-select {        padding: 10px 12px;        border-radius: 8px;        border: 1px solid var(--tg-df-border);        font-size: 15px;        outline: none;        background: var(--tg-df-bg-secondary);        color: var(--tg-df-text);        cursor: pointer;        width: 100%;    }    .tg-df-toggle {        position: relative;        display: inline-block;        width: 44px;        height: 24px;        flex-shrink: 0;    }    .tg-df-toggle input {        opacity: 0;        width: 0;        height: 0;    }    .tg-df-slider {        position: absolute;        cursor: pointer;        top: 0; left: 0; right: 0; bottom: 0;        background-color: #ccc;        transition: .2s;        border-radius: 24px;    }    .tg-df-slider:before {        position: absolute;        content: "";        height: 18px;        width: 18px;        left: 3px;        bottom: 3px;        background-color: white;        transition: .2s;        border-radius: 50%;    }    .tg-df-toggle input:checked + .tg-df-slider {        background-color: #1F69FF;    }    .tg-df-toggle input:checked + .tg-df-slider:before {        transform: translateX(20px);    }    .tg-df-dl-row {        flex-direction: row;        align-items: center;        justify-content: space-between;    }    .tg-df-dl-row-text {        font-size: 14px;        font-weight: 600;        color: var(--tg-df-text);    }    .tg-df-dl-row-subtext {        font-size: 12px;        font-weight: 400;        line-height: 1.3;        color: var(--tg-df-text-muted);        margin-top: 4px;        display: block;    }    .tg-df-filters {      display: flex;      gap: 12px;      justify-content: center;      flex-wrap: wrap;    }    .tg-df-sort-wrapper {      position: relative;      display: flex;      align-items: center;    }        .tg-df-sort-icon {      position: absolute;      left: 14px;      width: 14px;      height: 14px;      fill: var(--tg-df-text-muted);      pointer-events: none;    }    .tg-df-sort-select, .tg-df-filter-select {      padding: 10px 36px 10px 38px;      font-size: 14px;      border: 1px solid var(--tg-df-border);      border-radius: 100px;      outline: none;      appearance: none;      background-color: var(--tg-df-bg-secondary);      background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 12 12'%3E%3Cpath fill='%23555555' d='M6 8L1 3h10z'/%3E%3C/svg%3E");      background-repeat: no-repeat;      background-position: right 14px center;      color: var(--tg-df-text);      cursor: pointer;      font-weight: 500;      transition: all 0.2s ease;    }        .tg-df-price-input::-webkit-outer-spin-button,    .tg-df-price-input::-webkit-inner-spin-button {      -webkit-appearance: none;      margin: 0;    }    .tg-df-price-input {      -moz-appearance: textfield;    }    .tg-df-sort-select:hover, .tg-df-filter-select:hover {      background-color: #e2e8f0;    }    .tg-df-multiselect-container {      position: relative;    }        .tg-df-multiselect-trigger {      display: block;      background: #fff;      user-select: none;      width: 100%;      overflow: hidden;      white-space: nowrap;      text-overflow: ellipsis;    }        .tg-df-multiselect-dropdown {      display: none;      position: absolute;      top: calc(100% + 4px);      left: 0;      width: 100%;      min-width: 220px;      max-height: 300px;      overflow-y: auto;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 8px;      box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);      z-index: 100;      padding: 8px 0;    }    .tg-df-multiselect-dropdown.active {      display: block;    }    .tg-df-ms-option {      padding: 8px 16px;      display: flex;      align-items: center;      gap: 8px;      cursor: pointer;      font-size: 14px;    }    .tg-df-ms-option:hover {      background-color: var(--tg-df-bg-secondary);    }        .tg-df-ms-option input {      cursor: pointer;      accent-color: #1f69ff;    }    .tg-df-sort-select:focus, .tg-df-filter-select:focus {      border-color: #0000ff;      box-shadow: 0 0 0 3px rgba(0, 0, 255, 0.2);      background-color: var(--tg-df-bg);    }    /*       3. Deal Grid Layout    */    .tg-df-grid.tg-df-grid-auto {      padding-top: 24px;    }    .tg-df-grid, .tg-df-grid.layout-grid {      display: grid;      grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));      gap: 10px;    }    .tg-df-grid.layout-row {      grid-template-columns: 1fr;      gap: 16px;    }        .tg-df-grid.layout-row .tg-df-card {      flex-direction: row;      align-items: stretch;      height: auto;      box-shadow: none;      border-bottom: 1px solid var(--tg-df-border);    }    .tg-df-grid.layout-row .tg-df-card:hover {      box-shadow: none;    }    .tg-df-grid.layout-row .tg-df-card-image-box {      width: 140px;      min-width: 140px;      aspect-ratio: 3/4;      border-right: none;      padding: 16px 16px 16px 32px;    }    .tg-df-grid.layout-row .tg-df-card-body {      padding: 16px;      justify-content: space-between;    }    .tg-df-grid.layout-row .tg-df-card-title {      font-size: 15px;      margin-bottom: 16px;    }    .tg-df-grid.layout-row .tg-df-card-stars { margin-bottom: 8px; }    .tg-df-grid.layout-row .tg-df-card-footer {      flex-direction: column;      align-items: flex-start;      gap: 0;    }    .tg-df-grid.layout-row .tg-df-card-merchant-pill {      margin-bottom: 4px;    }    .tg-df-grid.layout-row .tg-df-card-price-group {      margin-bottom: 8px;    }    .tg-df-grid.layout-row .tg-df-price-group {      width: auto;    }    .tg-df-grid.layout-row .tg-df-card-cta {      width: 100%;      max-width: 200px;      padding: 10px 24px;      font-size: 13px;      flex-shrink: 0;      text-align: center;      justify-content: center;    }    /*       4. Deal Card Design    */    .tg-df-card {      position: relative;      display: flex;      flex-direction: column;      background-color: #ffffff;      border-radius: 0;      overflow: hidden;      transition: transform 0.2s ease, box-shadow 0.2s ease;      text-decoration: none;      color: inherit;      height: 100%;      box-shadow: 0 0 16px rgba(0, 0, 0, 0.08);      border: 1px solid var(--tg-df-border);    }    .tg-df-card:hover {      box-shadow: 0 0 24px rgba(0, 0, 0, 0.12);    }    .tg-df-card-image-box {      width: 100%;      aspect-ratio: 3/4;      background-color: #f8f8f8;      display: flex;      align-items: center;      justify-content: center;      position: relative;      overflow: hidden;      padding: 32px;      flex: 0 0 auto;    }    .tg-df-card-image {      max-width: 100%;      max-height: 100%;      width: auto;      height: auto;      object-fit: contain;      mix-blend-mode: multiply; /* Helps white background images blend into secondary bg */      transition: transform 0.3s ease;    }    .tg-df-card:hover .tg-df-card-image {      transform: scale(1.05); /* Zoom in on hover */    }    .tg-df-card-discount-badge {      position: absolute;      top: 12px;      left: 12px;      background: #dc2626; /* Red */      color: #ffffff;      padding: 6px 8px;      font-size: 11px;      font-weight: 500;      text-transform: uppercase;      letter-spacing: 0.5px;      border-radius: 0;      z-index: 10;    }        .tg-df-card-merchant-pill {      display: block;      padding: 0;      font-size: 11px;      font-weight: 600;      text-transform: uppercase;      letter-spacing: 0.5px;      border-radius: 0;      color: var(--tg-df-text-muted);      margin-bottom: 8px;      white-space: nowrap;      overflow: hidden;      text-overflow: ellipsis;    }    .tg-df-card-body {      padding: 16px;      display: flex;      flex-direction: column;      flex-grow: 1;      min-width: 0;    }    .tg-df-card-badges {      display: flex;      flex-wrap: wrap;      gap: 6px;      margin-bottom: 8px;    }    .tg-df-tag {      display: inline-flex;      align-items: center;      padding: 4px 6px;      font-size: 11px;      font-weight: 700;      text-transform: uppercase;      border-radius: 4px;      gap: 4px;    }    .tg-df-tag-prime {      background-color: #00A8E1;      color: #fff;    }    .tg-df-tag-coupons {      background-color: #f1f5f9;      color: #334155;      border: 1px solid #cbd5e1;      cursor: pointer;      transition: background-color 0.2s;    }    .tg-df-tag-coupons:hover {      background-color: #e2e8f0;    }        .tg-df-tag-outline {      background-color: #f1f5f9;      color: #334155;      border: 1px solid #cbd5e1;      cursor: pointer;      transition: background-color 0.2s;    }    .tg-df-tag-outline:hover {      background-color: #e2e8f0;    }        @keyframes tg-df-spin {      0% { transform: rotate(0deg); }      100% { transform: rotate(360deg); }    }    .tg-df-coupon-spinner {      border: 2px solid #e2e8f0;      border-top: 2px solid #3b82f6;      border-radius: 50%;      width: 14px;      height: 14px;      animation: tg-df-spin 1s linear infinite;      margin: 4px 8px;      display: inline-block;    }        /* Vouchers Modal */    .tg-df-modal-backdrop {      position: fixed;      top: 0; left: 0; right: 0; bottom: 0;      background: rgba(0,0,0,0.5);      z-index: 10000;      display: flex;      align-items: center;      justify-content: center;      opacity: 0;      pointer-events: none;      transition: opacity 0.3s;    }    .tg-df-modal-backdrop.active {      opacity: 1;      pointer-events: auto;    }    .tg-df-modal {      background: #fff;      border-radius: 12px;      width: 90%;      max-width: 400px;      max-height: 80vh;      display: flex;      flex-direction: column;      box-shadow: 0 10px 40px rgba(0,0,0,0.2);      transform: translateY(20px);      transition: transform 0.3s;    }    .tg-df-modal-backdrop.active .tg-df-modal {      transform: translateY(0);    }    .tg-df-modal-header {      padding: 16px;      border-bottom: 1px solid #e2e8f0;      display: flex;      align-items: center;      justify-content: space-between;    }    .tg-df-modal-title {      font-size: 16px;      font-weight: 600;      margin: 0;    }    .tg-df-modal-close {      background: none;      border: none;      cursor: pointer;      padding: 4px;      color: #64748b;    }    .tg-df-modal-body {      padding: 16px;      overflow-y: auto;    }    .tg-df-voucher-item {      padding: 12px;      border: 1px dashed #cbd5e1;      border-radius: 8px;      margin-bottom: 10px;      background: #f8fafc;      display: flex;      align-items: center;      gap: 12px;      text-decoration: none;      color: inherit;      transition: background-color 0.2s, border-color 0.2s;    }    .tg-df-voucher-item:hover {      background: #f1f5f9;      border-color: #94a3b8;    }    .tg-df-voucher-item:last-child {      margin-bottom: 0;    }    .tg-df-voucher-logo {      width: 48px;      height: 48px;      object-fit: contain;      border-radius: 4px;      background: #fff;      border: 1px solid #e2e8f0;      flex-shrink: 0;    }    .tg-df-voucher-content {      flex: 1;      min-width: 0;    }    .tg-df-voucher-title {      font-size: 14px;      font-weight: 600;      margin: 0 0 4px 0;      line-height: 1.3;      color: #0f172a;    }    .tg-df-voucher-expiry {      font-size: 12px;      color: #64748b;      display: flex;      align-items: center;      gap: 4px;      margin-top: 6px;    }    .tg-df-voucher-code {      display: inline-flex;      align-items: center;      background: #f1f5f9;      border: 1px dashed #cbd5e1;      padding: 6px 10px;      font-family: monospace;      font-weight: 700;      font-size: 14px;      color: #0f172a;      border-radius: 4px;      margin-top: 8px;      cursor: pointer;      transition: all 0.2s ease;    }    .tg-df-voucher-code:hover {      background: #e2e8f0;      border-color: #94a3b8;    }    .tg-df-voucher-code.copied {      background: #ecfdf5;      border-color: #10b981;      color: #10b981;    }    .tg-df-voucher-cta {      display: inline-block;      margin-top: 8px;      font-size: 13px;      font-weight: 600;      color: #2563eb;      text-decoration: none;    }    .tg-df-card-title {      font-size: 15px;      font-weight: 400;      line-height: 1.4;      margin: 0 0 12px 0;      color: var(--tg-df-text);      display: -webkit-box;      -webkit-line-clamp: 2;      -webkit-box-orient: vertical;      overflow: hidden;    }    .tg-df-card-footer {      margin-top: auto;      display: flex;      flex-direction: column;      width: 100%;    }    .tg-df-card-price-group {      display: flex;      flex-direction: row;      align-items: center;      gap: 8px;      margin-bottom: 12px;    }    .tg-df-card-price {      font-size: 16px;      font-weight: 700;      color: #dc2626; /* Red price */      line-height: 1;    }        .tg-df-card-msrp {      font-size: 13px;      color: var(--tg-df-text-muted);      text-decoration: line-through;    }    .tg-df-container .tg-df-card-cta {      display: flex;      align-items: center;      justify-content: center;      width: 100%;      box-sizing: border-box;      background-color: #1f69ff;      color: #ffffff;      font-size: 12px;      font-weight: 700;      text-transform: uppercase;      letter-spacing: 0.5px;      padding: 12px 16px;      border-radius: 0;      border: none;      cursor: pointer;      transition: background-color 0.2s ease;    }    .tg-df-card:hover .tg-df-card-cta,    .tg-df-card-cta:hover {      background-color: #1555cc;    }    .tg-df-container .tg-df-card-cta.tg-df-cta-savings-squad {      background-color: #3c8d0d;    }    .tg-df-card:hover .tg-df-card-cta.tg-df-cta-savings-squad,    .tg-df-card-cta.tg-df-cta-savings-squad:hover {      background-color: #2b6509;    }    /*       5. State & Skeleton Styles    */    .tg-df-message {      grid-column: 1 / -1;      text-align: center;      padding: 48px 24px;      color: var(--tg-df-text-muted);      font-size: 16px;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 8px;    }    @keyframes tg-df-shimmer {      0% { background-position: -200% 0; }      100% { background-position: 200% 0; }    }    .tg-df-skeleton {      background: linear-gradient(90deg, var(--tg-df-bg-secondary) 25%, #e2e8f0 50%, var(--tg-df-bg-secondary) 75%);      background-size: 200% 100%;      animation: tg-df-shimmer 1.5s infinite;      border-radius: 4px;    }    .tg-df-skeleton-img {      width: 100%;      height: 100%;      position: absolute;      top: 0; left: 0;    }        .tg-df-skeleton-text {      height: 16px;      margin-bottom: 8px;      width: 100%;    }    .tg-df-skeleton-text.short { width: 40%; }    .tg-df-skeleton-text.title { height: 20px; margin-bottom: 16px; }    /* Editor Floating Bar & Elements */    .tg-df-editor-bar {      position: sticky;      top: 0;      z-index: 1000;      background: #111827;      color: #fff;      padding: 12px 16px;      border-radius: 8px;      margin-bottom: 16px;      display: flex;      align-items: center;      justify-content: space-between;      box-shadow: 0 4px 12px rgba(0,0,0,0.15);    }    .tg-df-editor-bar-text {      font-weight: 600;      font-size: 14px;    }    .tg-df-editor-copy-btn {      background: #10b981;      color: #fff;      padding: 6px 16px;      border: none;      border-radius: 4px;      font-weight: 600;      cursor: pointer;      display: flex;      align-items: center;      font-size: 13px;    }    .tg-df-editor-copy-btn:hover { background: #059669; }        .tg-df-deal-checkbox {      position: absolute;      top: 12px;      right: 12px;      z-index: 10;      width: 20px;      height: 20px;      cursor: pointer;      pointer-events: auto;    }    /*       6. Mobile List View (Stacks into a cleaner horizontal row/list)    */    @container tg-df (max-width: 599px) {      .tg-df-controls {        padding: 0 16px;      }            .tg-df-top-bar {        width: 100%;      }            .tg-df-settings-dropdown {        position: fixed;        top: auto;        bottom: 0;        left: 0;        right: 0;        width: 100%;        border-radius: 20px 20px 0 0;        padding: 24px;        box-shadow: 0 -8px 32px rgba(0,0,0,0.15);        z-index: 1000;        border: none;        border-top: 1px solid var(--tg-df-border);      }            .tg-df-settings-dropdown-backdrop.active {        background: rgba(0,0,0,0.4);      }            .tg-df-search-wrapper {        box-shadow: 0 0 16px rgba(0,0,0,0.08);      }            .tg-df-filters {        width: calc(100% + 32px);        margin: 0 -16px;        padding: 0 16px 4px 16px;        display: flex;        justify-content: flex-start;        gap: 8px;        flex-wrap: nowrap;        overflow-x: auto;        -webkit-overflow-scrolling: touch;        scrollbar-width: none;      }      .tg-df-filters::after {        content: "";        display: block;        flex: 0 0 8px;      }      .tg-df-filters::-webkit-scrollbar {        display: none;      }            .tg-df-sort-wrapper {        flex: 0 0 max(42%, 130px);        min-width: 0;      }      .tg-df-sort-wrapper.tg-df-price-range-wrapper {        flex: 0 0 auto;        min-width: max-content;      }            .tg-df-sort-select, .tg-df-filter-select {        width: 100%;        text-align: left;        padding: 10px 24px 10px 32px;        background-position: right 8px center;        text-overflow: ellipsis;        white-space: nowrap;        overflow: hidden;      }      .tg-df-sort-icon {        left: 10px;      }      .tg-df-grid:not(.layout-grid):not(.layout-row),      .tg-df-grid.layout-row {        grid-template-columns: 1fr;        gap: 16px;      }            .tg-df-grid.tg-df-grid-auto {        padding-top: 24px;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card,      .tg-df-grid.layout-row .tg-df-card {        flex-direction: row;        align-items: stretch;        height: auto;        box-shadow: none; /* simple line on mobile if preferred, or keep */        border-bottom: 1px solid var(--tg-df-border);      }      .tg-df-grid.tg-df-grid-auto .tg-df-card:hover,      .tg-df-grid.layout-row .tg-df-card:hover {        box-shadow: none;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-image-box,      .tg-df-grid.layout-row .tg-df-card-image-box {        width: 120px;        min-width: 120px;        aspect-ratio: 3/4;        border-right: none;        padding: 12px;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-body,      .tg-df-grid.layout-row .tg-df-card-body {        padding: 12px;        justify-content: space-between;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-title,      .tg-df-grid.layout-row .tg-df-card-title {        font-size: 14px;        margin-bottom: 12px;        -webkit-line-clamp: 3;      }      /* Single column mobile grid override */      .tg-df-grid.layout-grid {        grid-template-columns: 1fr;        gap: 16px;      }      .tg-df-grid.layout-grid .tg-df-card-image-box {        padding: 12px;      }      .tg-df-grid.layout-grid .tg-df-card-body {        padding: 10px;      }      .tg-df-grid.layout-grid .tg-df-card-title {        font-size: 13px;        -webkit-line-clamp: 3;        margin-bottom: 8px;      }      .tg-df-grid.layout-grid .tg-df-card-price {        font-size: 14px;      }            .tg-df-card-footer {        flex-direction: column;        align-items: stretch;        gap: 0;        width: 100%;        min-width: 0;      }      .tg-df-card-merchant-pill {        margin-bottom: 4px;      }      .tg-df-card-price-group {        flex: 1 1 auto;        margin-bottom: 8px;      }      .tg-df-card-price {        font-size: 16px;      }      .tg-df-card-msrp {        display: block;       }      .tg-df-grid.layout-row .tg-df-card-cta,      .tg-df-container .tg-df-card-cta {        width: 100%;        max-width: none;        min-width: 0;        box-sizing: border-box;        padding: 8px 16px;        font-size: 12px;        flex: 0 0 auto;        text-align: center;        white-space: normal;        line-height: 1.2;      }    }    .tg-df-container.is-carousel {      min-height: 760px;      background-color: #E7F0FF;      padding: 0 0 24px 0;      border-radius: 24px;    }    .tg-df-container.is-carousel.hide-header-details {      min-height: 480px;    }    /*       7. Carousel View Mode    */    .tg-df-container .tg-df-carousel-host {      /* Layout is now handled by container wrapper */    }    .tg-df-container .tg-df-carousel-eyebrow {      color: #1F69FF;      font-weight: 700;      font-size: 14px;      text-transform: uppercase;      letter-spacing: 1px;      padding: 24px 16px 0 16px;      display: none;    }    .tg-df-container .tg-df-carousel-query-title {      color: #011535;      font-size: 28px;      font-weight: 600;      padding: 0 16px 24px 16px;      line-height: 1.2;      display: none;    }    .tg-df-container .tg-df-carousel-blue-box {      background-color: transparent;      border-radius: 0;      padding: 24px 24px 0 24px;      margin: 0;      color: #1F69FF;          position: relative;      overflow: hidden;    }    .tg-df-container .tg-df-carousel-bg-circle-1 {      display: none;    }    .tg-df-container .tg-df-carousel-bg-circle-2 {      display: none;    }    .tg-df-container .tg-df-carousel-bg-circle-3 {      display: none;    }    .tg-df-container .tg-df-carousel-box-content {      position: relative;      z-index: 10;    }    .tg-df-container .tg-df-carousel-box-eyebrow {      background-color: transparent;      color: #1F69FF;      font-weight: 700;      font-size: 14px;      text-transform: uppercase;      letter-spacing: 1px;      display: inline-block;      padding: 0;      border-radius: 0;    }    .tg-df-container .tg-df-carousel-box-title {      font-size: 28px;      font-weight: 600;      line-height: 1.2;      margin-top: 8px;      color: #1e293b;    }    .tg-df-container .tg-df-countdown-wrapper {      position: absolute;      top: 0;      right: 0;      display: flex;      flex-direction: column;      align-items: flex-end;      gap: 12px;      transform: scale(0.67);      transform-origin: top right;    }    .tg-df-container .tg-df-countdown-title {      font-size: 16px;      text-align: center;      width: 100%;      font-weight: 600;      color: #011535;      margin: 0;    }    .tg-df-container .tg-df-countdown-blocks {      display: flex;      gap: 16px;    }    .tg-df-container .tg-df-countdown-item {      display: flex;      flex-direction: column;      align-items: center;      gap: 4px;    }    .tg-df-container .tg-df-countdown-box {      width: 59px;      height: 59px;      background: #03FE9E;      border-radius: 15px;      display: flex;      align-items: center;      justify-content: center;    }    .tg-df-container .tg-df-countdown-num {      font-family: 'Inter', sans-serif;      font-weight: 700;      font-size: 20px;      line-height: normal;      color: #011535;    }    .tg-df-container .tg-df-countdown-label {      font-family: 'Inter', sans-serif;      font-weight: 500;      font-size: 16px;      line-height: normal;      color: #1e293b;      text-transform: uppercase;    }    .tg-df-container .tg-df-carousel-box-subtitle {      font-size: 16px;      margin-top: 8px;      font-weight: 300;      color: #1e293b;      line-height: 24px;    }    .tg-df-container .tg-df-carousel-roundels-wrapper {      position: relative;      margin-top: 24px;      margin-left: -24px;      margin-right: -24px;    }    .tg-df-container .tg-df-carousel-roundels {      display: flex;      gap: 16px;      overflow-x: auto;            scrollbar-width: none;      padding-top: 12px;      padding-bottom: 24px;      padding-left: 24px;      padding-right: 24px;      margin-left: 0;      margin-right: 0;    }        .tg-df-container .tg-df-carousel-scroll-left,    .tg-df-container .tg-df-carousel-scroll-right {      position: absolute;      top: 50%;      transform: translateY(-50%);      height: 36px;      width: 36px;      display: flex;      align-items: center;      justify-content: center;      border-radius: 50%;      background-color: #ffffff;      border: 1px solid #e2e8f0;      box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);      color: #1F69FF;      cursor: pointer;      transition: all 0.2s;      margin-top: -4px;      z-index: 20;    }    .tg-df-container .tg-df-carousel-scroll-left { left: 8px; }    .tg-df-container .tg-df-carousel-scroll-right { right: 8px; }    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-left { left: 0px; }    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-right { right: 0px; }    .tg-df-carousel-filters-outer { margin-left: -24px; margin-right: -24px; padding-left: 24px; padding-right: 24px; }    @container tg-df (max-width: 599px) { .tg-df-carousel-filters-outer { margin-left: -16px; margin-right: -16px; padding-left: 16px; padding-right: 16px; } }        .tg-df-container .tg-df-carousel-scroll-left:hover,    .tg-df-container .tg-df-carousel-scroll-right:hover {      background-color: #f8fafc;      border-color: #cbd5e1;    }        .tg-df-carousel-roundels-wrapper .tg-df-carousel-scroll-left,    .tg-df-carousel-roundels-wrapper .tg-df-carousel-scroll-right,    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-left,    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-right {      background-color: rgba(255, 255, 255, 0.4);      border: none;      box-shadow: none;      backdrop-filter: blur(4px);      -webkit-backdrop-filter: blur(4px);    }    .tg-df-carousel-roundels-wrapper .tg-df-carousel-scroll-left { left: 0; }    .tg-df-carousel-roundels-wrapper .tg-df-carousel-scroll-right { right: 0; }    .tg-df-grid-wrapper .tg-df-carousel-scroll-left { left: 0; }    .tg-df-grid-wrapper .tg-df-carousel-scroll-right { right: 0; }        .tg-df-carousel-roundels-wrapper .tg-df-carousel-scroll-left:hover,    .tg-df-carousel-roundels-wrapper .tg-df-carousel-scroll-right:hover {      background-color: rgba(255, 255, 255, 0.6);      border: none;    }    .tg-df-container .tg-df-carousel-roundels::-webkit-scrollbar {      display: none;    }    .tg-df-container .tg-df-carousel-roundels::after {      content: "";      flex: 0 0 32px;    }    .tg-df-container .tg-df-roundel {      display: flex;      flex-direction: column;      align-items: center;      gap: 8px;      cursor: pointer;      min-width: 120px;      flex-shrink: 0;    }    .tg-df-container .tg-df-roundel-img-box {      width: 120px;      height: 120px;      border-radius: 50%;      background: white;      display: flex;      align-items: center;      justify-content: center;      overflow: hidden;      box-shadow: 0px 3px 14px 0px rgba(30, 41, 59, 0.08);      transition: box-shadow 0.2s;    }    .tg-df-container .tg-df-roundel:hover .tg-df-roundel-img-box {      box-shadow: 0 0 0 2px #E7F0FF, 0 0 0 4px #1F69FF;    }    .tg-df-container .tg-df-roundel.active .tg-df-roundel-img-box {      box-shadow: 0 0 0 2px #E7F0FF, 0 0 0 4px #1F69FF;    }    .tg-df-container .tg-df-roundel:hover .tg-df-roundel-img-box img {      transform: scale(1.08);    }    .tg-df-container .tg-df-roundel-img-box img {      width: 100%;      height: 100%;      object-fit: contain;      padding: 10px;      box-sizing: border-box;      transition: transform 0.3s ease;    }    .tg-df-container .tg-df-roundel-label {      font-size: 13px;      font-weight: 400;      color: #1e293b;      text-align: center;      transition: font-weight 0.2s;    }    .tg-df-container .tg-df-roundel.active .tg-df-roundel-label {      font-weight: 700;    }    .tg-df-container .tg-df-carousel-filters-label {      font-size: 16px;      font-weight: 400;      color: #1e293b;      white-space: nowrap;      margin-right: 4px;    }    .tg-df-container .tg-df-carousel-filters-wrap {      display: flex;      align-items: center;      flex-wrap: nowrap;      gap: 8px;      margin-top: 8px;      overflow-x: auto;      scrollbar-width: none;      -webkit-overflow-scrolling: touch;      padding-bottom: 8px;      margin-left: -24px;      margin-right: -24px;      padding-left: 24px;      padding-right: 24px;    }    .tg-df-container .tg-df-carousel-filters-wrap::-webkit-scrollbar {      display: none;    }        .tg-df-container .tg-df-carousel-filter-btn img,    .tg-df-container .tg-df-carousel-filter-btn picture {      height: 20px;      width: 20px;      object-fit: contain;      object-position: center;      display: inline-flex;      align-items: center;      justify-content: center;      margin-right: 6px;    }    .tg-df-container .tg-df-carousel-filter-btn picture img {      margin-right: 0;      height: 100%;      width: 100%;    }    .tg-df-container .tg-df-carousel-filter-btn img.active-img,    .tg-df-container .tg-df-carousel-filter-btn picture:has(.active-img) {      display: none;    }    .tg-df-container .tg-df-carousel-filter-btn:hover img.inactive-img,    .tg-df-container .tg-df-carousel-filter-btn.active img.inactive-img,    .tg-df-container .tg-df-carousel-filter-btn:hover picture:has(.inactive-img),    .tg-df-container .tg-df-carousel-filter-btn.active picture:has(.inactive-img) {      display: none;    }    .tg-df-container .tg-df-carousel-filter-btn:hover img.active-img,    .tg-df-container .tg-df-carousel-filter-btn.active img.active-img,    .tg-df-container .tg-df-carousel-filter-btn:hover picture:has(.active-img),    .tg-df-container .tg-df-carousel-filter-btn.active picture:has(.active-img) {      display: inline-flex;    }    .tg-df-container .tg-df-carousel-filter-btn {      background: #ffffff;      border: 2px solid #1e293b;      color: #1e293b;      border-radius: 24px;      padding: 6px 16px;      font-size: 14px;      font-weight: 600;      cursor: pointer;      transition: all 0.2s;      flex-shrink: 0;      white-space: nowrap;      display: inline-flex;      align-items: center;      justify-content: center;      min-height: 36px;      box-sizing: border-box;    }    .tg-df-container .tg-df-carousel-filter-btn svg {      margin-right: 6px;    }    .tg-df-container .tg-df-carousel-filter-btn:hover {      background: #1e293b;      color: white;      border-color: #1e293b;    }    .tg-df-container .tg-df-carousel-filter-btn.active {      background: #1e293b;      color: white;      border-color: #1e293b;    }        .tg-df-grid.carousel-compact {      display: flex;      flex-wrap: nowrap;      overflow-x: auto;      gap: 16px;      padding: 16px 24px;      align-items: stretch;      scrollbar-width: none;    }    .tg-df-grid.carousel-compact::after {      content: "";      flex: 0 0 32px;    }    .tg-df-grid-wrapper {      position: relative;    }    .tg-df-grid.carousel-compact::-webkit-scrollbar {      display: none;    }    .tg-df-grid.carousel-compact .tg-df-load-more-card {      flex: 0 0 auto;      width: 100px;      border-radius: 15px;      box-shadow: 0 0 16px rgba(0,0,0,0.08);      border: 2px solid #1e293b;      background: white;      color: #1e293b;      display: flex;      flex-direction: column;      justify-content: center;      align-items: center;      font-weight: 600;      font-size: 14px;      cursor: pointer;      padding: 16px;      text-align: center;      transition: all 0.2s;    }    .tg-df-grid.carousel-compact .tg-df-load-more-card:hover {      background: #1e293b;      color: white;    }    .tg-df-grid.carousel-compact .tg-df-card {      flex: 0 0 auto;      width: 200px;      min-height: auto;      height: auto;      display: flex;      flex-direction: column;      border-radius: 15px;      border: none;      box-shadow: 0 0 16px rgba(0,0,0,0.08);      overflow: visible;    }    .tg-df-grid.carousel-compact .tg-df-card-image-box {      padding: 12px;      background-color: transparent;      border-radius: 15px 15px 0 0;      height: 130px;    }    .tg-df-grid.carousel-compact .tg-df-card-image {      mix-blend-mode: normal;    }    .tg-df-grid.carousel-compact .tg-df-card-discount-badge {      border-radius: 0;      top: 0px;      left: 0px;      padding: 4px 8px;      font-size: 11px;    }    .tg-df-grid.carousel-compact .tg-df-card-body {      padding: 8px 12px 12px 12px;    }    .tg-df-grid.carousel-compact .tg-df-card-title {      font-size: 14px;      font-weight: 400;      -webkit-line-clamp: 2;      margin-bottom: 8px;      color: #011535;    }    .tg-df-grid.carousel-compact .tg-df-card-body:not(:has(.tg-df-card-stars)):not(:has(.tg-df-tag-prime)):not(:has(.tg-df-coupon-wrapper:not([style*="none"]))) > .tg-df-card-title,    .tg-df-grid.carousel-compact .tg-df-card-body:not(:has(.tg-df-card-stars)):has(> .tg-df-card-title:first-child) > .tg-df-card-title {      -webkit-line-clamp: 3;    }    .tg-df-grid.carousel-compact .tg-df-card-cta {      border-radius: 5px;      padding: 8px 10px;      margin-top: 4px;      background-color: #1F69FF;    }    .tg-df-grid.carousel-compact .tg-df-card-price-group {      margin-bottom: 2px;    }    .tg-df-grid.carousel-compact .tg-df-card-merchant-pill {      margin-bottom: 2px;    }    @container tg-df (max-width: 599px) {      .tg-df-container .tg-df-carousel-blue-box-title {        font-size: 24px;      }      .tg-df-container .tg-df-countdown-title {        display: none;      }      .tg-df-container .tg-df-countdown-wrapper {        position: absolute;        top: 0;        right: 0;        align-items: flex-end;        transform: scale(0.45);        transform-origin: top right;      }      .tg-df-container .tg-df-roundel {        min-width: 88px;      }      .tg-df-container .tg-df-roundel-img-box {        width: 88px;        height: 88px;      }    }    /* REPLICA BLOCK STYLES */    .tg-df-grid.layout-replica-2 { grid-template-columns: repeat(2, 1fr) !important; gap: 20px; }    .tg-df-grid.layout-replica-1 { grid-template-columns: 1fr !important; gap: 20px; }        .tg-df-container .hawk-deal-widget-container { border-bottom: 1px solid #e5e7eb; display: flex; flex-direction: column; margin: 0; padding: 20px 0; box-sizing: border-box; font-family: inherit; }    .tg-df-container .hawk-deal-widget-wrap { display: flex; flex-direction: row; align-items: flex-start; width: 100%; gap: 24px; }    .tg-df-container .hawk-deal-widget-image-container { display: flex; flex-shrink: 0; justify-content: center; width: 160px; height: 160px; align-items: center; background: white; margin-bottom: 0px; }    .tg-df-container .hawk-deal-widget-title-product-title { color: #111827; font-size: 18px; font-weight: 700; line-height: 1.4; display: inline; }    .tg-df-container .hawk-deal-widget-title-price { font-size: 18px; font-weight: 700; line-height: 1.4; white-space: nowrap; color: #2563eb; }    .tg-df-container .hawk-deal-widget-title-price-now { font-weight: 700; }    .tg-df-container .hawk-deal-widget-title-retailer-price:hover { text-decoration: underline; }    .tg-df-container .hawk-deal-widget-title-retailer { font-size: 18px; font-weight: 700; line-height: 1.4; color: #2563eb; }    .tg-df-container .hawk-deal-widget-title-was-price { color: #dc2626; font-size: 16px; font-weight: 500; line-height: 1.4; text-decoration: line-through; white-space: nowrap; margin-left: 8px; margin-right: 8px; }    .tg-df-container .hawk-deal-widget-text-body-container { position: relative; width: 100%; box-sizing: border-box; }    .tg-df-container .hawk-deal-widget-text-body-main { font-size: 16px; width: 100%; margin-bottom: 12px; }    .tg-df-container .hawk-deal-widget-text-body-description { display: block; font-size: 15px; margin-top: 12px; color: #4b5563; line-height: 1.6; }    .tg-df-container .hawk-deal-widget-text-body-description p { margin: 0; line-height: 1.6; }    .tg-df-container .hawk-deal-widget-text-cta-container { display: flex; flex-direction: column; gap: 12px; width: 100%; flex: 1; min-width: 0; box-sizing: border-box; }    .tg-df-container .hawk-deal-widget-footer { display: flex; justify-content: flex-end; width: 100%; margin-top: auto; }    .tg-df-container .hawk-deal-widget-button-wrapper { display: flex; flex-direction: column; align-items: flex-end; justify-content: flex-end; width: 100%; }    .tg-df-container .hawk-deal-widget-preferred-partner-wrapper { display: flex; flex-direction: row; }        @container tg-df (min-width: 600px) {      .tg-df-mobile-only { display: none !important; }    }    @container tg-df (max-width: 599px) {      .tg-df-desktop-only { display: none !important; }      .tg-df-grid.layout-replica-2 { grid-template-columns: 1fr !important; }      .tg-df-grid.savings-squad-cards { grid-template-columns: 1fr !important; display: flex; flex-direction: column; }    }    .tg-df-grid.savings-squad-cards .tg-df-card-title {      -webkit-line-clamp: unset !important;      display: block !important;      overflow: visible !important;    }    @container tg-df (max-width: 500px) {      .tg-df-container .hawk-deal-widget-wrap { display: block; }      .tg-df-container .hawk-deal-widget-image-container { display: block; float: left; margin: 0 16px 8px 0; width: 120px; max-width: 120px; height: auto; align-items: normal; justify-content: normal; }      .tg-df-container .hawk-deal-widget-text-cta-container { display: block; text-align: left; }      .tg-df-container .hawk-deal-widget-footer { display: block; margin-top: 16px; clear: both; width: 100%; }      .tg-df-container .hawk-deal-widget-button-wrapper { display: block; width: 100%; }      .tg-df-container .hawk-deal-widget-button-wrapper .hawk-deal-widget-preferred-partner-wrapper { display: block; width: 100%; }      .tg-df-container .hawk-affiliate-link-deal-button { box-sizing: border-box !important; display: flex !important; max-width: none !important; width: 100% !important; margin: 0 !important; }    }        .tg-df-container .hawk-affiliate-link-deal-button {       align-items: center; background-color: #5aaf0b; box-sizing: border-box; color: #ffffff !important; display: flex; font-size: 14px; font-weight: 700; justify-content: center; letter-spacing: 0.5px; line-height: 1; min-width: 160px; padding: 14px 24px; text-align: center; text-decoration: none; text-transform: uppercase; width: 100%; word-break: normal; border-radius: 4px; border: 0; transition: background-color 0.2s;     }    .tg-df-container .hawk-affiliate-link-deal-button:hover { background-color: #4a9109; text-decoration: none; }    .tg-df-container .hawk-lazy-image-deal-widget { display: block; height: auto; margin: auto; max-height: 160px; max-width: 100%; mix-blend-mode: multiply; object-fit: contain; }    .tg-df-container .hawk-deal-widget-text-cta-container a { color: #2563eb; text-decoration: none; display: inline; }    .tg-df-container .hawk-deal-widget-text-cta-container a:hover { text-decoration: underline; }    .tg-df-container .hawk-deal-widget-text-cta-container a:has(.hawk-deal-widget-title-product-title) { color: #111827; }    .tg-df-container .hawk-deal-widget-text-cta-container a:hover .hawk-deal-widget-title-product-title,    .tg-df-container .hawk-deal-widget-text-cta-container a:hover .hawk-deal-widget-title-retailer-price { text-decoration: underline; }  \x3C/style>  \x3C!-- Widget Container --\x3E  \x3Cdiv class="tg-df-container" id="signal-deals-finder-root">    \x3C!-- Editor Floating Bar --\x3E    \x3Cdiv class="tg-df-editor-bar" id="tg-df-editor-bar" style="display:none;">      \x3Cdiv class="tg-df-editor-bar-text" style="display: flex; align-items: center;">        \x3Cspan id="tg-df-selected-count">0\x3C/span>\x26nbsp;Deals Selected        \x3Cbutton class="tg-df-editor-clear-btn" id="tg-df-editor-clear" type="button" style="margin-left: 12px; font-size: 13px; color: #9ca3af; background: none; border: none; cursor: pointer; text-decoration: underline;">Clear All\x3C/button>      \x3C/div>      \x3Cbutton class="tg-df-editor-copy-btn" id="tg-df-editor-copy" type="button">        \x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2">\x3C/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1">\x3C/path>\x3C/svg>        Copy to CMS      \x3C/button>    \x3C/div>    \x3Cdiv class="tg-df-carousel-host" id="tg-df-carousel-host" style="display: none;">      \x3Cdiv class="tg-df-carousel-eyebrow">DEAL FINDER\x3C/div>      \x3Cdiv class="tg-df-carousel-query-title" id="tg-df-carousel-title-label">Best Deals\x3C/div>            \x3Cdiv class="tg-df-carousel-blue-box">        \x3Cdiv class="tg-df-carousel-bg-circle-1" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-bg-circle-2" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-bg-circle-3" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-box-content">          \x3Cdiv class="tg-df-countdown-wrapper" id="tg-df-countdown-wrapper" style="display:none;">            \x3Cdiv class="tg-df-countdown-title" id="tg-df-countdown-title">Prime Day starts in\x3C/div>            \x3Cdiv class="tg-df-countdown-blocks">              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-days">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">DAYS\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-hrs">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">HRS\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-min">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">MIN\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-sec">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">SEC\x3C/div>\x3C/div>            \x3C/div>          \x3C/div>          \x3Cdiv class="tg-df-carousel-box-eyebrow">DEAL FINDER\x3C/div>          \x3Cdiv class="tg-df-carousel-box-title">Find Deals Fast\x3C/div>          \x3Cdiv class="tg-df-carousel-box-subtitle">The latest deals from the biggest retailers, all in one place\x3C/div>                    \x3Cdiv class="tg-df-carousel-roundels-wrapper">          \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-roundels').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>          \x3Cdiv class="tg-df-carousel-roundels">            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>          \x3C/div>          \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" onclick="this.parentElement.querySelector('.tg-df-carousel-roundels').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>        \x3C/div>        \x3Cdiv class="tg-df-carousel-filters-outer" style="position: relative;">          \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-filters-wrap').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>          \x3Cdiv class="tg-df-carousel-filters-wrap">                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="0">All\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-ot="amazon_lightning">              \x3Cimg src="https://cdn.mos.cms.futurecdn.net/HqAui7w97ft2NPqBtQ5r38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/yWPQ5yyQRhUwVKzGwYbh38-600-100.png" class="active-img" alt="" /> Lightning deals\x3C/button>            \x3Cbutton class="tg-df-carousel-filter-btn" data-ot="amazon_prime">              \x3Cimg src="https://cdn.mos.cms.futurecdn.net/fwoVXvL79turN3Ph535m38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/u75QjVpt3w2EsMimJiRo38-600-100.png" class="active-img" alt="" /> Prime deals\x3C/button>            \x3Cbutton class="tg-df-carousel-filter-btn" data-d="10">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 10% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="15">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 15% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="25">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 25% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-pr="under50">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-badge-dollar-sign">\x3Cpath d="M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z">\x3C/path>\x3Cpath d="M16 8h-6a2 2 0 1 0 0 4h4a2 2 0 1 1 0 4H8">\x3C/path>\x3Cpath d="M12 18V6">\x3C/path>\x3C/svg>            Under $50\x3C/button>        \x3C/div>        \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-filters-wrap').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>      \x3C/div>    \x3C/div>    \x3C/div>      \x3C!-- Search & Filter Controls --\x3E    \x3Cdiv class="tg-df-controls" id="tg-df-controls" style="display:flex;">      \x3Cdiv class="tg-df-top-bar">        \x3Cdiv class="tg-df-search-wrapper">          \x3Cinput type="text" class="tg-df-search-input" placeholder="Search for deals, products, or brands...">          \x3Cbutton type="button" class="tg-df-search-btn" aria-label="Search">              \x3Csvg class="tg-df-search-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">                \x3Cpath d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/>              \x3C/svg>          \x3C/button>          \x3Cdiv class="tg-df-autocomplete-dropdown" id="tg-df-autocomplete">\x3C/div>        \x3C/div>                \x3Cdiv class="tg-df-settings-wrapper">          \x3Cbutton type="button" class="tg-df-settings-btn" aria-label="Settings" id="tg-df-settings-toggle">            \x3Csvg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="20" height="20">                \x3Cpath d="M19.14 12.94c.04-.3.06-.61.06-.94 0-.32-.02-.64-.06-.94l2.03-1.58c.18-.14.23-.41.12-.61l-1.92-3.32c-.12-.22-.37-.29-.59-.22l-2.39.96c-.5-.38-1.03-.7-1.62-.94l-.36-2.54c-.04-.24-.24-.41-.48-.41h-3.84c-.24 0-.43.17-.47.41l-.36 2.54c-.59.24-1.13.57-1.62.94l-2.39-.96c-.22-.08-.47 0-.59.22L2.73 8.87c-.12.21-.08.47.12.61l2.03 1.58c-.05.3-.09.63-.09.94s.02.64.06.94l-2.03 1.58c-.18.14-.23.41-.12.61l1.92 3.32c.12.22.37.29.59.22l2.39-.96c.5.38 1.03.7 1.62.94l.36 2.54c.05.24.24.41.48.41h3.84c.24 0 .43-.17.47-.41l.36-2.54c.59-.24 1.13-.56 1.62-.94l2.39.96c.22.08.47 0 .59-.22l1.92-3.32c.12-.22.07-.49-.12-.61l-2.01-1.58zM12 15.6c-1.98 0-3.6-1.62-3.6-3.6s1.62-3.6 3.6-3.6 3.6 1.62 3.6 3.6-1.62 3.6-3.6 3.6z"/>            \x3C/svg>          \x3C/button>          \x3Cdiv class="tg-df-settings-dropdown-backdrop" id="tg-df-settings-backdrop">\x3C/div>          \x3Cdiv class="tg-df-settings-dropdown" id="tg-df-settings-panel">            \x3Cdiv class="tg-df-setting-item">              \x3Clabel class="tg-df-setting-label">Search Region\x3C/label>              \x3Cselect class="tg-df-region-select" id="tg-df-region-select">                \x3Coption value="auto">🌍 Auto-detect\x3C/option>                \x3Coption value="US">🇺🇸 United States (US)\x3C/option>                \x3Coption value="GB">🇬🇧 United Kingdom (UK)\x3C/option>                \x3Coption value="CA">🇨🇦 Canada (CA)\x3C/option>                \x3Coption value="AU">🇦🇺 Australia (AU)\x3C/option>                \x3Coption value="DE">🇩🇪 Germany (DE)\x3C/option>                \x3Coption value="FR">🇫🇷 France (FR)\x3C/option>                \x3Coption value="IT">🇮🇹 Italy (IT)\x3C/option>              \x3C/select>            \x3C/div>            \x3Cdiv class="tg-df-setting-item">              \x3Clabel class="tg-df-setting-label">Retailer\x3C/label>              \x3Cselect class="tg-df-region-select" id="tg-df-retailer-select">                \x3Coption value="">All Retailers\x3C/option>                \x3Coption value="Amazon">Amazon\x3C/option>                \x3Coption value="Walmart">Walmart\x3C/option>                \x3Coption value="Best Buy">Best Buy\x3C/option>                \x3Coption value="Target">Target\x3C/option>                \x3Coption value="John Lewis">John Lewis\x3C/option>                \x3Coption value="Currys">Currys\x3C/option>                \x3Coption value="Argos">Argos\x3C/option>              \x3C/select>            \x3C/div>            \x3Cdiv class="tg-df-setting-item">              \x3Clabel class="tg-df-setting-label">Offer Type\x3C/label>              \x3Cselect class="tg-df-region-select" id="tg-df-offer-type-select">                \x3Coption value="">All Offers\x3C/option>                \x3Coption value="amazon_prime">Amazon Prime\x3C/option>                \x3Coption value="recommended_promo">Recommended Promo\x3C/option>                \x3Coption value="amazon_lightning">Amazon Lightning Deal\x3C/option>              \x3C/select>            \x3C/div>            \x3Cdiv class="tg-df-setting-item">              \x3Clabel class="tg-df-setting-label">Result Count\x3C/label>              \x3Cselect class="tg-df-region-select" id="tg-df-rows-select">                \x3Coption value="3">3 Items\x3C/option>                \x3Coption value="4">4 Items\x3C/option>                \x3Coption value="6">6 Items\x3C/option>                \x3Coption value="12" selected>12 Items\x3C/option>                \x3Coption value="24">24 Items\x3C/option>                \x3Coption value="48">48 Items\x3C/option>              \x3C/select>            \x3C/div>            \x3Cdiv class="tg-df-setting-item tg-df-dl-row">              \x3Cdiv>                \x3Cspan class="tg-df-dl-row-text">Deal Mode\x3C/span>                \x3Cspan class="tg-df-dl-row-subtext">Only show products with active offers or previous prices (was_price)\x3C/span>              \x3C/div>              \x3Clabel class="tg-df-toggle">                \x3Cinput type="checkbox" id="tg-df-deal-mode">                \x3Cspan class="tg-df-slider">\x3C/span>              \x3C/label>            \x3C/div>            \x3Cdiv class="tg-df-setting-item tg-df-dl-row">              \x3Cdiv>                \x3Cspan class="tg-df-dl-row-text">Editor Mode\x3C/span>                \x3Cspan class="tg-df-dl-row-subtext">Enable multi-select to copy deals to CMS\x3C/span>              \x3C/div>              \x3Clabel class="tg-df-toggle">                \x3Cinput type="checkbox" id="tg-df-editor-mode">                \x3Cspan class="tg-df-slider">\x3C/span>              \x3C/label>            \x3C/div>            \x3Cdiv class="tg-df-setting-item">              \x3Clabel class="tg-df-setting-label">View Mode\x3C/label>              \x3Cselect class="tg-df-region-select" id="tg-df-view-mode-select">                \x3Coption value="auto">Auto Collection\x3C/option>                \x3Coption value="carousel">Carousel\x3C/option>                \x3Coption value="savings_squad">Savings Squad\x3C/option>                \x3Coption value="grid">Grid (Columns)\x3C/option>                \x3Coption value="row">Row (List)\x3C/option>              \x3C/select>            \x3C/div>          \x3C/div>        \x3C/div>      \x3C/div>      \x3Cdiv class="tg-df-filters">        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-category-filter-wrapper" style="display: none;">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-category-filter" aria-label="Category">            \x3Coption value="all">All Categories\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper tg-df-multiselect-container" id="tg-df-brand-filter-wrapper" style="display:none;">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M4.25 5.61C6.27 8.2 10 13 10 13v6c0 .55.45 1 1 1h2c.55 0 1-.45 1-1v-6s3.72-4.8 5.74-7.39A.998.998 0 0 0 18.95 4H5.04c-.83 0-1.3.95-.79 1.61z"/>          \x3C/svg>          \x3Cdiv class="tg-df-filter-select tg-df-multiselect-trigger" id="tg-df-brand-trigger" tabindex="0">            Any Brand          \x3C/div>          \x3Cdiv class="tg-df-multiselect-dropdown" id="tg-df-brand-dropdown">            \x3C!-- Populated via script --\x3E          \x3C/div>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M9 3L5 6.99h3V14h2V6.99h3L9 3zm7 14.01V10h-2v7.01h-3L15 21l4-3.99h-3z"/>          \x3C/svg>          \x3Cselect class="tg-df-sort-select" aria-label="Sort Deals">            \x3Coption value="date_desc">Newest First\x3C/option>            \x3Coption value="best_match">Sort by: Match\x3C/option>            \x3Coption value="price_asc">Price Low to High\x3C/option>            \x3Coption value="price_desc">Price High to Low\x3C/option>            \x3Coption value="discount_desc">Biggest Discount\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper tg-df-price-range-wrapper" id="tg-df-custom-price-wrapper" style="display: flex; align-items:center; justify-content:center; padding: 10px 20px; gap: 8px; border: 1px solid var(--tg-df-border); border-radius: 100px; background-color: var(--tg-df-bg);">          \x3Cspan style="font-size:14px; font-weight:500; color:var(--tg-df-text-primary);">Price\x3C/span>          \x3Cinput type="number" class="tg-df-price-input" id="tg-df-custom-price-min" placeholder="Min" style="width: 48px; background: transparent; border: none; color: var(--tg-df-text-primary); outline: none; font-size: 14px; text-align: center; padding: 0;">          \x3Cspan style="color:var(--tg-df-text-muted)">-\x3C/span>          \x3Cinput type="number" class="tg-df-price-input" id="tg-df-custom-price-max" placeholder="Max" style="width: 48px; background: transparent; border: none; color: var(--tg-df-text-primary); outline: none; font-size: 14px; text-align: center; padding: 0;">        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-legacy-price-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58.55 0 1.05-.22 1.41-.59l7-7c.37-.36.59-.86.59-1.41 0-.55-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-price-filter" aria-label="Filter Prices">            \x3Coption value="all">All Prices\x3C/option>            \x3Coption value="under50">Under $50\x3C/option>            \x3Coption value="50_100">$50 - $100\x3C/option>            \x3Coption value="100_200">$100 - $200\x3C/option>            \x3Coption value="200_500">$200 - $500\x3C/option>            \x3Coption value="over500">Over $500\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-discount-filter-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">            \x3Cpath d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58.55 0 1.05-.22 1.41-.59l7-7c.37-.36.59-.86.59-1.41 0-.55-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-discount-filter" aria-label="Discount Amount">            \x3Coption value="all">Any discount\x3C/option>            \x3Coption value="5">Min 5%\x3C/option>            \x3Coption value="10">Min 10%\x3C/option>            \x3Coption value="15">Min 15%\x3C/option>            \x3Coption value="20">Min 20%\x3C/option>            \x3Coption value="25">Min 25%\x3C/option>            \x3Coption value="30">Min 30%\x3C/option>            \x3Coption value="40">Min 40%\x3C/option>            \x3Coption value="50">Min 50%\x3C/option>            \x3Coption value="60">Min 60%\x3C/option>            \x3Coption value="70">Min 70%\x3C/option>          \x3C/select>        \x3C/div>      \x3C/div>    \x3C/div>    \x3C!-- Deals Grid Wrapper --\x3E    \x3Cdiv class="tg-df-grid-wrapper tg-df-carousel-cards-wrapper" id="tg-df-grid-wrapper">      \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('#tg-df-grid').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>      \x3Cdiv class="tg-df-grid" id="tg-df-grid">        \x3C!-- Content populated by JavaScript --\x3E      \x3C/div>      \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" style="display:none;" onclick="this.parentElement.querySelector('#tg-df-grid').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>    \x3C/div>        \x3C!-- Vouchers Modal --\x3E    \x3Cdiv class="tg-df-modal-backdrop" id="tg-df-vouchers-modal">      \x3Cdiv class="tg-df-modal">        \x3Cdiv class="tg-df-modal-header">          \x3Ch3 class="tg-df-modal-title" id="tg-df-vouchers-title">Available Coupons & Deals\x3C/h3>          \x3Cbutton class="tg-df-modal-close" id="tg-df-vouchers-close">            \x3Csvg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">              \x3Cline x1="18" y1="6" x2="6" y2="18">\x3C/line>              \x3Cline x1="6" y1="6" x2="18" y2="18">\x3C/line>            \x3C/svg>          \x3C/button>        \x3C/div>        \x3Cdiv class="tg-df-modal-body" id="tg-df-vouchers-content">          \x3C!-- Vouchers injected here --\x3E        \x3C/div>      \x3C/div>    \x3C/div>  \x3C/div>`;      if (!template) {        template = document.createElement('template');        template.innerHTML = rawTemplate;      }      let shadowRoot = null;      if (hostContainer && template) {        hostContainer.setAttribute('data-initialized', 'true');        shadowRoot = hostContainer.attachShadow({ mode: 'open' });        shadowRoot.appendChild(template.content.cloneNode(true));      }      class DealsFinderWidget {        constructor(config) {          this.rootNode = config.rootNode || document;          this.hostContainer = config.hostContainer || null;          this.rootId = config.rootId || 'signal-deals-finder-root';          this.root = this.rootNode.querySelector('#' + this.rootId);          if (!this.root) return;          this.widgetId = (window.crypto && window.crypto.randomUUID) ? window.crypto.randomUUID() : 'widget-' + Date.now() + '-' + Math.random().toString(36).slice(2);          this.grid = this.root.querySelector('#tg-df-grid');          this.tagsContainer = this.root.querySelector('#tg-df-tags-container');          this.categoryFilter = this.root.querySelector('#tg-df-category-filter');          this.categoryFilterWrapper = this.root.querySelector('#tg-df-category-filter-wrapper');          this.searchInput = this.root.querySelector('.tg-df-search-input');          this.autocompleteDropdown = this.root.querySelector('#tg-df-autocomplete');          this.sortSelect = this.root.querySelector('.tg-df-sort-select');          this.searchBtn = this.root.querySelector('.tg-df-search-btn');                    this.settingsToggle = this.root.querySelector('#tg-df-settings-toggle');          this.settingsPanel = this.root.querySelector('#tg-df-settings-panel');          this.settingsBackdrop = this.root.querySelector('#tg-df-settings-backdrop');          this.regionSelect = this.root.querySelector('#tg-df-region-select');          this.retailerSelect = this.root.querySelector('#tg-df-retailer-select');          this.offerTypeSelect = this.root.querySelector('#tg-df-offer-type-select');          this.viewModeSelect = this.root.querySelector('#tg-df-view-mode-select');          this.rowsSelect = this.root.querySelector('#tg-df-rows-select');          this.dealModeToggle = this.root.querySelector('#tg-df-deal-mode');          this.editorModeToggle = this.root.querySelector('#tg-df-editor-mode');          this.priceFilter = this.root.querySelector('#tg-df-price-filter');          this.discountFilter = this.root.querySelector('#tg-df-discount-filter');                    this.editorBar = this.root.querySelector('#tg-df-editor-bar');          this.editorSelectedCount = this.root.querySelector('#tg-df-selected-count');          this.editorCopyBtn = this.root.querySelector('#tg-df-editor-copy');          this.editorClearBtn = this.root.querySelector('#tg-df-editor-clear');                    this.apiUrl = 'https://search-api.fie.future.net.uk/widget.php';          this.deals = [];          this.displayLimit = 12;          this.airedaleArticles = null;          this.airedaleTags = [];          this.airedaleTagCounts = {};          this.activeDealTag = null;          this.selectedBrands = [];          this.currentQuery = '';          this.editorMode = this.hostContainer ? this.hostContainer.hasAttribute('data-editor-mode') : false;          this.viewModeOverride = this.hostContainer ? this.hostContainer.getAttribute('data-view-mode') : null;          this.selectedDeals = new Map();                    this.brandFilterWrapper = this.root.querySelector('#tg-df-brand-filter-wrapper');          this.brandTrigger = this.root.querySelector('#tg-df-brand-trigger');          this.brandDropdown = this.root.querySelector('#tg-df-brand-dropdown');                    this.customPriceWrapper = this.root.querySelector('#tg-df-custom-price-wrapper');          this.customPriceMin = this.root.querySelector('#tg-df-custom-price-min');          this.customPriceMax = this.root.querySelector('#tg-df-custom-price-max');          this.legacyPriceWrapper = this.root.querySelector('#tg-df-legacy-price-wrapper');          this.discountFilterWrapper = this.root.querySelector('#tg-df-discount-filter-wrapper');          this.initResizeObserver();          this.init();            if (['carousel', 'carousel-compact', 'auto', 'grid', 'row'].includes(this.getViewMode())) { this.loadCarouselSpreadsheet(); }        }        getViewMode() {          if (this.viewModeOverride && (!this.editorMode || !this.viewModeSelect)) {            return this.viewModeOverride;          }          return (this.viewModeSelect && this.viewModeSelect.value) ? this.viewModeSelect.value : (this.viewModeOverride || 'auto');        }        applyLayoutMode() {          if (!this.grid) return;          const mode = this.getViewMode();          this.grid.classList.remove('layout-row', 'layout-grid', 'tg-df-grid-auto', 'carousel-compact', 'layout-replica-1', 'layout-replica-2');                    const carouselHost = this.root.querySelector('#tg-df-carousel-host');          const controlsDiv = this.root.querySelector('#tg-df-controls');          if (mode === 'carousel' || mode === 'auto' || mode === 'grid' || mode === 'row') {             if (mode === 'carousel') this.grid.classList.add('carousel-compact');             if (carouselHost) carouselHost.style.display = 'block';             if (controlsDiv) controlsDiv.style.display = 'none';             if (this.root.classList.contains('tg-df-container') && mode === 'carousel') {               this.root.classList.add('is-carousel');             } else if (this.root.classList.contains('tg-df-container')) {               this.root.classList.remove('is-carousel');             }          } else {             if (carouselHost) carouselHost.style.display = 'none';             if (controlsDiv) controlsDiv.style.display = 'flex';             if (this.root.classList.contains('tg-df-container')) {               this.root.classList.remove('is-carousel');             }          }          if (mode === 'grid') {            this.grid.classList.add('layout-grid');          } else if (mode === 'row') {            this.grid.classList.add('layout-row');          } else if (mode === 'savings_squad') {            this.grid.classList.add('tg-df-grid-auto', 'savings-squad-cards');          } else if (mode !== 'carousel') {            this.grid.classList.add('tg-df-grid-auto');          }                    const settingsWrapper = this.root.querySelector('.tg-df-settings-wrapper');          if (settingsWrapper) {            settingsWrapper.style.display = mode === 'auto' ? 'none' : 'block';          }          if (this.customPriceWrapper) {             this.customPriceWrapper.style.display = mode === 'auto' ? 'flex' : 'none';          }          if (this.legacyPriceWrapper) {             this.legacyPriceWrapper.style.display = mode === 'auto' ? 'none' : 'flex';          }          if (this.discountFilterWrapper) {             this.discountFilterWrapper.style.display = mode === 'auto' ? 'none' : 'flex';          }        }        initResizeObserver() {          try {            if (window.parent === window) return;          } catch (e) {            // cross origin frame check threw          }          const emitHeight = () => {            try {              const height = document.documentElement.scrollHeight || document.body.scrollHeight;              const msg = { type: 'embed-size', height: height };              if (window.parent && window.parent !== window) {                window.parent.postMessage(msg, '*');                window.parent.postMessage(JSON.stringify({ ...msg, sentinel: 'amp' }), '*');              }            } catch (e) {}          };                    if (window.ResizeObserver) {            try {              const ro = new ResizeObserver(() => emitHeight());              ro.observe(document.body);              if (this.root) ro.observe(this.root);            } catch(e){ console.warn(e); }          }          window.addEventListener('resize', emitHeight);          setTimeout(emitHeight, 300);        }        initCountdown() {          this.cdWrapper = this.root.querySelector('#tg-df-countdown-wrapper');                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          this.showCountdown = params.get('show_countdown') === 'true';          const showHeaderDetails = params.get('show_header_details') !== 'false';          const eyebrow = this.root.querySelector('.tg-df-carousel-box-eyebrow');          const title = this.root.querySelector('.tg-df-carousel-box-title');          const subtitle = this.root.querySelector('.tg-df-carousel-box-subtitle');          if (!showHeaderDetails) {            let containerElement = this.root.classList.contains('tg-df-container') ? this.root : this.root.querySelector('.tg-df-container');            if (containerElement) containerElement.classList.add('hide-header-details');            if (eyebrow) eyebrow.style.display = 'none';            if (title) title.style.display = 'none';            if (subtitle) subtitle.style.display = 'none';          }          if (!this.cdWrapper) return;          this.cdTitle = this.root.querySelector('#tg-df-countdown-title');          this.cdDays = this.root.querySelector('#tg-df-cd-days');          this.cdHrs = this.root.querySelector('#tg-df-cd-hrs');          this.cdMin = this.root.querySelector('#tg-df-cd-min');          this.cdSec = this.root.querySelector('#tg-df-cd-sec');          this.updateCountdown();          this.cdInterval = setInterval(() => this.updateCountdown(), 1000);        }        updateCountdown() {          if (!this.cdWrapper) return;          if (!this.showCountdown) {            this.cdWrapper.style.display = 'none';            return;          }          const area = this.getAreaCode();          let offset = '-04:00';          if (['DE', 'FR', 'IT', 'ES', 'NL'].includes(area)) {             offset = '+02:00';          } else if (['GB', 'IE', 'UK'].includes(area)) {             offset = '+01:00';          }          const startTime = new Date('2026-06-23T00:00:00' + offset).getTime();          const endTime = new Date('2026-06-26T00:00:00' + offset).getTime();          const now = Date.now();          let targetTime = 0;          if (now < startTime) {             targetTime = startTime;             if (this.cdTitle) this.cdTitle.textContent = 'Prime Day starts in';             this.cdWrapper.style.display = 'flex';          } else if (now < endTime) {             targetTime = endTime;             if (this.cdTitle) this.cdTitle.textContent = 'Prime Day ends in';             this.cdWrapper.style.display = 'flex';          } else {             this.cdWrapper.style.display = 'none';             if (this.cdInterval) clearInterval(this.cdInterval);             return;          }          const diff = Math.max(0, targetTime - now);          const d = Math.floor(diff / (1000 * 60 * 60 * 24));          const h = Math.floor((diff / (1000 * 60 * 60)) % 24);          const m = Math.floor((diff / 1000 / 60) % 60);          const s = Math.floor((diff / 1000) % 60);          if (this.cdDays) this.cdDays.textContent = d;          if (this.cdHrs) this.cdHrs.textContent = h;          if (this.cdMin) this.cdMin.textContent = m;          if (this.cdSec) this.cdSec.textContent = s;        }        init() {          this.initCountdown();          try {            initAnalytics();          } catch (e) {            console.warn('Deals Widget Analytics Error:', e);          }                    this.bindEvents();                    let initialQuery = '';                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          let initialViewMode = params.get('view_mode');          if (!params.has('search') && !params.has('q') && !params.has('query') && initialViewMode !== 'savings_squad') {             initialQuery = 'Everything';             if (this.discountFilter && !params.has('min_discount_ratio')) {               this.discountFilter.value = '5';             }          }          const website = params.get('website') || 'tomsguide';          this.website = website;          if (website === 'techradar') {            const squadHeader = this.root.querySelector('.tg-df-savings-squad-header');            if (squadHeader) {               const pic = squadHeader.querySelector('picture');               if (pic) pic.style.display = 'none';            }            const style = document.createElement('style');            style.innerHTML = `              .tg-df-container .hawk-affiliate-link-deal-button, .tg-df-container .tg-df-card-cta { background-color: #5DAF08 !important; }              .tg-df-container .hawk-affiliate-link-deal-button:hover, .tg-df-container .tg-df-card-cta:hover { background-color: #4a8c06 !important; }            `;            this.root.appendChild(style);          }                    if (this.regionSelect) {            this.regionSelect.value = params.get('region') || 'auto';            this.updatePriceDropdownCurrency();          }                    if (this.retailerSelect && params.has('retailer')) {            this.retailerSelect.value = params.get('retailer');          }                    if (params.has('brands')) {            const b = params.get('brands');            if (b) {              this.selectedBrands = b.split(',');            }          }                    if (this.offerTypeSelect && params.has('offer_type')) {            this.offerTypeSelect.value = params.get('offer_type');          }          if (params.has('bg_color')) {            const bg = params.get('bg_color');            if (bg === 'white') {              this.root.style.setProperty('background-color', '#ffffff', 'important');            } else if (bg === 'transparent') {              this.root.style.setProperty('background-color', 'transparent', 'important');            } else if (bg === 'light_blue') {              this.root.style.setProperty('background-color', '#E7F0FF', 'important');            }          } else {             this.root.style.removeProperty('background-color');          }                    if (params.has('view_mode')) {            if (this.viewModeSelect) {              this.viewModeSelect.value = params.get('view_mode');            } else {              this.viewModeOverride = params.get('view_mode');            }          }          if (this.rowsSelect && params.has('rows')) {            this.rowsSelect.value = params.get('rows');          }          if (params.has('price')) {            const priceVal = params.get('price');            if (this.priceFilter) {               // Try assigning it directly to select. If it's not present implicitly ignores               this.priceFilter.value = priceVal;            }            if (priceVal.includes('_')) {               const parts = priceVal.split('_');               if (this.customPriceMin && parts[0]) this.customPriceMin.value = parts[0];               if (this.customPriceMax && parts[1]) this.customPriceMax.value = parts[1];            }          }          if (this.discountFilter && params.has('min_discount_ratio')) {            // Need to convert back from ratio (e.g. 0.8) to select value (e.g. "20")            const ratioStr = params.get('min_discount_ratio');            const ratioFloat = parseFloat(ratioStr);            if (!isNaN(ratioFloat)) {               const percentage = Math.round((1 - ratioFloat) * 100);               this.discountFilter.value = percentage.toString();            }          }          if (this.sortSelect) {            this.sortSelect.value = params.get('sort') || 'discount_desc';          }          if (this.dealModeToggle && params.has('deal_mode')) {            this.dealModeToggle.checked = params.get('deal_mode') === 'true' || params.get('deal_mode') === '1';          }                    // Re-apply layout after params have updated control values          this.applyLayoutMode();                    if (params.get('search')) {            initialQuery = params.get('search');          } else if (params.get('q')) {            initialQuery = params.get('q');          } else if (params.get('query')) {            initialQuery = params.get('query');          }                    this.currentQuery = initialQuery;          if (this.searchInput) {            this.searchInput.value = this.currentQuery;          }                    if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {            this.fetchDeals(this.currentQuery);          } else {            this.render();          }        }        updatePriceDropdownCurrency() {          if (!this.priceFilter || !this.regionSelect) return;          const currencySymbols = {            'US': '$',            'GB': '£',            'CA': '$CA',            'AU': '$AU',            'DE': '€',            'FR': '€',            'IT': '€',          };          const area = this.getAreaCode();          const cur = currencySymbols[area || 'US'] || '$';                    const options = this.priceFilter.options;          for (let i = 0; i < options.length; i++) {            const opt = options[i];            if (opt.value === 'all') {              opt.innerText = 'All Prices';            } else if (opt.value === 'under50') {              opt.innerText = `Under ${cur}50`;            } else if (opt.value === '50_100') {              opt.innerText = `${cur}50 - ${cur}100`;            } else if (opt.value === '100_200') {              opt.innerText = `${cur}100 - ${cur}200`;            } else if (opt.value === '200_500') {              opt.innerText = `${cur}200 - ${cur}500`;            } else if (opt.value === 'over500') {              opt.innerText = `Over ${cur}500`;            }          }        }        populateBrandDropdown(values) {          if (!this.brandDropdown || !this.brandFilterWrapper) return;          this.brandFilterWrapper.style.display = 'flex'; // show the wrapper                    let html = '';          const allChecked = this.selectedBrands.length === 0 ? 'checked' : '';          const _div = '<' + '/div>';          const _span = '<' + '/span>';          html += `\x3Cdiv class="tg-df-ms-option">\x3Cinput type="checkbox" value="" ${allChecked} class="tg-df-brand-chk"> Any Brand${_div}`;                    values.forEach(v => {             if (!v.formatted_value || v.formatted_value === 'Any Brand') return;             const isChecked = this.selectedBrands.includes(v.formatted_value) ? 'checked' : '';             html += `\x3Cdiv class="tg-df-ms-option">\x3Cinput type="checkbox" value="${this.escapeHTML(v.formatted_value)}" ${isChecked} class="tg-df-brand-chk"> ${this.escapeHTML(v.formatted_value)} \x3Cspan style="color:var(--tg-df-text-muted);font-size:12px">(${v.count || 0})${_span}${_div}`;          });                    this.brandDropdown.innerHTML = html;                    // Re-bind listeners          const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');          chks.forEach(chk => {            chk.addEventListener('change', (e) => {              const val = e.target.value;              if (val === '') {                this.selectedBrands = [];              } else {                if (e.target.checked) {                   if (!this.selectedBrands.includes(val)) this.selectedBrands.push(val);                } else {                   this.selectedBrands = this.selectedBrands.filter(b => b !== val);                }              }                            if (this.selectedBrands.length === 0) {                 this.brandTrigger.innerText = 'Any Brand';              } else if (this.selectedBrands.length === 1) {                 this.brandTrigger.innerText = this.selectedBrands[0];              } else {                 this.brandTrigger.innerText = `${this.selectedBrands.length} Brands selected`;              }                            // Only call API if changed from UI interactions              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                 this.updateURLParams();                 this.fetchDeals(this.currentQuery);              }            });          });                    // Update button text on load          if (this.selectedBrands.length === 0) {             this.brandTrigger.innerText = 'Any Brand';          } else if (this.selectedBrands.length === 1) {             this.brandTrigger.innerText = this.selectedBrands[0];          } else {             this.brandTrigger.innerText = `${this.selectedBrands.length} Brands selected`;          }        }        updateURLParams() {          const url = new URL(window.location);          if (this.currentQuery && this.currentQuery !== 'Gaming laptops') {            url.searchParams.set('q', this.currentQuery);          } else {            url.searchParams.delete('q');            url.searchParams.delete('search');            url.searchParams.delete('query');          }                    if (this.regionSelect && this.regionSelect.value !== 'auto') {            url.searchParams.set('region', this.regionSelect.value);          } else {            url.searchParams.delete('region');          }                    if (this.retailerSelect && this.retailerSelect.value) {            url.searchParams.set('retailer', this.retailerSelect.value);          } else {            url.searchParams.delete('retailer');          }                    if (this.selectedBrands && this.selectedBrands.length > 0) {            url.searchParams.set('brands', this.selectedBrands.join(','));          } else {            url.searchParams.delete('brands');          }                    if (this.offerTypeSelect && this.offerTypeSelect.value) {            url.searchParams.set('offer_type', this.offerTypeSelect.value);          } else {            url.searchParams.delete('offer_type');          }                    if (this.viewModeSelect && this.viewModeSelect.value !== 'auto') {            url.searchParams.set('view_mode', this.viewModeSelect.value);          } else {            url.searchParams.delete('view_mode');          }                    if (this.rowsSelect && this.rowsSelect.value !== '12') {            url.searchParams.set('rows', this.rowsSelect.value);          } else {            url.searchParams.delete('rows');          }                    const min = this.customPriceMin ? this.customPriceMin.value : '';          const max = this.customPriceMax ? this.customPriceMax.value : '';          if (min || max) {             url.searchParams.set('price', `${min}_${max}`);          } else if (this.priceFilter && this.priceFilter.value !== 'all') {            url.searchParams.set('price', this.priceFilter.value);          } else {            url.searchParams.delete('price');          }                    if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {            const v = parseInt(this.discountFilter.value);            if (!isNaN(v) && v > 0) {               const ratio = (100 - v) / 100;               url.searchParams.set('min_discount_ratio', ratio.toString());            }          } else {            url.searchParams.delete('min_discount_ratio');          }                    if (this.sortSelect && this.sortSelect.value !== 'discount_desc') {            url.searchParams.set('sort', this.sortSelect.value);          } else {            url.searchParams.delete('sort');          }                    if (this.dealModeToggle && this.dealModeToggle.checked) {            url.searchParams.set('deal_mode', 'true');          } else {            url.searchParams.delete('deal_mode');          }                    window.history.replaceState({}, '', url);        }        bindEvents() {          const roundels = this.root.querySelectorAll('.tg-df-carousel-cat.original-hardcoded');          roundels.forEach(r => {             r.addEventListener('click', () => {                const q = r.getAttribute('data-query');                const pr = r.getAttribute('data-pr');                if (typeof trackHawkEvent !== 'undefined') {                     trackHawkEvent({                         clickType: "CC",                         widgetId: this.widgetId,                         productCategoryName: "deals",                         zeroBasedProductIndexOrNull: null,                         totalDealsOrProducts: null,                         areaClicked: "Category Roundel",                         revenueId: this.revenueId,                         isoCurrencyCode: typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD',                         queryName: q,                         widgetTypeName: this.widgetTypeName                     });                 }                this.currentQuery = q;                const label = this.root.querySelector('#tg-df-carousel-title-label');                if (label) label.textContent = 'Best ' + q;                if (this.priceFilter) this.priceFilter.value = pr || 'all';                if (this.discountFilter) this.discountFilter.value = '5';                if (this.searchInput) this.searchInput.value = q;                                roundels.forEach(ro => ro.classList.remove('active'));                r.classList.add('active');                this.fetchDeals(this.currentQuery);             });          });          const discBtns = this.root.querySelectorAll('.tg-df-carousel-filter-btn');          discBtns.forEach(b => {             b.addEventListener('click', () => {                const d = b.getAttribute('data-d');                const pr = b.getAttribute('data-pr');                const ot = b.getAttribute('data-ot');                let label = b.innerText ? b.innerText.trim() : '';                let filterType = 'unknown';                let filterVal = 'unknown';                if (d !== null) { filterType = 'discount'; filterVal = d; }                else if (pr !== null) { filterType = 'price'; filterVal = pr; }                else if (ot !== null) { filterType = 'offertype'; filterVal = ot; }                if (typeof trackElementInteraction === 'function') trackElementInteraction({ id: `filter-${filterType}-${filterVal}`, name: 'Filter Button', label: label });                                if (d !== null) {                   if (this.discountFilter) this.discountFilter.value = this.discountFilter.value === d ? '0' : d;                } else if (pr !== null) {                   if (this.priceFilter) this.priceFilter.value = this.priceFilter.value === pr ? 'all' : pr;                } else if (ot !== null) {                   if (this.offerTypeSelect) this.offerTypeSelect.value = this.offerTypeSelect.value === ot ? 'all' : ot;                } else {                   if (this.discountFilter) this.discountFilter.value = '0';                   if (this.priceFilter) this.priceFilter.value = 'all';                   if (this.offerTypeSelect) this.offerTypeSelect.value = 'all';                }                if (d === null && pr === null && ot === null && b.getAttribute("data-type") !== "custom") {                   discBtns.forEach(ro => ro.classList.remove('active'));                   b.classList.add('active');                } else if (b.getAttribute("data-type") !== "custom") {                   // Only operate on hardcoded buttons (those without data-type)                   discBtns.forEach(ro => {                      if (!ro.getAttribute('data-d') && !ro.getAttribute('data-pr') && !ro.getAttribute('data-ot') && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active');                   });                                      let makeActive = true;                   if (d !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-d') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   } else if (pr !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-pr') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   } else if (ot !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-ot') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   }                                      if (makeActive) b.classList.add('active');                                      // Check if anything is active, if not activate "All"                   let anyActive = false;                   discBtns.forEach(ro => { if (ro.classList.contains('active') && ro.getAttribute('data-type') !== 'custom') anyActive = true; });                   if (!anyActive) {                       discBtns.forEach(ro => { if (!ro.getAttribute('data-d') && !ro.getAttribute('data-pr') && !ro.getAttribute('data-ot') && ro.getAttribute('data-type') !== 'custom') ro.classList.add('active'); });                   }                }                                this.fetchDeals(this.currentQuery);             });          });          if (this.brandTrigger && this.brandDropdown) {            this.brandTrigger.addEventListener('click', () => {              this.brandDropdown.classList.toggle('active');            });            document.addEventListener('click', (e) => {              if (this.brandFilterWrapper && !e.composedPath().includes(this.brandFilterWrapper)) {                this.brandDropdown.classList.remove('active');              }            });          }          let debounceTimer;          if(this.searchInput) {            this.searchInput.addEventListener('input', (e) => {              clearTimeout(debounceTimer);              const query = e.target.value.trim();              this.currentQuery = query;              if (this.getViewMode() === 'savings_squad' && this.autocompleteDropdown && this.airedaleTags && query.length > 0) {                 const matches = this.airedaleTags.filter(t => t.toLowerCase().includes(query.toLowerCase()) && t.toLowerCase() !== query.toLowerCase()).slice(0, 5);                 if (matches.length > 0) {                    this.autocompleteDropdown.innerHTML = matches.map(m => `\x3Cdiv class="tg-df-autocomplete-item" data-tag="${this.escapeHTML(m)}">${this.escapeHTML(m)}<` + `/div>`).join('');                    this.autocompleteDropdown.classList.add('active');                 } else {                    this.autocompleteDropdown.classList.remove('active');                 }              } else if (this.autocompleteDropdown) {                 this.autocompleteDropdown.classList.remove('active');              }              debounceTimer = setTimeout(() => {                this.updateURLParams();                if (query.length > 2) {                  this.fetchDeals(query);                } else if (query.length === 0) {                  this.deals = [];                  this.render();                }              }, 400);            });            this.searchInput.addEventListener('keypress', (e) => {              if (e.key === 'Enter') {                if (this.autocompleteDropdown) this.autocompleteDropdown.classList.remove('active');                clearTimeout(debounceTimer);                const query = e.target.value.trim();                this.currentQuery = query;                this.activeDealTag = null;                trackElementInteraction({ id: 'search-submit', name: 'Ask', label: 'Ask (main search)', text: query });                this.updateURLParams();                if (query.length > 2 || (this.getViewMode() === 'savings_squad')) {                   this.fetchDeals(query);                }              }            });          }          if (this.autocompleteDropdown) {             this.autocompleteDropdown.addEventListener('click', (e) => {                const item = e.target.closest('.tg-df-autocomplete-item');                if (item) {                   const tag = item.getAttribute('data-tag');                   this.currentQuery = tag;                   if (this.searchInput) this.searchInput.value = tag;                   this.activeDealTag = tag;                   this.autocompleteDropdown.classList.remove('active');                   this.updateURLParams();                   this.fetchDeals(tag);                }             });             document.addEventListener('click', (e) => {               if (this.autocompleteDropdown && this.searchInput && !e.composedPath().includes(this.searchInput) && !e.composedPath().includes(this.autocompleteDropdown)) {                 this.autocompleteDropdown.classList.remove('active');               }             });          }          if (this.searchBtn) {            this.searchBtn.addEventListener('click', () => {              if (this.autocompleteDropdown) this.autocompleteDropdown.classList.remove('active');              clearTimeout(debounceTimer);              const query = this.searchInput.value.trim();              trackElementInteraction({ id: 'search-submit', name: 'Ask', label: 'Ask (main search)', text: query });              this.activeDealTag = null;              this.currentQuery = query;              this.updateURLParams();              if (query.length > 2 || (this.getViewMode() === 'savings_squad')) {                 this.fetchDeals(query);              }            });          }          if(this.sortSelect) this.sortSelect.addEventListener('change', () => {            trackElementInteraction({ id: `sort-option-${this.sortSelect.value}`, name: 'Sort', label: `Sort: ${this.sortSelect.options[this.sortSelect.selectedIndex].text}` });            this.updateURLParams();            if (this.deals.length > 0) {              this.sortData();              this.render();            }          });                    const priceFilter = this.root.querySelector('#tg-df-price-filter');          if (priceFilter) {            this.priceFilter = priceFilter;            this.priceFilter.addEventListener('change', () => {              trackElementInteraction({ id: `filter-price-${this.priceFilter.value}`, name: 'Price', label: this.priceFilter.options[this.priceFilter.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }            });          }          const updateCustomPrice = () => {             this.updateURLParams();             if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);             } else {                this.render();             }          };          if (this.customPriceMin) {             this.customPriceMin.addEventListener('change', updateCustomPrice);             this.customPriceMin.addEventListener('keypress', (e) => {                if (e.key === 'Enter') updateCustomPrice();             });          }          if (this.customPriceMax) {             this.customPriceMax.addEventListener('change', updateCustomPrice);             this.customPriceMax.addEventListener('keypress', (e) => {                if (e.key === 'Enter') updateCustomPrice();             });          }          const discountFilter = this.root.querySelector('#tg-df-discount-filter');          if (discountFilter) {            this.discountFilter = discountFilter;            this.discountFilter.addEventListener('change', () => {              trackElementInteraction({ id: `filter-discount-${this.discountFilter.value}`, name: 'Discount', label: this.discountFilter.options[this.discountFilter.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }            });          }          if (this.categoryFilter) {            this.categoryFilter.addEventListener('change', (e) => {               const val = e.target.value === 'all' ? null : e.target.value;               this.activeDealTag = val;               this.fetchSavingsSquad();            });          }                    if (this.settingsToggle) {            this.settingsToggle.addEventListener('click', () => {              const o = this.settingsPanel.classList.toggle('active');              this.settingsBackdrop.classList.toggle('active');              if (o) trackElementInteraction({ id: 'filter-open', name: 'Filters', label: 'Open filters' });            });          }                    if (this.settingsBackdrop) {            this.settingsBackdrop.addEventListener('click', () => {              this.settingsPanel.classList.remove('active');              this.settingsBackdrop.classList.remove('active');            });          }                    if (this.regionSelect) {            this.regionSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-region-${this.regionSelect.value}`, name: 'Region', label: this.regionSelect.options[this.regionSelect.selectedIndex].text });              this.updateURLParams();              this.updatePriceDropdownCurrency();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.retailerSelect) {            this.retailerSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-merchant-${this.retailerSelect.value}`, name: 'Retailer', label: this.retailerSelect.options[this.retailerSelect.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.offerTypeSelect) {            this.offerTypeSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-offertype-${this.offerTypeSelect.value}`, name: 'Offer Type', label: this.offerTypeSelect.options[this.offerTypeSelect.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.viewModeSelect) {            this._prevViewMode = this.viewModeSelect.value;            this.viewModeSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-viewmode-${this.viewModeSelect.value}`, name: 'View Mode', label: this.viewModeSelect.options[this.viewModeSelect.selectedIndex].text });                            // Reset all active toggles and filters to prevent config carry-over              this.selectedBrands = [];              if (this.brandTrigger) this.brandTrigger.innerText = 'Select Brands';              if (this.brandDropdown) {                const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                chks.forEach(chk => { chk.checked = false; });              }              if (this.priceFilter) this.priceFilter.value = 'all';              if (this.customPriceMin) this.customPriceMin.value = '';              if (this.customPriceMax) this.customPriceMax.value = '';              if (this.sortSelect) this.sortSelect.value = this.viewModeSelect.value === 'savings_squad' ? 'date_desc' : 'discount_desc';              if (this.discountFilter) this.discountFilter.value = '0';              if (this.retailerSelect) this.retailerSelect.value = '';              if (this.offerTypeSelect) this.offerTypeSelect.value = '';              if (this.rowsSelect) this.rowsSelect.value = '12';              if (this.categoryFilter) this.categoryFilter.value = 'all';              this.activeDealTag = null;              this.updateURLParams();              this.applyLayoutMode();                            if (this.getViewMode() === 'savings_squad' || this._prevViewMode === 'savings_squad') {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }              this._prevViewMode = this.viewModeSelect.value;            });          }                    if (this.rowsSelect) {            this.rowsSelect.addEventListener('change', () => {              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.dealModeToggle) {            this.dealModeToggle.addEventListener('change', () => {              this.updateURLParams();              this.render();            });          }          if (this.editorModeToggle) {             this.editorModeToggle.addEventListener('change', (e) => {                this.editorMode = e.target.checked;                this.render();                this.updateFloatingCopyBar();             });          }          if (this.editorCopyBtn) {             this.editorCopyBtn.addEventListener('click', () => {                this.copySelectedDealsToCMS();             });          }          if (this.editorClearBtn) {             this.editorClearBtn.addEventListener('click', () => {                this.selectedDeals.clear();                this.render();                this.updateFloatingCopyBar();             });          }          if (this.grid) {            this.grid.addEventListener('change', (e) => {               if (e.target.classList.contains('tg-df-deal-checkbox')) {                  const dealId = e.target.getAttribute('data-id');                  if (e.target.checked) {                     const dealObj = this.deals.find(d => d.id === dealId);                     if (dealObj) this.selectedDeals.set(dealId, dealObj);                  } else {                     this.selectedDeals.delete(dealId);                  }                  this.updateFloatingCopyBar();               }            });            this.grid.addEventListener('click', (e) => {              const dealCard = e.target.closest('[data-action="deal-click"]');              const similarCard = e.target.closest('[data-action="view-similar-click"]');              const cardLink = dealCard || similarCard;              if (cardLink) {                const productName = cardLink.getAttribute('data-product-name');                const merchantName = cardLink.getAttribute('data-merchant-name');                const productId = cardLink.getAttribute('data-analytics-id');                const price = parseFloat(cardLink.getAttribute('data-price')) || null;                const prevPriceStr = cardLink.getAttribute('data-previous-price');                const previousPrice = prevPriceStr ? parseFloat(prevPriceStr) : null;                const originalLink = cardLink.getAttribute('data-original-link');                const rewrittenLink = cardLink.getAttribute('href');                const revenueId = cardLink.getAttribute('data-revenue-id');                const index = parseInt(cardLink.getAttribute('data-index'), 10) || 0;                const inStock = cardLink.getAttribute('data-in-stock') === 'true';                const totalText = cardLink.getAttribute('data-total');                const totalDeals = parseInt(totalText, 10) || 0;                const productCategoryName = 'deals';                const trackingParams = {                  widgetId: this.widgetId,                  productCategoryName: productCategoryName,                  product: {                    modelId: cardLink.getAttribute('data-model-id') || null,                    matchId: cardLink.getAttribute('data-match-id') || null,                    brand: cardLink.getAttribute('data-model-brand') || null,                    parent: cardLink.getAttribute('data-model-parent') || null,                    name: productName,                    price: price,                    previousPrice: previousPrice,                    link: rewrittenLink,                    originalLink: originalLink,                    inStock: inStock                  },                  zeroBasedProductIndexOrNull: index,                  totalDealsOrProducts: totalDeals,                   merchant: {                    id: cardLink.getAttribute('data-merchant-id') || null,                    network: cardLink.getAttribute('data-merchant-network') || null,                    url: cardLink.getAttribute('data-merchant-url') || null,                    name: merchantName                  },                  revenueId: revenueId,                  widgetTypeName: this.widgetTypeName,                  isoCurrencyCode: normalizeCurrency(this.escapeHTML(cardLink.getAttribute('data-currency') || '$'))                };                if (dealCard) {                  trackDealClick(trackingParams);                } else {                  trackViewSimilarClick(trackingParams);                }              }              const couponsBtn = e.target.closest('[data-action="coupons-click"]');              if (couponsBtn) {                trackElementInteraction({                  id: 'product-card-show-coupons',                  name: 'Coupons',                  label: `Product card coupons: ${couponsBtn.getAttribute('data-merchant')}`                });              }            });          }          this.setupScrollListeners();        }        setupScrollListeners() {          const containers = [             this.root.querySelector('.tg-df-carousel-roundels'),             this.root.querySelector('.tg-df-carousel-filters-wrap'),             this.root.querySelector('#tg-df-grid')          ];                    containers.forEach(container => {             if (!container) return;                          const checkScroll = () => {                if (!container.parentElement) return;                const leftBtn = container.parentElement.querySelector('.tg-df-carousel-scroll-left');                const rightBtn = container.parentElement.querySelector('.tg-df-carousel-scroll-right');                                if (leftBtn) {                   if (container.scrollLeft <= 5) leftBtn.style.display = 'none';                   else leftBtn.style.display = 'flex';                }                                if (rightBtn) {                   if (container.scrollWidth <= container.clientWidth) {                       rightBtn.style.display = 'none';                   } else if (container.scrollLeft >= container.scrollWidth - container.clientWidth - 5) {                       rightBtn.style.display = 'none';                   } else {                       rightBtn.style.display = 'flex';                   }                }             };                          container.addEventListener('scroll', checkScroll);             checkScroll();                          window.addEventListener('resize', checkScroll);                          const observer = new MutationObserver(checkScroll);             observer.observe(container, { childList: true, subtree: true, characterData: false });          });        }        get widgetTypeName() {          const mode = this.viewModeSelect ? this.viewModeSelect.value : (this.viewModeOverride || 'auto');          switch(mode) {              case 'carousel': return 'Carousel';              case 'savings_squad': return 'Savings Squad';              case 'grid': return 'Grid';              case 'row': return 'Row';              default: return 'Auto Collection';          }        }        getRowsLimit() {          if (this.rowsSelect && this.rowsSelect.value) return parseInt(this.rowsSelect.value, 10);          let configSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {             configSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {             configSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(configSource);          if (params.has('rows')) return parseInt(params.get('rows'), 10) || 12;          return 12;        }        getAreaCode() {          if (this.regionSelect && this.regionSelect.value) {            if (this.regionSelect.value === 'auto') return null;            return this.regionSelect.value;          }          let area = null;          try {            const locale = window.navigator.language || window.navigator.userLanguage;            if (locale && locale.includes('-')) {              area = locale.split('-')[1].toUpperCase();            } else if (locale && locale.length === 2) {              if (locale.toUpperCase() === 'EN') { area = 'US'; }              else { area = locale.toUpperCase(); }            }          } catch (e) { /* Ignore */ }                    // Map to known valid options or fallback to US          const valid = ['US', 'GB', 'CA', 'AU', 'DE', 'FR', 'IT'];          if (area === 'UK') area = 'GB';          if (valid.includes(area)) {             return area;          }          return 'US';        }                async loadCarouselSpreadsheet() {          try {              const parseCSVRow = (str) => {                  let result = [], cur = '', inQuotes = false;                  for (let i = 0; i < str.length; i++) {                      let char = str[i];                      if (inQuotes) {                          if (char === '"') {                              if (str[i + 1] === '"') { cur += '"'; i++; }                              else { inQuotes = false; }                          } else { cur += char; }                      } else {                          if (char === '"') { inQuotes = true; }                          else if (char === ',') { result.push(cur); cur = ''; }                          else { cur += char; }                      }                  }                  result.push(cur); return result;              };              const parseCSV = (str) => {                  const rows = []; let curRow = '', inQuotes = false;                  for (let i = 0; i < str.length; i++) {                      let char = str[i];                      if (char === '"') inQuotes = !inQuotes;                      if ((char === '\n' || char === '\r') && !inQuotes) {                          if (char === '\r' && str[i+1] === '\n') i++;                          if (curRow) rows.push(parseCSVRow(curRow));                          curRow = '';                      } else { curRow += char; }                  }                  if (curRow) rows.push(parseCSVRow(curRow));                  return rows;              };              const preloadedCSV = decodeURIComponent(escape(atob("LCwxLDIsMyw0LDUsNiw3LDgsOSwxMCwxMSwxMiwxMywxNCwxNQ0KUm91bmRlbCB0ZXh0LEFsbCxUVnMsRm9vdHdlYXIsQXBwYXJlbCxNYXR0cmVzZXMsQXBwbGlhbmNlcyxXZWFyYWJsZSB0ZWNoLEhlYWRwaG9uZXMsU21hcnQgSG9tZSxTcGVha2VycyxMYXB0b3BzLFRhYmxldHMsQ29tcHV0aW5nLFBob25lcyxHYW1pbmcsTGVnbw0KUm91bmRlbCBpbWFnZSxodHRwczovL3d3dy50b21zZ3VpZGUuY29tL3Byb2R1Y3RzL2Nhcm91c2VsL2FpLnBuZyxodHRwczovL3d3dy50b21zZ3VpZGUuY29tL3Byb2R1Y3RzL2Nhcm91c2VsL3R2cy5wbmcsaHR0cHM6Ly9pbWFnZXMuZmllLmZ1dHVyZWNkbi5uZXQvcHJvZHVjdHMvN2IzYTIyNGIwNzk2M2M2MjdiNmI5MDliZDc4MzM4MzZlMDJmZjgxOS5qcGcud2VicCxodHRwczovL2ltYWdlcy5maWUuZnV0dXJlY2RuLm5ldC9wcm9kdWN0cy84NGRhYzVkNDhlZDJkNDQ4NTU5ZWJhNjdhY2U4MzE0Y2M2N2NjZDk0LmpwZy53ZWJwLGh0dHBzOi8vd3d3LnRvbXNndWlkZS5jb20vcHJvZHVjdHMvY2Fyb3VzZWwvbWF0dHJlc3Nlcy5wbmcsaHR0cHM6Ly9pbWFnZXMuZmllLmZ1dHVyZWNkbi5uZXQvcHJvZHVjdHMvNzY4ZTk3Y2ViMDcxODAxZmFlMjA5MTBkMDgyMGIxNmY3NDdhZjkzOS5qcGcud2VicCxodHRwczovL3d3dy50b21zZ3VpZGUuY29tL3Byb2R1Y3RzL2Nhcm91c2VsL3dlbGxuZXNzLnBuZyxodHRwczovL3d3dy50b21zZ3VpZGUuY29tL3Byb2R1Y3RzL2Nhcm91c2VsL2hlYWRwaG9uZXMuanBnLGh0dHBzOi8vaW1hZ2VzLmZpZS5mdXR1cmVjZG4ubmV0L3Byb2R1Y3RzLzg5NTM1YmVlYmUyMGRiYmQ0YTM0NmQ2ZDZiZGZlOTFkOGE4ODRhMjEuanBnLndlYnAsaHR0cHM6Ly93d3cudG9tc2d1aWRlLmNvbS9wcm9kdWN0cy9jYXJvdXNlbC9hdWRpby5qcGcsaHR0cHM6Ly93d3cudG9tc2d1aWRlLmNvbS9wcm9kdWN0cy9jYXJvdXNlbC9sYXB0b3BzLmpwZyxodHRwczovL2ltYWdlcy5maWUuZnV0dXJlY2RuLm5ldC9wcm9kdWN0cy8yMzk3NTY0ZWQ3YTVmZjk0N2U5YjZiMzBlNTRmNDc0OTRiODQxZjg5LmpwZy53ZWJwLGh0dHBzOi8vd3d3LnRvbXNndWlkZS5jb20vcHJvZHVjdHMvY2Fyb3VzZWwvY29tcHV0aW5nLmpwZyxodHRwczovL3d3dy50b21zZ3VpZGUuY29tL3Byb2R1Y3RzL2Nhcm91c2VsL3Bob25lcy5wbmcsaHR0cHM6Ly93d3cudG9tc2d1aWRlLmNvbS9wcm9kdWN0cy9jYXJvdXNlbC9nYW1pbmcucG5nLGh0dHBzOi8vaW1hZ2VzLmZpZS5mdXR1cmVjZG4ubmV0L3Byb2R1Y3RzLzRmNmM2MjFjYWMwYmMxYTg1ZDU5M2UzNTk0YmE1YjM0OWVmZmQyOTIuanBnLndlYnANClNlYXJjaCBRdWVyeSxFdmVyeXRoaW5nLFRlbGV2aXNpb25zLCJTbmVha2VycywgcnVubmluZyBzaG9lcywgc2FuZGFscyIsQ2xvdGhpbmcsTWF0dHJlc3NlcyxIb21lIEFwcGxpYW5jZXMsV2VhcmFibGVzICYgRml0bmVzcyBUZWNoLEhlYWRwaG9uZXMsSG9tZSBUZWNoLFNwZWFrZXJzLExhcHRvcHMsVGFibGV0cyxDb21wdXRpbmcsUGhvbmVzLEdhbWluZyxDb25zdHJ1Y3Rpb24gVG95cw0KRGlzY291bnQgQW1vdW50LG1pbiA1JSxtaW4gMTAlLG1pbiA1JSxtaW4gNSUsbWluIDUlLG1pbiA1JSxtaW4gNSUsbWluIDUlLG1pbiA1JSxtaW4gNSUsbWluIDUlLG1pbiA1JSxtaW4gNSUsbWluIDUlLG1pbiA1JSxtaW4gNSUNClByaWNlIFJhbmdlLCwsLCxtaW4gJDQwMCwsLCxtaW4gJDI1LCxtaW4gJDMwMCwsLG1pbiAkMTAwLCwNCkJyYW5kIFNlbGVjdGlvbiwsLCwsLCwsLCwsLCwsLCwNCkZpbHRlciBidXR0b25zLCwsLCwsLCwsLCwsLCwsLA0KMSxMaWdodG5pbmcgZGVhbHMsTGlnaHRuaW5nIGRlYWxzLExpZ2h0bmluZyBkZWFscyxMaWdodG5pbmcgZGVhbHMsTGlnaHRuaW5nIGRlYWxzLExpZ2h0bmluZyBkZWFscyxMaWdodG5pbmcgZGVhbHMsTGlnaHRuaW5nIGRlYWxzLExpZ2h0bmluZyBkZWFscyxMaWdodG5pbmcgZGVhbHMsTGlnaHRuaW5nIGRlYWxzLExpZ2h0bmluZyBkZWFscyxMaWdodG5pbmcgZGVhbHMsTGlnaHRuaW5nIGRlYWxzLExpZ2h0bmluZyBkZWFscyxMaWdodG5pbmcgZGVhbHMNCjIsQW1hem9uIGRlYWxzLFVuZGVyICQxMDAwLDUwJSBvZmYsQWRpZGFzLEFtYXpvbiBkZWFscyxBbWF6b24gZGVhbHMsNTAlIG9mZixBbWF6b24gZGVhbHMsQW1hem9uIGRlYWxzLEFtYXpvbiBkZWFscyxBbWF6b24gZGVhbHMsQW1hem9uIGRlYWxzLEFtYXpvbiBkZWFscyxBbWF6b24gZGVhbHMsQW1hem9uIGRlYWxzLEFtYXpvbiBkZWFscw0KMyxPdmVyICQ0MDAsVW5kZXIgJDUwMCxIb2thLE5pa2UsU2FhdHZhLE5pbmphLDQwJSBvZmYsSkxhYiwsSkJMLERlbGwsLEFzdXMsQXBwbGUsQ29uc29sZXMsU3RhciBXYXJzDQo0LFVuZGVyICQxMDAwLDUwJSBvZmYsU2tlY2hlcnMsVW5kZXIgQXJtb3VyLEhlbGl4LFNoYXJrLEdhcm1pbixBbmtlciBTb3VuZGNvcmUsUmluZyxTb25vcyxBcHBsZSxBcHBsZSxUUC1saW5rLFNhbXN1bmcsQWNjZXNzb3JpZXMsVW5kZXIgJDI1DQo1LFVuZGVyICQ1MDAsTEcsQXNpY3MsQ29sdW1iaWEsRHJlYW1DbG91ZCxLZXVyaWcsQXBwbGUsU29ueSxHb3ZlZSxUcmliaXQsTGVub3ZvLFNhbXN1bmcsRWVybyxHb29nbGUsR2FtZXMsVW5kZXIgJDUwDQo2LDUwJSBvZmYsU2Ftc3VuZyxOaWtlLFBhdGFnb25pYSxOZWN0YXIsRGUnTG9uZ2hpLEFtYXpmaXQsQXBwbGUsS2FzYSBzbWFydCxTb255LEFsaWVud2FyZSxUQ0wsTmV0Z2VhcixNb3Rvcm9sYSxOaW50ZW5kbyxCb3RhbmljYWxzDQo3LEFtYXpvbixIaXNlbnNlLE5ldyBCYWxhbmNlLEFyYyd0ZXJ5eCxUZW1wdXItcGVkaWMsRHlzb24sRml0Yml0LEJlYXRzLFBoaWxpcHMgSHVlLEFua2VyLEFjZXIsT25lUGx1cyxEZWxsLE9uZVBsdXMsU29ueSxEaXNuZXkNCjgsQXBwbGUsVENMLEFkaWRhcyxDYXJoYXJ0dCxCZWFyLEJpc3NlbGwsU2Ftc3VuZyxFYXJmdW4sQmxpbmssQmVhdHMsTVNJLE1pY3Jvc29mdCxBY2VyLE5vdGhpbmcsWGJveCxNYXJ2ZWwNCjksLFNvbnksU2F1Y29ueSxUaGUgTm9ydGggRmFjZSxTaWVuYSxOdXRyaWJ1bGxldCxPdXJhLFNhbXN1bmcsR29vZ2xlIE5lc3QgLE1hcnNoYWxsLFNhbXN1bmcsTGVub3ZvLExlbm92bywsLFBva2Vtb24NCjEwLCxSb2t1LEJpcmtlbnN0b2NrLENSWiBZb2dhLFdpbmtCZWRzLEJsYWNrIGFuZCBEZWNrZXIsUmluZ2Nvbm4sQ01GLEV1ZnksU2Ftc3VuZyxNaWNyb3NvZnQsUmVNYXJrYWJsZSxBbGllbndhcmUsLCwNCjExLCwsQnJvb2tzLFRoZSBHeW0gUGVvcGxlLEJyb29rbHluIGJlZGRpbmcsTmVzcHJlc3NvLCwxTW9yZSxBcmxvLCxSYXplciwsQ29yc2FpciwsLA0KMTIsLCxDcm9jcywsRWlnaHQgU2xlZXAsQ3Vpc2luYXJ0LCxKQkwsLCwsLEhQLCwsDQpOb3RlcywsLCwsLCwsLCwsLCwsLCwNCiwsIlByaW9yaXRpc2UgYmlnZ2VzdCAlLyQgZGlzY291bnQsIFR2cyB3aXRoIH41MCUgb2ZmIGhhdmUgYmVlbiB0aGUgbW9zdCBwb3B1bGFyIGV2ZW4gaWYgdGhleSBhcmUgc3RpbGwgZXhwZW5zaXZlIiwiTm8gcGF0dGVybiB0byBwcmljaW5nL2Rpc2NvdW50LCByZWFkZXJzIG1haW5seSBzaG9wIGJ5IGJyYW5kL3JlY29nbmlzYWJsZSBzaG9lcyIsIk5vIHBhdHRlcm4gdG8gcHJpY2luZy9kaXNjb3VudCwgcmVhZGVycyBtYWlubHkgc2hvcCBieSBicmFuZCIsIkEgbGFiZWwgd2lsbCBkZWZpbml0ZWx5IGhlbHAgaGVyZSBlLmcuIGJlc3QgZm9yIHNpZGUgc2xlZXBlciwgYmVzdCBtZW1vcnkgZm9hbSIsIkFwcGxpYW5jZXMgaXMgYSBiaWcgY2F0ZWdvcnksIGlzIGl0IHBvc3NpYmxlIHRvIHNwbGl0IGludG8ga2l0Y2hlbiBhcHBsaWFuY2VzLCBmbG9vcmNhcmUsIGFpciBoZWFsdGgvY29vbGluZz8gT3Igc2ltaWxhciIsIkZvY3VzIG9uIHZhbHVlIGZvciBtb25leSwgR2FybWlucyB3aXRoIH41MCUgb2ZmIGhhdmUgYmVlbiBwb3B1bGFyIGV2ZW4gdGhvdWdoIHRoZXkgYXJlIHN0aWxsICQ1MDAiLCwsLCxJbmNsdWRlIEtpbmRsZXMsSSB3b3VsZCBpbmNsdWRlIHdpZmkgcm91dGVycyBoZXJlIGluc3RlYWQgb2Ygc21hcnQgaG9tZSxDYW4gd2Ugc3VyZmFjZSBwaG9uZSBwcm92aWRlciBkZWFscz8gVC1tb2JpbGUgYW5kIHZlcml6b24gd291bGQgbWFrZSBhIGxvdCBtb3JlIG1vbmV5IHRoYW4gQW1hem9uLCwNCiwsaGF2aW5nIGEgJ2Jlc3QgZm9yJyBsYWJlbCB3b3VsZCBiZSBoZWxwZnVsIGUuZy4gYmVzdCBmb3IgYnJpZ2h0IHJvb20sQ2FuIHdlIHN0b3Aga2lkcyBzaG9lcyBmcm9tIHB1bGxpbmcgdGhyb3VnaD8sIldpbGwgdGhpcyBpbmNsdWRlIGFjY2Vzc29yaWVzIGUuZy4gY2FwcywgYmFncywgaWYgc28gbWFrZSBzdXJlIHRoZXNlIGFyZSBtaXhlZCB0aHJvdWdob3V0IGNsb3RoaW5nIGRlYWxzIixXaWxsIHRoaXMgaW5jbHVkZSB0b3BwZXJzIGFuZCBwaWxsb3dzPyBTZWVpbmcgbW9yZSBtb21lbnR1bSB3aXRoIHRoaXMgY2F0ZWdvcnkgcmVjZW50bHkgc28gYSBiZWRkaW5nIHRhYiBtaWdodCB3b3JrLCwiTmVlZCB0byBtYWtlIHN1cmUgYmFuZHMsIHNjcmVlbiBwcm90ZWN0b3JzIGV0Yy4gZG9uJ3QgcHVsbCBpbnRvIGhlcmUiLCwsLCwsLCwsDQosLCJQcmlvcml0aXNlIDY1JycgYW5kIDU1JyBpbmNoIFRWcywgdGhlbiBiaWdnZXIgc2NyZWVucyBiZWZvcmUgdGhlIHNtYWxsZXIgc2l6ZXMiLCwsUXVlZW4gaXMgdGhlIG1vc3QgcG9wdWxhciBzaXplIGluIHRoZSBVUyAtIHByaW9yaXRpc2UgZGVhbHMgZm9yIHRoaXMgc2l6ZSwsLCwsLCwsLCwsDQosLCwsLCwsLCwsLCwsLCwsDQpDYXRlZ29yaWVzIHRvIGNvbnNpZGVyLCxQcm9kdWN0cyBpbmNsdWRlZCwsLCwsLCwsLCwsLCwsDQpVbmRlciAkNTA/LCxBaXIgdGFncywsLCwsLCwsLCwsLCwsDQosLFBvcnRhYmxlIGNoYXJnZXJzL3dpcmVsZXNzIGNoYXJnZXJzLCwsLCwsLCwsLCwsLCwNCiwsIldhdGVyIGJvdHRsZXMgKHN0YW5sZXlzLCBPd2FsYSwgSHlkcm8gZmxhc2ssIFlldGkpIiwsLCwsLCwsLCwsLCwsDQosLEhhbmQgaGVsZCBmYW5zLCwsLCwsLCwsLCwsLCwNCiwsLCwsLCwsLCwsLCwsLCwNCmhvbWUgb2ZmaWNlLCxvZmZpY2UgY2hhaXJzLCwsLCwsLCwsLCwsLCwNCiwsc3RhbmRpbmcgZGVza3MsLCwsLCwsLCwsLCwsLA0KLCxtb25pdG9ycywsLCwsLCwsLCwsLCwsDQosLEtleWJvYXJkcywsLCwsLCwsLCwsLCwsDQosLGRvY2tpbmcgc3RhdGlvbiwsLCwsLCwsLCwsLCwsDQosLCwsLCwsLCwsLCwsLCwsDQpHYW1pbmcsLENvbnNvbGVzLCwsLCwsLCwsLCwsLCwNCiwsQWNjZXNzb3JpZXMsLCwsLCwsLCwsLCwsLA0KLCxHYW1lcywsLCwsLCwsLCwsLCwsDQosLENvdWxkIGluY2x1ZGUgTGVnbz8sLCwsLCwsLCwsLCwsLA==")));              const text = preloadedCSV;              const parsed = parseCSV(text);                            const rowsByName = {};              let filterStart = -1;              parsed.forEach((rc, i) => {                 if (rc && rc.length > 0 && rc[0]) rowsByName[rc[0]] = rc;                 if (rc && rc.length > 0 && rc[0] === 'Filter buttons') filterStart = i;              });                            const cols = [];              if(rowsByName['Roundel text']) {                const headerRow = rowsByName['Roundel text'];                for(let col = 1; col < headerRow.length; col++) {                   let label = headerRow[col];                   if (!label) continue;                                      let q = rowsByName['Search Query'] && rowsByName['Search Query'][col] ? rowsByName['Search Query'][col] : '';                   let img = rowsByName['Roundel image'] && rowsByName['Roundel image'][col] ? rowsByName['Roundel image'][col] : '';                   let ds = rowsByName['Discount Amount'] && rowsByName['Discount Amount'][col] ? rowsByName['Discount Amount'][col] : '';                   let pr = rowsByName['Price Range'] && rowsByName['Price Range'][col] ? rowsByName['Price Range'][col] : '';                   let rt = rowsByName['Retailer'] && rowsByName['Retailer'][col] ? rowsByName['Retailer'][col] : '';                   let ot = rowsByName['Offer Type'] && rowsByName['Offer Type'][col] ? rowsByName['Offer Type'][col] : '';                                      let filters = [];                   if(filterStart > 0) {                     for(let r = filterStart + 1; r < parsed.length; r++) {                         if(!parsed[r] || parsed[r][0] === 'Notes' || parsed[r][0] === 'Categories to consider') break;                         let f = parsed[r][col];                         if(f) filters.push(f);                     }                   }                   cols.push({ label, img, q, ds, pr, rt, ot, filters });                }              }              this.carouselData = cols;              if (this.carouselData && this.carouselData.length > 0) {                 const isMatched = this.carouselData.some(c => c.q === this.currentQuery || c.label === this.currentQuery);                 if (!isMatched) {                    const first = this.carouselData[0];                    this.currentQuery = first.q || first.label;                    if (this.priceFilter) this.priceFilter.value = 'all';                    if (this.customPriceMin) this.customPriceMin.value = '';                    if (this.customPriceMax) this.customPriceMax.value = '';                    let dPr = first.pr || 'all';                    if (typeof dPr === 'string' && dPr !== 'all') {                       let prLower = dPr.toLowerCase();                       if (prLower.includes('min') || prLower.includes('over')) {                          let m = dPr.match(/(\d+)/);                          if (m && this.customPriceMin) this.customPriceMin.value = m[1];                       } else if (prLower.includes('max') || prLower.includes('under')) {                          let m = dPr.match(/(\d+)/);                          if (m && this.customPriceMax) this.customPriceMax.value = m[1];                       }                    }                    let dAm = '0';                    if(first.ds && typeof first.ds === 'string') {                       let m = first.ds.match(/(\d+)/);                       if(m) dAm = m[1];                    }                    if (this.discountFilter) this.discountFilter.value = dAm;                    if (this.offerTypeSelect) this.offerTypeSelect.value = first.ot || '';                    if (this.retailerSelect) this.retailerSelect.value = first.rt || '';                    this.selectedBrands = [];                    if (this.brandDropdown) {                        const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                        chks.forEach(chk => chk.checked = false);                    }                    if (this.searchInput) this.searchInput.value = this.currentQuery;                 }              }              this.renderCarouselUI();          } catch(e){ console.warn(e); }        }                renderCarouselUI() {           const roundelWrapper = this.root.querySelector('.tg-df-carousel-roundels');           if(!roundelWrapper || !this.carouselData) return;                      let html = '';           this.carouselData.forEach(r => {              const q = r.q || r.label;              const isActive = (this.currentQuery === q || this.currentQuery === r.label) ? 'active' : '';              const imgHtml = r.img ? `\x3Cimg src="${r.img}" alt="${r.label}" />` : `\x3Csvg width="32" height="32" fill="#1F69FF" viewBox="0 0 24 24">\x3Cpath d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z"/>\x3C/svg>`;              html += `                \x3Cdiv class="tg-df-roundel tg-df-carousel-cat ${isActive}" data-label="${this.escapeHTML(r.label)}">                  \x3Cdiv class="tg-df-roundel-img-box">${imgHtml}\x3C/div>                  \x3Cspan class="tg-df-roundel-label">${this.escapeHTML(r.label)}\x3C/span>                \x3C/div>              `;           });           roundelWrapper.innerHTML = html;                      // Rebind clicks           const roundels = this.root.querySelectorAll('.tg-df-carousel-cat');           roundels.forEach(rNode => {             rNode.addEventListener('click', () => {                const r = this.carouselData.find(c => c.label === rNode.getAttribute('data-label'));                 if(!r) return;                                  if (typeof trackHawkEvent !== 'undefined') {                     trackHawkEvent({                         clickType: "CC",                         widgetId: this.widgetId,                         productCategoryName: "deals",                         zeroBasedProductIndexOrNull: null,                         totalDealsOrProducts: null,                         areaClicked: "Category Roundel",                         revenueId: this.revenueId,                         isoCurrencyCode: typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD',                         queryName: r.label,                         widgetTypeName: this.widgetTypeName                     });                 }                this.currentQuery = r.q || r.label;                const labelTitle = this.root.querySelector('#tg-df-carousel-title-label');                if (labelTitle) labelTitle.textContent = 'Best ' + this.currentQuery;                if (this.priceFilter) this.priceFilter.value = 'all';                if (this.customPriceMin) this.customPriceMin.value = '';                if (this.customPriceMax) this.customPriceMax.value = '';                let dPr = r.pr || 'all';                if (typeof dPr === 'string' && dPr !== 'all') {                   let prLower = dPr.toLowerCase();                   if (prLower.includes('min') || prLower.includes('over')) {                      let m = dPr.match(/(\d+)/);                      if (m && this.customPriceMin) this.customPriceMin.value = m[1];                   } else if (prLower.includes('max') || prLower.includes('under')) {                      let m = dPr.match(/(\d+)/);                      if (m && this.customPriceMax) this.customPriceMax.value = m[1];                   }                }                                let discountAmount = '0';                if(r.ds && typeof r.ds === 'string') {                   let m = r.ds.match(/(\d+)/);                   if(m) discountAmount = m[1];                }                if (this.discountFilter) this.discountFilter.value = discountAmount;                if (this.offerTypeSelect) this.offerTypeSelect.value = r.ot || '';                if (this.retailerSelect) this.retailerSelect.value = r.rt || '';                                // Clear brands                    this.selectedBrands = [];                    if (this.brandDropdown) {                    const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                    chks.forEach(chk => chk.checked = false);                }                                if (this.searchInput) this.searchInput.value = this.currentQuery;                                roundels.forEach(ro => ro.classList.remove('active'));                if (rNode) rNode.classList.add('active');                                this.renderCarouselFilters(r);                this.fetchDeals(this.currentQuery);             });           });                      // Auto-highlight active           const activeR = this.carouselData.find(c => c.q === this.currentQuery || c.label === this.currentQuery);           if(activeR) this.renderCarouselFilters(activeR);        }                renderCarouselFilters(r) {           const filtersWrap = this.root.querySelector('.tg-df-carousel-filters-wrap');           if(!filtersWrap) return;                      let html = `\x3Cbutton class="tg-df-carousel-filter-btn" data-type="all">All\x3C/button>`;                      r.filters.forEach(f => {              let fL = f.toLowerCase();              let icon = '';              let logic = `data-type="custom" data-v="${this.escapeHTML(f)}"`;              if (fL === 'amazon deals' || fL === 'prime deals') {                 html += `\x3Cbutton class="tg-df-carousel-filter-btn" ${logic}>\x3Cimg src="https://cdn.mos.cms.futurecdn.net/fwoVXvL79turN3Ph535m38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/u75QjVpt3w2EsMimJiRo38-600-100.png" class="active-img" alt="" /> Prime deals\x3C/button>`;              } else if (fL === 'lightning deals') {                 html += `\x3Cbutton class="tg-df-carousel-filter-btn" ${logic}>\x3Cimg src="https://cdn.mos.cms.futurecdn.net/HqAui7w97ft2NPqBtQ5r38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/yWPQ5yyQRhUwVKzGwYbh38-600-100.png" class="active-img" alt="" /> Lightning deals\x3C/button>`;              } else {                 if (fL.includes('lightning')) {                    icon = `\x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-zap">\x3Cpolygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2">\x3C/polygon>\x3C/svg>`;                 } else if (fL.includes('% off')) {                    icon = `\x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>`;                 } else if (fL.includes('under') || fL.includes('min ')) {                    icon = `\x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-badge-dollar-sign">\x3Cpath d="M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z">\x3C/path>\x3Cpath d="M16 8h-6a2 2 0 1 0 0 4h4a2 2 0 1 1 0 4H8">\x3C/path>\x3Cpath d="M12 18V6">\x3C/path>\x3C/svg>`;                 }                 html += `\x3Cbutton class="tg-df-carousel-filter-btn" ${logic}>${icon} ${this.escapeHTML(f)}\x3C/button>`;              }           });                      filtersWrap.innerHTML = html;                      const btns = filtersWrap.querySelectorAll('button');           btns.forEach(b => {             b.addEventListener('click', () => {                const type = b.getAttribute('data-type');                if (type === 'custom') {                   const v = b.getAttribute('data-v');                   if (typeof trackElementInteraction === 'function') trackElementInteraction({ id: `filter-custom-${(v||'').toLowerCase().replace(/[^a-z0-9]+/g, '-')}`, name: 'Custom Filter', label: v });                }                if (type === 'all') {                   if (typeof trackElementInteraction === 'function') trackElementInteraction({ id: 'filter-clear-all', name: 'Clear all', label: 'Clear all filters' });                   // reset everything                   btns.forEach(btn => btn.classList.remove('active'));                   b.classList.add('active');                                      // Reset prices                   if (this.priceFilter) this.priceFilter.value = 'all';                   if (this.customPriceMin) this.customPriceMin.value = '';                   if (this.customPriceMax) this.customPriceMax.value = '';                   let dPr = r.pr || 'all';                   if (typeof dPr === 'string' && dPr !== 'all') {                      let prLower = dPr.toLowerCase();                      if (prLower.includes('min') || prLower.includes('over')) {                         let m = dPr.match(/(\d+)/);                         if (m && this.customPriceMin) this.customPriceMin.value = m[1];                      } else if (prLower.includes('max') || prLower.includes('under')) {                         let m = dPr.match(/(\d+)/);                         if (m && this.customPriceMax) this.customPriceMax.value = m[1];                      }                   }                                      let discountAmount = '0';                   if(r.ds && typeof r.ds === 'string') {                      let m = r.ds.match(/(\d+)/);                      if(m) discountAmount = m[1];                   }                   if (this.discountFilter) this.discountFilter.value = discountAmount;                   if (this.offerTypeSelect) this.offerTypeSelect.value = r.ot || '';                   if (this.retailerSelect) this.retailerSelect.value = r.rt || '';                   this.selectedBrands = [];                   if (this.brandDropdown) {                     const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                     chks.forEach(chk => chk.checked = false);                   }                } else {                   const v = b.getAttribute('data-v');                   const fL = v.toLowerCase();                                      let mapRet = ['amazon', 'walmart', 'best buy', 'target', 'john lewis', 'currys', 'argos'];                   const getCategory = (s) => {                      if (s === 'lightning deals' || s === 'amazon deals' || s === 'prime deals') return 'offer';                      if (s.includes('% off')) return 'discount';                      if (s.includes('under') || s.includes('over') || s.includes('min') || s.includes('max')) return 'price';                      if (mapRet.includes(s)) return 'retailer';                      return 'brand';                   };                   const cat = getCategory(fL);                   const wasActive = b.classList.contains('active');                   if (cat !== 'brand') {                      btns.forEach(btn => {                          if (btn === b) return;                          if (btn.getAttribute('data-type') === 'all') return;                          const bV = btn.getAttribute('data-v');                          if (!bV) return;                          if (getCategory(bV.toLowerCase()) === cat) btn.classList.remove('active');                      });                   }                   if (wasActive) b.classList.remove('active');                   else b.classList.add('active');                   let anyActive = Array.from(btns).some(btn => btn !== btns[0] && btn.classList.contains('active'));                   if (!anyActive) {                       btns[0].click();                       return;                   } else {                       btns[0].classList.remove('active');                   }                                      if (this.priceFilter) this.priceFilter.value = 'all';                   if (this.customPriceMin) this.customPriceMin.value = '';                   if (this.customPriceMax) this.customPriceMax.value = '';                   let dPr = r.pr || 'all';                   if (typeof dPr === 'string' && dPr !== 'all') {                      let prLower = dPr.toLowerCase();                      if (prLower.includes('min') || prLower.includes('over')) {                         let m = dPr.match(/(\d+)/);                         if (m && this.customPriceMin) this.customPriceMin.value = m[1];                      } else if (prLower.includes('max') || prLower.includes('under')) {                         let m = dPr.match(/(\d+)/);                         if (m && this.customPriceMax) this.customPriceMax.value = m[1];                      }                   }                                      let discountAmount = '0';                   if(r.ds && typeof r.ds === 'string') {                      let m = r.ds.match(/(\d+)/);                      if(m) discountAmount = m[1];                   }                   if (this.discountFilter) this.discountFilter.value = discountAmount;                   if (this.offerTypeSelect) this.offerTypeSelect.value = r.ot || '';                   if (this.retailerSelect) this.retailerSelect.value = r.rt || '';                   this.selectedBrands = [];                   btns.forEach(btn => {                       if (!btn.classList.contains('active') || btn.getAttribute('data-type') === 'all') return;                       const vv = btn.getAttribute('data-v');                       const vl = vv.toLowerCase();                                              if (vl === 'lightning deals') {                          if (this.offerTypeSelect) this.offerTypeSelect.value = 'amazon_lightning';                       } else if (vl === 'amazon deals' || vl === 'prime deals') {                          if (this.offerTypeSelect) this.offerTypeSelect.value = 'amazon_prime';                       } else if (vl.includes('% off')) {                          let m = vl.match(/(\d+)%/);                          if (m && this.discountFilter) this.discountFilter.value = m[1];                       } else if (vl.includes('under') || vl.includes('max')) {                          let m = vl.match(/(\d+)/);                          if (m && this.customPriceMax) this.customPriceMax.value = m[1];                       } else if (vl.includes('min') || vl.includes('over')) {                          let m = vl.match(/(\d+)/);                          if (m && this.customPriceMin) this.customPriceMin.value = m[1];                       } else {                          let foundR = mapRet.find(x => x === vl);                          if (foundR) {                             let realR = ['Amazon', 'Walmart', 'Best Buy', 'Target', 'John Lewis', 'Currys', 'Argos'].find(x => x.toLowerCase() === vl);                             if (this.retailerSelect) this.retailerSelect.value = realR;                          } else {                             this.selectedBrands.push(vv);                          }                       }                   });                                      if (this.brandDropdown) {                       const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                       chks.forEach(c => c.checked = this.selectedBrands.includes(c.value));                   }                                      if (r.pr && typeof r.pr === 'string') {                       let prL = r.pr.toLowerCase();                       if (prL.includes('under $')) {                           let m = prL.match(/under \$(\d+)/i);                           if (m && this.customPriceMax && !this.customPriceMax.value) this.customPriceMax.value = m[1];                       }                   }                }                                this.fetchDeals(this.currentQuery);             });           });                      // default to highlighting first           btns[0].classList.add('active');        }async fetchDeals(query, append = false) {          if (!append) {             this.showLoading();             this.deals = [];             this.displayLimit = this.getRowsLimit();          } else {             this.displayLimit += this.getRowsLimit();          }                    try {            if (this.getViewMode() === 'savings_squad') {               await this.fetchSavingsSquad(append);            } else {               if (this.isBroadQuery(query)) {                 await this.fetchAdviserDeals(query, append);               } else {                 await this.fetchHawkDeals(query, append);                 if (this.deals.length === 0) {                   await this.fetchAdviserDeals(query, append);                 }               }            }          } catch (error) {            console.warn("[Tom's Guide Widget] Fetch error:", error);            this.showError();          }        }        async fetchSavingsSquad() {          let topArticles = this.airedaleArticles;          if (!topArticles) {            const airedaleUrl = `https://airedale.futurecdn.net/feeds/feed_1776420579726.json?site=tomsguide&articleType=deals&limit=50`;            let res;            try {               res = await fetch(airedaleUrl);            } catch(e) {               try { res = await fetch(`https://airedale.futurecdn.net/feeds/feed_1776420579726.json?site=tomsguide&articleType=deals&limit=50`); } catch (err) { console.warn("Fallback fetch failed", err); return; }            }            if (!res.ok) throw new Error('Airedale API Error');            const articles = await res.json();            topArticles = Array.isArray(articles) ? articles.slice(0, 50) : ((articles.data && Array.isArray(articles.data)) ? articles.data.slice(0, 50) : []);            this.airedaleArticles = topArticles;                        let tagCounts = {};            topArticles.forEach((a) => {              let articleTags = new Set();              if (a.articlecategory && Array.isArray(a.articlecategory)) {                 a.articlecategory.forEach((t) => articleTags.add(t));              }              articleTags.forEach(t => {                 tagCounts[t] = (tagCounts[t] || 0) + 1;              });            });                        this.airedaleTags = Object.keys(tagCounts).sort((a, b) => tagCounts[b] - tagCounts[a]);            this.airedaleTagCounts = tagCounts;          }                    let targetArticles = topArticles;          if (this.activeDealTag) {             const cleanTag = this.activeDealTag.toLowerCase().replace(/&/g, '').replace(/[^a-z0-9]+/g, '-').replace(/-+/g, '-').replace(/^-|-$/g, '');             const encodedTag = encodeURIComponent(cleanTag);             const url = `https://airedale.futurecdn.net/feeds/feed_1776420579726.json?site=tomsguide&articleType=deals&limit=50&articleCategoryHandle=${encodedTag}`;             try {                const res = await fetch(url);                if (res.ok) {                   const articles = await res.json();                   targetArticles = Array.isArray(articles) ? articles.slice(0, 50) : ((articles.data && Array.isArray(articles.data)) ? articles.data.slice(0, 50) : []);                }             } catch(e) {                console.warn("Failed to fetch by activeDealTag", e);             }          }          let extractedDeals = [];          let dynamicBrandsCounts = {};                    targetArticles.forEach((article) => {             if (!article.articlepage) return;                          let pageData = [];             try {                pageData = JSON.parse(article.articlepage[0]);             } catch(e){ console.warn(e); }                          const savingsSquad = pageData.filter((p) => p.type === 'deal' || p.type === 'featured-product');                          savingsSquad.forEach((block, idx) => {                const data = block.data || {};                const isFeatured = block.type === 'featured-product';                                const link = data.link || {};                const priceObj = data.price || {};                const image = data.image || {};                                if (data.brand) {                   data.brand = data.brand.replace(/^\d+\.\s*/, '').trim();                   dynamicBrandsCounts[data.brand] = (dynamicBrandsCounts[data.brand] || 0) + 1;                }                const externalUrl = isFeatured ? data.url : (link.href || null);                let summaryTitle = isFeatured ? (data.name || data.brand) : (data.productName || link.label || article.articlename);                let description = isFeatured ? (data.strapline || '') : (data.text || '');                                if (!isFeatured && !data.productName && data.text) {                   const brSplit = data.text.split(new RegExp('\x3Cbr\\s*\\/?\\x3E', 'i'));                   if (brSplit.length > 1) {                     summaryTitle = brSplit[0].replace(/<[^>]+>/g, '').trim();                     description = brSplit.slice(1).join(' ').replace(/<br\s*\/?>/gi, ' ').replace(/<\/?(p|div)[^>]*>/gi, ' ').replace(/<[^>]+>/g, '').replace(/\s+/g, ' ').trim();                   } else {                     const match = data.text.match(/\x3Cstrong>(.*?)<\/strong>/);                     if (match) {                       summaryTitle = match[1].replace(/<[^>]+>/g, '').trim();                       if (summaryTitle.endsWith(':')) summaryTitle = summaryTitle.slice(0, -1);                     }                   }                }                                let imageUrl = isFeatured ? image.mos : (image.src || null);                if (imageUrl && imageUrl.startsWith('//')) imageUrl = 'https:' + imageUrl;                                description = description.replace(/<br\s*\/?>/gi, ' ').replace(/<\/?(p|div)[^>]*>/gi, ' ').replace(/<[^>]+>/g, '').replace(/\s+/g, ' ').replace(/View Deal$/i, '').trim();                                let merchantName = data.retailer || '';                if (!merchantName && externalUrl) {                   try {                     merchantName = new URL(externalUrl).hostname.replace('www.', '').split('.')[0];                     merchantName = merchantName.charAt(0).toUpperCase() + merchantName.slice(1);                   }catch(e){ console.warn(e); }                }                if (!merchantName) merchantName = 'Retailer';                const q = (this.currentQuery || '').toLowerCase();                const activeTagLogic = (this.activeDealTag || '').toLowerCase();                if (q.length > 2 && q !== activeTagLogic) {                   const searchTarget = `${summaryTitle || ''} ${description || ''}`.toLowerCase();                   if (!searchTarget.includes(q)) return;                }                let rawPrice = 0;                let rawMsrp = 0;                let currencyStr = '$';                if (isFeatured) {                   rawPrice = typeof data.salePrice === 'number' && data.salePrice > 0 ? data.salePrice : (typeof data.price === 'number' ? data.price : 0);                   rawMsrp = typeof data.salePrice === 'number' && typeof data.price === 'number' && data.price > data.salePrice ? data.price : 0;                   currencyStr = data.currency === 'GBP' ? '£' : '$';                } else {                   rawPrice = priceObj.amount ? parseFloat(priceObj.amount) : 0;                   rawMsrp = priceObj.amountWas ? parseFloat(priceObj.amountWas) : 0;                   currencyStr = priceObj.currency === 'GBP' ? '£' : '$';                }                                let savingAmt = 0;                let savingLabel = '';                if (rawPrice > 0 && rawMsrp > rawPrice) {                   savingAmt = parseFloat((rawMsrp - rawPrice).toFixed(2));                   savingLabel = `Save ${currencyStr}${savingAmt}`;                }                                // Apply Brand filter                if (this.selectedBrands && this.selectedBrands.length > 0) {                   const itemBrand = (data.brand || '').toLowerCase();                   const hasMatch = this.selectedBrands.some(sb => sb.toLowerCase() === itemBrand);                   if (!hasMatch) return;                }                // Apply Price filter                let priceFilterVal = null;                const min = this.customPriceMin ? this.customPriceMin.value : '';                const max = this.customPriceMax ? this.customPriceMax.value : '';                if (min || max) {                   priceFilterVal = `${min}_${max}`;                } else if (this.priceFilter && this.priceFilter.value !== 'all') {                   priceFilterVal = this.priceFilter.value;                }                if (priceFilterVal && rawPrice > 0) {                   if (priceFilterVal === 'under50' && rawPrice >= 50) return;                   if (priceFilterVal === 'over50' && rawPrice <= 50) return;                   if (priceFilterVal === 'over30' && rawPrice <= 30) return;                   if (priceFilterVal === 'over500' && rawPrice <= 500) return;                   if (priceFilterVal.includes('_')) {                      const parts = priceFilterVal.split('_');                      const min = parseFloat(parts[0]);                      const max = parseFloat(parts[1]);                      if (!isNaN(min) && rawPrice < min) return;                      if (!isNaN(max) && rawPrice > max) return;                   }                }                // Apply Discount filter                if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {                   const requiredDiscount = parseInt(this.discountFilter.value);                   if (!isNaN(requiredDiscount) && requiredDiscount > 0) {                      if (!rawMsrp || rawMsrp <= rawPrice) return;                      const ratio = Math.round((1 - (rawPrice / rawMsrp)) * 100);                      if (ratio < requiredDiscount) return;                   }                }                                extractedDeals.push({                   id: `airedale-${article.id || Math.random()}-${idx}`,                   url: externalUrl,                   image: imageUrl,                   fallbackImage: imageUrl,                   title: summaryTitle,                   brand: data.brand || '',                   productName: data.productName || '',                   merchant: merchantName,                   rawPrice: rawPrice,                   rawMsrp: rawMsrp,                   price: rawPrice > 0 ? rawPrice.toString() : '',                   msrp: rawMsrp > 0 ? rawMsrp.toString() : '',                   currency: currencyStr,                   isCheckPrice: !rawPrice,                   savingLabel: savingLabel,                   savingType: rawMsrp > rawPrice ? 'amount' : 'none',                   isPrime: false,                   starRating: null,                   description: description,                   text: data.text || ''                });             });          });                    const airedaleBrandsList = Object.keys(dynamicBrandsCounts).map(b => ({              formatted_value: b,              count: dynamicBrandsCounts[b]          })).sort((a,b) => b.count - a.count);                    if (this.getViewMode() === 'savings_squad') {             this.populateBrandDropdown(airedaleBrandsList.slice(0, 15));             if (this.brandFilterWrapper) {                if (airedaleBrandsList.length === 0) {                    this.brandFilterWrapper.style.display = 'none';                } else {                    this.brandFilterWrapper.style.display = 'flex';                }             }          }                    this.deals = extractedDeals;          this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        isBroadQuery(query) {          const q = query.toLowerCase();          const intentModifiers = ['deals', 'best', 'sale', 'under', 'cheap', 'offers', 'discount'];          return intentModifiers.some(term => q.includes(term));        }        async fetchHawkDeals(query, append = false) {          const url = new URL(this.apiUrl);          url.searchParams.append('model_name', query);          const areaCode = this.getAreaCode();          if (areaCode) {            url.searchParams.append('area', areaCode);          }                    if (append && this.deals.length > 0) {            url.searchParams.append('offset', this.deals.length.toString());          }                    if (this.retailerSelect && this.retailerSelect.value) {            url.searchParams.append('filter_merchant_name', this.retailerSelect.value);          }                    if (this.selectedBrands && this.selectedBrands.length > 0) {            url.searchParams.append('filter_label[text_brand]', this.selectedBrands.join(','));          }                    let priceVal = null;          const min = this.customPriceMin ? this.customPriceMin.value : '';          const max = this.customPriceMax ? this.customPriceMax.value : '';          if (min || max) {             priceVal = `${min}_${max}`;          } else if (this.priceFilter && this.priceFilter.value !== 'all') {             priceVal = this.priceFilter.value;          }          if (priceVal) {            if (priceVal === 'under50') {              url.searchParams.append('filter_max_price', '50');            } else if (priceVal === 'over50') {              url.searchParams.append('filter_min_price', '50');            } else if (priceVal === 'over30') {              url.searchParams.append('filter_min_price', '30');            } else if (priceVal === 'over500') {              url.searchParams.append('filter_min_price', '500');            } else if (priceVal.includes('_')) {              const parts = priceVal.split('_');              if (parts[0]) url.searchParams.append('filter_min_price', parts[0]);              if (parts[1]) url.searchParams.append('filter_max_price', parts[1]);            }          }                    if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {            const v = parseInt(this.discountFilter.value);            if (!isNaN(v) && v > 0) {              const ratio = (100 - v) / 100;              url.searchParams.append('min_discount_ratio', ratio.toString());            }          }                    if (this.offerTypeSelect && this.offerTypeSelect.value) {            url.searchParams.append('offer', this.offerTypeSelect.value);          }                    url.searchParams.append('filter_product_types', 'deals');                    url.searchParams.append('rows', this.getRowsLimit().toString());          let response;          try {             response = await fetch(url.toString());          } catch(e) {             if (window.location.protocol === 'file:') {                console.warn("[Tom's Guide Widget] fetch from file:// blocked by local CORS policy, falling back to Adviser mock.");                await this.fetchAdviserDeals(query);                return;             }             console.warn("Hawk fetch failed", e);             this.deals = [];             this.render();             return;          }          if (!response.ok) {            throw new Error('Hawk API Response Error');          }          const rawData = await response.json();          // Safely locate data array from potentially wrapped response          let offers = [];          let modelInfoArray = [];                    let brandFilterData = null;          if (rawData && rawData.widget && rawData.widget.data && Array.isArray(rawData.widget.data.filters)) {             brandFilterData = rawData.widget.data.filters.find(f => f.type === 'label_text_brand');          } else if (rawData && rawData.data && Array.isArray(rawData.data.filters)) {             brandFilterData = rawData.data.filters.find(f => f.type === 'label_text_brand');          }          if (brandFilterData && Array.isArray(brandFilterData.values) && brandFilterData.values.length > 0) {             this.populateBrandDropdown(brandFilterData.values);          } else {             if (this.brandFilterWrapper && this.selectedBrands.length === 0) {                this.brandFilterWrapper.style.display = 'none';             }          }                    if (rawData && rawData.widget && rawData.widget.data) {            if (Array.isArray(rawData.widget.data.offers)) offers = rawData.widget.data.offers;            if (rawData.widget.data.model_info && typeof rawData.widget.data.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.widget.data.model_info) ? rawData.widget.data.model_info : Object.values(rawData.widget.data.model_info);            }          } else if (rawData && rawData.data) {            if (Array.isArray(rawData.data.offers)) offers = rawData.data.offers;            if (rawData.data.model_info && typeof rawData.data.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.data.model_info) ? rawData.data.model_info : Object.values(rawData.data.model_info);            }          } else {            if (Array.isArray(rawData)) offers = rawData;            else if (rawData && Array.isArray(rawData.offers)) offers = rawData.offers;            else if (rawData && rawData.offers && Array.isArray(rawData.offers.offer)) offers = rawData.offers.offer;            else if (rawData && rawData.offers) offers = [].concat(rawData.offers);                        if (rawData && rawData.model_info && typeof rawData.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.model_info) ? rawData.model_info : Object.values(rawData.model_info);            }          }          let modelDetails = {};          modelInfoArray.forEach(m => {            const mId = m.model_id || m.id;            if (mId) {              modelDetails[mId] = {                score: m.score != null ? parseFloat(m.score) : null,                brand: m.brand || null,                parent: (m.parents && Array.isArray(m.parents) && m.parents.length > 0) ? m.parents[0].name : null              };            }          });          offers.forEach(item => {            let data = { ...item };            const mId = data.model_id;            if (mId && modelDetails[mId]) {              data.review_score = modelDetails[mId].score;              data.model_brand = modelDetails[mId].brand;              data.model_parent = modelDetails[mId].parent;            } else {              data.review_score = null;            }                        let itemOffers = [];            if (Array.isArray(item.offers)) itemOffers = item.offers;            else if (Array.isArray(item.offer)) itemOffers = item.offer;            else if (item.offers && typeof item.offers === 'object') itemOffers = [item.offers];            else if (item.offer && typeof item.offer === 'object') itemOffers = [item.offer];            if (itemOffers.length > 0) {              itemOffers.forEach(subItem => {                let subData = { ...item, ...subItem };                const subId = subData.model_id;                if (subId && modelDetails[subId]) {                  subData.review_score = modelDetails[subId].score;                  subData.model_brand = modelDetails[subId].brand;                  subData.model_parent = modelDetails[subId].parent;                } else if (data.review_score != null) {                  subData.review_score = data.review_score;                }                if (subData.merchant && typeof subData.merchant === 'object') {                  subData.merchant_name = subData.merchant.name;                }                this.deals.push(this.extractDealData(subData));              });              return;            }                        if (item.merchant && typeof item.merchant === 'object') {              data.merchant_name = item.merchant.name;            }                        this.deals.push(this.extractDealData(data));          });                    this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        async fetchAdviserDeals(query) {          // ======================================================================          // TODO: ADVISER API REPLACEMENT          // The code below simulates the Adviser API response using mock data.          // Once the real endpoint is ready, remove getAdviserMockData() and           // perform an actual fetch() request similar to fetchHawkDeals().          // Example:          // const area = this.getAreaCode();          // let apiUrl = `https://your-adviser-api.com/search?q=${query}&area=${area}`;          // if (this.priceFilter && this.priceFilter.value !== 'all') {          //   const val = this.priceFilter.value;          //   if (val === 'under50') apiUrl += '&filter_max_price=50';          //   else if (val === '50_100') apiUrl += '&filter_max_price=100';          //   else if (val === '100_200') apiUrl += '&filter_max_price=200';          //   else if (val === '200_500') apiUrl += '&filter_max_price=500';          // }          // const res = await fetch(apiUrl);          // const rawData = await res.json();          // ======================================================================          // Simulating network latency          await new Promise(resolve => setTimeout(resolve, 400));                    const rawData = this.getAdviserMockData();          let offers = [];                    if (rawData && rawData.data && rawData.data.Get && Array.isArray(rawData.data.Get.Deal)) {            offers = rawData.data.Get.Deal;          }                    // Basic client-side filtering for the mock if we want it to react to the query          const q = query.toLowerCase();          const selectedRetailer = (this.retailerSelect && this.retailerSelect.value) ? this.retailerSelect.value.toLowerCase() : null;                    offers.forEach(item => {            const dataObj = item;                        // Apply retailer filter            const itemRetailer = (dataObj.dataRetailer || '').toLowerCase();            if (selectedRetailer && itemRetailer !== selectedRetailer && !itemRetailer.includes(selectedRetailer)) {              return;            }                        // Apply mock price filter            let price = dataObj.dataDiscountedPrice || 0;            if (typeof price === 'string') {              price = parseFloat(price.replace(/[^0-9.]/g, ''));            }            let priceVal = null;            const min = this.customPriceMin ? this.customPriceMin.value : '';            const max = this.customPriceMax ? this.customPriceMax.value : '';            if (min || max) {               priceVal = `${min}_${max}`;            } else if (this.priceFilter && this.priceFilter.value !== 'all') {               priceVal = this.priceFilter.value;            }            if (priceVal) {              if (priceVal === 'under50' && price >= 50) return;              if (priceVal === 'over50' && price <= 50) return;              if (priceVal === 'over30' && price <= 30) return;              if (priceVal === 'over500' && price <= 500) return;              if (priceVal.includes('_')) {                 const parts = priceVal.split('_');                 if (parts[0] && price < parseFloat(parts[0])) return;                 if (parts[1] && price > parseFloat(parts[1])) return;              }            }                        // Map Adviser schema to our widget's expected schema            const mappedData = {              url: dataObj.linkHREF || dataObj.dataLink || '#',              image: dataObj.imageURL || (dataObj.image && dataObj.image.src) || '',              title: dataObj.dataProduct || (dataObj.product && dataObj.product.name) || 'Product Deal',              merchant: dataObj.dataRetailer || 'Retailer',              price: dataObj.dataDiscountedPrice || 0,              currency: dataObj.dataCurrency === 'USD' ? '$' : (dataObj.dataCurrency || '$'),              msrp: dataObj.dataOriginalPrice || null            };                        const titleLow = mappedData.title.toLowerCase();            const merchLow = mappedData.merchant.toLowerCase();                        // Smarter mock filtering            let isMatch = false;            if (q === '' || this.isBroadQuery(q)) {              isMatch = true;            } else if (titleLow.includes(q) || merchLow.includes(q)) {              isMatch = true;            } else if ((q.includes('laptop') || q.includes('mac') || q.includes('pc')) && (titleLow.includes('macbook') || titleLow.includes('laptop'))) {              isMatch = true;            } else if ((q.includes('tv') || q.includes('television')) && (titleLow.includes('tv') || titleLow.includes('oled') || titleLow.includes('qled'))) {              isMatch = true;            } else if ((q.includes('phone') || q.includes('smartphone')) && (titleLow.includes('galaxy') || titleLow.includes('phone'))) {              isMatch = true;            } else if ((q.match(/watch|fitness|run|shoe/)) && (titleLow.includes('forerunner') || titleLow.includes('saucony') || titleLow.includes('watch'))) {              isMatch = true;            }                        if (isMatch) {               this.deals.push(this.extractDealData(mappedData));            }          });                    let rowLimit = this.getRowsLimit();          // Intentionally omitting the slice here to allow "Load More" to work if the API returns more                    this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        getAdviserMockData() {          return {            "data": {              "Get": {                "Deal": [                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 300,                    "dataOriginalPrice": 399,                    "dataProduct": "Samsung Galaxy A36",                    "dataRetailer": "Samsung",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/MqDYsukV3JBG54te6dEs7j.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 14,                    "dataOriginalPrice": 24,                    "dataProduct": "Blink Mini",                    "dataRetailer": "Amazon",                    "imageURL": "http://cdn.mos.cms.futurecdn.net/3JurmAjHsDa5tPdaHAwEV8.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 59,                    "dataOriginalPrice": 99,                    "dataProduct": "Ring Video Doorbell",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/rAh4uR7AsAsALCCLTXnLNJ.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 10,                    "dataOriginalPrice": 599,                    "dataProduct": "MacBook Neo",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/Lg4Dvg68j9SbB5CPNrTEpH.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 749,                    "dataOriginalPrice": 849,                    "dataProduct": "65\\\" Fire TV Omni 4K QLED TV",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/SG34ZWodUkLTxJvMTbjPYR.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 71,                    "dataOriginalPrice": 160,                    "dataProduct": "Saucony Hurricane 24",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/vxf7UD5T2Am7guVzFoFcZ4.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 649,                    "dataOriginalPrice": 749,                    "dataProduct": "Garmin Forerunner 970",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/3GKnEu7CdhtxPMfnPCMCiA.png"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 1049,                    "dataOriginalPrice": 1499,                    "dataProduct": "LG 48\\\" C4 4K OLED TV",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/imvwZV9zoMD6fn9Afuge35.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 1499,                    "dataOriginalPrice": 2199,                    "dataProduct": "Samsung 49\\\" Odyssey Neo G9 4K Gaming Monitor",                    "dataRetailer": "Amazon",                    "imageURL": "http://cdn.mos.cms.futurecdn.net/XWDEJ5dUAE2nhK8k3Jk7k7.png"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 299,                    "dataOriginalPrice": 699,                    "dataProduct": "EGOHOME Black Memory Foam Mattress (queen)",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/hMUemtAejNETLVYxNrktzm.jpg"                  }                ]              }            }          };        }        decodeHTML(html) {          if (!html) return '';          const txt = document.createElement("textarea");          txt.innerHTML = String(html);          return txt.value;        }        extractDealData(item) {          const priceRawStr = String(item.price || item.current_price || '0');          const msrpRawStr = String(item.was_price || item.msrp || item.original_price || '0');          const rawPrice = parseFloat(priceRawStr.replace(/[^\d.]/g, '')) || 0;          const rawMsrp = parseFloat(msrpRawStr.replace(/[^\d.]/g, '')) || 0;          const isCheckPrice = rawPrice === 0 || priceRawStr === '0.00' || priceRawStr === '0';                    let originalImageUrl = item.image || item.image_url || item.product_image || '';          let imageUrl = originalImageUrl;          if ((!imageUrl || isCheckPrice) && item.model_image_url) {             imageUrl = item.model_image_url;             originalImageUrl = imageUrl;          } else if ((!imageUrl || isCheckPrice) && item.model_image) {             imageUrl = item.model_image;             originalImageUrl = imageUrl;          }                    if (imageUrl) {            imageUrl = imageUrl.replace(/-(\d+)-(\d+)(\.[a-z.]+)$/i, '$3');          }                    let fallbackImage = '';          if (originalImageUrl && originalImageUrl !== imageUrl) {             fallbackImage = originalImageUrl;          } else if (item.model_image && item.model_image !== imageUrl) {             fallbackImage = item.model_image;          } else if (item.model_image_url && item.model_image_url !== imageUrl) {             fallbackImage = item.model_image_url;          }                    const rawCurrency = item.currency || item.currency_symbol || '$';                    let savingLabel = item.percentage_saving_label || '';          if (!savingLabel && rawMsrp > rawPrice && rawPrice > 0) {            const pct = Math.round(((rawMsrp - rawPrice) / rawMsrp) * 100);            if (pct > 0) {              savingLabel = `${pct}% OFF`;            }          }                    const isPrime = item.shipping && item.shipping.prime === true;                    let scoreRaw = (item.review_score !== undefined && item.review_score !== null && item.review_score > 0) ? parseFloat(item.review_score) : null;          let starRating = 0;          if (scoreRaw !== null) {            starRating = Math.round((scoreRaw > 10 ? scoreRaw / 20 : scoreRaw / 2) * 2) / 2;          }                    return {            id: item.offer_id || item.link || item.url || item.offer_link || Math.random().toString(),            url: item.link || item.url || item.offer_link || '#',            image: imageUrl,            fallbackImage: fallbackImage,            title: item.name || item.title || item.model_name || item.product_name || 'Unknown Product',            brand: item.brand || '',            productName: item.model_name || item.product_name || item.name || '',            merchant: item.merchant_name || item.merchant || item.retailer || 'Retailer',            price: item.price !== undefined ? String(item.price) : '0.00',            currency: this.decodeHTML(rawCurrency),            msrp: item.was_price || item.msrp || item.original_price || null,            rawPrice: rawPrice,            rawMsrp: rawMsrp,            hasWasPrice: (item.was_price !== undefined && item.was_price !== null),            isCheckPrice: isCheckPrice,            savingLabel: savingLabel,            isPrime: isPrime,            starRating: starRating > 0 ? starRating : null,            modelId: item.model_id || '',            productKey: item.product_key || '',            merchantId: (item.merchant && typeof item.merchant === 'object') ? item.merchant.id || '' : '',            matchId: item.match_id || '',            merchantNetwork: (item.merchant && typeof item.merchant === 'object') ? item.merchant.an || '' : '',            merchantUrl: (item.merchant && typeof item.merchant === 'object') ? item.merchant.url || '' : '',            modelBrand: item.model_brand || item.brand || '',            modelParent: item.model_parent || ''          };        }        sortData() {          const sortVal = this.sortSelect ? this.sortSelect.value : (this.getViewMode() === 'savings_squad' ? 'date_desc' : 'discount_desc');          if (sortVal === 'price_asc') {            this.deals.sort((a, b) => a.rawPrice - b.rawPrice);          } else if (sortVal === 'price_desc') {            this.deals.sort((a, b) => b.rawPrice - a.rawPrice);          } else if (sortVal === 'discount_desc') {            this.deals.sort((a, b) => {              const aDiscount = a.rawMsrp > a.rawPrice ? (a.rawMsrp - a.rawPrice) : 0;              const bDiscount = b.rawMsrp > b.rawPrice ? (b.rawMsrp - b.rawPrice) : 0;              return bDiscount - aDiscount;            });          } else if (sortVal === 'date_desc') {             this.deals.sort((a, b) => {                let dateA = 0;                let dateB = 0;                if (a && a.modifiedDate) {                   const valA = Array.isArray(a.modifiedDate) ? a.modifiedDate[0] : a.modifiedDate;                   dateA = new Date(valA).getTime();                   if (isNaN(dateA)) dateA = 0;                }                if (b && b.modifiedDate) {                   const valB = Array.isArray(b.modifiedDate) ? b.modifiedDate[0] : b.modifiedDate;                   dateB = new Date(valB).getTime();                   if (isNaN(dateB)) dateB = 0;                }                return dateB - dateA;             });          }        }        getFilteredDeals() {          let filteredDeals = [...this.deals];                    if (this.dealModeToggle && this.dealModeToggle.checked) {            filteredDeals = filteredDeals.filter(d => d.hasWasPrice || (d.msrp && d.rawMsrp > d.rawPrice));          }                    return filteredDeals;        }        showLoading() {          const _div = '<' + '/div>';          const skeletonCardHtml = `            \x3Cdiv class="tg-df-card">              \x3Cdiv class="tg-df-card-image-box">                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-img">${_div}              ${_div}              \x3Cdiv class="tg-df-card-body">                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short">${_div}                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text title">${_div}                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text title">${_div}                \x3Cdiv class="tg-df-card-footer mt-auto">                  \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="height:24px;">${_div}                  \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text" style="height:44px; margin-top:8px;">${_div}                ${_div}              ${_div}            ${_div}`;          this.grid.innerHTML = Array(4).fill(skeletonCardHtml).join('');        }        showError() {          const _div = '<' + '/div>';          this.grid.innerHTML = `\x3Cdiv class="tg-df-message">            An error occurred while finding deals. Please check your connection and try again.          ${_div}`;        }        escapeHTML(str) {          if (!str) return '';          return String(str).replace(/[&<>'"]/g, tag => ({              '&': '&', '<': '<', '>': '>', "'": ''', '"': '"'          }[tag] || tag));        }                bindCouponButtons() {          const btns = this.root.querySelectorAll('.tg-df-tag-coupons');          btns.forEach(btn => {            btn.addEventListener('click', (e) => {              e.preventDefault();              e.stopPropagation();              const merchant = btn.getAttribute('data-merchant');              this.openVouchersModal(merchant);            });          });                    const closeBtn = this.root.querySelector('#tg-df-vouchers-close');          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          if (closeBtn) {            closeBtn.onclick = () => this.closeVouchersModal();          }          if (backdrop) {            backdrop.onclick = (e) => {              if (e.target === backdrop) this.closeVouchersModal();            };          }        }                closeVouchersModal() {          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          if (backdrop) backdrop.classList.remove('active');        }                async checkMerchantsCouponsBulk(merchants) {          if (!merchants || merchants.length === 0) return {};          const controller = new AbortController();          const timeoutId = setTimeout(() => controller.abort(), 4000);          try {            const area = this.getAreaCode();            const url = new URL('https://search-api.fie.future.net.uk/widget.php');            url.searchParams.append('model_name', 'Everything');            url.searchParams.append('language', 'en-GB');            if (area) url.searchParams.append('area', area);            url.searchParams.append('combine_product_types', '1');            url.searchParams.append('filter_merchant_name', merchants.join(','));            url.searchParams.append('all_filters', 'false');            url.searchParams.append('exclude_unlabelled', 'false');            url.searchParams.append('include_specs', 'false');            url.searchParams.append('sort', 'voucher');            url.searchParams.append('distinct_merchants', 'natural');            url.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');            url.searchParams.append('rows', '120');            url.searchParams.append('origin', 'widgets-clientside');                        let res; try { res = await fetch(url.toString(), { signal: controller.signal }); } catch (e) { return {}; }            clearTimeout(timeoutId);            if (!res.ok) return {};            const data = await res.json();                        let offers = [];            if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {              offers = data.widget.data.offers;            } else if (data && data.data && Array.isArray(data.data.offers)) {              offers = data.data.offers;            } else if (Array.isArray(data)) {              offers = data;            } else if (data && Array.isArray(data.offers)) {              offers = data.offers;            } else if (data && data.offers && Array.isArray(data.offers.offer)) {              offers = data.offers.offer;            } else if (data && Array.isArray(data.data)) {              offers = data.data;            }                        const foundMerchants = new Set();            offers.forEach(o => {              let mName = o.merchant_name || o.merchant || o.retailer;              if (mName && typeof mName === 'object') mName = mName.name;              if (mName) foundMerchants.add(String(mName).toLowerCase());            });            const resultMap = {};            merchants.forEach(m => {              if (m) resultMap[m] = foundMerchants.has(String(m).toLowerCase());            });            return resultMap;          } catch (e) {            return {};          }        }                async openVouchersModal(merchantName) {          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          const title = this.root.querySelector('#tg-df-vouchers-title');          const content = this.root.querySelector('#tg-df-vouchers-content');                    if (!backdrop || !content) return;                    // HACK: Hide closing tags          const _div = '<' + '/div>';          const _span = '<' + '/span>';          const _a = '<' + '/a>';          const _h4 = '<' + '/h4>';          const _svg = '<' + '/svg>';          const _circle = '<' + '/circle>';          const _polyline = '<' + '/polyline>';          const _rect = '<' + '/rect>';          const _path = '<' + '/path>';                    title.innerText = `${merchantName} Coupons & Deals`;          content.innerHTML = `\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text">${_div}                               \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text">${_div}`;          backdrop.classList.add('active');                    try {            const area = this.getAreaCode();            const url = new URL('https://search-api.fie.future.net.uk/widget.php');            url.searchParams.append('model_name', 'Everything');            url.searchParams.append('language', 'en-GB');            if (area) url.searchParams.append('area', area);            url.searchParams.append('combine_product_types', '1');            url.searchParams.append('filter_merchant_name', merchantName);            url.searchParams.append('all_filters', 'false');            url.searchParams.append('exclude_unlabelled', 'false');            url.searchParams.append('include_specs', 'false');            url.searchParams.append('sort', 'voucher');            url.searchParams.append('distinct_merchants', 'natural');            url.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');            url.searchParams.append('rows', '50');            url.searchParams.append('origin', 'widgets-clientside');                        const res = await fetch(url.toString());            if (!res.ok) throw new Error('API Error');            const data = await res.json();                        let offers = [];            if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {              offers = data.widget.data.offers;            } else if (data && data.data && Array.isArray(data.data.offers)) {              offers = data.data.offers;            } else if (Array.isArray(data)) {              offers = data;            } else if (data && Array.isArray(data.offers)) {              offers = data.offers;            } else if (data && data.offers && Array.isArray(data.offers.offer)) {              offers = data.offers.offer;            } else if (data && Array.isArray(data.data)) {              offers = data.data;            }                        if (offers.length === 0) {              content.innerHTML = `\x3Cdiv class="tg-df-message">No vouchers currently available for ${this.escapeHTML(merchantName)}.${_div}`;              return;            }                        content.innerHTML = offers.map((v, idx) => {              let offerObj = v;              if (v.offers && v.offers.offer) {                offerObj = Array.isArray(v.offers.offer) ? v.offers.offer[0] : v.offers.offer;              } else if (v.offer) {                offerObj = Array.isArray(v.offer) ? v.offer[0] : v.offer;              }              let logoUrl = v.logo_url || offerObj.logo_url || '';              if (!logoUrl && v.merchant) {                if (Array.isArray(v.merchant) && v.merchant.length > 0) logoUrl = v.merchant[0].logo_url || '';                else logoUrl = v.merchant.logo_url || '';              }                            const offerName = offerObj.name || offerObj.title || v.name || v.title || 'Special Offer';              const endTime = offerObj.end_time || v.end_time || '';              const linkUrl = offerObj.link || offerObj.url || v.link || v.url || '#';                            let foundVoucherCode = '';              const findVoucherCode = (obj) => {                if (!obj || typeof obj !== 'object') return;                if (obj.type === 'voucher_code' && obj.display_value) {                  foundVoucherCode = obj.display_value;                  return;                }                if (Array.isArray(obj)) {                  for (const item of obj) {                    findVoucherCode(item);                    if (foundVoucherCode) return;                  }                } else {                  for (const k in obj) {                    if (Object.prototype.hasOwnProperty.call(obj, k)) {                      findVoucherCode(obj[k]);                      if (foundVoucherCode) return;                    }                  }                }              };              findVoucherCode(offerObj);              if (!foundVoucherCode) findVoucherCode(v);                            const voucherCode = foundVoucherCode || offerObj.voucher_code || v.voucher_code || '';              const codeHtml = voucherCode ? `\x3Cspan class="tg-df-voucher-code" data-action="copy-code" data-code="${this.escapeHTML(voucherCode)}" title="Copy to clipboard">                \x3Cspan class="tg-df-voucher-code-text">${this.escapeHTML(voucherCode)}${_span}                \x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-left:6px;flex-shrink:0;" class="tg-df-voucher-copy-icon">                  \x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2">${_rect}                  \x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1">${_path}                ${_svg}              ${_span}` : '';                            const logoHtml = logoUrl                 ? `\x3Cimg src="${this.escapeHTML(logoUrl)}" alt="${this.escapeHTML(offerName)}" class="tg-df-voucher-logo" />`                 : `\x3Cdiv class="tg-df-voucher-logo" style="background:#e2e8f0;">${_div}`;                            let expiryHtml = '';              if (endTime) {                let dStr = endTime;                if (!isNaN(dStr) && String(dStr).length === 10) dStr = Number(dStr) * 1000;                const d = new Date(dStr);                if (!isNaN(d.getTime())) {                  const options = { year: 'numeric', month: 'short', day: 'numeric' };                  expiryHtml = `                    \x3Cdiv class="tg-df-voucher-expiry">                      \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">                        \x3Ccircle cx="12" cy="12" r="10">${_circle}                        \x3Cpolyline points="12 6 12 12 16 14">${_polyline}                      ${_svg}                      Expires ${d.toLocaleDateString(undefined, options)}                    ${_div}`;                }              }              const revenueIdVal = generateRevenueId(linkUrl, offerName, merchantName, null);              const rewrittenLinkUrl = rewriteAffiliateLink(linkUrl, area, revenueIdVal);              return `                \x3Ca href="${this.escapeHTML(rewrittenLinkUrl)}" target="_blank" rel="noopener nofollow" class="tg-df-voucher-item"                  data-action="voucher-click"                  data-product-name="${this.escapeHTML(offerName)}"                  data-merchant-name="${this.escapeHTML(merchantName)}"                  data-analytics-id="${this.escapeHTML(offerObj.offer_id || offerObj.id || v.id || '')}"                  data-price=""                  data-previous-price=""                  data-original-link="${this.escapeHTML(linkUrl)}"                  data-revenue-id="${revenueIdVal}"                  data-index="${idx}"                  data-total="${offers.length}"                  data-in-stock="true"                  data-currency="USD"                  data-model-id="${this.escapeHTML(offerObj.model_id || v.model_id || offerObj.id || v.id || '')}"                  data-merchant-id="${this.escapeHTML(offerObj.merchant_id || offerObj.merchant?.id || '')}"                >                  ${logoHtml}                  \x3Cdiv class="tg-df-voucher-content">                    \x3Ch4 class="tg-df-voucher-title">${this.escapeHTML(offerName)}${_h4}                    ${codeHtml}                    ${expiryHtml}                  ${_div}                ${_a}              `;            }).join('');                        // Attach copy functionality            const copyBtns = content.querySelectorAll('[data-action="copy-code"]');            copyBtns.forEach(btn => {              btn.addEventListener('click', async (e) => {                e.preventDefault();                e.stopPropagation();                                const code = btn.getAttribute('data-code');                if (!code) return;                                try {                  const copyToClipboard = async (text) => {                     if (window.navigator.clipboard && window.isSecureContext) {                        try { await window.navigator.clipboard.writeText(text); return; } catch (e) {}                     }                     const textArea = document.createElement("textarea");                     textArea.value = text;                     textArea.style.position = "fixed";                     document.body.appendChild(textArea);                     textArea.focus();                     textArea.select();                     document.execCommand('copy');                     textArea.remove();                  };                  await copyToClipboard(code);                                    // Visual feedback                  btn.classList.add('copied');                  const textSpan = btn.querySelector('.tg-df-voucher-code-text');                  const iconSvg = btn.querySelector('.tg-df-voucher-copy-icon');                                    const origText = textSpan.innerText;                  const origIcon = iconSvg.innerHTML;                                    textSpan.innerText = 'Copied!';                  iconSvg.innerHTML = `\x3Cpolyline points="20 6 9 17 4 12">${_polyline}`;                                    setTimeout(() => {                    if (btn) {                      btn.classList.remove('copied');                      if (textSpan) textSpan.innerText = origText;                      if (iconSvg) iconSvg.innerHTML = origIcon;                    }                  }, 2000);                                    trackElementInteraction({                    id: 'voucher-code-copy',                    name: 'Copy Voucher Code',                    label: `Copied ${code} for ${merchantName}`                  });                } catch (err) {                  console.warn('Failed to copy text: ', err);                }              });            });            // Attach voucher click tracking            const voucherBtns = content.querySelectorAll('[data-action="voucher-click"]');            voucherBtns.forEach(btn => {              btn.addEventListener('click', (e) => {                if (e.target.closest('[data-action="copy-code"]')) return;                                const productName = btn.getAttribute('data-product-name');                const merchantNameAttr = btn.getAttribute('data-merchant-name');                const productId = btn.getAttribute('data-analytics-id');                const price = parseFloat(btn.getAttribute('data-price')) || null;                const prevPriceStr = btn.getAttribute('data-previous-price');                const previousPrice = prevPriceStr ? parseFloat(prevPriceStr) : null;                const originalLink = btn.getAttribute('data-original-link');                const rewrittenLink = btn.getAttribute('href');                const revenueId = btn.getAttribute('data-revenue-id');                const index = parseInt(btn.getAttribute('data-index'), 10) || 0;                const inStock = btn.getAttribute('data-in-stock') === 'true';                const totalText = btn.getAttribute('data-total');                const totalDeals = parseInt(totalText, 10) || 0;                const productCategoryName = 'deals';                const trackingParams = {                  widgetId: this.widgetId,                  productCategoryName: productCategoryName,                  product: {                    modelId: btn.getAttribute('data-model-id') || null,                    matchId: btn.getAttribute('data-match-id') || null,                    brand: btn.getAttribute('data-model-brand') || null,                    parent: btn.getAttribute('data-model-parent') || null,                    name: productName,                    price: price,                    previousPrice: previousPrice,                    link: rewrittenLink,                    originalLink: originalLink,                    inStock: inStock                  },                  zeroBasedProductIndexOrNull: index,                  totalDealsOrProducts: totalDeals,                   merchant: {                    id: btn.getAttribute('data-merchant-id') || null,                    network: btn.getAttribute('data-merchant-network') || null,                    url: btn.getAttribute('data-merchant-url') || null,                    name: merchantNameAttr                  },                  revenueId: revenueId,                  widgetTypeName: this.widgetTypeName,                  isoCurrencyCode: btn.getAttribute('data-currency') || 'USD'                };                if (typeof trackDealClick === 'function') {                  trackDealClick(trackingParams);                }              });            });                                  } catch (e) {            console.warn(e);            content.innerHTML = `\x3Cdiv class="tg-df-message">Failed to load vouchers.${_div}`;          }        }        render() {          try {            if (this.getViewMode() === 'savings_squad' && this.airedaleTags.length > 0) {              if (this.categoryFilterWrapper) {                 this.categoryFilterWrapper.style.display = 'flex';              }              if (this.categoryFilter) {                 const _option = '<' + '/option>';                 let optionsHtml = `\x3Coption value="all">All Categories${_option}`;                 this.airedaleTags.forEach(tag => {                    const isSelected = this.activeDealTag === tag ? 'selected' : '';                    optionsHtml += `\x3Coption value="${this.escapeHTML(tag)}" ${isSelected}>${this.escapeHTML(tag)} (${this.airedaleTagCounts[tag] || 0})${_option}`;                 });                 this.categoryFilter.innerHTML = optionsHtml;                 this.categoryFilter.value = this.activeDealTag || 'all';              }            } else {               if (this.categoryFilterWrapper) {                  this.categoryFilterWrapper.style.display = 'none';               }            }            const displayDeals = this.getFilteredDeals();          // HACK: Hide closing tags from the CMS HTML sanitizer so it doesn't strip them during in-page injection          const _div = '<' + '/div>';          const _span = '<' + '/span>';          const _a = '<' + '/a>';          const _h3 = '<' + '/h3>';          const _p = '<' + '/p>';          const _strong = '<' + '/strong>';          const _sup = '<' + '/sup>';          const _button = '<' + '/button>';          if (displayDeals.length === 0) {            if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {              if (this.deals.length > 0) {                 this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                  No deals match your selected filters.                ${_div}`;              } else if (this.getViewMode() === 'savings_squad' && this.currentQuery.length <= 2) {                 // Do not show "no exact matches" if query is empty for savings_squad                 this.grid.innerHTML = '';              } else {                 this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                  No exact matches found for "\x3Cstrong>${this.escapeHTML(this.currentQuery)}${_strong}". Try adjusting your search term.                ${_div}`;              }            } else {              this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                Search product or category names to discover the best deals from across the web.              ${_div}`;            }            return;          }          let dealsHtml = displayDeals.slice(0, this.displayLimit).map((deal, index) => {            try {               const currencySym = this.escapeHTML(deal.currency);               const isoCurrencyCode = normalizeCurrency(currencySym);               const escapedPrice = this.escapeHTML(deal.price);               const escapedMsrp = this.escapeHTML(deal.msrp);               const areaCode = this.getAreaCode();                              const revenueId = generateRevenueId(deal.url, deal.title, deal.merchant, null);               const originalLink = deal.url;               const rewrittenLink = rewriteAffiliateLink(deal.url, areaCode, revenueId);                        const productCategoryName = 'deals';            const dataAttr = `              data-action="${deal.isCheckPrice ? 'view-similar-click' : 'deal-click'}"              data-analytics-id="${this.escapeHTML(deal.externalProductId || deal.id || '')}"              data-product-name="${this.escapeHTML(deal.title)}"              data-merchant-name="${this.escapeHTML(deal.merchant)}"              data-price="${deal.rawPrice || ''}"              data-previous-price="${deal.rawMsrp || ''}"              data-original-link="${this.escapeHTML(originalLink)}"              data-revenue-id="${revenueId}"              data-index="${index}"              data-total="${displayDeals.length}"              data-in-stock="${deal.inStock !== false}"              data-currency="${this.escapeHTML(isoCurrencyCode)}"              data-model-id="${this.escapeHTML(deal.modelId || '')}"              data-product-key="${this.escapeHTML(deal.productKey || '')}"              data-merchant-id="${this.escapeHTML(deal.merchantId || '')}"            `;                        let priceGroupHtml = '';            let isSavingsSquadMode = this.getViewMode() === 'savings_squad';            let ctaText = 'View Deal';            let formattedPrice = '';            let msrpHtml = '';                        if (deal.isCheckPrice) {              ctaText = isSavingsSquadMode ? 'View Deal' : 'Check Price';              if (isSavingsSquadMode) {                priceGroupHtml = `                  \x3Cdiv class="tg-df-card-merchant-wrapper">                    \x3Cspan class="tg-df-card-merchant-pill" title="${this.escapeHTML(deal.merchant)}">${this.escapeHTML(deal.merchant)}${_span}                  ${_div}                  \x3Cdiv class="tg-df-card-price-group">                  ${_div}                `;              } else {                priceGroupHtml = `                  \x3Cdiv class="tg-df-card-merchant-wrapper">                    \x3Cspan class="tg-df-card-merchant-pill" title="${this.escapeHTML(deal.merchant)}">${this.escapeHTML(deal.merchant)}${_span}                  ${_div}                  \x3Cdiv class="tg-df-card-price-group">                    \x3Cspan class="tg-df-card-price" style="font-size: 15px; font-weight: 500; font-style: italic;">See price at retailer${_span}                  ${_div}                `;              }            } else {              // Format Price              formattedPrice = escapedPrice.includes(currencySym)                 ? escapedPrice                 : `${currencySym}${escapedPrice}`;                              // Format MSRP              msrpHtml = deal.msrp && deal.rawMsrp > deal.rawPrice                ? `\x3Cspan class="tg-df-card-msrp">${escapedMsrp.includes(currencySym) ? escapedMsrp : currencySym + escapedMsrp}${_span}`                : '';                              priceGroupHtml = `                \x3Cdiv class="tg-df-card-merchant-wrapper">                  \x3Cspan class="tg-df-card-merchant-pill" title="${this.escapeHTML(deal.merchant)}">${this.escapeHTML(deal.merchant)}${_span}                ${_div}                \x3Cdiv class="tg-df-card-price-group">                  ${isSavingsSquadMode ? '' : `                  \x3Cspan class="tg-df-card-price">${formattedPrice}${_span}                  ${msrpHtml}                  `}                ${_div}              `;            }                        const discountBadgeHtml = deal.savingLabel && !deal.isCheckPrice              ? `\x3Cspan class="tg-df-card-discount-badge">${this.escapeHTML(deal.savingLabel)}${_span}`              : '';                          // HACK for CMS            const _button = '<' + '/button>';            const _svg = '<' + '/svg>';            const _path = '<' + '/path>';            const _rect = '<' + '/rect>';            const _circle = '<' + '/circle>';            const _polyline = '<' + '/polyline>';            const _line = '<' + '/line>';                        let badgesHtml = '';            const primeBadge = deal.isPrime ? `              \x3Cspan class="tg-df-tag tg-df-tag-prime">                \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="currentColor">                  \x3Cpath d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z">${_path}                ${_svg} Prime              ${_span}            ` : '';                        const couponsBadge = deal.merchant && deal.merchant.toLowerCase().includes('amazon') ? '' : `              \x3Cdiv class="tg-df-coupon-wrapper" data-merchant="${this.escapeHTML(deal.merchant)}" style="display:inline-flex; align-items:center;">                \x3Cdiv class="tg-df-coupon-spinner">${_div}                \x3Cbutton type="button" class="tg-df-tag tg-df-tag-coupons" data-action="coupons-click" data-merchant="${this.escapeHTML(deal.merchant)}" style="display:none;">                  \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">                    \x3Cpath d="M20.59 13.41l-7.17 7.17a2 2 0 0 1-2.83 0L2 12V2h10l8.59 8.59a2 2 0 0 1 0 2.82z">${_path}                    \x3Cline x1="7" y1="7" x2="7.01" y2="7">${_line}                  ${_svg} Coupons                ${_button}              ${_div}            `;                        // Note: We always add coupons badge if there's a chance, but to allow 3-line titles we check wrapper display state            badgesHtml = `              \x3Cdiv class="tg-df-card-badges">                ${primeBadge}                ${couponsBadge}              ${_div}            `;            const _linearGradient = '<' + '/linearGradient>';            const _polygon = '<' + '/polygon>';            const _stop = '<' + '/stop>';            const _defs = '<' + '/defs>';                        let starHtml = '';            if (deal.starRating) {              let rating = deal.starRating;                            if (rating > 0) {                const fullStars = Math.floor(rating);                const halfStar = (rating - fullStars) >= 0.5 ? 1 : 0;                const emptyStars = Math.max(0, 5 - fullStars - halfStar);                const blue = '#1f69ff'; // Tom's guide brand color from VIEW DEAL button                const gray = '#cbd5e1';                                const starSvgFull = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="${blue}" stroke="${blue}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26">${_polygon}${_svg}`;                                const gradId = 'half_grad_' + Math.floor(Math.random()*1000000);                const starSvgHalf = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" stroke="${blue}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cdefs>\x3ClinearGradient id="${gradId}" x1="0" x2="1" y1="0" y2="0">\x3Cstop offset="50%" stop-color="${blue}">${_stop}\x3Cstop offset="50%" stop-color="transparent">${_stop}${_linearGradient}${_defs}                  \x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26" fill="url(#${gradId})">${_polygon}${_svg}`;                                  const starSvgEmpty = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="${gray}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26">${_polygon}${_svg}`;                                let stars = [];                for (let i=0; i<fullStars; i++) stars.push(starSvgFull);                if (halfStar) stars.push(starSvgHalf);                for (let i=0; i<emptyStars; i++) stars.push(starSvgEmpty);                                starHtml = `\x3Cdiv class="tg-df-card-stars" style="display:flex;align-items:center;margin-bottom:8px;font-size:13px;font-weight:600;color:var(--tg-df-text-muted);">                  \x3Cspan style="margin-right:6px;">Tom's Guide:${_span}                  \x3Cdiv style="display:flex;gap:2px;">                    ${stars.join('')}                  ${_div}                ${_div}`;              }            }            let htmlOutput = '';            if (isSavingsSquadMode) {              htmlOutput += `              \x3Cdiv class="hawk-deal-widget-container tg-df-mobile-only" data-collapsible="true">                ${this.editorMode ? `\x3Cinput type="checkbox" class="tg-df-deal-checkbox" data-id="${this.escapeHTML(deal.id)}" ${this.selectedDeals.has(deal.id) ? 'checked' : ''} style="margin-bottom: 10px;">` : ''}                \x3Cdiv class="hawk-deal-widget-wrap">                  \x3Cdiv class="hawk-deal-widget-image-container">                    \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" rel="sponsored noopener" target="_blank" class="hawk-affiliate-link-deal-widget" ${dataAttr}>                      \x3Cimg ${deal.image ? `src="${this.escapeHTML(deal.image)}"` : ''} alt="${this.escapeHTML(deal.title)}" class="hawk-lazy-image-deal-widget" loading="lazy" width="140" height="160" onerror="${deal.fallbackImage ? `if(!this.dataset.fb) { this.dataset.fb='1'; this.src='${this.escapeHTML(deal.fallbackImage)}'; } else { this.style.opacity='0'; }` : `this.style.opacity='0';`}">                    ${_a}                  ${_div}                  \x3Cdiv class="hawk-deal-widget-text-cta-container">                    \x3Cdiv class="hawk-deal-widget-text-body-container">                      \x3Cdiv class="hawk-deal-widget-text-body-main">                        \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                          ${deal.isCheckPrice ? `                            \x3Cspan class="hawk-deal-widget-title-product-title">${this.escapeHTML(deal.title)}${_span}                          ` : `                            \x3Cspan class="hawk-deal-widget-title-product-title">${deal.brand ? this.escapeHTML(deal.brand) + ' ' : ''}${this.escapeHTML(deal.productName || deal.title || '')}:${_span}                          `}                        ${_a}                        ${!deal.isCheckPrice && deal.rawMsrp && deal.rawMsrp > deal.rawPrice ? `                          \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                            \x3Cspan class="hawk-deal-widget-title-was-price">was ${currencySym}${escapedMsrp}${_span}                          ${_a}                        ` : ''}                        \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                          \x3Cspan class="hawk-deal-widget-title-retailer-price">                            ${!deal.isCheckPrice ? `                              \x3Cspan class="hawk-deal-widget-title-price">now ${formattedPrice}${_span}                              \x3Cspan class="hawk-deal-widget-title-retailer"> at ${this.escapeHTML(deal.merchant)}${_span}                            ` : `                              \x3Cspan class="hawk-deal-widget-title-price">See price at ${this.escapeHTML(deal.merchant)}${_span}                            `}                          ${_span}                        ${_a}                        ${deal.description ? `\x3Cdiv class="hawk-deal-widget-text-body-description">\x3Cp>${this.escapeHTML(deal.description)}${_p}${_div}` : ''}                      ${_div}                    ${_div}                    \x3Cdiv class="hawk-deal-widget-footer">                      \x3Cdiv class="hawk-deal-widget-button-wrapper">                        \x3Cdiv class="hawk-deal-widget-preferred-partner-wrapper">                          \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-deal-button" rel="sponsored noopener" target="_blank" ${dataAttr}>                            \x3Cspan>${deal.isCheckPrice ? 'Check Price' : 'View Deal'}${_span}                          ${_a}                        ${_div}                      ${_div}                    ${_div}                  ${_div}                ${_div}              ${_div}              `;            }            htmlOutput += `              \x3Cdiv class="tg-df-card ${isSavingsSquadMode ? 'tg-df-desktop-only' : ''}">                ${this.editorMode ? `\x3Cinput type="checkbox" class="tg-df-deal-checkbox" data-id="${this.escapeHTML(deal.id)}" ${this.selectedDeals.has(deal.id) ? 'checked' : ''}>` : ''}                \x3Cdiv class="tg-df-card-image-box">                  ${discountBadgeHtml}                  \x3Ca href="${this.escapeHTML(rewrittenLink)}" ${dataAttr} target="_blank" rel="noopener nofollow" style="display: flex; align-items: center; justify-content: center; width: 100%; height: 100%;">                    \x3Cimg ${deal.image ? `src="${this.escapeHTML(deal.image)}"` : ''} alt="${this.escapeHTML(deal.title)}" class="tg-df-card-image" loading="lazy" onerror="${deal.fallbackImage ? `if(!this.dataset.fb) { this.dataset.fb='1'; this.src='${this.escapeHTML(deal.fallbackImage)}'; } else { this.style.opacity='0'; }` : `this.style.opacity='0';`}">                  ${_a}                ${_div}                \x3Cdiv class="tg-df-card-body">                  ${starHtml}                  ${badgesHtml}                  \x3Ch3 class="tg-df-card-title tg-df-custom-savings-squad-title" title="${this.escapeHTML(deal.title)}">                    \x3Ca href="${this.escapeHTML(rewrittenLink)}" disable-tracking="true" target="_blank" rel="noopener nofollow" style="text-decoration: none; color: inherit;">                      ${isSavingsSquadMode                         ? (deal.isCheckPrice                             ? (deal.title && deal.title.includes(':')                                 ? `\x3Cstrong>${this.escapeHTML(deal.title.substring(0, deal.title.indexOf(':') + 1))}${_strong}\x3Cspan style="color: #1f69ff; font-weight: normal;">${this.escapeHTML(deal.title.substring(deal.title.indexOf(':') + 1))}${_span}`                                : this.escapeHTML(deal.title)                              )                             : `\x3Cstrong>${deal.brand ? this.escapeHTML(deal.brand) + ' ' : ''}${this.escapeHTML(deal.productName || deal.title || '')}:${_strong} ${deal.rawMsrp && deal.rawMsrp > deal.rawPrice ? `\x3Cspan style="color: #d0021b; text-decoration: line-through; font-weight: normal; margin-right: 4px;">was ${currencySym}${escapedMsrp}${_span} ` : ''}\x3Cspan style="color: #1f69ff; font-weight: normal;">now ${formattedPrice} at ${this.escapeHTML(deal.merchant)}${_span}`                          )                        : this.escapeHTML(deal.title)                      }                    ${_a}                  ${_h3}                  ${deal.description ? `\x3Cp style="font-size: 13px; color: var(--tg-df-text-muted); margin-bottom: 12px; line-height: 1.4;">${this.escapeHTML(deal.description)}${_p}` : ''}                  \x3Cdiv class="tg-df-card-footer">                    ${priceGroupHtml}                    \x3Ca href="${this.escapeHTML(rewrittenLink)}" ${dataAttr} target="_blank" rel="noopener nofollow" class="tg-df-card-cta ${isSavingsSquadMode ? 'tg-df-cta-savings-squad' : ''}" style="text-decoration: none;">${ctaText}${_a}                  ${_div}                ${_div}              ${_div}            `;                        return htmlOutput;            } catch (e) {               console.log("Error rendering deal in map for index", index, typeof deal === 'object' ? JSON.stringify(deal) : deal, "MSG:", e.message);               return '';            }          }).join('');                    if (displayDeals.length > this.displayLimit || ((this.getViewMode() === 'carousel' || this.getViewMode() === 'auto') && displayDeals.length > 0 && displayDeals.length % ((this.rowsSelect && this.rowsSelect.value) ? parseInt(this.rowsSelect.value, 10) : 12) === 0)) {            if (this.getViewMode() === 'carousel') {               dealsHtml += `                 \x3Cbutton type="button" class="tg-df-load-more-card tg-df-load-more">                   \x3Csvg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-bottom: 8px;">\x3Cpath d="M5 12h14">\x3C/path>\x3Cpath d="m12 5 7 7-7 7">\x3C/path>\x3C/svg>                   Load More                 ${_button}               `;            } else {               dealsHtml += `                 \x3Cdiv style="width: 100%; display: flex; justify-content: center; margin-top: 16px; grid-column: 1 / -1;">                   \x3Cbutton type="button" class="tg-df-tag-outline tg-df-load-more" style="padding: 8px 24px; border-radius: 100px; font-weight: 600; font-size: 14px; cursor: pointer; display: flex; align-items: center;">Load More${_button}                 ${_div}               `;            }          }                    this.grid.innerHTML = dealsHtml;          // Inject JSON-LD          try {            let targetNode = this.hostContainer || document.head;            let jsonLdScript = targetNode.querySelector('#tg-df-json-ld-' + this.widgetId);            if (!jsonLdScript) {                jsonLdScript = document.createElement('script');                jsonLdScript.type = 'application/ld+json';                jsonLdScript.id = 'tg-df-json-ld-' + this.widgetId;                targetNode.appendChild(jsonLdScript);            }            const jsonLdData = {              "@context": "https://schema.org",              "@type": "ItemList",              "itemListElement": displayDeals.slice(0, this.displayLimit).map((deal, index) => {                 let isoCurrency = "USD";                 if (deal.currency === '£') isoCurrency = "GBP";                 else if (deal.currency === '€') isoCurrency = "EUR";                 else if (deal.currency === 'A$') isoCurrency = "AUD";                 else if (deal.currency === 'CA$') isoCurrency = "CAD";                 const areaCode = typeof this.getAreaCode === 'function' ? this.getAreaCode() : 'US';                 const revenueId = typeof generateRevenueId === 'function' ? generateRevenueId(deal.url, deal.title, deal.merchant, null) : '';                 const rewrittenLink = typeof rewriteAffiliateLink === 'function' ? rewriteAffiliateLink(deal.url, areaCode, revenueId) : deal.url;                 return {                   "@type": "ListItem",                   "position": index + 1,                   "item": {                     "@type": "Product",                     "name": deal.title,                     "image": deal.image || "",                     "description": deal.description || "",                     "brand": {                       "@type": "Brand",                       "name": deal.brand || ""                     },                     "offers": {                       "@type": "Offer",                       "priceCurrency": isoCurrency,                       "price": deal.rawPrice || 0,                       "url": rewrittenLink,                       "seller": {                         "@type": "Organization",                         "name": deal.merchant || ""                       }                     }                   }                 };              }).filter(item => item.item.name)            };            jsonLdScript.textContent = JSON.stringify(jsonLdData);          } catch(e) { console.warn("JSON-LD generation failed", e); }                    let gridWrapper = this.grid.parentElement;          if (gridWrapper && gridWrapper.classList.contains('tg-df-grid-wrapper')) {             let rightChevron = gridWrapper.querySelector('.tg-df-carousel-scroll-right');             let leftChevron = gridWrapper.querySelector('.tg-df-carousel-scroll-left');             if (this.getViewMode() === 'carousel') {                 // The observer set up in setupScrollListeners handles visibility.                 if (rightChevron) rightChevron.style.display = 'flex';                 if (leftChevron) leftChevron.style.display = 'none'; // reset correctly             } else {                 if (rightChevron) rightChevron.style.display = 'none';                 if (leftChevron) leftChevron.style.display = 'none';             }          }                    const loadMoreBtn = this.grid.querySelector('.tg-df-load-more');          if (loadMoreBtn) {            loadMoreBtn.addEventListener('click', async () => {              if (typeof trackElementInteraction === 'function') {                trackElementInteraction({ id: 'load-more', name: 'Load more', label: 'Load More Results' });              }              if (displayDeals.length <= this.displayLimit) {                 loadMoreBtn.innerHTML = `                  <svg class="tg-df-spinner" style="width: 16px; height: 16px; display: inline-block; vertical-align: middle; margin-right: 8px;" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" d="M12 2v4m0 12v4M4.93 4.93l2.83 2.83m8.48 8.48l2.83 2.83M2 12h4m12 0h4M4.93 19.07l2.83-2.83m8.48-8.48l2.83-2.83"/></svg>                  Loading...                 `;                 loadMoreBtn.disabled = true;                 await this.fetchDeals(this.currentQuery, true);              } else {                 this.displayLimit += this.getRowsLimit();                 this.render();              }            });          }                      this.bindCouponButtons();            this.checkAndUpdateCoupons();                        // Allow hawklinks.js to discover and rewrite our widget links             // by appending the .article-body class and manually triggering processArticle.            let container = this.root.classList.contains('tg-df-container') ? this.root : this.root.querySelector('.tg-df-container');            if (container && !container.classList.contains('article-body')) {               container.classList.add('article-body');            }            setTimeout(() => {               if (this.grid && !this.grid.classList.contains('article-body')) this.grid.classList.add('article-body');               document.dispatchEvent(new CustomEvent('processArticle', { detail: { element: this.root } }));            }, 50);          } catch(e) {            console.warn("Widget render error", e);          }        }                async checkAndUpdateCoupons() {          const wrappers = Array.from(this.root.querySelectorAll('.tg-df-coupon-wrapper'));          if (wrappers.length === 0) return;                    const merchants = [...new Set(wrappers.map(w => w.getAttribute('data-merchant')).filter(Boolean))];          if (merchants.length === 0) return;          const couponResultsMap = await this.checkMerchantsCouponsBulk(merchants);                    for (const merchant of merchants) {            const hasCoupons = !!couponResultsMap[merchant];            const merchantWrappers = wrappers.filter(w => w.getAttribute('data-merchant') === merchant);            merchantWrappers.forEach(wrapper => {              const spinner = wrapper.querySelector('.tg-df-coupon-spinner');              const btn = wrapper.querySelector('.tg-df-tag-coupons');                            if (spinner) spinner.style.display = 'none';                            if (hasCoupons && btn) {                btn.style.display = 'inline-flex';              } else if (!hasCoupons) {                wrapper.style.display = 'none';              }            });          }        }        updateFloatingCopyBar() {          if (!this.editorBar || !this.editorSelectedCount) return;          if (this.editorMode && this.selectedDeals.size > 0) {            this.editorBar.style.display = 'flex';            this.editorSelectedCount.innerText = this.selectedDeals.size;          } else {            this.editorBar.style.display = 'none';          }        }        async copySelectedDealsToCMS() {           function htmlToSlate(htmlString) {              if (!htmlString) return [{ type: 'paragraph', children: [{ text: '' }] }];              let doc;              if (typeof window !== 'undefined' && window.DOMParser) {                 doc = new DOMParser().parseFromString(htmlString, 'text/html');              } else {                 doc = document.implementation.createHTMLDocument('');                 doc.body.innerHTML = htmlString;              }                            function parseNode(node, marks = {}) {                  if (node.nodeType === 3) {                      const text = node.textContent;                      if (!text) return null;                      return { text: text, ...marks };                  }                  if (node.nodeType === 1) {                      const tagName = node.tagName.toLowerCase();                      if (tagName === 'br') {                          return { type: 'line-break', children: [{ text: '' }] };                      }                      if (tagName === 'p') {                          let children = Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                          if (children.length === 0) children.push({ text: "" });                          return { type: 'paragraph', children };                      }                      if (tagName === 'strong' || tagName === 'b') {                          const newMarks = { ...marks, bold: true };                          return Array.from(node.childNodes).map(child => parseNode(child, newMarks)).flat().filter(Boolean);                      }                      if (tagName === 'em' || tagName === 'i') {                          const newMarks = { ...marks, italic: true };                          return Array.from(node.childNodes).map(child => parseNode(child, newMarks)).flat().filter(Boolean);                      }                      if (tagName === 'a') {                          const href = node.getAttribute('href') || '';                          let children = Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                          if (children.length === 0) children.push({ text: "" });                          return {                              type: 'link',                              url: href,                              isNoFollow: (node.getAttribute('rel') || '').includes('nofollow'),                              isSponsored: (node.getAttribute('rel') || '').includes('sponsored'),                              isOpenNewTab: node.getAttribute('target') === '_blank',                              isPreventDataRewrite: false,                              children: children                          };                      }                      return Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                  }                  return null;              }                            let blocksArray = [];              let currentParagraphChildren = [];              function flushParagraph() {                  if (currentParagraphChildren.length > 0) {                      blocksArray.push({ type: 'paragraph', children: currentParagraphChildren });                      currentParagraphChildren = [];                  }              }              Array.from(doc.body.childNodes).forEach(node => {                  const parsed = parseNode(node, {});                  const parsedItems = Array.isArray(parsed) ? parsed : (parsed ? [parsed] : []);                  parsedItems.forEach(item => {                      if (item.type === 'paragraph') {                          flushParagraph();                          blocksArray.push(item);                      } else {                          currentParagraphChildren.push(item);                      }                  });              });              flushParagraph();              if (blocksArray.length === 0) {                  blocksArray = [{ type: 'paragraph', children: [{ text: '' }] }];              }              return blocksArray;           }           const blocks = [];                      this.editorCopyBtn.innerHTML = '\x3Cspan class="tg-df-coupon-spinner" style="display:inline-block; margin-right:8px; border-top-color:#fff;">' + '<' + '/span> Copying...';           for (const deal of Array.from(this.selectedDeals.values())) {              const url = deal.url;              const merchant = deal.merchant;              const title = deal.title;              const image = deal.image;              const currentPrice = deal.currency + deal.rawPrice;              const wasPrice = deal.hasWasPrice && deal.rawMsrp > deal.rawPrice ? deal.currency + deal.rawMsrp : '';                            let couponsChildren = [];              try {                  const area = this.getAreaCode();                  const apiUrl = new URL('https://search-api.fie.future.net.uk/widget.php');                  apiUrl.searchParams.append('model_name', 'Everything');                  apiUrl.searchParams.append('language', 'en-GB');                  apiUrl.searchParams.append('area', area);                  apiUrl.searchParams.append('combine_product_types', '1');                  apiUrl.searchParams.append('filter_merchant_name', merchant);                  apiUrl.searchParams.append('all_filters', 'false');                  apiUrl.searchParams.append('exclude_unlabelled', 'false');                  apiUrl.searchParams.append('include_specs', 'false');                  apiUrl.searchParams.append('sort', 'voucher');                  apiUrl.searchParams.append('distinct_merchants', 'natural');                  apiUrl.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');                  apiUrl.searchParams.append('rows', '3');                  apiUrl.searchParams.append('origin', 'widgets-clientside');                                    let res; try { res = await fetch(apiUrl.toString()); } catch (e) { return; }                  if (res.ok) {                      const data = await res.json();                      let offers = [];                      if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {                        offers = data.widget.data.offers;                      } else if (data && data.data && Array.isArray(data.data.offers)) {                        offers = data.data.offers;                      }                                            if (offers.length > 0) {                          couponsChildren.push({ text: "Also check out these coupons: ", bold: true });                          offers.slice(0, 3).forEach((offer, idx) => {                              const actualOffer = offer.offer || offer;                              const offerName = actualOffer.name || actualOffer.title || offer.model_name || offer.title || offer.name || 'Coupon';                              const linkUrl = actualOffer.link || actualOffer.url || actualOffer.offer_link || '#';                              couponsChildren.push({ type: "line-break", children: [{ text: "" }] });                              couponsChildren.push({ text: "🎟️ " });                              couponsChildren.push({                                  type: "link",                                  url: linkUrl,                                  isNoFollow: true,                                  isSponsored: false,                                  isOpenNewTab: true,                                  isPreventDataRewrite: false,                                  children: [{ text: offerName, bold: true }]                              });                          });                      }                  }              } catch (err) {                  console.warn('Failed to fetch coupons for', merchant, err);              }              let descriptionValue = [];              if (deal.text) {                 descriptionValue = htmlToSlate(deal.text);              } else {                 const dealDescriptions = [                   `Don't miss out on this fantastic deal for the ${title}. It is currently available at ${merchant} for a highly competitive price.`,                   `We've spotted an excellent price drop on the ${title}. Grab it now at ${merchant} before it's gone.`,                   `The ${title} is currently seeing a generous discount over at ${merchant}. This is a perfect time to buy if you've been holding out.`,                   `If you're in the market for the ${title}, ${merchant} has just the deal for you.`,                   `Score the ${title} for less at ${merchant} right now. This is a rare chance to save big.`,                   `Upgrade your setup with the ${title}, now available at a stellar price via ${merchant}.`                 ];                 const randomDescription = dealDescriptions[Math.floor(Math.random() * dealDescriptions.length)];                 descriptionValue = [                    { type: "paragraph", children: [{ text: randomDescription }] }                 ];              }                            if (couponsChildren.length > 0) {                 let lastBlock = descriptionValue[descriptionValue.length - 1];                 if (lastBlock && lastBlock.type === 'paragraph') {                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children.push({ text: "Also check out these coupons: ", bold: true });                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children = lastBlock.children.concat(couponsChildren);                 } else {                     descriptionValue.push({                         type: "paragraph",                         children: [                             { type: "line-break", children: [{ text: "" }] },                             { type: "line-break", children: [{ text: "" }] },                             { text: "Also check out these coupons: ", bold: true },                             { type: "line-break", children: [{ text: "" }] },                             ...couponsChildren                         ]                     });                 }              }              function normalizeCurrencyToISO(symbol) {                const map = { '£': 'GBP', '$': 'USD', 'A$': 'AUD', 'CA$': 'CAD', '€': 'EUR' };                return map[symbol] || symbol;              }              const isoCurrency = normalizeCurrencyToISO(deal.currency);              blocks.push({                 id: (window.crypto && window.crypto.randomUUID) ? window.crypto.randomUUID() : 'cms-' + Date.now() + Math.random(),                 blockTypeName: "deal",                 excludeFrom: [],                 collapsible: false,                 props: {                    description: {                       value: descriptionValue,                       touched: false,                       validationMessage: ""                    },                    image: {                       value: {                          credit: [{ type: "paragraph", children: [{ text: merchant }] }],                          dateCreated: Date.now(),                          dateModified: Date.now(),                          distribution: [],                          fileSize: 0,                          height: 1000,                          id: deal.id,                          imageRights: "",                          src: image,                          name: title + ".jpg",                          tags: [],                          width: 1000                       },                       touched: false,                       validationMessage: ""                    },                    showDealButton: { value: true, touched: false, validationMessage: "" },                    isPreferredPartner: { value: false, touched: false, validationMessage: "" },                    linkHref: { value: url, touched: false, validationMessage: "" },                    linkLabel: { value: "", touched: false, validationMessage: "" },                    linkIsNoFollow: { value: true, touched: false, validationMessage: "" },                    linkIsSponsored: { value: false, touched: false, validationMessage: "" },                    linkIsOpenNewWindow: { value: true, touched: false, validationMessage: "" },                    customPromoFlags: { value: [], touched: false, validationMessage: "" },                    showStarDeal: { value: false, touched: false, validationMessage: "" },                    savingType: { value: "none", touched: false, validationMessage: "" },                    starDealPromoFlag: { value: "", touched: false, validationMessage: "" },                    showEditorsChoice: { value: false, touched: false, validationMessage: "" },                    editorsChoiceTitle: { value: "", touched: false, validationMessage: "" },                    hawkPriceCurrency: { value: { value: isoCurrency, label: isoCurrency }, touched: false, validationMessage: "" },                    hawkPrice: { value: deal.hasWasPrice ? String(deal.rawMsrp) : String(deal.rawPrice), touched: false, validationMessage: "" },                    hawkSalePrice: { value: String(deal.rawPrice), touched: false, validationMessage: "" },                    lastCheckedPriceDate: { value: "", touched: false, validationMessage: "" },                    hawkModel: { touched: false, validationMessage: "" },                    productId: { value: "", touched: false, validationMessage: "" },                    voucherId: { value: "", touched: false, validationMessage: "" },                    brand: { value: deal.brand || merchant, touched: false, validationMessage: "" },                    productName: { value: title, touched: false, validationMessage: "" },                    label: { value: "", touched: false, validationMessage: "" },                    retailer: { value: merchant, touched: false, validationMessage: "" },                    priceCheckError: false                 },                 failedFetchError: ""              });           }           const payload = {              type: "articleBuilderPages",              data: blocks           };           const jsonStr = JSON.stringify(payload);                      if (navigator.clipboard && navigator.clipboard.writeText) {              navigator.clipboard.writeText(jsonStr).then(() => {                 this.editorCopyBtn.innerHTML = 'Copied!';                 setTimeout(() => {                    this.editorCopyBtn.innerHTML = '\x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2"><' + '/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"><' + '/path><' + '/svg> Copy to CMS';                 }, 2000);              }).catch(err => {                 console.warn('Failed to copy text: ', err);                 alert('Failed to copy deals to clipboard. See console.');              });           } else {              // Fallback              const textArea = document.createElement("textarea");              textArea.value = jsonStr;              document.body.appendChild(textArea);              textArea.focus();              textArea.select();              try {                 document.execCommand('copy');                 this.editorCopyBtn.innerHTML = 'Copied!';                 setTimeout(() => {                    this.editorCopyBtn.innerHTML = '\x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2"><' + '/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"><' + '/path><' + '/svg> Copy to CMS';                 }, 2000);              } catch (err) {                 console.warn('Fallback: Oops, unable to copy', err);                 alert('Fallback: Failed to copy deals to clipboard.');              }              document.body.removeChild(textArea);           }        }      }      // Initialize the Widget      if (document.readyState === 'loading') {        document.addEventListener('DOMContentLoaded', () => new DealsFinderWidget({ rootId: 'signal-deals-finder-root', rootNode: shadowRoot, hostContainer: hostContainer }));      } else {        new DealsFinderWidget({ rootId: 'signal-deals-finder-root', rootNode: shadowRoot, hostContainer: hostContainer });      }    })();  </script></div> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/home/kitchen-dining/these-15-ninja-deals-are-too-good-to-miss-ahead-of-labor-day-save-up-to-40-percent-on-blenders-air-fryers-and-more</link>
                                                                            <description>
                            <![CDATA[ A bunch of Ninja appliances are on sale at Amazon — check out the biggest upgrades for your home and kitchen. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">sfpKEdWYWGXpHxDyudu2pL</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/RSq6p7Tgy8whV7xn5Ruf6J-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Thu, 27 Aug 2026 14:32:10 +0000</pubDate>                                                                                                                                <updated>Fri, 04 Sep 2026 11:52:43 +0000</updated>
                                                                                                                                            <category><![CDATA[Kitchen & Dining]]></category>
                                                    <category><![CDATA[Home]]></category>
                                                    <category><![CDATA[Home Appliances]]></category>
                                                                                                                    <dc:creator><![CDATA[ Olivia Halevy ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/YAg7Fmh9dGKbg3hULBMWiU.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Olivia is a Deals Writer at Tom’s Guide. She loves all things lifestyle, shopping and sourcing the best deals from some of the top brands, retailers and websites around. From fashion and beauty to smart home and tech, she has an eye for finding practical, stylish, and reasonably-priced items that help make life simpler (and a little more aesthetically-pleasing).&amp;nbsp;Olivia has over five years of experience writing lifestyle, commerce, and branded content for &lt;a href=&quot;http://patch.com/&quot;&gt;Patch.com&lt;/a&gt;. She&#039;s covered major shopping holidays like Amazon Prime Day, Black Friday and Cyber Monday. In her free time, she enjoys trying out new exercise classes, binge-watching the latest viral TV shows, cooking, spending time with family and taking long walks with her dog, Gus.&amp;nbsp;&lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/RSq6p7Tgy8whV7xn5Ruf6J-1280-80.jpg">
                                                            <media:credit><![CDATA[Amazon]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Ninja deals]]></media:description>                                                            <media:text><![CDATA[Ninja deals]]></media:text>
                                <media:title type="plain"><![CDATA[Ninja deals]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/RSq6p7Tgy8whV7xn5Ruf6J-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Labor Day is almost here — and if you're hosting any backyard barbecues or celebrations, chances are you could use a little help. That's where Ninja comes into play! The kitchen appliance brand has everything you need to meal prep and get grilling! </p><p>Fortunately, <a href="https://www.amazon.com/stores/page/471F718E-0761-48DF-ABAF-0FC6590C695B" target="_blank" rel="nofollow">Amazon is closing out the summer with a bunch of Ninja appliance deals</a>. From high-quality blenders and air fryers to pizza ovens and grills, there are some discounts here that you definitely don't want to miss — especially since the best deals are currently up to 40% off.</p><p>I've been scouring the sale and have found the best cooking deals to help you in the kitchen this Labor Day and beyond. I've listed all my favorites below, so keep scrolling to check them out.</p><h3 class="article-body__section" id="section-quick-links"><span>Quick Links</span></h3><ul><li><a href="https://www.amazon.com/stores/page/471F718E-0761-48DF-ABAF-0FC6590C695B" target="_blank" rel="nofollow"><strong>shop all Ninja deals at Amazon</strong></a></li><li><strong>Ninja Blast Max: </strong><a href="https://www.amazon.com/dp/B0DB964918?" target="_blank" rel="nofollow"><strong>was $99 now $69</strong></a></li><li><strong>Ninja Iced Coffee Maker: </strong><a href="https://www.amazon.com/Ninja-Specialty-Single-Serve-Compatible-PB055ABL/dp/B0D1LNKN4Z?" target="_blank" rel="nofollow"><strong>was $129 now $99</strong></a></li><li><strong>Ninja Crispi 4-in-1 Portable Glass Air Fryer: </strong><a href="https://www.amazon.com/Ninja-Microwave-Dishwasher-Containers-FN101GY/dp/B0DDDD8WD6?" target="_blank" rel="nofollow"><strong>was $179 now $159</strong></a></li><li><strong>Ninja Double Oven, 12-in-1: </strong><a href="https://www.amazon.com/Ninja-DCT401-FlavorSeal-Convection-Stainless/dp/B0BRQS5BH6" target="_blank" rel="nofollow"><strong>was $379 now $219</strong></a></li><li><strong>Ninja Woodfire Oven & Smoker: </strong><a href="https://www.amazon.com/Ninja-Woodfire-Technology-terracotta-OO101/dp/B0C6BQVDX3/" target="_blank" rel="nofollow"><strong>was $399 now $279</strong></a></li><li><strong>Ninja Luxe Café Premier: </strong><a href="https://www.amazon.com/dp/B0FGDTHY1Y" target="_blank" rel="nofollow"><strong>now $599</strong></a></li><li><strong>Ninja FlexFlame Propane Grill: </strong><a href="https://www.amazon.com/Ninja-FlexFlame-Electric-Stainless-PG301/dp/B0GJ76517J" target="_blank" rel="nofollow"><strong>was $1,119 now $999</strong></a></li></ul><h3 class="article-body__section" id="section-ninja-deals"><span>Ninja Deals</span></h3><div class="product"><a data-dimension112="69b0fedc-a21f-11f1-8a6e-418eb9d3d485" data-action="Deal Block" data-label="Blast Max" data-dimension48="Blast Max" data-dimension25="$69" href="https://www.amazon.com/dp/B0DB964918?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1216px;"><p class="vanilla-image-block" style="padding-top:123.36%;"><img id="9Q4QY399FaozAFUt4j8dTW" name="ninja-blast-max-portable-blender--twist--bb517479-54ce-4a77-974c-58e2f44dde33.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/9Q4QY399FaozAFUt4j8dTW.jpg" mos="" align="middle" fullscreen="" width="1216" height="1500" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>The Ninja Blast Max is capable of taking on any challenge you throw at it, including crushing ice and blitzing berries to make yummy smoothies. It comes with multiple blend settings to make sure your blender is using the right level of power for the task at hand, and the compact size means it’s a great option for anyone with a small kitchen. <a class="view-deal button" href="https://www.amazon.com/dp/B0DB964918?" target="_blank" rel="nofollow" data-dimension112="69b0fedc-a21f-11f1-8a6e-418eb9d3d485" data-action="Deal Block" data-label="Blast Max" data-dimension48="Blast Max" data-dimension25="$69">View Deal</a></p></div><div class="product"><a data-dimension112="69b0ff4a-a21f-11f1-9b87-d7697e968c6e" data-action="Deal Block" data-label="Professional Blender" data-dimension48="Professional Blender" data-dimension25="$79" href="https://www.amazon.com/Ninja-BR201AMZ-Professional-Smoothies-Dishwasher-Safe/dp/B0GH8PVFHS?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:679px;"><p class="vanilla-image-block" style="padding-top:162.30%;"><img id="sFftzctqbej7oaSQLEtBRj" name="Ninja Pro Blender" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/sFftzctqbej7oaSQLEtBRj.jpg" mos="" align="middle" fullscreen="" width="679" height="1102" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Ninja-BR201AMZ-Professional-Smoothies-Dishwasher-Safe/dp/B0GH8PVFHS?" target="_blank" rel="nofollow" data-dimension112="69b0ff4a-a21f-11f1-9b87-d7697e968c6e" data-action="Deal Block" data-label="Professional Blender" data-dimension48="Professional Blender" data-dimension25="$79">Professional Blender: was $109 now $79</a></strong><br>Be it daily smoothies or making ice cream, this blender can tackle it all, at the touch of a button. Also featured on our <a href="https://www.tomsguide.com/best-picks/best-blenders">best blenders</a> guide, this comes with 3 preset Auto-iQ programs that creates smoothies, frozen drinks, and ice cream, and its powerful blades can crush ice in no time. This is a great deal if you want an easy-to-use blender, with professional results.  <a class="view-deal button" href="https://www.amazon.com/Ninja-BR201AMZ-Professional-Smoothies-Dishwasher-Safe/dp/B0GH8PVFHS?" target="_blank" rel="nofollow" data-dimension112="69b0ff4a-a21f-11f1-9b87-d7697e968c6e" data-action="Deal Block" data-label="Professional Blender" data-dimension48="Professional Blender" data-dimension25="$79">View Deal</a></p></div><div class="product"><a data-dimension112="69b0ffc2-a21f-11f1-b219-a33e5661b9bb" data-action="Deal Block" data-label="Air Fryer Pro 4-in-1" data-dimension48="Air Fryer Pro 4-in-1" data-dimension25="$89" href="https://www.amazon.com/dp/B0CSZ7WBYW" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:560px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="f49Q8qGkV5TG2EsuDo3or5" name="Ninja Air Fryer Pro 4 in 1" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/f49Q8qGkV5TG2EsuDo3or5.jpg" mos="" align="middle" fullscreen="" width="560" height="560" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>The Ninja Air Fryer Pro 4-in-1 is a versatile kitchen appliance that air fries, roasts, reheats, and dehydrates. With its 5-quart capacity, it cooks food quickly using hot air circulation, delivering crispy, healthier meals with little to no oil. That makes it <em>perfect </em>for everyday cooking and batch meal prep!<a class="view-deal button" href="https://www.amazon.com/dp/B0CSZ7WBYW" target="_blank" rel="nofollow" data-dimension112="69b0ffc2-a21f-11f1-b219-a33e5661b9bb" data-action="Deal Block" data-label="Air Fryer Pro 4-in-1" data-dimension48="Air Fryer Pro 4-in-1" data-dimension25="$89">View Deal</a></p></div><div class="product"><a data-dimension112="69b10030-a21f-11f1-87c3-c57969611a45" data-action="Deal Block" data-label="Pods & Grounds Specialty Single-Serve Iced Coffee Maker" data-dimension48="Pods & Grounds Specialty Single-Serve Iced Coffee Maker" data-dimension25="$99" href="https://www.amazon.com/Ninja-Specialty-Single-Serve-Compatible-PB055ABL/dp/B0D1LP9SF1?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:679px;"><p class="vanilla-image-block" style="padding-top:99.56%;"><img id="4uiaRXRKY8Go6F4ZpM7UdA" name="Ninja coffee" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/4uiaRXRKY8Go6F4ZpM7UdA.jpg" mos="" align="middle" fullscreen="" width="679" height="676" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Ninja-Specialty-Single-Serve-Compatible-PB055ABL/dp/B0D1LP9SF1?" target="_blank" rel="nofollow" data-dimension112="69b10030-a21f-11f1-87c3-c57969611a45" data-action="Deal Block" data-label="Pods & Grounds Specialty Single-Serve Iced Coffee Maker" data-dimension48="Pods & Grounds Specialty Single-Serve Iced Coffee Maker" data-dimension25="$99">Pods & Grounds Specialty Single-Serve Iced Coffee Maker: was $129 now $99</a></strong><br>This stylish Ninja coffee maker comes in a gorgeous Sage colorway and is now on sale for $30 off. Whether you prefer pods or grounds, this device makes tasty brews in 7 sizes (6-oz. to 24-oz) and has a built-in, fold-away milk frother!<a class="view-deal button" href="https://www.amazon.com/Ninja-Specialty-Single-Serve-Compatible-PB055ABL/dp/B0D1LP9SF1?" target="_blank" rel="nofollow" data-dimension112="69b10030-a21f-11f1-87c3-c57969611a45" data-action="Deal Block" data-label="Pods & Grounds Specialty Single-Serve Iced Coffee Maker" data-dimension48="Pods & Grounds Specialty Single-Serve Iced Coffee Maker" data-dimension25="$99">View Deal</a></p></div><div class="product"><a data-dimension112="69b100a8-a21f-11f1-9e18-95eb917f62af" data-action="Deal Block" data-label="BlendBOSS Blender" data-dimension48="BlendBOSS Blender" data-dimension25="$109" href="https://www.amazon.com/Ninja-BlendbossTM-Detachable-Technology-DB351CY/dp/B0FSGSYF79?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1500px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="JkaewDaMJCoHarzBbjk5u8" name="Ninja BlendBOSS deal block" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/JkaewDaMJCoHarzBbjk5u8.jpg" mos="" align="middle" fullscreen="" width="1500" height="1500" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Ninja-BlendbossTM-Detachable-Technology-DB351CY/dp/B0FSGSYF79?" target="_blank" rel="nofollow" data-dimension112="69b100a8-a21f-11f1-9e18-95eb917f62af" data-action="Deal Block" data-label="BlendBOSS Blender" data-dimension48="BlendBOSS Blender" data-dimension25="$109">BlendBOSS Blender: was $129 now $109</a></strong><br>The Ninja BlendBOSS is one of the best personal blenders we've used. In our <a href="https://www.tomsguide.com/home/home-appliances/ninja-blendboss-review">Ninja BlendBOSS review</a>, we said the Editor's Choice blender is great at everything from making hummus to lump-free smoothies. Its' compact, comes in a range of colors, and it's simply the best personal blender you can buy at this price point. <a class="view-deal button" href="https://www.amazon.com/Ninja-BlendbossTM-Detachable-Technology-DB351CY/dp/B0FSGSYF79?" target="_blank" rel="nofollow" data-dimension112="69b100a8-a21f-11f1-9e18-95eb917f62af" data-action="Deal Block" data-label="BlendBOSS Blender" data-dimension48="BlendBOSS Blender" data-dimension25="$109">View Deal</a></p></div><div class="product"><a data-dimension112="69b10120-a21f-11f1-8d7b-654bb46f6692" data-action="Deal Block" data-label="NeverClog Cold Press Juicer" data-dimension48="NeverClog Cold Press Juicer" data-dimension25="$129" href="https://www.amazon.com/dp/B0BR8HZL9V?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:522px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="pKMqdL3azKMYSNwdTHk4m9" name="Ninja Never Clog" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/pKMqdL3azKMYSNwdTHk4m9.jpg" mos="" align="middle" fullscreen="" width="522" height="522" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0BR8HZL9V?" target="_blank" rel="nofollow" data-dimension112="69b10120-a21f-11f1-8d7b-654bb46f6692" data-action="Deal Block" data-label="NeverClog Cold Press Juicer" data-dimension48="NeverClog Cold Press Juicer" data-dimension25="$129">NeverClog Cold Press Juicer: was $149 now $129</a></strong><br>Create healthy juices from the comforts of your home with the Ninja Cold Press Juicer Pro. It features a powerful high torque motor and includes two one-touch programs that make it easy to operate. We also like that it has a pulp control that allows you to customize your juice with pulp or without.<a class="view-deal button" href="https://www.amazon.com/dp/B0BR8HZL9V?" target="_blank" rel="nofollow" data-dimension112="69b10120-a21f-11f1-8d7b-654bb46f6692" data-action="Deal Block" data-label="NeverClog Cold Press Juicer" data-dimension48="NeverClog Cold Press Juicer" data-dimension25="$129">View Deal</a></p></div><div class="product"><a data-dimension112="69b10198-a21f-11f1-8c60-5be5d32ce5bf" data-action="Deal Block" data-label="Mega Kitchen System" data-dimension48="Mega Kitchen System" data-dimension25="$159" href="https://www.amazon.com/dp/B00939I7EK" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1676px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="sWibiMn9jcqpLxyQRazy6f" name="Ninja Amazon 2.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/sWibiMn9jcqpLxyQRazy6f.jpg" mos="" align="middle" fullscreen="" width="1676" height="1676" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B00939I7EK" target="_blank" rel="nofollow" data-dimension112="69b10198-a21f-11f1-8c60-5be5d32ce5bf" data-action="Deal Block" data-label="Mega Kitchen System" data-dimension48="Mega Kitchen System" data-dimension25="$159">Mega Kitchen System: was $219 now $159</a></strong><br>Leave all the multi-tasking in the kitchen to one appliance with this Ninja blender. With four functions for smoothies, processing, dough, drinks and more it will quickly become your go-to kitchen appliance. With this ultimate appliance, you’ll be enjoying fresh, healthy drinks, homemade bread and sweet bakes.<a class="view-deal button" href="https://www.amazon.com/dp/B00939I7EK" target="_blank" rel="nofollow" data-dimension112="69b10198-a21f-11f1-8c60-5be5d32ce5bf" data-action="Deal Block" data-label="Mega Kitchen System" data-dimension48="Mega Kitchen System" data-dimension25="$159">View Deal</a></p></div><div class="product"><a data-dimension112="69b10206-a21f-11f1-b6d6-d311f0210fc6" data-action="Deal Block" data-label="Crispi 4-in-1 Portable Glass Air Fryer" data-dimension48="Crispi 4-in-1 Portable Glass Air Fryer" data-dimension25="$159" href="https://www.amazon.com/Ninja-Microwave-Dishwasher-Containers-FN101GY/dp/B0DDDD8WD6?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:679px;"><p class="vanilla-image-block" style="padding-top:85.86%;"><img id="zNkXNCVYCubXhCRwjaoGPj" name="Ninjs Crispi" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/zNkXNCVYCubXhCRwjaoGPj.jpg" mos="" align="middle" fullscreen="" width="679" height="583" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Ninja-Microwave-Dishwasher-Containers-FN101GY/dp/B0DDDD8WD6?" target="_blank" rel="nofollow" data-dimension112="69b10206-a21f-11f1-b6d6-d311f0210fc6" data-action="Deal Block" data-label="Crispi 4-in-1 Portable Glass Air Fryer" data-dimension48="Crispi 4-in-1 Portable Glass Air Fryer" data-dimension25="$159">Crispi 4-in-1 Portable Glass Air Fryer: was $179 now $159</a></strong><br>The Ninja Crispi is one of Ninja's most interesting recent releases. It features a removable cooking lid and interchangeable glass containers to cook meals of a range of sizes. In our <a href="https://www.tomsguide.com/home/air-fryers/ninja-crispi-air-fryer-review">Ninja Crispi review</a>, it earned a well-deserved 4.5 stars.  <a class="view-deal button" href="https://www.amazon.com/Ninja-Microwave-Dishwasher-Containers-FN101GY/dp/B0DDDD8WD6?" target="_blank" rel="nofollow" data-dimension112="69b10206-a21f-11f1-b6d6-d311f0210fc6" data-action="Deal Block" data-label="Crispi 4-in-1 Portable Glass Air Fryer" data-dimension48="Crispi 4-in-1 Portable Glass Air Fryer" data-dimension25="$159">View Deal</a></p></div><div class="product"><a data-dimension112="69b1027e-a21f-11f1-b242-23fcfb084303" data-action="Deal Block" data-label="Double Oven, 12-in-1" data-dimension48="Double Oven, 12-in-1" data-dimension25="$219" href="https://www.amazon.com/Ninja-DCT401-FlavorSeal-Convection-Stainless/dp/B0BRQS5BH6" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:875px;"><p class="vanilla-image-block" style="padding-top:85.60%;"><img id="LQBDeKyzWKbLWRQgh54YmA" name="Double Oven, 12-in-1 DCT401" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/LQBDeKyzWKbLWRQgh54YmA.jpg" mos="" align="middle" fullscreen="" width="875" height="749" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Ninja-DCT401-FlavorSeal-Convection-Stainless/dp/B0BRQS5BH6" target="_blank" rel="nofollow" data-dimension112="69b1027e-a21f-11f1-b242-23fcfb084303" data-action="Deal Block" data-label="Double Oven, 12-in-1" data-dimension48="Double Oven, 12-in-1" data-dimension25="$219">Double Oven, 12-in-1: was $379 now $219</a></strong><br>We couldn’t recommend this toaster oven more. Although it has since been replaced by a newer model, the DCT401 is a previous winner on our list of the <a href="https://www.tomsguide.com/best-picks/best-toaster-ovens">best toaster ovens</a>. We love that it divides into two ovens you can access separately via the FlexDoor, so you can cook two things at once. There are 12 functions overall, including toast, bake, whole roast, air fry, convection and pizza — meaning you can cook pretty much anything in there however you like.<a class="view-deal button" href="https://www.amazon.com/Ninja-DCT401-FlavorSeal-Convection-Stainless/dp/B0BRQS5BH6" target="_blank" rel="nofollow" data-dimension112="69b1027e-a21f-11f1-b242-23fcfb084303" data-action="Deal Block" data-label="Double Oven, 12-in-1" data-dimension48="Double Oven, 12-in-1" data-dimension25="$219">View Deal</a></p></div><div class="product"><a data-dimension112="69b102ec-a21f-11f1-9afb-01ba23bf4691" data-action="Deal Block" data-label="Foodi XL Pro Air Fry Oven, 10-in-1" data-dimension48="Foodi XL Pro Air Fry Oven, 10-in-1" data-dimension25="$229" href="https://www.amazon.com/Ninja-DT201-Countertop-Convection-Dehydrate/dp/B08BXX69K4" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1500px;"><p class="vanilla-image-block" style="padding-top:75.80%;"><img id="sFc44K8P9eTgsrZ4Kc25oB" name="Foodi XL Pro Air Fry Oven, 10-in-1" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/sFc44K8P9eTgsrZ4Kc25oB.jpg" mos="" align="middle" fullscreen="" width="1500" height="1137" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Ninja-DT201-Countertop-Convection-Dehydrate/dp/B08BXX69K4" target="_blank" rel="nofollow" data-dimension112="69b102ec-a21f-11f1-9afb-01ba23bf4691" data-action="Deal Block" data-label="Foodi XL Pro Air Fry Oven, 10-in-1" data-dimension48="Foodi XL Pro Air Fry Oven, 10-in-1" data-dimension25="$229">Foodi XL Pro Air Fry Oven, 10-in-1: was $379 now $229</a></strong><br>40% off is one of the biggest Ninja discounts you'll find right now. While this XL air fryer/oven takes up a lot of space, it offers plenty of cooking functions and perfect cooking results every time. <a class="view-deal button" href="https://www.amazon.com/Ninja-DT201-Countertop-Convection-Dehydrate/dp/B08BXX69K4" target="_blank" rel="nofollow" data-dimension112="69b102ec-a21f-11f1-9afb-01ba23bf4691" data-action="Deal Block" data-label="Foodi XL Pro Air Fry Oven, 10-in-1" data-dimension48="Foodi XL Pro Air Fry Oven, 10-in-1" data-dimension25="$229">View Deal</a></p></div><div class="product"><a data-dimension112="69b10364-a21f-11f1-85ce-a5e1ab8f06dc" data-action="Deal Block" data-label="Woodfire ProConnect Premium XL Outdoor 7-in-1 Grill & Smoker" data-dimension48="Woodfire ProConnect Premium XL Outdoor 7-in-1 Grill & Smoker" data-dimension25="$242" href="https://www.amazon.com/Ninja-Woodfire-Functionality-Authentic-OG301/dp/B0DZF2DV3T?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1429px;"><p class="vanilla-image-block" style="padding-top:104.97%;"><img id="zyLJdnsjZA39kWuyNGm55G" name="Woodire outdoor and grill" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/zyLJdnsjZA39kWuyNGm55G.jpg" mos="" align="middle" fullscreen="" width="1429" height="1500" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Ninja-Woodfire-Functionality-Authentic-OG301/dp/B0DZF2DV3T?" target="_blank" rel="nofollow" data-dimension112="69b10364-a21f-11f1-85ce-a5e1ab8f06dc" data-action="Deal Block" data-label="Woodfire ProConnect Premium XL Outdoor 7-in-1 Grill & Smoker" data-dimension48="Woodfire ProConnect Premium XL Outdoor 7-in-1 Grill & Smoker" data-dimension25="$242">Woodfire ProConnect Premium XL Outdoor 7-in-1 Grill & Smoker: was $349 now $242</a></strong><br>You can score almost $100 off this Ninja outdoor grill and smoker right now. This smart grill lets you monitor cooking progress from your phone, which is great if you're juggling multiple dishes at once during a cookout! Be sure to apply the on-page coupon.<a class="view-deal button" href="https://www.amazon.com/Ninja-Woodfire-Functionality-Authentic-OG301/dp/B0DZF2DV3T?" target="_blank" rel="nofollow" data-dimension112="69b10364-a21f-11f1-85ce-a5e1ab8f06dc" data-action="Deal Block" data-label="Woodfire ProConnect Premium XL Outdoor 7-in-1 Grill & Smoker" data-dimension48="Woodfire ProConnect Premium XL Outdoor 7-in-1 Grill & Smoker" data-dimension25="$242">View Deal</a></p></div><div class="product"><a data-dimension112="69b103d2-a21f-11f1-9608-5fa98b37418f" data-action="Deal Block" data-label="Woodfire Oven & Smoker" data-dimension48="Woodfire Oven & Smoker" data-dimension25="$279" href="https://www.amazon.com/Ninja-Woodfire-Technology-terracotta-OO101/dp/B0C6BQVDX3/" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1500px;"><p class="vanilla-image-block" style="padding-top:90.20%;"><img id="C5KWDYUzjspNSP6tT8AAQP" name="81IeXOFExqL._AC_SL1500_.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/C5KWDYUzjspNSP6tT8AAQP.jpg" mos="" align="middle" fullscreen="" width="1500" height="1353" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>The Ninja Woodfire Oven & Smoker is a favorite with the Tom's Guide team. It makes amazing pizzas, smoked wings and many things in between. It's perfect to keep the summer vibes going all year long with delicious dishes.<a class="view-deal button" href="https://www.amazon.com/Ninja-Woodfire-Technology-terracotta-OO101/dp/B0C6BQVDX3/" target="_blank" rel="nofollow" data-dimension112="69b103d2-a21f-11f1-9608-5fa98b37418f" data-action="Deal Block" data-label="Woodfire Oven & Smoker" data-dimension48="Woodfire Oven & Smoker" data-dimension25="$279">View Deal</a></p></div><div class="product"><a data-dimension112="69b1044a-a21f-11f1-8f9c-c9e6b35d6a60" data-action="Deal Block" data-label="Fireside360 Outdoor Heater and Firepit" data-dimension48="Fireside360 Outdoor Heater and Firepit" data-dimension25="$404" href="https://www.amazon.com/Ninja-Fireside360-Fire-Heater-Modes/dp/B0GWFP3T3N?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:889px;"><p class="vanilla-image-block" style="padding-top:168.73%;"><img id="hCnMFizeFWLfCRyTyyFyuc" name="Ninja fireside" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/hCnMFizeFWLfCRyTyyFyuc.jpg" mos="" align="middle" fullscreen="" width="889" height="1500" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Ninja-Fireside360-Fire-Heater-Modes/dp/B0GWFP3T3N?" target="_blank" rel="nofollow" data-dimension112="69b1044a-a21f-11f1-8f9c-c9e6b35d6a60" data-action="Deal Block" data-label="Fireside360 Outdoor Heater and Firepit" data-dimension48="Fireside360 Outdoor Heater and Firepit" data-dimension25="$404">Fireside360 Outdoor Heater and Firepit: was $499 now $404</a></strong><br>The newly-launched Fireside360 is a smokeless firepit and heater in one neat unit. There are three heat modes, you can feel the warmth up to 13ft. away, and since its powered by propane, there's nothing to clean away. Be sure to apply the on-page coupon to get this price.<a class="view-deal button" href="https://www.amazon.com/Ninja-Fireside360-Fire-Heater-Modes/dp/B0GWFP3T3N?" target="_blank" rel="nofollow" data-dimension112="69b1044a-a21f-11f1-8f9c-c9e6b35d6a60" data-action="Deal Block" data-label="Fireside360 Outdoor Heater and Firepit" data-dimension48="Fireside360 Outdoor Heater and Firepit" data-dimension25="$404">View Deal</a></p></div><div class="product"><a data-dimension112="69b104c2-a21f-11f1-a622-75b3da269b63" data-action="Deal Block" data-label="Luxe Café Premier" data-dimension48="Luxe Café Premier" data-dimension25="$599" href="https://www.amazon.com/dp/B0FGDTHY1Y" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:541px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="HcnQ36qmUJg5VJidxsJ76X" name="Ninja Luxe Cafe.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/HcnQ36qmUJg5VJidxsJ76X.jpg" mos="" align="middle" fullscreen="" width="541" height="541" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>It's not on sale, but the Ninja Luxe Café Premier is just that good. This 3-in-1 coffee machine brews quality espresso, drip coffee, and fast cold brew using its Barista Assist technology, an integrated grinder, and weight-based dosing. Plus, it makes creating pro-level microfoam easy, thanks to its Dual Froth system. Our reviewer called it "the best beginner-friendly espresso machine I’ve ever tested" in our <a href="https://www.tomsguide.com/home/ninja-luxe-cafe-premier-series-espresso-machine-review" data-dimension112="69b104c2-a21f-11f1-a622-75b3da269b63" data-action="Deal Block" data-label="Luxe Café Premier" data-dimension48="Luxe Café Premier" data-dimension25="$599">Ninja Luxe Café coffee maker review</a>.<a class="view-deal button" href="https://www.amazon.com/dp/B0FGDTHY1Y" target="_blank" rel="nofollow" data-dimension112="69b104c2-a21f-11f1-a622-75b3da269b63" data-action="Deal Block" data-label="Luxe Café Premier" data-dimension48="Luxe Café Premier" data-dimension25="$599">View Deal</a></p></div><div class="product"><a data-dimension112="69b10530-a21f-11f1-8a88-1d69015b22f5" data-action="Deal Block" data-label="FlexFlame Propane Grill" data-dimension48="FlexFlame Propane Grill" data-dimension25="$999" href="https://www.amazon.com/Ninja-FlexFlame-Electric-Stainless-PG301/dp/B0GJ76517J" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1490px;"><p class="vanilla-image-block" style="padding-top:100.67%;"><img id="anfQB46xz27Fy6KWn9ysqX" name="Ninja Flexflame" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/anfQB46xz27Fy6KWn9ysqX.jpg" mos="" align="middle" fullscreen="" width="1490" height="1500" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Ninja-FlexFlame-Electric-Stainless-PG301/dp/B0GJ76517J" target="_blank" rel="nofollow" data-dimension112="69b10530-a21f-11f1-8a88-1d69015b22f5" data-action="Deal Block" data-label="FlexFlame Propane Grill" data-dimension48="FlexFlame Propane Grill" data-dimension25="$999">FlexFlame Propane Grill: was $1119 now $999</a></strong><br>The Ninja FlexFlame is Ninja's first attempt at a propane grill, and it offers all the ingeniuity you'd expect from a Ninja product. It's got a pellet chamber to infuse your food with an authentic smoked flavor, but can also sear and even be converted to a griddle with the use of add-ons.<a class="view-deal button" href="https://www.amazon.com/Ninja-FlexFlame-Electric-Stainless-PG301/dp/B0GJ76517J" target="_blank" rel="nofollow" data-dimension112="69b10530-a21f-11f1-8a88-1d69015b22f5" data-action="Deal Block" data-label="FlexFlame Propane Grill" data-dimension48="FlexFlame Propane Grill" data-dimension25="$999">View Deal</a></p></div><h3 class="article-body__section" id="section-more-deals"><span>More Deals</span></h3><div class="vizualizer-embed"><div class="tg-df-widget-host" data-widget-config="?search=Home+Appliances&brands=Ninja%2CShark&min_discount_ratio=0.95&offer_type=all&view_mode=carousel&widget_title=Top+Deals+Handpicked+by+Our+Editors&widget_subtitle=Discover+the+best+discounts+currently+available%2C+curated+daily+by+the+Tom%27s+Guide+Savings+Squad.&bg_color=light_blue" data-vizualizer-embed="true"></div>    <script>    /**     * Tom's Guide Deals Finder - Vanilla JS Encapsulated Engine     */    (function() {      // --- Freyr Analytics Adapter ---      function initAnalytics() {        window.dataLayer = window.dataLayer || [];        window.googletag = window.googletag || {};        window.googletag.cmd = window.googletag.cmd || [];        window.hawk = window.hawk || { analytics: { freyr: [] } };        window.hawk.analytics = window.hawk.analytics || { freyr: [] };        window.hawk.analytics.freyr = window.hawk.analytics.freyr || [];        window.freyr = window.freyr || { cmd: [] };        const scriptSrc = 'https://freyr.futurecdn.net/freyr.js';        const hostname = typeof window !== 'undefined' ? window.location.hostname : '';        const isTestEnv = typeof window.navigator !== 'undefined' && (window.navigator.webdriver || window.navigator.userAgent.includes('Headless'));        const shouldSendRealAnalytics = !isTestEnv && hostname && hostname !== 'localhost' && hostname !== '127.0.0.1' && !hostname.includes('run.app');        if (shouldSendRealAnalytics && !document.querySelector(`script[src="${scriptSrc}"]`)) {          const script = document.createElement('script');          script.src = scriptSrc;          script.async = true;          document.head.appendChild(script);        }      }      function storeEventForDebug(name, data) {        if (!window.hawk || !window.hawk.analytics || !window.hawk.analytics.freyr) return;        window.hawk.analytics.freyr.push({ name, data });        try {          if (typeof window !== 'undefined' && window.localStorage) {            window.localStorage.setItem("hawk", JSON.stringify(window.hawk));          }        } catch (e) {          // Ignore storage issues        }        try {          window.dispatchEvent(new CustomEvent("hawk-analytics-update"));        } catch (e) {}      }      function sendToFreyr(eventName, data) {        if (typeof window === 'undefined') return;        window.freyr = window.freyr || { cmd: [] };        window.freyr.cmd.push(() => {          if (window.freyr && window.freyr.pushAndUpdate) {            window.freyr.pushAndUpdate(eventName, data);          }        });      }      function sendEvent(event, skip = false) {        try {          storeEventForDebug(event.name, event.data);          if (!skip) {            sendToFreyr(event.name, event.data);          }        } catch (e) {          // Ensure tracking errors don't surface to the user        }      }      function getCookie(name) {        try {          const match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));          return match ? match[2] : null;        } catch (e) {          return null;        }      }      function normalizeCurrency(symbol) {        const map = {          '£': 'GBP',          '$': 'USD',          'A$': 'AUD',          'CA$': 'CAD',          '€': 'EUR'        };        return map[symbol] || symbol;      }      function trackElementInteraction(props) {        sendEvent({          name: 'elementInteraction',          data: {            element: {              action: props.action || "click",              id: props.id || undefined,              class: props.class || undefined,              name: props.name || undefined,              text: props.text || undefined,              label: props.label || undefined,              container: props.container || undefined,              url: props.url || undefined,              articleId: props.articleId || undefined            }          }        });      }      function generateRevenueId(url, productName, merchantName, modelId) {        const str = `${window.location.href}|${productName}|${merchantName}|${modelId || ''}|${new Date().toDateString()}|tomsguide`;        let hash = 0;        for (let i = 0; i < str.length; i++) {          const char = str.charCodeAt(i);          hash = ((hash << 5) - hash) + char;          hash = hash & hash;        }        let numericStr = Math.abs(hash).toString();        while (numericStr.length < 19) {          numericStr += Math.floor(Math.random() * 10).toString();        }        return numericStr.substring(0, 19);      }      function rewriteAffiliateLink(url, territory, revenueId) {        if (!url) return url;        const t = (territory || 'gb').toLowerCase();        return url.replace(/hawk-custom-tracking/g, `tomsguide-${t}-${revenueId}`);      }      function trackHawkEvent(params) {        const { clickType, widgetId, productCategoryName, product, productsArray, zeroBasedProductIndexOrNull, totalDealsOrProducts, areaClicked, merchant, revenueId, isoCurrencyCode, queryName, widgetTypeName } = params;        const data = {          event: "hawkEvent",          category: "Affiliates",          affiliate: {            action: {              type: clickType,              id: widgetId,              event: clickType === "appeared" ? "viewed" : "Click from",              timestamp: Date.now()            },            component: {              flag: "Editor",              product: productCategoryName || "deals",              category: `Signal Deal Finder ${widgetTypeName || "Carousel"} widget`,              type: clickType === "appeared" ? "review" : "signal product",              label: queryName || (product ? (product.name || "") : ""),              index: zeroBasedProductIndexOrNull === null || zeroBasedProductIndexOrNull === undefined ? -1 : zeroBasedProductIndexOrNull,              linkCount: totalDealsOrProducts || 0,              blockLayout: "",              areaClicked: areaClicked || ""            }          },          products: productsArray || (product && merchant ? [            {              product: {                primary: {                  id: product.id || product.matchId || null,                  name: product.name,                  type: "deal",                  price: product.price,                  previousPrice: product.previousPrice || null,                  currency: isoCurrencyCode || "USD",                  preorder: false,                  labels: [],                  link: product.link,                  originalLink: product.originalLink || null,                  revenueId: revenueId || null,                  startTime: null,                  endTime: null,                  voucherCode: null,                  voucherAudience: null,                  voucherPercentageSaving: null,                  voucherMoneySaving: null,                  voucherType: null,                  offerExclusive: false,                  offerScope: null,                  globalId: product.globalId || null,                  inStock: product.inStock !== false,                  contractProvider: null,                  contractMinutes: null,                  contractTexts: null,                  contractData: null,                  contractLength: null,                  contractMonthlyPrice: null,                  contractCurrency: isoCurrencyCode || "USD"                }              },              merchant: {                id: merchant.id || null,                name: merchant.name,                url: merchant.url || null,                network: merchant.network || null              },              model: {                id: product.modelId || null,                brand: product.brand || null,                name: product.name,                parent: product.parent || null              }            }          ] : []),          reviews: [],          _clear: true,          "gtm.uniqueEventId": Date.now() % 10000        };        sendEvent({ name: 'hawkEvent', data });      }      function trackDealClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Product Card" });      }      function trackViewSimilarClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Product Card View Similar" });      }      function trackPriceComparisonClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Price Comparison" });      }      function trackReviewClick(params) {        trackHawkEvent({ ...params, clickType: "review", areaClicked: "Signal Product Card Review Link" });      }      function trackShare(params) {        trackHawkEvent({ ...params, clickType: "share", areaClicked: "Signal Product Card Share" });      }      function trackDealsAppeared(widgetId, deals, revenueId, currency, queryName, widgetTypeName) {         if (!deals || deals.length === 0) return;                  const productsArray = deals.slice(0, 50).map((deal) => {            let voucherPct = null;            let rawPrice = parseFloat(deal.rawPrice) || parseFloat(deal.price) || null;            let rawMsrp = parseFloat(deal.rawMsrp) || parseFloat(deal.msrp) || null;            if (rawMsrp > rawPrice && rawPrice > 0) {              voucherPct = Math.round((1 - (rawPrice / rawMsrp)) * 100);            }            let numId = null;            if (deal.externalProductId && !isNaN(parseInt(deal.externalProductId))) {              numId = parseInt(deal.externalProductId);            } else if (deal.id && !isNaN(parseInt(deal.id))) {              numId = parseInt(deal.id);            } else {              numId = deal.matchId || null;            }            return {              product: {                primary: {                  id: numId,                  name: deal.productName || deal.title || "",                  type: "deal",                  price: rawPrice,                  previousPrice: rawMsrp,                  currency: currency || 'USD',                  preorder: false,                  labels: deal.modelBrand || deal.brand ? [                     { type: "brand", value: deal.modelBrand || deal.brand }                  ] : [],                  link: deal.url,                  originalLink: deal.url,                  revenueId: revenueId || null,                  startTime: null,                  endTime: null,                  voucherCode: null,                  voucherAudience: null,                  voucherPercentageSaving: voucherPct,                  voucherMoneySaving: null,                  voucherType: null,                  offerExclusive: false,                  offerScope: null,                  globalId: deal.productKey || null,                  inStock: deal.inStock !== false,                  contractProvider: null,                  contractMinutes: null,                  contractTexts: null,                  contractData: null,                  contractLength: null,                  contractMonthlyPrice: null,                  contractCurrency: currency || 'USD'                }              },              merchant: {                id: deal.merchantId ? parseInt(deal.merchantId) : null,                name: deal.merchant || "Retailer",                url: deal.merchantUrl || null,                network: deal.merchantNetwork || null              },              model: {                id: deal.modelId ? parseInt(deal.modelId) : null,                brand: deal.modelBrand || deal.brand || null,                name: deal.productName || deal.title || "",                parent: deal.modelParent || null              }            };         });                  trackHawkEvent({             clickType: "appeared",             widgetId: widgetId,             productCategoryName: "deals",             zeroBasedProductIndexOrNull: null,             totalDealsOrProducts: deals.length,             productsArray: productsArray,             queryName: queryName,             widgetTypeName: widgetTypeName         });      }      // 1. Setup Shadow DOM Sandbox      const currentScript = document.currentScript;      let hostContainer = null;      let template = null;            if (currentScript) {        let prev = currentScript.previousElementSibling;        while (prev) {          if (prev.tagName === 'TEMPLATE' && prev.classList.contains('tg-df-widget-template')) {            template = prev;          } else if (prev.tagName === 'DIV' && prev.classList.contains('tg-df-widget-host') && !prev.hasAttribute('data-initialized')) {            hostContainer = prev;            break;          }          prev = prev.previousElementSibling;        }      }            // Fallbacks in case script is deferred      if (!hostContainer) {        const hosts = document.querySelectorAll('.tg-df-widget-host:not([data-initialized])');        if (hosts.length > 0) hostContainer = hosts[0];      }            // Safely embedded template for CMS environments      const rawTemplate = `  \x3Cstyle>    /* --- Shadow DOM Base Reset --- */    *, *::before, *::after {      box-sizing: border-box;    }    img, picture, svg, video {      max-width: 100%;      height: auto;      display: block;    }    /*       1. Scoped CSS for Tom's Guide Deals Widget       All classes are prefixed with \`tg-df-\` to prevent CMS style leakage.    */    .tg-df-container {      container-type: inline-size;      container-name: tg-df;      --tg-df-blue: #1F69FF;      --tg-df-blue-hover: #004d8c;      --tg-df-text: #222222;      --tg-df-text-muted: #555555;      --tg-df-bg: #ffffff;      --tg-df-bg-secondary: #f4f4f4;      --tg-df-border: #e2e8f0;      font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;      color: var(--tg-df-text);      background-color: transparent;       width: 100%;      max-width: 1200px;      margin: 0 auto;      padding-bottom: 24px;    }    .tg-df-container *, .tg-df-container *::before, .tg-df-container *::after {      margin: 0;      padding: 0;      box-sizing: border-box;    }    .tg-df-container img {      border: none;      margin: 0;      padding: 0;    }    .tg-df-container a {      text-decoration: none;      color: inherit;    }    /*       2. Search & Filter Bar    */    .tg-df-controls {      display: flex;      flex-direction: column;      align-items: center;      gap: 20px;      margin-bottom: 32px;      width: 100%;    }    .tg-df-top-bar {      display: flex;      width: 100%;      max-width: 760px;      gap: 12px;      align-items: center;    }    .tg-df-search-wrapper {      position: relative;      flex: 1;      width: 100%;      box-shadow: 0 8px 24px rgba(0,0,0,0.06);      border-radius: 40px;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      z-index: 100;    }    .tg-df-autocomplete-dropdown {      position: absolute;      top: calc(100% + 4px);      left: 0;      right: 0;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 12px;      box-shadow: 0 8px 32px rgba(0,0,0,0.12);      max-height: 300px;      overflow-y: auto;      z-index: 200;      display: none;    }    .tg-df-autocomplete-dropdown.active {      display: block;    }    .tg-df-autocomplete-item {      padding: 12px 24px;      cursor: pointer;      font-size: 14px;      color: var(--tg-df-text);      transition: background 0.1s ease;    }    .tg-df-autocomplete-item:hover {      background: var(--tg-df-bg-secondary);    }    .tg-df-search-input {      width: 100%;      padding: 16px 64px 16px 24px;      font-size: 16px;      border: 2px solid transparent;      border-radius: 40px;      outline: none;      transition: border-color 0.2s ease, box-shadow 0.2s ease;      color: var(--tg-df-text);      background: transparent;    }    .tg-df-search-input:focus {      border-color: transparent;      box-shadow: 0 0 0 3px rgba(0, 108, 196, 0.15);    }    .tg-df-search-input::placeholder {      color: #999999;    }        .tg-df-search-btn {      position: absolute;      right: 8px;      top: 50%;      transform: translateY(-50%);      width: 40px;      height: 40px;      border-radius: 50%;      background: #222;      border: none;      display: flex;      align-items: center;      justify-content: center;      cursor: pointer;      transition: background 0.2s ease;    }        .tg-df-search-btn:hover {      background: #000;    }    .tg-df-search-icon {      width: 16px;      height: 16px;      fill: #fff;    }    .tg-df-settings-wrapper {      position: relative;    }        .tg-df-settings-btn {      width: 48px;      height: 48px;      border-radius: 50%;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      box-shadow: 0 4px 12px rgba(0,0,0,0.04);      display: flex;      align-items: center;      justify-content: center;      cursor: pointer;      transition: all 0.2s ease;      color: var(--tg-df-text-muted);      flex-shrink: 0;    }    .tg-df-settings-btn:hover {      background: var(--tg-df-bg-secondary);      border-color: #0000ff;      color: var(--tg-df-text);    }    .tg-df-settings-btn svg {      width: 24px;      height: 24px;      fill: currentColor;    }    .tg-df-settings-dropdown {      position: absolute;      top: calc(100% + 8px);      right: 0;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 12px;      box-shadow: 0 8px 32px rgba(0,0,0,0.12);      width: 280px;      padding: 20px;      display: none;      z-index: 100;      flex-direction: column;      gap: 20px;    }    .tg-df-settings-dropdown.active {      display: flex;    }        .tg-df-settings-dropdown-backdrop {      display: none;      position: fixed;      inset: 0;      z-index: 99;    }        .tg-df-settings-dropdown-backdrop.active {      display: block;    }    .tg-df-setting-item {      display: flex;      flex-direction: column;      gap: 10px;    }    .tg-df-setting-label {      font-size: 11px;      font-weight: 700;      color: var(--tg-df-text-muted);      text-transform: uppercase;      letter-spacing: 0.5px;    }        .tg-df-region-select {        padding: 10px 12px;        border-radius: 8px;        border: 1px solid var(--tg-df-border);        font-size: 15px;        outline: none;        background: var(--tg-df-bg-secondary);        color: var(--tg-df-text);        cursor: pointer;        width: 100%;    }    .tg-df-toggle {        position: relative;        display: inline-block;        width: 44px;        height: 24px;        flex-shrink: 0;    }    .tg-df-toggle input {        opacity: 0;        width: 0;        height: 0;    }    .tg-df-slider {        position: absolute;        cursor: pointer;        top: 0; left: 0; right: 0; bottom: 0;        background-color: #ccc;        transition: .2s;        border-radius: 24px;    }    .tg-df-slider:before {        position: absolute;        content: "";        height: 18px;        width: 18px;        left: 3px;        bottom: 3px;        background-color: white;        transition: .2s;        border-radius: 50%;    }    .tg-df-toggle input:checked + .tg-df-slider {        background-color: #1F69FF;    }    .tg-df-toggle input:checked + .tg-df-slider:before {        transform: translateX(20px);    }    .tg-df-dl-row {        flex-direction: row;        align-items: center;        justify-content: space-between;    }    .tg-df-dl-row-text {        font-size: 14px;        font-weight: 600;        color: var(--tg-df-text);    }    .tg-df-dl-row-subtext {        font-size: 12px;        font-weight: 400;        line-height: 1.3;        color: var(--tg-df-text-muted);        margin-top: 4px;        display: block;    }    .tg-df-filters {      display: flex;      gap: 12px;      justify-content: center;      flex-wrap: wrap;    }    .tg-df-sort-wrapper {      position: relative;      display: flex;      align-items: center;    }        .tg-df-sort-icon {      position: absolute;      left: 14px;      width: 14px;      height: 14px;      fill: var(--tg-df-text-muted);      pointer-events: none;    }    .tg-df-sort-select, .tg-df-filter-select {      padding: 10px 36px 10px 38px;      font-size: 14px;      border: 1px solid var(--tg-df-border);      border-radius: 100px;      outline: none;      appearance: none;      background-color: var(--tg-df-bg-secondary);      background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 12 12'%3E%3Cpath fill='%23555555' d='M6 8L1 3h10z'/%3E%3C/svg%3E");      background-repeat: no-repeat;      background-position: right 14px center;      color: var(--tg-df-text);      cursor: pointer;      font-weight: 500;      transition: all 0.2s ease;    }        .tg-df-price-input::-webkit-outer-spin-button,    .tg-df-price-input::-webkit-inner-spin-button {      -webkit-appearance: none;      margin: 0;    }    .tg-df-price-input {      -moz-appearance: textfield;    }    .tg-df-sort-select:hover, .tg-df-filter-select:hover {      background-color: #e2e8f0;    }    .tg-df-multiselect-container {      position: relative;    }        .tg-df-multiselect-trigger {      display: block;      background: #fff;      user-select: none;      width: 100%;      overflow: hidden;      white-space: nowrap;      text-overflow: ellipsis;    }        .tg-df-multiselect-dropdown {      display: none;      position: absolute;      top: calc(100% + 4px);      left: 0;      width: 100%;      min-width: 220px;      max-height: 300px;      overflow-y: auto;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 8px;      box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);      z-index: 100;      padding: 8px 0;    }    .tg-df-multiselect-dropdown.active {      display: block;    }    .tg-df-ms-option {      padding: 8px 16px;      display: flex;      align-items: center;      gap: 8px;      cursor: pointer;      font-size: 14px;    }    .tg-df-ms-option:hover {      background-color: var(--tg-df-bg-secondary);    }        .tg-df-ms-option input {      cursor: pointer;      accent-color: #1f69ff;    }    .tg-df-sort-select:focus, .tg-df-filter-select:focus {      border-color: #0000ff;      box-shadow: 0 0 0 3px rgba(0, 0, 255, 0.2);      background-color: var(--tg-df-bg);    }    /*       3. Deal Grid Layout    */    .tg-df-grid.tg-df-grid-auto {      padding-top: 24px;    }    .tg-df-grid, .tg-df-grid.layout-grid {      display: grid;      grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));      gap: 10px;    }    .tg-df-grid.layout-row {      grid-template-columns: 1fr;      gap: 16px;    }        .tg-df-grid.layout-row .tg-df-card {      flex-direction: row;      align-items: stretch;      height: auto;      box-shadow: none;      border-bottom: 1px solid var(--tg-df-border);    }    .tg-df-grid.layout-row .tg-df-card:hover {      box-shadow: none;    }    .tg-df-grid.layout-row .tg-df-card-image-box {      width: 140px;      min-width: 140px;      aspect-ratio: 3/4;      border-right: none;      padding: 16px 16px 16px 32px;    }    .tg-df-grid.layout-row .tg-df-card-body {      padding: 16px;      justify-content: space-between;    }    .tg-df-grid.layout-row .tg-df-card-title {      font-size: 15px;      margin-bottom: 16px;    }    .tg-df-grid.layout-row .tg-df-card-stars { margin-bottom: 8px; }    .tg-df-grid.layout-row .tg-df-card-footer {      flex-direction: column;      align-items: flex-start;      gap: 0;    }    .tg-df-grid.layout-row .tg-df-card-merchant-pill {      margin-bottom: 4px;    }    .tg-df-grid.layout-row .tg-df-card-price-group {      margin-bottom: 8px;    }    .tg-df-grid.layout-row .tg-df-price-group {      width: auto;    }    .tg-df-grid.layout-row .tg-df-card-cta {      width: 100%;      max-width: 200px;      padding: 10px 24px;      font-size: 13px;      flex-shrink: 0;      text-align: center;      justify-content: center;    }    /*       4. Deal Card Design    */    .tg-df-card {      position: relative;      display: flex;      flex-direction: column;      background-color: #ffffff;      border-radius: 0;      overflow: hidden;      transition: transform 0.2s ease, box-shadow 0.2s ease;      text-decoration: none;      color: inherit;      height: 100%;      box-shadow: 0 0 16px rgba(0, 0, 0, 0.08);      border: 1px solid var(--tg-df-border);    }    .tg-df-card:hover {      box-shadow: 0 0 24px rgba(0, 0, 0, 0.12);    }    .tg-df-card-image-box {      width: 100%;      aspect-ratio: 3/4;      background-color: #f8f8f8;      display: flex;      align-items: center;      justify-content: center;      position: relative;      overflow: hidden;      padding: 32px;      flex: 0 0 auto;    }    .tg-df-card-image {      max-width: 100%;      max-height: 100%;      width: auto;      height: auto;      object-fit: contain;      mix-blend-mode: multiply; /* Helps white background images blend into secondary bg */      transition: transform 0.3s ease;    }    .tg-df-card:hover .tg-df-card-image {      transform: scale(1.05); /* Zoom in on hover */    }    .tg-df-card-discount-badge {      position: absolute;      top: 12px;      left: 12px;      background: #dc2626; /* Red */      color: #ffffff;      padding: 6px 8px;      font-size: 11px;      font-weight: 500;      text-transform: uppercase;      letter-spacing: 0.5px;      border-radius: 0;      z-index: 10;    }        .tg-df-card-merchant-pill {      display: block;      padding: 0;      font-size: 11px;      font-weight: 600;      text-transform: uppercase;      letter-spacing: 0.5px;      border-radius: 0;      color: var(--tg-df-text-muted);      margin-bottom: 8px;      white-space: nowrap;      overflow: hidden;      text-overflow: ellipsis;    }    .tg-df-card-body {      padding: 16px;      display: flex;      flex-direction: column;      flex-grow: 1;      min-width: 0;    }    .tg-df-card-badges {      display: flex;      flex-wrap: wrap;      gap: 6px;      margin-bottom: 8px;    }    .tg-df-tag {      display: inline-flex;      align-items: center;      padding: 4px 6px;      font-size: 11px;      font-weight: 700;      text-transform: uppercase;      border-radius: 4px;      gap: 4px;    }    .tg-df-tag-prime {      background-color: #00A8E1;      color: #fff;    }    .tg-df-tag-coupons {      background-color: #f1f5f9;      color: #334155;      border: 1px solid #cbd5e1;      cursor: pointer;      transition: background-color 0.2s;    }    .tg-df-tag-coupons:hover {      background-color: #e2e8f0;    }        .tg-df-tag-outline {      background-color: #f1f5f9;      color: #334155;      border: 1px solid #cbd5e1;      cursor: pointer;      transition: background-color 0.2s;    }    .tg-df-tag-outline:hover {      background-color: #e2e8f0;    }        @keyframes tg-df-spin {      0% { transform: rotate(0deg); }      100% { transform: rotate(360deg); }    }    .tg-df-coupon-spinner {      border: 2px solid #e2e8f0;      border-top: 2px solid #3b82f6;      border-radius: 50%;      width: 14px;      height: 14px;      animation: tg-df-spin 1s linear infinite;      margin: 4px 8px;      display: inline-block;    }        /* Vouchers Modal */    .tg-df-modal-backdrop {      position: fixed;      top: 0; left: 0; right: 0; bottom: 0;      background: rgba(0,0,0,0.5);      z-index: 10000;      display: flex;      align-items: center;      justify-content: center;      opacity: 0;      pointer-events: none;      transition: opacity 0.3s;    }    .tg-df-modal-backdrop.active {      opacity: 1;      pointer-events: auto;    }    .tg-df-modal {      background: #fff;      border-radius: 12px;      width: 90%;      max-width: 400px;      max-height: 80vh;      display: flex;      flex-direction: column;      box-shadow: 0 10px 40px rgba(0,0,0,0.2);      transform: translateY(20px);      transition: transform 0.3s;    }    .tg-df-modal-backdrop.active .tg-df-modal {      transform: translateY(0);    }    .tg-df-modal-header {      padding: 16px;      border-bottom: 1px solid #e2e8f0;      display: flex;      align-items: center;      justify-content: space-between;    }    .tg-df-modal-title {      font-size: 16px;      font-weight: 600;      margin: 0;    }    .tg-df-modal-close {      background: none;      border: none;      cursor: pointer;      padding: 4px;      color: #64748b;    }    .tg-df-modal-body {      padding: 16px;      overflow-y: auto;    }    .tg-df-voucher-item {      padding: 12px;      border: 1px dashed #cbd5e1;      border-radius: 8px;      margin-bottom: 10px;      background: #f8fafc;      display: flex;      align-items: center;      gap: 12px;      text-decoration: none;      color: inherit;      transition: background-color 0.2s, border-color 0.2s;    }    .tg-df-voucher-item:hover {      background: #f1f5f9;      border-color: #94a3b8;    }    .tg-df-voucher-item:last-child {      margin-bottom: 0;    }    .tg-df-voucher-logo {      width: 48px;      height: 48px;      object-fit: contain;      border-radius: 4px;      background: #fff;      border: 1px solid #e2e8f0;      flex-shrink: 0;    }    .tg-df-voucher-content {      flex: 1;      min-width: 0;    }    .tg-df-voucher-title {      font-size: 14px;      font-weight: 600;      margin: 0 0 4px 0;      line-height: 1.3;      color: #0f172a;    }    .tg-df-voucher-expiry {      font-size: 12px;      color: #64748b;      display: flex;      align-items: center;      gap: 4px;      margin-top: 6px;    }    .tg-df-voucher-code {      display: inline-flex;      align-items: center;      background: #f1f5f9;      border: 1px dashed #cbd5e1;      padding: 6px 10px;      font-family: monospace;      font-weight: 700;      font-size: 14px;      color: #0f172a;      border-radius: 4px;      margin-top: 8px;      cursor: pointer;      transition: all 0.2s ease;    }    .tg-df-voucher-code:hover {      background: #e2e8f0;      border-color: #94a3b8;    }    .tg-df-voucher-code.copied {      background: #ecfdf5;      border-color: #10b981;      color: #10b981;    }    .tg-df-voucher-cta {      display: inline-block;      margin-top: 8px;      font-size: 13px;      font-weight: 600;      color: #2563eb;      text-decoration: none;    }    .tg-df-card-title {      font-size: 15px;      font-weight: 400;      line-height: 1.4;      margin: 0 0 12px 0;      color: var(--tg-df-text);      display: -webkit-box;      -webkit-line-clamp: 2;      -webkit-box-orient: vertical;      overflow: hidden;    }    .tg-df-card-footer {      margin-top: auto;      display: flex;      flex-direction: column;      width: 100%;    }    .tg-df-card-price-group {      display: flex;      flex-direction: row;      align-items: center;      gap: 8px;      margin-bottom: 12px;    }    .tg-df-card-price {      font-size: 16px;      font-weight: 700;      color: #dc2626; /* Red price */      line-height: 1;    }        .tg-df-card-msrp {      font-size: 13px;      color: var(--tg-df-text-muted);      text-decoration: line-through;    }    .tg-df-container .tg-df-card-cta {      display: flex;      align-items: center;      justify-content: center;      width: 100%;      box-sizing: border-box;      background-color: #1f69ff;      color: #ffffff;      font-size: 12px;      font-weight: 700;      text-transform: uppercase;      letter-spacing: 0.5px;      padding: 12px 16px;      border-radius: 0;      border: none;      cursor: pointer;      transition: background-color 0.2s ease;    }    .tg-df-card:hover .tg-df-card-cta,    .tg-df-card-cta:hover {      background-color: #1555cc;    }    .tg-df-container .tg-df-card-cta.tg-df-cta-savings-squad {      background-color: #3c8d0d;    }    .tg-df-card:hover .tg-df-card-cta.tg-df-cta-savings-squad,    .tg-df-card-cta.tg-df-cta-savings-squad:hover {      background-color: #2b6509;    }    /*       5. State & Skeleton Styles    */    .tg-df-message {      grid-column: 1 / -1;      text-align: center;      padding: 48px 24px;      color: var(--tg-df-text-muted);      font-size: 16px;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 8px;    }    @keyframes tg-df-shimmer {      0% { background-position: -200% 0; }      100% { background-position: 200% 0; }    }    .tg-df-skeleton {      background: linear-gradient(90deg, var(--tg-df-bg-secondary) 25%, #e2e8f0 50%, var(--tg-df-bg-secondary) 75%);      background-size: 200% 100%;      animation: tg-df-shimmer 1.5s infinite;      border-radius: 4px;    }    .tg-df-skeleton-img {      width: 100%;      height: 100%;      position: absolute;      top: 0; left: 0;    }        .tg-df-skeleton-text {      height: 16px;      margin-bottom: 8px;      width: 100%;    }    .tg-df-skeleton-text.short { width: 40%; }    .tg-df-skeleton-text.title { height: 20px; margin-bottom: 16px; }    /* Editor Floating Bar & Elements */    .tg-df-editor-bar {      position: sticky;      top: 0;      z-index: 1000;      background: #111827;      color: #fff;      padding: 12px 16px;      border-radius: 8px;      margin-bottom: 16px;      display: flex;      align-items: center;      justify-content: space-between;      box-shadow: 0 4px 12px rgba(0,0,0,0.15);    }    .tg-df-editor-bar-text {      font-weight: 600;      font-size: 14px;    }    .tg-df-editor-copy-btn {      background: #10b981;      color: #fff;      padding: 6px 16px;      border: none;      border-radius: 4px;      font-weight: 600;      cursor: pointer;      display: flex;      align-items: center;      font-size: 13px;    }    .tg-df-editor-copy-btn:hover { background: #059669; }        .tg-df-deal-checkbox {      position: absolute;      top: 12px;      right: 12px;      z-index: 10;      width: 20px;      height: 20px;      cursor: pointer;      pointer-events: auto;    }    /*       6. Mobile List View (Stacks into a cleaner horizontal row/list)    */    @container tg-df (max-width: 599px) {      .tg-df-controls {        padding: 0 16px;      }            .tg-df-top-bar {        width: 100%;      }            .tg-df-settings-dropdown {        position: fixed;        top: auto;        bottom: 0;        left: 0;        right: 0;        width: 100%;        border-radius: 20px 20px 0 0;        padding: 24px;        box-shadow: 0 -8px 32px rgba(0,0,0,0.15);        z-index: 1000;        border: none;        border-top: 1px solid var(--tg-df-border);      }            .tg-df-settings-dropdown-backdrop.active {        background: rgba(0,0,0,0.4);      }            .tg-df-search-wrapper {        box-shadow: 0 0 16px rgba(0,0,0,0.08);      }            .tg-df-filters {        width: calc(100% + 32px);        margin: 0 -16px;        padding: 0 16px 4px 16px;        display: flex;        justify-content: flex-start;        gap: 8px;        flex-wrap: nowrap;        overflow-x: auto;        -webkit-overflow-scrolling: touch;        scrollbar-width: none;      }      .tg-df-filters::after {        content: "";        display: block;        flex: 0 0 8px;      }      .tg-df-filters::-webkit-scrollbar {        display: none;      }            .tg-df-sort-wrapper {        flex: 0 0 max(42%, 130px);        min-width: 0;      }      .tg-df-sort-wrapper.tg-df-price-range-wrapper {        flex: 0 0 auto;        min-width: max-content;      }            .tg-df-sort-select, .tg-df-filter-select {        width: 100%;        text-align: left;        padding: 10px 24px 10px 32px;        background-position: right 8px center;        text-overflow: ellipsis;        white-space: nowrap;        overflow: hidden;      }      .tg-df-sort-icon {        left: 10px;      }      .tg-df-grid:not(.layout-grid):not(.layout-row),      .tg-df-grid.layout-row {        grid-template-columns: 1fr;        gap: 16px;      }            .tg-df-grid.tg-df-grid-auto {        padding-top: 24px;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card,      .tg-df-grid.layout-row .tg-df-card {        flex-direction: row;        align-items: stretch;        height: auto;        box-shadow: none; /* simple line on mobile if preferred, or keep */        border-bottom: 1px solid var(--tg-df-border);      }      .tg-df-grid.tg-df-grid-auto .tg-df-card:hover,      .tg-df-grid.layout-row .tg-df-card:hover {        box-shadow: none;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-image-box,      .tg-df-grid.layout-row .tg-df-card-image-box {        width: 120px;        min-width: 120px;        aspect-ratio: 3/4;        border-right: none;        padding: 12px;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-body,      .tg-df-grid.layout-row .tg-df-card-body {        padding: 12px;        justify-content: space-between;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-title,      .tg-df-grid.layout-row .tg-df-card-title {        font-size: 14px;        margin-bottom: 12px;        -webkit-line-clamp: 3;      }      /* Single column mobile grid override */      .tg-df-grid.layout-grid {        grid-template-columns: 1fr;        gap: 16px;      }      .tg-df-grid.layout-grid .tg-df-card-image-box {        padding: 12px;      }      .tg-df-grid.layout-grid .tg-df-card-body {        padding: 10px;      }      .tg-df-grid.layout-grid .tg-df-card-title {        font-size: 13px;        -webkit-line-clamp: 3;        margin-bottom: 8px;      }      .tg-df-grid.layout-grid .tg-df-card-price {        font-size: 14px;      }            .tg-df-card-footer {        flex-direction: column;        align-items: stretch;        gap: 0;        width: 100%;        min-width: 0;      }      .tg-df-card-merchant-pill {        margin-bottom: 4px;      }      .tg-df-card-price-group {        flex: 1 1 auto;        margin-bottom: 8px;      }      .tg-df-card-price {        font-size: 16px;      }      .tg-df-card-msrp {        display: block;       }      .tg-df-grid.layout-row .tg-df-card-cta,      .tg-df-container .tg-df-card-cta {        width: 100%;        max-width: none;        min-width: 0;        box-sizing: border-box;        padding: 8px 16px;        font-size: 12px;        flex: 0 0 auto;        text-align: center;        white-space: normal;        line-height: 1.2;      }    }    .tg-df-container.is-carousel {      min-height: 760px;      background-color: #E7F0FF;      padding: 0 0 24px 0;      border-radius: 24px;    }    .tg-df-container.is-carousel.hide-header-details {      min-height: 480px;    }    /*       7. Carousel View Mode    */    .tg-df-container .tg-df-carousel-host {      /* Layout is now handled by container wrapper */    }    .tg-df-container .tg-df-carousel-eyebrow {      color: #1F69FF;      font-weight: 700;      font-size: 14px;      text-transform: uppercase;      letter-spacing: 1px;      padding: 24px 16px 0 16px;      display: none;    }    .tg-df-container .tg-df-carousel-query-title {      color: #011535;      font-size: 28px;      font-weight: 600;      padding: 0 16px 24px 16px;      line-height: 1.2;      display: none;    }    .tg-df-container .tg-df-carousel-blue-box {      background-color: transparent;      border-radius: 0;      padding: 24px 24px 0 24px;      margin: 0;      color: #1F69FF;          position: relative;      overflow: hidden;    }    .tg-df-container .tg-df-carousel-bg-circle-1 {      display: none;    }    .tg-df-container .tg-df-carousel-bg-circle-2 {      display: none;    }    .tg-df-container .tg-df-carousel-bg-circle-3 {      display: none;    }    .tg-df-container .tg-df-carousel-box-content {      position: relative;      z-index: 10;    }    .tg-df-container .tg-df-carousel-box-eyebrow {      background-color: transparent;      color: #1F69FF;      font-weight: 700;      font-size: 14px;      text-transform: uppercase;      letter-spacing: 1px;      display: inline-block;      padding: 0;      border-radius: 0;    }    .tg-df-container .tg-df-carousel-box-title {      font-size: 28px;      font-weight: 600;      line-height: 1.2;      margin-top: 8px;      color: #1e293b;    }    .tg-df-container .tg-df-countdown-wrapper {      position: absolute;      top: 0;      right: 0;      display: flex;      flex-direction: column;      align-items: flex-end;      gap: 12px;      transform: scale(0.67);      transform-origin: top right;    }    .tg-df-container .tg-df-countdown-title {      font-size: 16px;      text-align: center;      width: 100%;      font-weight: 600;      color: #011535;      margin: 0;    }    .tg-df-container .tg-df-countdown-blocks {      display: flex;      gap: 16px;    }    .tg-df-container .tg-df-countdown-item {      display: flex;      flex-direction: column;      align-items: center;      gap: 4px;    }    .tg-df-container .tg-df-countdown-box {      width: 59px;      height: 59px;      background: #03FE9E;      border-radius: 15px;      display: flex;      align-items: center;      justify-content: center;    }    .tg-df-container .tg-df-countdown-num {      font-family: 'Inter', sans-serif;      font-weight: 700;      font-size: 20px;      line-height: normal;      color: #011535;    }    .tg-df-container .tg-df-countdown-label {      font-family: 'Inter', sans-serif;      font-weight: 500;      font-size: 16px;      line-height: normal;      color: #1e293b;      text-transform: uppercase;    }    .tg-df-container .tg-df-carousel-box-subtitle {      font-size: 16px;      margin-top: 8px;      font-weight: 300;      color: #1e293b;      line-height: 24px;    }    .tg-df-container .tg-df-carousel-roundels-wrapper {      position: relative;      margin-top: 24px;      margin-left: -24px;      margin-right: -24px;    }    .tg-df-container .tg-df-carousel-roundels {      display: flex;      gap: 16px;      overflow-x: auto;            scrollbar-width: none;      padding-top: 12px;      padding-bottom: 24px;      padding-left: 24px;      padding-right: 24px;      margin-left: 0;      margin-right: 0;    }        .tg-df-container .tg-df-carousel-scroll-left,    .tg-df-container .tg-df-carousel-scroll-right {      position: absolute;      top: 50%;      transform: translateY(-50%);      height: 36px;      width: 36px;      display: flex;      align-items: center;      justify-content: center;      border-radius: 50%;      background-color: #ffffff;      border: 1px solid #e2e8f0;      box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);      color: #1F69FF;      cursor: pointer;      transition: all 0.2s;      margin-top: -4px;      z-index: 20;    }    .tg-df-container .tg-df-carousel-scroll-left { left: 8px; }    .tg-df-container .tg-df-carousel-scroll-right { right: 8px; }    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-left { left: 0px; }    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-right { right: 0px; }    .tg-df-carousel-filters-outer { margin-left: -24px; margin-right: -24px; padding-left: 24px; padding-right: 24px; }    @container tg-df (max-width: 599px) { .tg-df-carousel-filters-outer { margin-left: -16px; margin-right: -16px; padding-left: 16px; padding-right: 16px; } }        .tg-df-container .tg-df-carousel-scroll-left:hover,    .tg-df-container .tg-df-carousel-scroll-right:hover {      background-color: #f8fafc;      border-color: #cbd5e1;    }        .tg-df-carousel-roundels-wrapper .tg-df-carousel-scroll-left,    .tg-df-carousel-roundels-wrapper .tg-df-carousel-scroll-right,    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-left,    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-right {      background-color: rgba(255, 255, 255, 0.4);      border: none;      box-shadow: none;      backdrop-filter: blur(4px);      -webkit-backdrop-filter: blur(4px);    }    .tg-df-carousel-roundels-wrapper .tg-df-carousel-scroll-left { left: 0; }    .tg-df-carousel-roundels-wrapper .tg-df-carousel-scroll-right { right: 0; }    .tg-df-grid-wrapper .tg-df-carousel-scroll-left { left: 0; }    .tg-df-grid-wrapper .tg-df-carousel-scroll-right { right: 0; }        .tg-df-carousel-roundels-wrapper .tg-df-carousel-scroll-left:hover,    .tg-df-carousel-roundels-wrapper .tg-df-carousel-scroll-right:hover {      background-color: rgba(255, 255, 255, 0.6);      border: none;    }    .tg-df-container .tg-df-carousel-roundels::-webkit-scrollbar {      display: none;    }    .tg-df-container .tg-df-carousel-roundels::after {      content: "";      flex: 0 0 32px;    }    .tg-df-container .tg-df-roundel {      display: flex;      flex-direction: column;      align-items: center;      gap: 8px;      cursor: pointer;      min-width: 120px;      flex-shrink: 0;    }    .tg-df-container .tg-df-roundel-img-box {      width: 120px;      height: 120px;      border-radius: 50%;      background: white;      display: flex;      align-items: center;      justify-content: center;      overflow: hidden;      box-shadow: 0px 3px 14px 0px rgba(30, 41, 59, 0.08);      transition: box-shadow 0.2s;    }    .tg-df-container .tg-df-roundel:hover .tg-df-roundel-img-box {      box-shadow: 0 0 0 2px #E7F0FF, 0 0 0 4px #1F69FF;    }    .tg-df-container .tg-df-roundel.active .tg-df-roundel-img-box {      box-shadow: 0 0 0 2px #E7F0FF, 0 0 0 4px #1F69FF;    }    .tg-df-container .tg-df-roundel:hover .tg-df-roundel-img-box img {      transform: scale(1.08);    }    .tg-df-container .tg-df-roundel-img-box img {      width: 100%;      height: 100%;      object-fit: contain;      padding: 10px;      box-sizing: border-box;      transition: transform 0.3s ease;    }    .tg-df-container .tg-df-roundel-label {      font-size: 13px;      font-weight: 400;      color: #1e293b;      text-align: center;      transition: font-weight 0.2s;    }    .tg-df-container .tg-df-roundel.active .tg-df-roundel-label {      font-weight: 700;    }    .tg-df-container .tg-df-carousel-filters-label {      font-size: 16px;      font-weight: 400;      color: #1e293b;      white-space: nowrap;      margin-right: 4px;    }    .tg-df-container .tg-df-carousel-filters-wrap {      display: flex;      align-items: center;      flex-wrap: nowrap;      gap: 8px;      margin-top: 8px;      overflow-x: auto;      scrollbar-width: none;      -webkit-overflow-scrolling: touch;      padding-bottom: 8px;      margin-left: -24px;      margin-right: -24px;      padding-left: 24px;      padding-right: 24px;    }    .tg-df-container .tg-df-carousel-filters-wrap::-webkit-scrollbar {      display: none;    }        .tg-df-container .tg-df-carousel-filter-btn img,    .tg-df-container .tg-df-carousel-filter-btn picture {      height: 20px;      width: 20px;      object-fit: contain;      object-position: center;      display: inline-flex;      align-items: center;      justify-content: center;      margin-right: 6px;    }    .tg-df-container .tg-df-carousel-filter-btn picture img {      margin-right: 0;      height: 100%;      width: 100%;    }    .tg-df-container .tg-df-carousel-filter-btn img.active-img,    .tg-df-container .tg-df-carousel-filter-btn picture:has(.active-img) {      display: none;    }    .tg-df-container .tg-df-carousel-filter-btn:hover img.inactive-img,    .tg-df-container .tg-df-carousel-filter-btn.active img.inactive-img,    .tg-df-container .tg-df-carousel-filter-btn:hover picture:has(.inactive-img),    .tg-df-container .tg-df-carousel-filter-btn.active picture:has(.inactive-img) {      display: none;    }    .tg-df-container .tg-df-carousel-filter-btn:hover img.active-img,    .tg-df-container .tg-df-carousel-filter-btn.active img.active-img,    .tg-df-container .tg-df-carousel-filter-btn:hover picture:has(.active-img),    .tg-df-container .tg-df-carousel-filter-btn.active picture:has(.active-img) {      display: inline-flex;    }    .tg-df-container .tg-df-carousel-filter-btn {      background: #ffffff;      border: 2px solid #1e293b;      color: #1e293b;      border-radius: 24px;      padding: 6px 16px;      font-size: 14px;      font-weight: 600;      cursor: pointer;      transition: all 0.2s;      flex-shrink: 0;      white-space: nowrap;      display: inline-flex;      align-items: center;      justify-content: center;      min-height: 36px;      box-sizing: border-box;    }    .tg-df-container .tg-df-carousel-filter-btn svg {      margin-right: 6px;    }    .tg-df-container .tg-df-carousel-filter-btn:hover {      background: #1e293b;      color: white;      border-color: #1e293b;    }    .tg-df-container .tg-df-carousel-filter-btn.active {      background: #1e293b;      color: white;      border-color: #1e293b;    }        .tg-df-grid.carousel-compact {      display: flex;      flex-wrap: nowrap;      overflow-x: auto;      gap: 16px;      padding: 16px 24px;      align-items: stretch;      scrollbar-width: none;    }    .tg-df-grid.carousel-compact::after {      content: "";      flex: 0 0 32px;    }    .tg-df-grid-wrapper {      position: relative;    }    .tg-df-grid.carousel-compact::-webkit-scrollbar {      display: none;    }    .tg-df-grid.carousel-compact .tg-df-load-more-card {      flex: 0 0 auto;      width: 100px;      border-radius: 15px;      box-shadow: 0 0 16px rgba(0,0,0,0.08);      border: 2px solid #1e293b;      background: white;      color: #1e293b;      display: flex;      flex-direction: column;      justify-content: center;      align-items: center;      font-weight: 600;      font-size: 14px;      cursor: pointer;      padding: 16px;      text-align: center;      transition: all 0.2s;    }    .tg-df-grid.carousel-compact .tg-df-load-more-card:hover {      background: #1e293b;      color: white;    }    .tg-df-grid.carousel-compact .tg-df-card {      flex: 0 0 auto;      width: 200px;      min-height: auto;      height: auto;      display: flex;      flex-direction: column;      border-radius: 15px;      border: none;      box-shadow: 0 0 16px rgba(0,0,0,0.08);      overflow: visible;    }    .tg-df-grid.carousel-compact .tg-df-card-image-box {      padding: 12px;      background-color: transparent;      border-radius: 15px 15px 0 0;      height: 130px;    }    .tg-df-grid.carousel-compact .tg-df-card-image {      mix-blend-mode: normal;    }    .tg-df-grid.carousel-compact .tg-df-card-discount-badge {      border-radius: 0;      top: 0px;      left: 0px;      padding: 4px 8px;      font-size: 11px;    }    .tg-df-grid.carousel-compact .tg-df-card-body {      padding: 8px 12px 12px 12px;    }    .tg-df-grid.carousel-compact .tg-df-card-title {      font-size: 14px;      font-weight: 400;      -webkit-line-clamp: 2;      margin-bottom: 8px;      color: #011535;    }    .tg-df-grid.carousel-compact .tg-df-card-body:not(:has(.tg-df-card-stars)):not(:has(.tg-df-tag-prime)):not(:has(.tg-df-coupon-wrapper:not([style*="none"]))) > .tg-df-card-title,    .tg-df-grid.carousel-compact .tg-df-card-body:not(:has(.tg-df-card-stars)):has(> .tg-df-card-title:first-child) > .tg-df-card-title {      -webkit-line-clamp: 3;    }    .tg-df-grid.carousel-compact .tg-df-card-cta {      border-radius: 5px;      padding: 8px 10px;      margin-top: 4px;      background-color: #1F69FF;    }    .tg-df-grid.carousel-compact .tg-df-card-price-group {      margin-bottom: 2px;    }    .tg-df-grid.carousel-compact .tg-df-card-merchant-pill {      margin-bottom: 2px;    }    @container tg-df (max-width: 599px) {      .tg-df-container .tg-df-carousel-blue-box-title {        font-size: 24px;      }      .tg-df-container .tg-df-countdown-title {        display: none;      }      .tg-df-container .tg-df-countdown-wrapper {        position: absolute;        top: 0;        right: 0;        align-items: flex-end;        transform: scale(0.45);        transform-origin: top right;      }      .tg-df-container .tg-df-roundel {        min-width: 88px;      }      .tg-df-container .tg-df-roundel-img-box {        width: 88px;        height: 88px;      }    }    /* REPLICA BLOCK STYLES */    .tg-df-grid.layout-replica-2 { grid-template-columns: repeat(2, 1fr) !important; gap: 20px; }    .tg-df-grid.layout-replica-1 { grid-template-columns: 1fr !important; gap: 20px; }        .tg-df-container .hawk-deal-widget-container { border-bottom: 1px solid #e5e7eb; display: flex; flex-direction: column; margin: 0; padding: 20px 0; box-sizing: border-box; font-family: inherit; }    .tg-df-container .hawk-deal-widget-wrap { display: flex; flex-direction: row; align-items: flex-start; width: 100%; gap: 24px; }    .tg-df-container .hawk-deal-widget-image-container { display: flex; flex-shrink: 0; justify-content: center; width: 160px; height: 160px; align-items: center; background: white; margin-bottom: 0px; }    .tg-df-container .hawk-deal-widget-title-product-title { color: #111827; font-size: 18px; font-weight: 700; line-height: 1.4; display: inline; }    .tg-df-container .hawk-deal-widget-title-price { font-size: 18px; font-weight: 700; line-height: 1.4; white-space: nowrap; color: #2563eb; }    .tg-df-container .hawk-deal-widget-title-price-now { font-weight: 700; }    .tg-df-container .hawk-deal-widget-title-retailer-price:hover { text-decoration: underline; }    .tg-df-container .hawk-deal-widget-title-retailer { font-size: 18px; font-weight: 700; line-height: 1.4; color: #2563eb; }    .tg-df-container .hawk-deal-widget-title-was-price { color: #dc2626; font-size: 16px; font-weight: 500; line-height: 1.4; text-decoration: line-through; white-space: nowrap; margin-left: 8px; margin-right: 8px; }    .tg-df-container .hawk-deal-widget-text-body-container { position: relative; width: 100%; box-sizing: border-box; }    .tg-df-container .hawk-deal-widget-text-body-main { font-size: 16px; width: 100%; margin-bottom: 12px; }    .tg-df-container .hawk-deal-widget-text-body-description { display: block; font-size: 15px; margin-top: 12px; color: #4b5563; line-height: 1.6; }    .tg-df-container .hawk-deal-widget-text-body-description p { margin: 0; line-height: 1.6; }    .tg-df-container .hawk-deal-widget-text-cta-container { display: flex; flex-direction: column; gap: 12px; width: 100%; flex: 1; min-width: 0; box-sizing: border-box; }    .tg-df-container .hawk-deal-widget-footer { display: flex; justify-content: flex-end; width: 100%; margin-top: auto; }    .tg-df-container .hawk-deal-widget-button-wrapper { display: flex; flex-direction: column; align-items: flex-end; justify-content: flex-end; width: 100%; }    .tg-df-container .hawk-deal-widget-preferred-partner-wrapper { display: flex; flex-direction: row; }        @container tg-df (min-width: 600px) {      .tg-df-mobile-only { display: none !important; }    }    @container tg-df (max-width: 599px) {      .tg-df-desktop-only { display: none !important; }      .tg-df-grid.layout-replica-2 { grid-template-columns: 1fr !important; }      .tg-df-grid.savings-squad-cards { grid-template-columns: 1fr !important; display: flex; flex-direction: column; }    }    .tg-df-grid.savings-squad-cards .tg-df-card-title {      -webkit-line-clamp: unset !important;      display: block !important;      overflow: visible !important;    }    @container tg-df (max-width: 500px) {      .tg-df-container .hawk-deal-widget-wrap { display: block; }      .tg-df-container .hawk-deal-widget-image-container { display: block; float: left; margin: 0 16px 8px 0; width: 120px; max-width: 120px; height: auto; align-items: normal; justify-content: normal; }      .tg-df-container .hawk-deal-widget-text-cta-container { display: block; text-align: left; }      .tg-df-container .hawk-deal-widget-footer { display: block; margin-top: 16px; clear: both; width: 100%; }      .tg-df-container .hawk-deal-widget-button-wrapper { display: block; width: 100%; }      .tg-df-container .hawk-deal-widget-button-wrapper .hawk-deal-widget-preferred-partner-wrapper { display: block; width: 100%; }      .tg-df-container .hawk-affiliate-link-deal-button { box-sizing: border-box !important; display: flex !important; max-width: none !important; width: 100% !important; margin: 0 !important; }    }        .tg-df-container .hawk-affiliate-link-deal-button {       align-items: center; background-color: #5aaf0b; box-sizing: border-box; color: #ffffff !important; display: flex; font-size: 14px; font-weight: 700; justify-content: center; letter-spacing: 0.5px; line-height: 1; min-width: 160px; padding: 14px 24px; text-align: center; text-decoration: none; text-transform: uppercase; width: 100%; word-break: normal; border-radius: 4px; border: 0; transition: background-color 0.2s;     }    .tg-df-container .hawk-affiliate-link-deal-button:hover { background-color: #4a9109; text-decoration: none; }    .tg-df-container .hawk-lazy-image-deal-widget { display: block; height: auto; margin: auto; max-height: 160px; max-width: 100%; mix-blend-mode: multiply; object-fit: contain; }    .tg-df-container .hawk-deal-widget-text-cta-container a { color: #2563eb; text-decoration: none; display: inline; }    .tg-df-container .hawk-deal-widget-text-cta-container a:hover { text-decoration: underline; }    .tg-df-container .hawk-deal-widget-text-cta-container a:has(.hawk-deal-widget-title-product-title) { color: #111827; }    .tg-df-container .hawk-deal-widget-text-cta-container a:hover .hawk-deal-widget-title-product-title,    .tg-df-container .hawk-deal-widget-text-cta-container a:hover .hawk-deal-widget-title-retailer-price { text-decoration: underline; }  \x3C/style>  \x3C!-- Widget Container --\x3E  \x3Cdiv class="tg-df-container" id="signal-deals-finder-root">    \x3C!-- Editor Floating Bar --\x3E    \x3Cdiv class="tg-df-editor-bar" id="tg-df-editor-bar" style="display:none;">      \x3Cdiv class="tg-df-editor-bar-text" style="display: flex; align-items: center;">        \x3Cspan id="tg-df-selected-count">0\x3C/span>\x26nbsp;Deals Selected        \x3Cbutton class="tg-df-editor-clear-btn" id="tg-df-editor-clear" type="button" style="margin-left: 12px; font-size: 13px; color: #9ca3af; background: none; border: none; cursor: pointer; text-decoration: underline;">Clear All\x3C/button>      \x3C/div>      \x3Cbutton class="tg-df-editor-copy-btn" id="tg-df-editor-copy" type="button">        \x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2">\x3C/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1">\x3C/path>\x3C/svg>        Copy to CMS      \x3C/button>    \x3C/div>    \x3Cdiv class="tg-df-carousel-host" id="tg-df-carousel-host" style="display: none;">      \x3Cdiv class="tg-df-carousel-eyebrow">DEAL FINDER\x3C/div>      \x3Cdiv class="tg-df-carousel-query-title" id="tg-df-carousel-title-label">Best Deals\x3C/div>            \x3Cdiv class="tg-df-carousel-blue-box">        \x3Cdiv class="tg-df-carousel-bg-circle-1" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-bg-circle-2" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-bg-circle-3" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-box-content">          \x3Cdiv class="tg-df-countdown-wrapper" id="tg-df-countdown-wrapper" style="display:none;">            \x3Cdiv class="tg-df-countdown-title" id="tg-df-countdown-title">Prime Day starts in\x3C/div>            \x3Cdiv class="tg-df-countdown-blocks">              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-days">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">DAYS\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-hrs">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">HRS\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-min">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">MIN\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-sec">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">SEC\x3C/div>\x3C/div>            \x3C/div>          \x3C/div>          \x3Cdiv class="tg-df-carousel-box-eyebrow">DEAL FINDER\x3C/div>          \x3Cdiv class="tg-df-carousel-box-title">Find Deals Fast\x3C/div>          \x3Cdiv class="tg-df-carousel-box-subtitle">The latest deals from the biggest retailers, all in one place\x3C/div>                    \x3Cdiv class="tg-df-carousel-roundels-wrapper">          \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-roundels').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>          \x3Cdiv class="tg-df-carousel-roundels">            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>          \x3C/div>          \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" onclick="this.parentElement.querySelector('.tg-df-carousel-roundels').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>        \x3C/div>        \x3Cdiv class="tg-df-carousel-filters-outer" style="position: relative;">          \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-filters-wrap').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>          \x3Cdiv class="tg-df-carousel-filters-wrap">                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="0">All\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-ot="amazon_lightning">              \x3Cimg src="https://cdn.mos.cms.futurecdn.net/HqAui7w97ft2NPqBtQ5r38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/yWPQ5yyQRhUwVKzGwYbh38-600-100.png" class="active-img" alt="" /> Lightning deals\x3C/button>            \x3Cbutton class="tg-df-carousel-filter-btn" data-ot="amazon_prime">              \x3Cimg src="https://cdn.mos.cms.futurecdn.net/fwoVXvL79turN3Ph535m38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/u75QjVpt3w2EsMimJiRo38-600-100.png" class="active-img" alt="" /> Prime deals\x3C/button>            \x3Cbutton class="tg-df-carousel-filter-btn" data-d="10">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 10% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="15">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 15% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="25">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 25% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-pr="under50">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-badge-dollar-sign">\x3Cpath d="M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z">\x3C/path>\x3Cpath d="M16 8h-6a2 2 0 1 0 0 4h4a2 2 0 1 1 0 4H8">\x3C/path>\x3Cpath d="M12 18V6">\x3C/path>\x3C/svg>            Under $50\x3C/button>        \x3C/div>        \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-filters-wrap').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>      \x3C/div>    \x3C/div>    \x3C/div>      \x3C!-- Search & Filter Controls --\x3E    \x3Cdiv class="tg-df-controls" id="tg-df-controls" style="display:flex;">      \x3Cdiv class="tg-df-top-bar">        \x3Cdiv class="tg-df-search-wrapper">          \x3Cinput type="text" class="tg-df-search-input" placeholder="Search for deals, products, or brands...">          \x3Cbutton type="button" class="tg-df-search-btn" aria-label="Search">              \x3Csvg class="tg-df-search-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">                \x3Cpath d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/>              \x3C/svg>          \x3C/button>          \x3Cdiv class="tg-df-autocomplete-dropdown" id="tg-df-autocomplete">\x3C/div>        \x3C/div>                \x3Cdiv class="tg-df-settings-wrapper">          \x3Cbutton type="button" class="tg-df-settings-btn" aria-label="Settings" id="tg-df-settings-toggle">            \x3Csvg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="20" height="20">                \x3Cpath d="M19.14 12.94c.04-.3.06-.61.06-.94 0-.32-.02-.64-.06-.94l2.03-1.58c.18-.14.23-.41.12-.61l-1.92-3.32c-.12-.22-.37-.29-.59-.22l-2.39.96c-.5-.38-1.03-.7-1.62-.94l-.36-2.54c-.04-.24-.24-.41-.48-.41h-3.84c-.24 0-.43.17-.47.41l-.36 2.54c-.59.24-1.13.57-1.62.94l-2.39-.96c-.22-.08-.47 0-.59.22L2.73 8.87c-.12.21-.08.47.12.61l2.03 1.58c-.05.3-.09.63-.09.94s.02.64.06.94l-2.03 1.58c-.18.14-.23.41-.12.61l1.92 3.32c.12.22.37.29.59.22l2.39-.96c.5.38 1.03.7 1.62.94l.36 2.54c.05.24.24.41.48.41h3.84c.24 0 .43-.17.47-.41l.36-2.54c.59-.24 1.13-.56 1.62-.94l2.39.96c.22.08.47 0 .59-.22l1.92-3.32c.12-.22.07-.49-.12-.61l-2.01-1.58zM12 15.6c-1.98 0-3.6-1.62-3.6-3.6s1.62-3.6 3.6-3.6 3.6 1.62 3.6 3.6-1.62 3.6-3.6 3.6z"/>            \x3C/svg>          \x3C/button>          \x3Cdiv class="tg-df-settings-dropdown-backdrop" id="tg-df-settings-backdrop">\x3C/div>          \x3Cdiv class="tg-df-settings-dropdown" id="tg-df-settings-panel">            \x3Cdiv class="tg-df-setting-item">              \x3Clabel class="tg-df-setting-label">Search Region\x3C/label>              \x3Cselect class="tg-df-region-select" id="tg-df-region-select">                \x3Coption value="auto">🌍 Auto-detect\x3C/option>                \x3Coption value="US">🇺🇸 United States (US)\x3C/option>                \x3Coption value="GB">🇬🇧 United Kingdom (UK)\x3C/option>                \x3Coption value="CA">🇨🇦 Canada (CA)\x3C/option>                \x3Coption value="AU">🇦🇺 Australia (AU)\x3C/option>                \x3Coption value="DE">🇩🇪 Germany (DE)\x3C/option>                \x3Coption value="FR">🇫🇷 France (FR)\x3C/option>                \x3Coption value="IT">🇮🇹 Italy (IT)\x3C/option>              \x3C/select>            \x3C/div>            \x3Cdiv class="tg-df-setting-item">              \x3Clabel class="tg-df-setting-label">Retailer\x3C/label>              \x3Cselect class="tg-df-region-select" id="tg-df-retailer-select">                \x3Coption value="">All Retailers\x3C/option>                \x3Coption value="Amazon">Amazon\x3C/option>                \x3Coption value="Walmart">Walmart\x3C/option>                \x3Coption value="Best Buy">Best Buy\x3C/option>                \x3Coption value="Target">Target\x3C/option>                \x3Coption value="John Lewis">John Lewis\x3C/option>                \x3Coption value="Currys">Currys\x3C/option>                \x3Coption value="Argos">Argos\x3C/option>              \x3C/select>            \x3C/div>            \x3Cdiv class="tg-df-setting-item">              \x3Clabel class="tg-df-setting-label">Offer Type\x3C/label>              \x3Cselect class="tg-df-region-select" id="tg-df-offer-type-select">                \x3Coption value="">All Offers\x3C/option>                \x3Coption value="amazon_prime">Amazon Prime\x3C/option>                \x3Coption value="recommended_promo">Recommended Promo\x3C/option>                \x3Coption value="amazon_lightning">Amazon Lightning Deal\x3C/option>              \x3C/select>            \x3C/div>            \x3Cdiv class="tg-df-setting-item">              \x3Clabel class="tg-df-setting-label">Result Count\x3C/label>              \x3Cselect class="tg-df-region-select" id="tg-df-rows-select">                \x3Coption value="3">3 Items\x3C/option>                \x3Coption value="4">4 Items\x3C/option>                \x3Coption value="6">6 Items\x3C/option>                \x3Coption value="12" selected>12 Items\x3C/option>                \x3Coption value="24">24 Items\x3C/option>                \x3Coption value="48">48 Items\x3C/option>              \x3C/select>            \x3C/div>            \x3Cdiv class="tg-df-setting-item tg-df-dl-row">              \x3Cdiv>                \x3Cspan class="tg-df-dl-row-text">Deal Mode\x3C/span>                \x3Cspan class="tg-df-dl-row-subtext">Only show products with active offers or previous prices (was_price)\x3C/span>              \x3C/div>              \x3Clabel class="tg-df-toggle">                \x3Cinput type="checkbox" id="tg-df-deal-mode">                \x3Cspan class="tg-df-slider">\x3C/span>              \x3C/label>            \x3C/div>            \x3Cdiv class="tg-df-setting-item tg-df-dl-row">              \x3Cdiv>                \x3Cspan class="tg-df-dl-row-text">Editor Mode\x3C/span>                \x3Cspan class="tg-df-dl-row-subtext">Enable multi-select to copy deals to CMS\x3C/span>              \x3C/div>              \x3Clabel class="tg-df-toggle">                \x3Cinput type="checkbox" id="tg-df-editor-mode">                \x3Cspan class="tg-df-slider">\x3C/span>              \x3C/label>            \x3C/div>            \x3Cdiv class="tg-df-setting-item">              \x3Clabel class="tg-df-setting-label">View Mode\x3C/label>              \x3Cselect class="tg-df-region-select" id="tg-df-view-mode-select">                \x3Coption value="auto">Auto Collection\x3C/option>                \x3Coption value="carousel">Carousel\x3C/option>                \x3Coption value="savings_squad">Savings Squad\x3C/option>                \x3Coption value="grid">Grid (Columns)\x3C/option>                \x3Coption value="row">Row (List)\x3C/option>              \x3C/select>            \x3C/div>          \x3C/div>        \x3C/div>      \x3C/div>      \x3Cdiv class="tg-df-filters">        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-category-filter-wrapper" style="display: none;">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-category-filter" aria-label="Category">            \x3Coption value="all">All Categories\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper tg-df-multiselect-container" id="tg-df-brand-filter-wrapper" style="display:none;">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M4.25 5.61C6.27 8.2 10 13 10 13v6c0 .55.45 1 1 1h2c.55 0 1-.45 1-1v-6s3.72-4.8 5.74-7.39A.998.998 0 0 0 18.95 4H5.04c-.83 0-1.3.95-.79 1.61z"/>          \x3C/svg>          \x3Cdiv class="tg-df-filter-select tg-df-multiselect-trigger" id="tg-df-brand-trigger" tabindex="0">            Any Brand          \x3C/div>          \x3Cdiv class="tg-df-multiselect-dropdown" id="tg-df-brand-dropdown">            \x3C!-- Populated via script --\x3E          \x3C/div>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M9 3L5 6.99h3V14h2V6.99h3L9 3zm7 14.01V10h-2v7.01h-3L15 21l4-3.99h-3z"/>          \x3C/svg>          \x3Cselect class="tg-df-sort-select" aria-label="Sort Deals">            \x3Coption value="date_desc">Newest First\x3C/option>            \x3Coption value="best_match">Sort by: Match\x3C/option>            \x3Coption value="price_asc">Price Low to High\x3C/option>            \x3Coption value="price_desc">Price High to Low\x3C/option>            \x3Coption value="discount_desc">Biggest Discount\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper tg-df-price-range-wrapper" id="tg-df-custom-price-wrapper" style="display: flex; align-items:center; justify-content:center; padding: 10px 20px; gap: 8px; border: 1px solid var(--tg-df-border); border-radius: 100px; background-color: var(--tg-df-bg);">          \x3Cspan style="font-size:14px; font-weight:500; color:var(--tg-df-text-primary);">Price\x3C/span>          \x3Cinput type="number" class="tg-df-price-input" id="tg-df-custom-price-min" placeholder="Min" style="width: 48px; background: transparent; border: none; color: var(--tg-df-text-primary); outline: none; font-size: 14px; text-align: center; padding: 0;">          \x3Cspan style="color:var(--tg-df-text-muted)">-\x3C/span>          \x3Cinput type="number" class="tg-df-price-input" id="tg-df-custom-price-max" placeholder="Max" style="width: 48px; background: transparent; border: none; color: var(--tg-df-text-primary); outline: none; font-size: 14px; text-align: center; padding: 0;">        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-legacy-price-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58.55 0 1.05-.22 1.41-.59l7-7c.37-.36.59-.86.59-1.41 0-.55-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-price-filter" aria-label="Filter Prices">            \x3Coption value="all">All Prices\x3C/option>            \x3Coption value="under50">Under $50\x3C/option>            \x3Coption value="50_100">$50 - $100\x3C/option>            \x3Coption value="100_200">$100 - $200\x3C/option>            \x3Coption value="200_500">$200 - $500\x3C/option>            \x3Coption value="over500">Over $500\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-discount-filter-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">            \x3Cpath d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58.55 0 1.05-.22 1.41-.59l7-7c.37-.36.59-.86.59-1.41 0-.55-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-discount-filter" aria-label="Discount Amount">            \x3Coption value="all">Any discount\x3C/option>            \x3Coption value="5">Min 5%\x3C/option>            \x3Coption value="10">Min 10%\x3C/option>            \x3Coption value="15">Min 15%\x3C/option>            \x3Coption value="20">Min 20%\x3C/option>            \x3Coption value="25">Min 25%\x3C/option>            \x3Coption value="30">Min 30%\x3C/option>            \x3Coption value="40">Min 40%\x3C/option>            \x3Coption value="50">Min 50%\x3C/option>            \x3Coption value="60">Min 60%\x3C/option>            \x3Coption value="70">Min 70%\x3C/option>          \x3C/select>        \x3C/div>      \x3C/div>    \x3C/div>    \x3C!-- Deals Grid Wrapper --\x3E    \x3Cdiv class="tg-df-grid-wrapper tg-df-carousel-cards-wrapper" id="tg-df-grid-wrapper">      \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('#tg-df-grid').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>      \x3Cdiv class="tg-df-grid" id="tg-df-grid">        \x3C!-- Content populated by JavaScript --\x3E      \x3C/div>      \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" style="display:none;" onclick="this.parentElement.querySelector('#tg-df-grid').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>    \x3C/div>        \x3C!-- Vouchers Modal --\x3E    \x3Cdiv class="tg-df-modal-backdrop" id="tg-df-vouchers-modal">      \x3Cdiv class="tg-df-modal">        \x3Cdiv class="tg-df-modal-header">          \x3Ch3 class="tg-df-modal-title" id="tg-df-vouchers-title">Available Coupons & Deals\x3C/h3>          \x3Cbutton class="tg-df-modal-close" id="tg-df-vouchers-close">            \x3Csvg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">              \x3Cline x1="18" y1="6" x2="6" y2="18">\x3C/line>              \x3Cline x1="6" y1="6" x2="18" y2="18">\x3C/line>            \x3C/svg>          \x3C/button>        \x3C/div>        \x3Cdiv class="tg-df-modal-body" id="tg-df-vouchers-content">          \x3C!-- Vouchers injected here --\x3E        \x3C/div>      \x3C/div>    \x3C/div>  \x3C/div>`;      if (!template) {        template = document.createElement('template');        template.innerHTML = rawTemplate;      }      let shadowRoot = null;      if (hostContainer && template) {        hostContainer.setAttribute('data-initialized', 'true');        shadowRoot = hostContainer.attachShadow({ mode: 'open' });        shadowRoot.appendChild(template.content.cloneNode(true));      }      class DealsFinderWidget {        constructor(config) {          this.rootNode = config.rootNode || document;          this.hostContainer = config.hostContainer || null;          this.rootId = config.rootId || 'signal-deals-finder-root';          this.root = this.rootNode.querySelector('#' + this.rootId);          if (!this.root) return;          this.widgetId = (window.crypto && window.crypto.randomUUID) ? window.crypto.randomUUID() : 'widget-' + Date.now() + '-' + Math.random().toString(36).slice(2);          this.grid = this.root.querySelector('#tg-df-grid');          this.tagsContainer = this.root.querySelector('#tg-df-tags-container');          this.categoryFilter = this.root.querySelector('#tg-df-category-filter');          this.categoryFilterWrapper = this.root.querySelector('#tg-df-category-filter-wrapper');          this.searchInput = this.root.querySelector('.tg-df-search-input');          this.autocompleteDropdown = this.root.querySelector('#tg-df-autocomplete');          this.sortSelect = this.root.querySelector('.tg-df-sort-select');          this.searchBtn = this.root.querySelector('.tg-df-search-btn');                    this.settingsToggle = this.root.querySelector('#tg-df-settings-toggle');          this.settingsPanel = this.root.querySelector('#tg-df-settings-panel');          this.settingsBackdrop = this.root.querySelector('#tg-df-settings-backdrop');          this.regionSelect = this.root.querySelector('#tg-df-region-select');          this.retailerSelect = this.root.querySelector('#tg-df-retailer-select');          this.offerTypeSelect = this.root.querySelector('#tg-df-offer-type-select');          this.viewModeSelect = this.root.querySelector('#tg-df-view-mode-select');          this.rowsSelect = this.root.querySelector('#tg-df-rows-select');          this.dealModeToggle = this.root.querySelector('#tg-df-deal-mode');          this.editorModeToggle = this.root.querySelector('#tg-df-editor-mode');          this.priceFilter = this.root.querySelector('#tg-df-price-filter');          this.discountFilter = this.root.querySelector('#tg-df-discount-filter');                    this.editorBar = this.root.querySelector('#tg-df-editor-bar');          this.editorSelectedCount = this.root.querySelector('#tg-df-selected-count');          this.editorCopyBtn = this.root.querySelector('#tg-df-editor-copy');          this.editorClearBtn = this.root.querySelector('#tg-df-editor-clear');                    this.apiUrl = 'https://search-api.fie.future.net.uk/widget.php';          this.deals = [];          this.displayLimit = 12;          this.airedaleArticles = null;          this.airedaleTags = [];          this.airedaleTagCounts = {};          this.activeDealTag = null;          this.selectedBrands = [];          this.currentQuery = '';          this.editorMode = this.hostContainer ? this.hostContainer.hasAttribute('data-editor-mode') : false;          this.viewModeOverride = this.hostContainer ? this.hostContainer.getAttribute('data-view-mode') : null;          this.selectedDeals = new Map();                    this.brandFilterWrapper = this.root.querySelector('#tg-df-brand-filter-wrapper');          this.brandTrigger = this.root.querySelector('#tg-df-brand-trigger');          this.brandDropdown = this.root.querySelector('#tg-df-brand-dropdown');                    this.customPriceWrapper = this.root.querySelector('#tg-df-custom-price-wrapper');          this.customPriceMin = this.root.querySelector('#tg-df-custom-price-min');          this.customPriceMax = this.root.querySelector('#tg-df-custom-price-max');          this.legacyPriceWrapper = this.root.querySelector('#tg-df-legacy-price-wrapper');          this.discountFilterWrapper = this.root.querySelector('#tg-df-discount-filter-wrapper');          this.initResizeObserver();          this.init();            if (['carousel', 'carousel-compact', 'auto', 'grid', 'row'].includes(this.getViewMode())) { this.loadCarouselSpreadsheet(); }        }        getViewMode() {          if (this.viewModeOverride && (!this.editorMode || !this.viewModeSelect)) {            return this.viewModeOverride;          }          return (this.viewModeSelect && this.viewModeSelect.value) ? this.viewModeSelect.value : (this.viewModeOverride || 'auto');        }        applyLayoutMode() {          if (!this.grid) return;          const mode = this.getViewMode();          this.grid.classList.remove('layout-row', 'layout-grid', 'tg-df-grid-auto', 'carousel-compact', 'layout-replica-1', 'layout-replica-2');                    const carouselHost = this.root.querySelector('#tg-df-carousel-host');          const controlsDiv = this.root.querySelector('#tg-df-controls');          if (mode === 'carousel' || mode === 'auto' || mode === 'grid' || mode === 'row') {             if (mode === 'carousel') this.grid.classList.add('carousel-compact');             if (carouselHost) carouselHost.style.display = 'block';             if (controlsDiv) controlsDiv.style.display = 'none';             if (this.root.classList.contains('tg-df-container') && mode === 'carousel') {               this.root.classList.add('is-carousel');             } else if (this.root.classList.contains('tg-df-container')) {               this.root.classList.remove('is-carousel');             }          } else {             if (carouselHost) carouselHost.style.display = 'none';             if (controlsDiv) controlsDiv.style.display = 'flex';             if (this.root.classList.contains('tg-df-container')) {               this.root.classList.remove('is-carousel');             }          }          if (mode === 'grid') {            this.grid.classList.add('layout-grid');          } else if (mode === 'row') {            this.grid.classList.add('layout-row');          } else if (mode === 'savings_squad') {            this.grid.classList.add('tg-df-grid-auto', 'savings-squad-cards');          } else if (mode !== 'carousel') {            this.grid.classList.add('tg-df-grid-auto');          }                    const settingsWrapper = this.root.querySelector('.tg-df-settings-wrapper');          if (settingsWrapper) {            settingsWrapper.style.display = mode === 'auto' ? 'none' : 'block';          }          if (this.customPriceWrapper) {             this.customPriceWrapper.style.display = mode === 'auto' ? 'flex' : 'none';          }          if (this.legacyPriceWrapper) {             this.legacyPriceWrapper.style.display = mode === 'auto' ? 'none' : 'flex';          }          if (this.discountFilterWrapper) {             this.discountFilterWrapper.style.display = mode === 'auto' ? 'none' : 'flex';          }        }        initResizeObserver() {          try {            if (window.parent === window) return;          } catch (e) {            // cross origin frame check threw          }          const emitHeight = () => {            try {              const height = document.documentElement.scrollHeight || document.body.scrollHeight;              const msg = { type: 'embed-size', height: height };              if (window.parent && window.parent !== window) {                window.parent.postMessage(msg, '*');                window.parent.postMessage(JSON.stringify({ ...msg, sentinel: 'amp' }), '*');              }            } catch (e) {}          };                    if (window.ResizeObserver) {            try {              const ro = new ResizeObserver(() => emitHeight());              ro.observe(document.body);              if (this.root) ro.observe(this.root);            } catch(e){ console.warn(e); }          }          window.addEventListener('resize', emitHeight);          setTimeout(emitHeight, 300);        }        initCountdown() {          this.cdWrapper = this.root.querySelector('#tg-df-countdown-wrapper');                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          this.showCountdown = params.get('show_countdown') === 'true';          const showHeaderDetails = params.get('show_header_details') !== 'false';          const eyebrow = this.root.querySelector('.tg-df-carousel-box-eyebrow');          const title = this.root.querySelector('.tg-df-carousel-box-title');          const subtitle = this.root.querySelector('.tg-df-carousel-box-subtitle');          if (!showHeaderDetails) {            let containerElement = this.root.classList.contains('tg-df-container') ? this.root : this.root.querySelector('.tg-df-container');            if (containerElement) containerElement.classList.add('hide-header-details');            if (eyebrow) eyebrow.style.display = 'none';            if (title) title.style.display = 'none';            if (subtitle) subtitle.style.display = 'none';          }          if (!this.cdWrapper) return;          this.cdTitle = this.root.querySelector('#tg-df-countdown-title');          this.cdDays = this.root.querySelector('#tg-df-cd-days');          this.cdHrs = this.root.querySelector('#tg-df-cd-hrs');          this.cdMin = this.root.querySelector('#tg-df-cd-min');          this.cdSec = this.root.querySelector('#tg-df-cd-sec');          this.updateCountdown();          this.cdInterval = setInterval(() => this.updateCountdown(), 1000);        }        updateCountdown() {          if (!this.cdWrapper) return;          if (!this.showCountdown) {            this.cdWrapper.style.display = 'none';            return;          }          const area = this.getAreaCode();          let offset = '-04:00';          if (['DE', 'FR', 'IT', 'ES', 'NL'].includes(area)) {             offset = '+02:00';          } else if (['GB', 'IE', 'UK'].includes(area)) {             offset = '+01:00';          }          const startTime = new Date('2026-06-23T00:00:00' + offset).getTime();          const endTime = new Date('2026-06-26T00:00:00' + offset).getTime();          const now = Date.now();          let targetTime = 0;          if (now < startTime) {             targetTime = startTime;             if (this.cdTitle) this.cdTitle.textContent = 'Prime Day starts in';             this.cdWrapper.style.display = 'flex';          } else if (now < endTime) {             targetTime = endTime;             if (this.cdTitle) this.cdTitle.textContent = 'Prime Day ends in';             this.cdWrapper.style.display = 'flex';          } else {             this.cdWrapper.style.display = 'none';             if (this.cdInterval) clearInterval(this.cdInterval);             return;          }          const diff = Math.max(0, targetTime - now);          const d = Math.floor(diff / (1000 * 60 * 60 * 24));          const h = Math.floor((diff / (1000 * 60 * 60)) % 24);          const m = Math.floor((diff / 1000 / 60) % 60);          const s = Math.floor((diff / 1000) % 60);          if (this.cdDays) this.cdDays.textContent = d;          if (this.cdHrs) this.cdHrs.textContent = h;          if (this.cdMin) this.cdMin.textContent = m;          if (this.cdSec) this.cdSec.textContent = s;        }        init() {          this.initCountdown();          try {            initAnalytics();          } catch (e) {            console.warn('Deals Widget Analytics Error:', e);          }                    this.bindEvents();                    let initialQuery = '';                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          let initialViewMode = params.get('view_mode');          if (!params.has('search') && !params.has('q') && !params.has('query') && initialViewMode !== 'savings_squad') {             initialQuery = 'Everything';             if (this.discountFilter && !params.has('min_discount_ratio')) {               this.discountFilter.value = '5';             }          }          const website = params.get('website') || 'tomsguide';          this.website = website;          if (website === 'techradar') {            const squadHeader = this.root.querySelector('.tg-df-savings-squad-header');            if (squadHeader) {               const pic = squadHeader.querySelector('picture');               if (pic) pic.style.display = 'none';            }            const style = document.createElement('style');            style.innerHTML = `              .tg-df-container .hawk-affiliate-link-deal-button, .tg-df-container .tg-df-card-cta { background-color: #5DAF08 !important; }              .tg-df-container .hawk-affiliate-link-deal-button:hover, .tg-df-container .tg-df-card-cta:hover { background-color: #4a8c06 !important; }            `;            this.root.appendChild(style);          }                    if (this.regionSelect) {            this.regionSelect.value = params.get('region') || 'auto';            this.updatePriceDropdownCurrency();          }                    if (this.retailerSelect && params.has('retailer')) {            this.retailerSelect.value = params.get('retailer');          }                    if (params.has('brands')) {            const b = params.get('brands');            if (b) {              this.selectedBrands = b.split(',');            }          }                    if (this.offerTypeSelect && params.has('offer_type')) {            this.offerTypeSelect.value = params.get('offer_type');          }          if (params.has('bg_color')) {            const bg = params.get('bg_color');            if (bg === 'white') {              this.root.style.setProperty('background-color', '#ffffff', 'important');            } else if (bg === 'transparent') {              this.root.style.setProperty('background-color', 'transparent', 'important');            } else if (bg === 'light_blue') {              this.root.style.setProperty('background-color', '#E7F0FF', 'important');            }          } else {             this.root.style.removeProperty('background-color');          }                    if (params.has('view_mode')) {            if (this.viewModeSelect) {              this.viewModeSelect.value = params.get('view_mode');            } else {              this.viewModeOverride = params.get('view_mode');            }          }          if (this.rowsSelect && params.has('rows')) {            this.rowsSelect.value = params.get('rows');          }          if (params.has('price')) {            const priceVal = params.get('price');            if (this.priceFilter) {               // Try assigning it directly to select. If it's not present implicitly ignores               this.priceFilter.value = priceVal;            }            if (priceVal.includes('_')) {               const parts = priceVal.split('_');               if (this.customPriceMin && parts[0]) this.customPriceMin.value = parts[0];               if (this.customPriceMax && parts[1]) this.customPriceMax.value = parts[1];            }          }          if (this.discountFilter && params.has('min_discount_ratio')) {            // Need to convert back from ratio (e.g. 0.8) to select value (e.g. "20")            const ratioStr = params.get('min_discount_ratio');            const ratioFloat = parseFloat(ratioStr);            if (!isNaN(ratioFloat)) {               const percentage = Math.round((1 - ratioFloat) * 100);               this.discountFilter.value = percentage.toString();            }          }          if (this.sortSelect) {            this.sortSelect.value = params.get('sort') || 'discount_desc';          }          if (this.dealModeToggle && params.has('deal_mode')) {            this.dealModeToggle.checked = params.get('deal_mode') === 'true' || params.get('deal_mode') === '1';          }                    // Re-apply layout after params have updated control values          this.applyLayoutMode();                    if (params.get('search')) {            initialQuery = params.get('search');          } else if (params.get('q')) {            initialQuery = params.get('q');          } else if (params.get('query')) {            initialQuery = params.get('query');          }                    this.currentQuery = initialQuery;          if (this.searchInput) {            this.searchInput.value = this.currentQuery;          }                    if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {            this.fetchDeals(this.currentQuery);          } else {            this.render();          }        }        updatePriceDropdownCurrency() {          if (!this.priceFilter || !this.regionSelect) return;          const currencySymbols = {            'US': '$',            'GB': '£',            'CA': '$CA',            'AU': '$AU',            'DE': '€',            'FR': '€',            'IT': '€',          };          const area = this.getAreaCode();          const cur = currencySymbols[area || 'US'] || '$';                    const options = this.priceFilter.options;          for (let i = 0; i < options.length; i++) {            const opt = options[i];            if (opt.value === 'all') {              opt.innerText = 'All Prices';            } else if (opt.value === 'under50') {              opt.innerText = `Under ${cur}50`;            } else if (opt.value === '50_100') {              opt.innerText = `${cur}50 - ${cur}100`;            } else if (opt.value === '100_200') {              opt.innerText = `${cur}100 - ${cur}200`;            } else if (opt.value === '200_500') {              opt.innerText = `${cur}200 - ${cur}500`;            } else if (opt.value === 'over500') {              opt.innerText = `Over ${cur}500`;            }          }        }        populateBrandDropdown(values) {          if (!this.brandDropdown || !this.brandFilterWrapper) return;          this.brandFilterWrapper.style.display = 'flex'; // show the wrapper                    let html = '';          const allChecked = this.selectedBrands.length === 0 ? 'checked' : '';          const _div = '<' + '/div>';          const _span = '<' + '/span>';          html += `\x3Cdiv class="tg-df-ms-option">\x3Cinput type="checkbox" value="" ${allChecked} class="tg-df-brand-chk"> Any Brand${_div}`;                    values.forEach(v => {             if (!v.formatted_value || v.formatted_value === 'Any Brand') return;             const isChecked = this.selectedBrands.includes(v.formatted_value) ? 'checked' : '';             html += `\x3Cdiv class="tg-df-ms-option">\x3Cinput type="checkbox" value="${this.escapeHTML(v.formatted_value)}" ${isChecked} class="tg-df-brand-chk"> ${this.escapeHTML(v.formatted_value)} \x3Cspan style="color:var(--tg-df-text-muted);font-size:12px">(${v.count || 0})${_span}${_div}`;          });                    this.brandDropdown.innerHTML = html;                    // Re-bind listeners          const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');          chks.forEach(chk => {            chk.addEventListener('change', (e) => {              const val = e.target.value;              if (val === '') {                this.selectedBrands = [];              } else {                if (e.target.checked) {                   if (!this.selectedBrands.includes(val)) this.selectedBrands.push(val);                } else {                   this.selectedBrands = this.selectedBrands.filter(b => b !== val);                }              }                            if (this.selectedBrands.length === 0) {                 this.brandTrigger.innerText = 'Any Brand';              } else if (this.selectedBrands.length === 1) {                 this.brandTrigger.innerText = this.selectedBrands[0];              } else {                 this.brandTrigger.innerText = `${this.selectedBrands.length} Brands selected`;              }                            // Only call API if changed from UI interactions              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                 this.updateURLParams();                 this.fetchDeals(this.currentQuery);              }            });          });                    // Update button text on load          if (this.selectedBrands.length === 0) {             this.brandTrigger.innerText = 'Any Brand';          } else if (this.selectedBrands.length === 1) {             this.brandTrigger.innerText = this.selectedBrands[0];          } else {             this.brandTrigger.innerText = `${this.selectedBrands.length} Brands selected`;          }        }        updateURLParams() {          const url = new URL(window.location);          if (this.currentQuery && this.currentQuery !== 'Gaming laptops') {            url.searchParams.set('q', this.currentQuery);          } else {            url.searchParams.delete('q');            url.searchParams.delete('search');            url.searchParams.delete('query');          }                    if (this.regionSelect && this.regionSelect.value !== 'auto') {            url.searchParams.set('region', this.regionSelect.value);          } else {            url.searchParams.delete('region');          }                    if (this.retailerSelect && this.retailerSelect.value) {            url.searchParams.set('retailer', this.retailerSelect.value);          } else {            url.searchParams.delete('retailer');          }                    if (this.selectedBrands && this.selectedBrands.length > 0) {            url.searchParams.set('brands', this.selectedBrands.join(','));          } else {            url.searchParams.delete('brands');          }                    if (this.offerTypeSelect && this.offerTypeSelect.value) {            url.searchParams.set('offer_type', this.offerTypeSelect.value);          } else {            url.searchParams.delete('offer_type');          }                    if (this.viewModeSelect && this.viewModeSelect.value !== 'auto') {            url.searchParams.set('view_mode', this.viewModeSelect.value);          } else {            url.searchParams.delete('view_mode');          }                    if (this.rowsSelect && this.rowsSelect.value !== '12') {            url.searchParams.set('rows', this.rowsSelect.value);          } else {            url.searchParams.delete('rows');          }                    const min = this.customPriceMin ? this.customPriceMin.value : '';          const max = this.customPriceMax ? this.customPriceMax.value : '';          if (min || max) {             url.searchParams.set('price', `${min}_${max}`);          } else if (this.priceFilter && this.priceFilter.value !== 'all') {            url.searchParams.set('price', this.priceFilter.value);          } else {            url.searchParams.delete('price');          }                    if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {            const v = parseInt(this.discountFilter.value);            if (!isNaN(v) && v > 0) {               const ratio = (100 - v) / 100;               url.searchParams.set('min_discount_ratio', ratio.toString());            }          } else {            url.searchParams.delete('min_discount_ratio');          }                    if (this.sortSelect && this.sortSelect.value !== 'discount_desc') {            url.searchParams.set('sort', this.sortSelect.value);          } else {            url.searchParams.delete('sort');          }                    if (this.dealModeToggle && this.dealModeToggle.checked) {            url.searchParams.set('deal_mode', 'true');          } else {            url.searchParams.delete('deal_mode');          }                    window.history.replaceState({}, '', url);        }        bindEvents() {          const roundels = this.root.querySelectorAll('.tg-df-carousel-cat.original-hardcoded');          roundels.forEach(r => {             r.addEventListener('click', () => {                const q = r.getAttribute('data-query');                const pr = r.getAttribute('data-pr');                if (typeof trackHawkEvent !== 'undefined') {                     trackHawkEvent({                         clickType: "CC",                         widgetId: this.widgetId,                         productCategoryName: "deals",                         zeroBasedProductIndexOrNull: null,                         totalDealsOrProducts: null,                         areaClicked: "Category Roundel",                         revenueId: this.revenueId,                         isoCurrencyCode: typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD',                         queryName: q,                         widgetTypeName: this.widgetTypeName                     });                 }                this.currentQuery = q;                const label = this.root.querySelector('#tg-df-carousel-title-label');                if (label) label.textContent = 'Best ' + q;                if (this.priceFilter) this.priceFilter.value = pr || 'all';                if (this.discountFilter) this.discountFilter.value = '5';                if (this.searchInput) this.searchInput.value = q;                                roundels.forEach(ro => ro.classList.remove('active'));                r.classList.add('active');                this.fetchDeals(this.currentQuery);             });          });          const discBtns = this.root.querySelectorAll('.tg-df-carousel-filter-btn');          discBtns.forEach(b => {             b.addEventListener('click', () => {                const d = b.getAttribute('data-d');                const pr = b.getAttribute('data-pr');                const ot = b.getAttribute('data-ot');                let label = b.innerText ? b.innerText.trim() : '';                let filterType = 'unknown';                let filterVal = 'unknown';                if (d !== null) { filterType = 'discount'; filterVal = d; }                else if (pr !== null) { filterType = 'price'; filterVal = pr; }                else if (ot !== null) { filterType = 'offertype'; filterVal = ot; }                if (typeof trackElementInteraction === 'function') trackElementInteraction({ id: `filter-${filterType}-${filterVal}`, name: 'Filter Button', label: label });                                if (d !== null) {                   if (this.discountFilter) this.discountFilter.value = this.discountFilter.value === d ? '0' : d;                } else if (pr !== null) {                   if (this.priceFilter) this.priceFilter.value = this.priceFilter.value === pr ? 'all' : pr;                } else if (ot !== null) {                   if (this.offerTypeSelect) this.offerTypeSelect.value = this.offerTypeSelect.value === ot ? 'all' : ot;                } else {                   if (this.discountFilter) this.discountFilter.value = '0';                   if (this.priceFilter) this.priceFilter.value = 'all';                   if (this.offerTypeSelect) this.offerTypeSelect.value = 'all';                }                if (d === null && pr === null && ot === null && b.getAttribute("data-type") !== "custom") {                   discBtns.forEach(ro => ro.classList.remove('active'));                   b.classList.add('active');                } else if (b.getAttribute("data-type") !== "custom") {                   // Only operate on hardcoded buttons (those without data-type)                   discBtns.forEach(ro => {                      if (!ro.getAttribute('data-d') && !ro.getAttribute('data-pr') && !ro.getAttribute('data-ot') && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active');                   });                                      let makeActive = true;                   if (d !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-d') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   } else if (pr !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-pr') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   } else if (ot !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-ot') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   }                                      if (makeActive) b.classList.add('active');                                      // Check if anything is active, if not activate "All"                   let anyActive = false;                   discBtns.forEach(ro => { if (ro.classList.contains('active') && ro.getAttribute('data-type') !== 'custom') anyActive = true; });                   if (!anyActive) {                       discBtns.forEach(ro => { if (!ro.getAttribute('data-d') && !ro.getAttribute('data-pr') && !ro.getAttribute('data-ot') && ro.getAttribute('data-type') !== 'custom') ro.classList.add('active'); });                   }                }                                this.fetchDeals(this.currentQuery);             });          });          if (this.brandTrigger && this.brandDropdown) {            this.brandTrigger.addEventListener('click', () => {              this.brandDropdown.classList.toggle('active');            });            document.addEventListener('click', (e) => {              if (this.brandFilterWrapper && !e.composedPath().includes(this.brandFilterWrapper)) {                this.brandDropdown.classList.remove('active');              }            });          }          let debounceTimer;          if(this.searchInput) {            this.searchInput.addEventListener('input', (e) => {              clearTimeout(debounceTimer);              const query = e.target.value.trim();              this.currentQuery = query;              if (this.getViewMode() === 'savings_squad' && this.autocompleteDropdown && this.airedaleTags && query.length > 0) {                 const matches = this.airedaleTags.filter(t => t.toLowerCase().includes(query.toLowerCase()) && t.toLowerCase() !== query.toLowerCase()).slice(0, 5);                 if (matches.length > 0) {                    this.autocompleteDropdown.innerHTML = matches.map(m => `\x3Cdiv class="tg-df-autocomplete-item" data-tag="${this.escapeHTML(m)}">${this.escapeHTML(m)}<` + `/div>`).join('');                    this.autocompleteDropdown.classList.add('active');                 } else {                    this.autocompleteDropdown.classList.remove('active');                 }              } else if (this.autocompleteDropdown) {                 this.autocompleteDropdown.classList.remove('active');              }              debounceTimer = setTimeout(() => {                this.updateURLParams();                if (query.length > 2) {                  this.fetchDeals(query);                } else if (query.length === 0) {                  this.deals = [];                  this.render();                }              }, 400);            });            this.searchInput.addEventListener('keypress', (e) => {              if (e.key === 'Enter') {                if (this.autocompleteDropdown) this.autocompleteDropdown.classList.remove('active');                clearTimeout(debounceTimer);                const query = e.target.value.trim();                this.currentQuery = query;                this.activeDealTag = null;                trackElementInteraction({ id: 'search-submit', name: 'Ask', label: 'Ask (main search)', text: query });                this.updateURLParams();                if (query.length > 2 || (this.getViewMode() === 'savings_squad')) {                   this.fetchDeals(query);                }              }            });          }          if (this.autocompleteDropdown) {             this.autocompleteDropdown.addEventListener('click', (e) => {                const item = e.target.closest('.tg-df-autocomplete-item');                if (item) {                   const tag = item.getAttribute('data-tag');                   this.currentQuery = tag;                   if (this.searchInput) this.searchInput.value = tag;                   this.activeDealTag = tag;                   this.autocompleteDropdown.classList.remove('active');                   this.updateURLParams();                   this.fetchDeals(tag);                }             });             document.addEventListener('click', (e) => {               if (this.autocompleteDropdown && this.searchInput && !e.composedPath().includes(this.searchInput) && !e.composedPath().includes(this.autocompleteDropdown)) {                 this.autocompleteDropdown.classList.remove('active');               }             });          }          if (this.searchBtn) {            this.searchBtn.addEventListener('click', () => {              if (this.autocompleteDropdown) this.autocompleteDropdown.classList.remove('active');              clearTimeout(debounceTimer);              const query = this.searchInput.value.trim();              trackElementInteraction({ id: 'search-submit', name: 'Ask', label: 'Ask (main search)', text: query });              this.activeDealTag = null;              this.currentQuery = query;              this.updateURLParams();              if (query.length > 2 || (this.getViewMode() === 'savings_squad')) {                 this.fetchDeals(query);              }            });          }          if(this.sortSelect) this.sortSelect.addEventListener('change', () => {            trackElementInteraction({ id: `sort-option-${this.sortSelect.value}`, name: 'Sort', label: `Sort: ${this.sortSelect.options[this.sortSelect.selectedIndex].text}` });            this.updateURLParams();            if (this.deals.length > 0) {              this.sortData();              this.render();            }          });                    const priceFilter = this.root.querySelector('#tg-df-price-filter');          if (priceFilter) {            this.priceFilter = priceFilter;            this.priceFilter.addEventListener('change', () => {              trackElementInteraction({ id: `filter-price-${this.priceFilter.value}`, name: 'Price', label: this.priceFilter.options[this.priceFilter.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }            });          }          const updateCustomPrice = () => {             this.updateURLParams();             if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);             } else {                this.render();             }          };          if (this.customPriceMin) {             this.customPriceMin.addEventListener('change', updateCustomPrice);             this.customPriceMin.addEventListener('keypress', (e) => {                if (e.key === 'Enter') updateCustomPrice();             });          }          if (this.customPriceMax) {             this.customPriceMax.addEventListener('change', updateCustomPrice);             this.customPriceMax.addEventListener('keypress', (e) => {                if (e.key === 'Enter') updateCustomPrice();             });          }          const discountFilter = this.root.querySelector('#tg-df-discount-filter');          if (discountFilter) {            this.discountFilter = discountFilter;            this.discountFilter.addEventListener('change', () => {              trackElementInteraction({ id: `filter-discount-${this.discountFilter.value}`, name: 'Discount', label: this.discountFilter.options[this.discountFilter.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }            });          }          if (this.categoryFilter) {            this.categoryFilter.addEventListener('change', (e) => {               const val = e.target.value === 'all' ? null : e.target.value;               this.activeDealTag = val;               this.fetchSavingsSquad();            });          }                    if (this.settingsToggle) {            this.settingsToggle.addEventListener('click', () => {              const o = this.settingsPanel.classList.toggle('active');              this.settingsBackdrop.classList.toggle('active');              if (o) trackElementInteraction({ id: 'filter-open', name: 'Filters', label: 'Open filters' });            });          }                    if (this.settingsBackdrop) {            this.settingsBackdrop.addEventListener('click', () => {              this.settingsPanel.classList.remove('active');              this.settingsBackdrop.classList.remove('active');            });          }                    if (this.regionSelect) {            this.regionSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-region-${this.regionSelect.value}`, name: 'Region', label: this.regionSelect.options[this.regionSelect.selectedIndex].text });              this.updateURLParams();              this.updatePriceDropdownCurrency();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.retailerSelect) {            this.retailerSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-merchant-${this.retailerSelect.value}`, name: 'Retailer', label: this.retailerSelect.options[this.retailerSelect.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.offerTypeSelect) {            this.offerTypeSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-offertype-${this.offerTypeSelect.value}`, name: 'Offer Type', label: this.offerTypeSelect.options[this.offerTypeSelect.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.viewModeSelect) {            this._prevViewMode = this.viewModeSelect.value;            this.viewModeSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-viewmode-${this.viewModeSelect.value}`, name: 'View Mode', label: this.viewModeSelect.options[this.viewModeSelect.selectedIndex].text });                            // Reset all active toggles and filters to prevent config carry-over              this.selectedBrands = [];              if (this.brandTrigger) this.brandTrigger.innerText = 'Select Brands';              if (this.brandDropdown) {                const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                chks.forEach(chk => { chk.checked = false; });              }              if (this.priceFilter) this.priceFilter.value = 'all';              if (this.customPriceMin) this.customPriceMin.value = '';              if (this.customPriceMax) this.customPriceMax.value = '';              if (this.sortSelect) this.sortSelect.value = this.viewModeSelect.value === 'savings_squad' ? 'date_desc' : 'discount_desc';              if (this.discountFilter) this.discountFilter.value = '0';              if (this.retailerSelect) this.retailerSelect.value = '';              if (this.offerTypeSelect) this.offerTypeSelect.value = '';              if (this.rowsSelect) this.rowsSelect.value = '12';              if (this.categoryFilter) this.categoryFilter.value = 'all';              this.activeDealTag = null;              this.updateURLParams();              this.applyLayoutMode();                            if (this.getViewMode() === 'savings_squad' || this._prevViewMode === 'savings_squad') {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }              this._prevViewMode = this.viewModeSelect.value;            });          }                    if (this.rowsSelect) {            this.rowsSelect.addEventListener('change', () => {              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.dealModeToggle) {            this.dealModeToggle.addEventListener('change', () => {              this.updateURLParams();              this.render();            });          }          if (this.editorModeToggle) {             this.editorModeToggle.addEventListener('change', (e) => {                this.editorMode = e.target.checked;                this.render();                this.updateFloatingCopyBar();             });          }          if (this.editorCopyBtn) {             this.editorCopyBtn.addEventListener('click', () => {                this.copySelectedDealsToCMS();             });          }          if (this.editorClearBtn) {             this.editorClearBtn.addEventListener('click', () => {                this.selectedDeals.clear();                this.render();                this.updateFloatingCopyBar();             });          }          if (this.grid) {            this.grid.addEventListener('change', (e) => {               if (e.target.classList.contains('tg-df-deal-checkbox')) {                  const dealId = e.target.getAttribute('data-id');                  if (e.target.checked) {                     const dealObj = this.deals.find(d => d.id === dealId);                     if (dealObj) this.selectedDeals.set(dealId, dealObj);                  } else {                     this.selectedDeals.delete(dealId);                  }                  this.updateFloatingCopyBar();               }            });            this.grid.addEventListener('click', (e) => {              const dealCard = e.target.closest('[data-action="deal-click"]');              const similarCard = e.target.closest('[data-action="view-similar-click"]');              const cardLink = dealCard || similarCard;              if (cardLink) {                const productName = cardLink.getAttribute('data-product-name');                const merchantName = cardLink.getAttribute('data-merchant-name');                const productId = cardLink.getAttribute('data-analytics-id');                const price = parseFloat(cardLink.getAttribute('data-price')) || null;                const prevPriceStr = cardLink.getAttribute('data-previous-price');                const previousPrice = prevPriceStr ? parseFloat(prevPriceStr) : null;                const originalLink = cardLink.getAttribute('data-original-link');                const rewrittenLink = cardLink.getAttribute('href');                const revenueId = cardLink.getAttribute('data-revenue-id');                const index = parseInt(cardLink.getAttribute('data-index'), 10) || 0;                const inStock = cardLink.getAttribute('data-in-stock') === 'true';                const totalText = cardLink.getAttribute('data-total');                const totalDeals = parseInt(totalText, 10) || 0;                const productCategoryName = 'deals';                const trackingParams = {                  widgetId: this.widgetId,                  productCategoryName: productCategoryName,                  product: {                    modelId: cardLink.getAttribute('data-model-id') || null,                    matchId: cardLink.getAttribute('data-match-id') || null,                    brand: cardLink.getAttribute('data-model-brand') || null,                    parent: cardLink.getAttribute('data-model-parent') || null,                    name: productName,                    price: price,                    previousPrice: previousPrice,                    link: rewrittenLink,                    originalLink: originalLink,                    inStock: inStock                  },                  zeroBasedProductIndexOrNull: index,                  totalDealsOrProducts: totalDeals,                   merchant: {                    id: cardLink.getAttribute('data-merchant-id') || null,                    network: cardLink.getAttribute('data-merchant-network') || null,                    url: cardLink.getAttribute('data-merchant-url') || null,                    name: merchantName                  },                  revenueId: revenueId,                  widgetTypeName: this.widgetTypeName,                  isoCurrencyCode: normalizeCurrency(this.escapeHTML(cardLink.getAttribute('data-currency') || '$'))                };                if (dealCard) {                  trackDealClick(trackingParams);                } else {                  trackViewSimilarClick(trackingParams);                }              }              const couponsBtn = e.target.closest('[data-action="coupons-click"]');              if (couponsBtn) {                trackElementInteraction({                  id: 'product-card-show-coupons',                  name: 'Coupons',                  label: `Product card coupons: ${couponsBtn.getAttribute('data-merchant')}`                });              }            });          }          this.setupScrollListeners();        }        setupScrollListeners() {          const containers = [             this.root.querySelector('.tg-df-carousel-roundels'),             this.root.querySelector('.tg-df-carousel-filters-wrap'),             this.root.querySelector('#tg-df-grid')          ];                    containers.forEach(container => {             if (!container) return;                          const checkScroll = () => {                if (!container.parentElement) return;                const leftBtn = container.parentElement.querySelector('.tg-df-carousel-scroll-left');                const rightBtn = container.parentElement.querySelector('.tg-df-carousel-scroll-right');                                if (leftBtn) {                   if (container.scrollLeft <= 5) leftBtn.style.display = 'none';                   else leftBtn.style.display = 'flex';                }                                if (rightBtn) {                   if (container.scrollWidth <= container.clientWidth) {                       rightBtn.style.display = 'none';                   } else if (container.scrollLeft >= container.scrollWidth - container.clientWidth - 5) {                       rightBtn.style.display = 'none';                   } else {                       rightBtn.style.display = 'flex';                   }                }             };                          container.addEventListener('scroll', checkScroll);             checkScroll();                          window.addEventListener('resize', checkScroll);                          const observer = new MutationObserver(checkScroll);             observer.observe(container, { childList: true, subtree: true, characterData: false });          });        }        get widgetTypeName() {          const mode = this.viewModeSelect ? this.viewModeSelect.value : (this.viewModeOverride || 'auto');          switch(mode) {              case 'carousel': return 'Carousel';              case 'savings_squad': return 'Savings Squad';              case 'grid': return 'Grid';              case 'row': return 'Row';              default: return 'Auto Collection';          }        }        getRowsLimit() {          if (this.rowsSelect && this.rowsSelect.value) return parseInt(this.rowsSelect.value, 10);          let configSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {             configSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {             configSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(configSource);          if (params.has('rows')) return parseInt(params.get('rows'), 10) || 12;          return 12;        }        getAreaCode() {          if (this.regionSelect && this.regionSelect.value) {            if (this.regionSelect.value === 'auto') return null;            return this.regionSelect.value;          }          let area = null;          try {            const locale = window.navigator.language || window.navigator.userLanguage;            if (locale && locale.includes('-')) {              area = locale.split('-')[1].toUpperCase();            } else if (locale && locale.length === 2) {              if (locale.toUpperCase() === 'EN') { area = 'US'; }              else { area = locale.toUpperCase(); }            }          } catch (e) { /* Ignore */ }                    // Map to known valid options or fallback to US          const valid = ['US', 'GB', 'CA', 'AU', 'DE', 'FR', 'IT'];          if (area === 'UK') area = 'GB';          if (valid.includes(area)) {             return area;          }          return 'US';        }                async loadCarouselSpreadsheet() {          try {              const parseCSVRow = (str) => {                  let result = [], cur = '', inQuotes = false;                  for (let i = 0; i < str.length; i++) {                      let char = str[i];                      if (inQuotes) {                          if (char === '"') {                              if (str[i + 1] === '"') { cur += '"'; i++; }                              else { inQuotes = false; }                          } else { cur += char; }                      } else {                          if (char === '"') { inQuotes = true; }                          else if (char === ',') { result.push(cur); cur = ''; }                          else { cur += char; }                      }                  }                  result.push(cur); return result;              };              const parseCSV = (str) => {                  const rows = []; let curRow = '', inQuotes = false;                  for (let i = 0; i < str.length; i++) {                      let char = str[i];                      if (char === '"') inQuotes = !inQuotes;                      if ((char === '\n' || char === '\r') && !inQuotes) {                          if (char === '\r' && str[i+1] === '\n') i++;                          if (curRow) rows.push(parseCSVRow(curRow));                          curRow = '';                      } else { curRow += char; }                  }                  if (curRow) rows.push(parseCSVRow(curRow));                  return rows;              };              const preloadedCSV = decodeURIComponent(escape(atob("LCwxLDIsMyw0LDUsNiw3LDgsOSwxMCwxMSwxMiwxMywxNCwxNQ0KUm91bmRlbCB0ZXh0LEFsbCxUVnMsRm9vdHdlYXIsQXBwYXJlbCxNYXR0cmVzZXMsQXBwbGlhbmNlcyxXZWFyYWJsZSB0ZWNoLEhlYWRwaG9uZXMsU21hcnQgSG9tZSxTcGVha2VycyxMYXB0b3BzLFRhYmxldHMsQ29tcHV0aW5nLFBob25lcyxHYW1pbmcsTGVnbw0KUm91bmRlbCBpbWFnZSxodHRwczovL3d3dy50b21zZ3VpZGUuY29tL3Byb2R1Y3RzL2Nhcm91c2VsL2FpLnBuZyxodHRwczovL3d3dy50b21zZ3VpZGUuY29tL3Byb2R1Y3RzL2Nhcm91c2VsL3R2cy5wbmcsaHR0cHM6Ly9pbWFnZXMuZmllLmZ1dHVyZWNkbi5uZXQvcHJvZHVjdHMvN2IzYTIyNGIwNzk2M2M2MjdiNmI5MDliZDc4MzM4MzZlMDJmZjgxOS5qcGcud2VicCxodHRwczovL2ltYWdlcy5maWUuZnV0dXJlY2RuLm5ldC9wcm9kdWN0cy84NGRhYzVkNDhlZDJkNDQ4NTU5ZWJhNjdhY2U4MzE0Y2M2N2NjZDk0LmpwZy53ZWJwLGh0dHBzOi8vd3d3LnRvbXNndWlkZS5jb20vcHJvZHVjdHMvY2Fyb3VzZWwvbWF0dHJlc3Nlcy5wbmcsaHR0cHM6Ly9pbWFnZXMuZmllLmZ1dHVyZWNkbi5uZXQvcHJvZHVjdHMvNzY4ZTk3Y2ViMDcxODAxZmFlMjA5MTBkMDgyMGIxNmY3NDdhZjkzOS5qcGcud2VicCxodHRwczovL3d3dy50b21zZ3VpZGUuY29tL3Byb2R1Y3RzL2Nhcm91c2VsL3dlbGxuZXNzLnBuZyxodHRwczovL3d3dy50b21zZ3VpZGUuY29tL3Byb2R1Y3RzL2Nhcm91c2VsL2hlYWRwaG9uZXMuanBnLGh0dHBzOi8vaW1hZ2VzLmZpZS5mdXR1cmVjZG4ubmV0L3Byb2R1Y3RzLzg5NTM1YmVlYmUyMGRiYmQ0YTM0NmQ2ZDZiZGZlOTFkOGE4ODRhMjEuanBnLndlYnAsaHR0cHM6Ly93d3cudG9tc2d1aWRlLmNvbS9wcm9kdWN0cy9jYXJvdXNlbC9hdWRpby5qcGcsaHR0cHM6Ly93d3cudG9tc2d1aWRlLmNvbS9wcm9kdWN0cy9jYXJvdXNlbC9sYXB0b3BzLmpwZyxodHRwczovL2ltYWdlcy5maWUuZnV0dXJlY2RuLm5ldC9wcm9kdWN0cy8yMzk3NTY0ZWQ3YTVmZjk0N2U5YjZiMzBlNTRmNDc0OTRiODQxZjg5LmpwZy53ZWJwLGh0dHBzOi8vd3d3LnRvbXNndWlkZS5jb20vcHJvZHVjdHMvY2Fyb3VzZWwvY29tcHV0aW5nLmpwZyxodHRwczovL3d3dy50b21zZ3VpZGUuY29tL3Byb2R1Y3RzL2Nhcm91c2VsL3Bob25lcy5wbmcsaHR0cHM6Ly93d3cudG9tc2d1aWRlLmNvbS9wcm9kdWN0cy9jYXJvdXNlbC9nYW1pbmcucG5nLGh0dHBzOi8vaW1hZ2VzLmZpZS5mdXR1cmVjZG4ubmV0L3Byb2R1Y3RzLzRmNmM2MjFjYWMwYmMxYTg1ZDU5M2UzNTk0YmE1YjM0OWVmZmQyOTIuanBnLndlYnANClNlYXJjaCBRdWVyeSxFdmVyeXRoaW5nLFRlbGV2aXNpb25zLCJTbmVha2VycywgcnVubmluZyBzaG9lcywgc2FuZGFscyIsQ2xvdGhpbmcsTWF0dHJlc3NlcyxIb21lIEFwcGxpYW5jZXMsV2VhcmFibGVzICYgRml0bmVzcyBUZWNoLEhlYWRwaG9uZXMsSG9tZSBUZWNoLFNwZWFrZXJzLExhcHRvcHMsVGFibGV0cyxDb21wdXRpbmcsUGhvbmVzLEdhbWluZyxDb25zdHJ1Y3Rpb24gVG95cw0KRGlzY291bnQgQW1vdW50LG1pbiA1JSxtaW4gMTAlLG1pbiA1JSxtaW4gNSUsbWluIDUlLG1pbiA1JSxtaW4gNSUsbWluIDUlLG1pbiA1JSxtaW4gNSUsbWluIDUlLG1pbiA1JSxtaW4gNSUsbWluIDUlLG1pbiA1JSxtaW4gNSUNClByaWNlIFJhbmdlLCwsLCxtaW4gJDQwMCwsLCxtaW4gJDI1LCxtaW4gJDMwMCwsLG1pbiAkMTAwLCwNCkJyYW5kIFNlbGVjdGlvbiwsLCwsLCwsLCwsLCwsLCwNCkZpbHRlciBidXR0b25zLCwsLCwsLCwsLCwsLCwsLA0KMSxMaWdodG5pbmcgZGVhbHMsTGlnaHRuaW5nIGRlYWxzLExpZ2h0bmluZyBkZWFscyxMaWdodG5pbmcgZGVhbHMsTGlnaHRuaW5nIGRlYWxzLExpZ2h0bmluZyBkZWFscyxMaWdodG5pbmcgZGVhbHMsTGlnaHRuaW5nIGRlYWxzLExpZ2h0bmluZyBkZWFscyxMaWdodG5pbmcgZGVhbHMsTGlnaHRuaW5nIGRlYWxzLExpZ2h0bmluZyBkZWFscyxMaWdodG5pbmcgZGVhbHMsTGlnaHRuaW5nIGRlYWxzLExpZ2h0bmluZyBkZWFscyxMaWdodG5pbmcgZGVhbHMNCjIsQW1hem9uIGRlYWxzLFVuZGVyICQxMDAwLDUwJSBvZmYsQWRpZGFzLEFtYXpvbiBkZWFscyxBbWF6b24gZGVhbHMsNTAlIG9mZixBbWF6b24gZGVhbHMsQW1hem9uIGRlYWxzLEFtYXpvbiBkZWFscyxBbWF6b24gZGVhbHMsQW1hem9uIGRlYWxzLEFtYXpvbiBkZWFscyxBbWF6b24gZGVhbHMsQW1hem9uIGRlYWxzLEFtYXpvbiBkZWFscw0KMyxPdmVyICQ0MDAsVW5kZXIgJDUwMCxIb2thLE5pa2UsU2FhdHZhLE5pbmphLDQwJSBvZmYsSkxhYiwsSkJMLERlbGwsLEFzdXMsQXBwbGUsQ29uc29sZXMsU3RhciBXYXJzDQo0LFVuZGVyICQxMDAwLDUwJSBvZmYsU2tlY2hlcnMsVW5kZXIgQXJtb3VyLEhlbGl4LFNoYXJrLEdhcm1pbixBbmtlciBTb3VuZGNvcmUsUmluZyxTb25vcyxBcHBsZSxBcHBsZSxUUC1saW5rLFNhbXN1bmcsQWNjZXNzb3JpZXMsVW5kZXIgJDI1DQo1LFVuZGVyICQ1MDAsTEcsQXNpY3MsQ29sdW1iaWEsRHJlYW1DbG91ZCxLZXVyaWcsQXBwbGUsU29ueSxHb3ZlZSxUcmliaXQsTGVub3ZvLFNhbXN1bmcsRWVybyxHb29nbGUsR2FtZXMsVW5kZXIgJDUwDQo2LDUwJSBvZmYsU2Ftc3VuZyxOaWtlLFBhdGFnb25pYSxOZWN0YXIsRGUnTG9uZ2hpLEFtYXpmaXQsQXBwbGUsS2FzYSBzbWFydCxTb255LEFsaWVud2FyZSxUQ0wsTmV0Z2VhcixNb3Rvcm9sYSxOaW50ZW5kbyxCb3RhbmljYWxzDQo3LEFtYXpvbixIaXNlbnNlLE5ldyBCYWxhbmNlLEFyYyd0ZXJ5eCxUZW1wdXItcGVkaWMsRHlzb24sRml0Yml0LEJlYXRzLFBoaWxpcHMgSHVlLEFua2VyLEFjZXIsT25lUGx1cyxEZWxsLE9uZVBsdXMsU29ueSxEaXNuZXkNCjgsQXBwbGUsVENMLEFkaWRhcyxDYXJoYXJ0dCxCZWFyLEJpc3NlbGwsU2Ftc3VuZyxFYXJmdW4sQmxpbmssQmVhdHMsTVNJLE1pY3Jvc29mdCxBY2VyLE5vdGhpbmcsWGJveCxNYXJ2ZWwNCjksLFNvbnksU2F1Y29ueSxUaGUgTm9ydGggRmFjZSxTaWVuYSxOdXRyaWJ1bGxldCxPdXJhLFNhbXN1bmcsR29vZ2xlIE5lc3QgLE1hcnNoYWxsLFNhbXN1bmcsTGVub3ZvLExlbm92bywsLFBva2Vtb24NCjEwLCxSb2t1LEJpcmtlbnN0b2NrLENSWiBZb2dhLFdpbmtCZWRzLEJsYWNrIGFuZCBEZWNrZXIsUmluZ2Nvbm4sQ01GLEV1ZnksU2Ftc3VuZyxNaWNyb3NvZnQsUmVNYXJrYWJsZSxBbGllbndhcmUsLCwNCjExLCwsQnJvb2tzLFRoZSBHeW0gUGVvcGxlLEJyb29rbHluIGJlZGRpbmcsTmVzcHJlc3NvLCwxTW9yZSxBcmxvLCxSYXplciwsQ29yc2FpciwsLA0KMTIsLCxDcm9jcywsRWlnaHQgU2xlZXAsQ3Vpc2luYXJ0LCxKQkwsLCwsLEhQLCwsDQpOb3RlcywsLCwsLCwsLCwsLCwsLCwNCiwsIlByaW9yaXRpc2UgYmlnZ2VzdCAlLyQgZGlzY291bnQsIFR2cyB3aXRoIH41MCUgb2ZmIGhhdmUgYmVlbiB0aGUgbW9zdCBwb3B1bGFyIGV2ZW4gaWYgdGhleSBhcmUgc3RpbGwgZXhwZW5zaXZlIiwiTm8gcGF0dGVybiB0byBwcmljaW5nL2Rpc2NvdW50LCByZWFkZXJzIG1haW5seSBzaG9wIGJ5IGJyYW5kL3JlY29nbmlzYWJsZSBzaG9lcyIsIk5vIHBhdHRlcm4gdG8gcHJpY2luZy9kaXNjb3VudCwgcmVhZGVycyBtYWlubHkgc2hvcCBieSBicmFuZCIsIkEgbGFiZWwgd2lsbCBkZWZpbml0ZWx5IGhlbHAgaGVyZSBlLmcuIGJlc3QgZm9yIHNpZGUgc2xlZXBlciwgYmVzdCBtZW1vcnkgZm9hbSIsIkFwcGxpYW5jZXMgaXMgYSBiaWcgY2F0ZWdvcnksIGlzIGl0IHBvc3NpYmxlIHRvIHNwbGl0IGludG8ga2l0Y2hlbiBhcHBsaWFuY2VzLCBmbG9vcmNhcmUsIGFpciBoZWFsdGgvY29vbGluZz8gT3Igc2ltaWxhciIsIkZvY3VzIG9uIHZhbHVlIGZvciBtb25leSwgR2FybWlucyB3aXRoIH41MCUgb2ZmIGhhdmUgYmVlbiBwb3B1bGFyIGV2ZW4gdGhvdWdoIHRoZXkgYXJlIHN0aWxsICQ1MDAiLCwsLCxJbmNsdWRlIEtpbmRsZXMsSSB3b3VsZCBpbmNsdWRlIHdpZmkgcm91dGVycyBoZXJlIGluc3RlYWQgb2Ygc21hcnQgaG9tZSxDYW4gd2Ugc3VyZmFjZSBwaG9uZSBwcm92aWRlciBkZWFscz8gVC1tb2JpbGUgYW5kIHZlcml6b24gd291bGQgbWFrZSBhIGxvdCBtb3JlIG1vbmV5IHRoYW4gQW1hem9uLCwNCiwsaGF2aW5nIGEgJ2Jlc3QgZm9yJyBsYWJlbCB3b3VsZCBiZSBoZWxwZnVsIGUuZy4gYmVzdCBmb3IgYnJpZ2h0IHJvb20sQ2FuIHdlIHN0b3Aga2lkcyBzaG9lcyBmcm9tIHB1bGxpbmcgdGhyb3VnaD8sIldpbGwgdGhpcyBpbmNsdWRlIGFjY2Vzc29yaWVzIGUuZy4gY2FwcywgYmFncywgaWYgc28gbWFrZSBzdXJlIHRoZXNlIGFyZSBtaXhlZCB0aHJvdWdob3V0IGNsb3RoaW5nIGRlYWxzIixXaWxsIHRoaXMgaW5jbHVkZSB0b3BwZXJzIGFuZCBwaWxsb3dzPyBTZWVpbmcgbW9yZSBtb21lbnR1bSB3aXRoIHRoaXMgY2F0ZWdvcnkgcmVjZW50bHkgc28gYSBiZWRkaW5nIHRhYiBtaWdodCB3b3JrLCwiTmVlZCB0byBtYWtlIHN1cmUgYmFuZHMsIHNjcmVlbiBwcm90ZWN0b3JzIGV0Yy4gZG9uJ3QgcHVsbCBpbnRvIGhlcmUiLCwsLCwsLCwsDQosLCJQcmlvcml0aXNlIDY1JycgYW5kIDU1JyBpbmNoIFRWcywgdGhlbiBiaWdnZXIgc2NyZWVucyBiZWZvcmUgdGhlIHNtYWxsZXIgc2l6ZXMiLCwsUXVlZW4gaXMgdGhlIG1vc3QgcG9wdWxhciBzaXplIGluIHRoZSBVUyAtIHByaW9yaXRpc2UgZGVhbHMgZm9yIHRoaXMgc2l6ZSwsLCwsLCwsLCwsDQosLCwsLCwsLCwsLCwsLCwsDQpDYXRlZ29yaWVzIHRvIGNvbnNpZGVyLCxQcm9kdWN0cyBpbmNsdWRlZCwsLCwsLCwsLCwsLCwsDQpVbmRlciAkNTA/LCxBaXIgdGFncywsLCwsLCwsLCwsLCwsDQosLFBvcnRhYmxlIGNoYXJnZXJzL3dpcmVsZXNzIGNoYXJnZXJzLCwsLCwsLCwsLCwsLCwNCiwsIldhdGVyIGJvdHRsZXMgKHN0YW5sZXlzLCBPd2FsYSwgSHlkcm8gZmxhc2ssIFlldGkpIiwsLCwsLCwsLCwsLCwsDQosLEhhbmQgaGVsZCBmYW5zLCwsLCwsLCwsLCwsLCwNCiwsLCwsLCwsLCwsLCwsLCwNCmhvbWUgb2ZmaWNlLCxvZmZpY2UgY2hhaXJzLCwsLCwsLCwsLCwsLCwNCiwsc3RhbmRpbmcgZGVza3MsLCwsLCwsLCwsLCwsLA0KLCxtb25pdG9ycywsLCwsLCwsLCwsLCwsDQosLEtleWJvYXJkcywsLCwsLCwsLCwsLCwsDQosLGRvY2tpbmcgc3RhdGlvbiwsLCwsLCwsLCwsLCwsDQosLCwsLCwsLCwsLCwsLCwsDQpHYW1pbmcsLENvbnNvbGVzLCwsLCwsLCwsLCwsLCwNCiwsQWNjZXNzb3JpZXMsLCwsLCwsLCwsLCwsLA0KLCxHYW1lcywsLCwsLCwsLCwsLCwsDQosLENvdWxkIGluY2x1ZGUgTGVnbz8sLCwsLCwsLCwsLCwsLA==")));              const text = preloadedCSV;              const parsed = parseCSV(text);                            const rowsByName = {};              let filterStart = -1;              parsed.forEach((rc, i) => {                 if (rc && rc.length > 0 && rc[0]) rowsByName[rc[0]] = rc;                 if (rc && rc.length > 0 && rc[0] === 'Filter buttons') filterStart = i;              });                            const cols = [];              if(rowsByName['Roundel text']) {                const headerRow = rowsByName['Roundel text'];                for(let col = 1; col < headerRow.length; col++) {                   let label = headerRow[col];                   if (!label) continue;                                      let q = rowsByName['Search Query'] && rowsByName['Search Query'][col] ? rowsByName['Search Query'][col] : '';                   let img = rowsByName['Roundel image'] && rowsByName['Roundel image'][col] ? rowsByName['Roundel image'][col] : '';                   let ds = rowsByName['Discount Amount'] && rowsByName['Discount Amount'][col] ? rowsByName['Discount Amount'][col] : '';                   let pr = rowsByName['Price Range'] && rowsByName['Price Range'][col] ? rowsByName['Price Range'][col] : '';                   let rt = rowsByName['Retailer'] && rowsByName['Retailer'][col] ? rowsByName['Retailer'][col] : '';                   let ot = rowsByName['Offer Type'] && rowsByName['Offer Type'][col] ? rowsByName['Offer Type'][col] : '';                                      let filters = [];                   if(filterStart > 0) {                     for(let r = filterStart + 1; r < parsed.length; r++) {                         if(!parsed[r] || parsed[r][0] === 'Notes' || parsed[r][0] === 'Categories to consider') break;                         let f = parsed[r][col];                         if(f) filters.push(f);                     }                   }                   cols.push({ label, img, q, ds, pr, rt, ot, filters });                }              }              this.carouselData = cols;              if (this.carouselData && this.carouselData.length > 0) {                 const isMatched = this.carouselData.some(c => c.q === this.currentQuery || c.label === this.currentQuery);                 if (!isMatched) {                    const first = this.carouselData[0];                    this.currentQuery = first.q || first.label;                    if (this.priceFilter) this.priceFilter.value = 'all';                    if (this.customPriceMin) this.customPriceMin.value = '';                    if (this.customPriceMax) this.customPriceMax.value = '';                    let dPr = first.pr || 'all';                    if (typeof dPr === 'string' && dPr !== 'all') {                       let prLower = dPr.toLowerCase();                       if (prLower.includes('min') || prLower.includes('over')) {                          let m = dPr.match(/(\d+)/);                          if (m && this.customPriceMin) this.customPriceMin.value = m[1];                       } else if (prLower.includes('max') || prLower.includes('under')) {                          let m = dPr.match(/(\d+)/);                          if (m && this.customPriceMax) this.customPriceMax.value = m[1];                       }                    }                    let dAm = '0';                    if(first.ds && typeof first.ds === 'string') {                       let m = first.ds.match(/(\d+)/);                       if(m) dAm = m[1];                    }                    if (this.discountFilter) this.discountFilter.value = dAm;                    if (this.offerTypeSelect) this.offerTypeSelect.value = first.ot || '';                    if (this.retailerSelect) this.retailerSelect.value = first.rt || '';                    this.selectedBrands = [];                    if (this.brandDropdown) {                        const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                        chks.forEach(chk => chk.checked = false);                    }                    if (this.searchInput) this.searchInput.value = this.currentQuery;                 }              }              this.renderCarouselUI();          } catch(e){ console.warn(e); }        }                renderCarouselUI() {           const roundelWrapper = this.root.querySelector('.tg-df-carousel-roundels');           if(!roundelWrapper || !this.carouselData) return;                      let html = '';           this.carouselData.forEach(r => {              const q = r.q || r.label;              const isActive = (this.currentQuery === q || this.currentQuery === r.label) ? 'active' : '';              const imgHtml = r.img ? `\x3Cimg src="${r.img}" alt="${r.label}" />` : `\x3Csvg width="32" height="32" fill="#1F69FF" viewBox="0 0 24 24">\x3Cpath d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z"/>\x3C/svg>`;              html += `                \x3Cdiv class="tg-df-roundel tg-df-carousel-cat ${isActive}" data-label="${this.escapeHTML(r.label)}">                  \x3Cdiv class="tg-df-roundel-img-box">${imgHtml}\x3C/div>                  \x3Cspan class="tg-df-roundel-label">${this.escapeHTML(r.label)}\x3C/span>                \x3C/div>              `;           });           roundelWrapper.innerHTML = html;                      // Rebind clicks           const roundels = this.root.querySelectorAll('.tg-df-carousel-cat');           roundels.forEach(rNode => {             rNode.addEventListener('click', () => {                const r = this.carouselData.find(c => c.label === rNode.getAttribute('data-label'));                 if(!r) return;                                  if (typeof trackHawkEvent !== 'undefined') {                     trackHawkEvent({                         clickType: "CC",                         widgetId: this.widgetId,                         productCategoryName: "deals",                         zeroBasedProductIndexOrNull: null,                         totalDealsOrProducts: null,                         areaClicked: "Category Roundel",                         revenueId: this.revenueId,                         isoCurrencyCode: typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD',                         queryName: r.label,                         widgetTypeName: this.widgetTypeName                     });                 }                this.currentQuery = r.q || r.label;                const labelTitle = this.root.querySelector('#tg-df-carousel-title-label');                if (labelTitle) labelTitle.textContent = 'Best ' + this.currentQuery;                if (this.priceFilter) this.priceFilter.value = 'all';                if (this.customPriceMin) this.customPriceMin.value = '';                if (this.customPriceMax) this.customPriceMax.value = '';                let dPr = r.pr || 'all';                if (typeof dPr === 'string' && dPr !== 'all') {                   let prLower = dPr.toLowerCase();                   if (prLower.includes('min') || prLower.includes('over')) {                      let m = dPr.match(/(\d+)/);                      if (m && this.customPriceMin) this.customPriceMin.value = m[1];                   } else if (prLower.includes('max') || prLower.includes('under')) {                      let m = dPr.match(/(\d+)/);                      if (m && this.customPriceMax) this.customPriceMax.value = m[1];                   }                }                                let discountAmount = '0';                if(r.ds && typeof r.ds === 'string') {                   let m = r.ds.match(/(\d+)/);                   if(m) discountAmount = m[1];                }                if (this.discountFilter) this.discountFilter.value = discountAmount;                if (this.offerTypeSelect) this.offerTypeSelect.value = r.ot || '';                if (this.retailerSelect) this.retailerSelect.value = r.rt || '';                                // Clear brands                    this.selectedBrands = [];                    if (this.brandDropdown) {                    const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                    chks.forEach(chk => chk.checked = false);                }                                if (this.searchInput) this.searchInput.value = this.currentQuery;                                roundels.forEach(ro => ro.classList.remove('active'));                if (rNode) rNode.classList.add('active');                                this.renderCarouselFilters(r);                this.fetchDeals(this.currentQuery);             });           });                      // Auto-highlight active           const activeR = this.carouselData.find(c => c.q === this.currentQuery || c.label === this.currentQuery);           if(activeR) this.renderCarouselFilters(activeR);        }                renderCarouselFilters(r) {           const filtersWrap = this.root.querySelector('.tg-df-carousel-filters-wrap');           if(!filtersWrap) return;                      let html = `\x3Cbutton class="tg-df-carousel-filter-btn" data-type="all">All\x3C/button>`;                      r.filters.forEach(f => {              let fL = f.toLowerCase();              let icon = '';              let logic = `data-type="custom" data-v="${this.escapeHTML(f)}"`;              if (fL === 'amazon deals' || fL === 'prime deals') {                 html += `\x3Cbutton class="tg-df-carousel-filter-btn" ${logic}>\x3Cimg src="https://cdn.mos.cms.futurecdn.net/fwoVXvL79turN3Ph535m38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/u75QjVpt3w2EsMimJiRo38-600-100.png" class="active-img" alt="" /> Prime deals\x3C/button>`;              } else if (fL === 'lightning deals') {                 html += `\x3Cbutton class="tg-df-carousel-filter-btn" ${logic}>\x3Cimg src="https://cdn.mos.cms.futurecdn.net/HqAui7w97ft2NPqBtQ5r38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/yWPQ5yyQRhUwVKzGwYbh38-600-100.png" class="active-img" alt="" /> Lightning deals\x3C/button>`;              } else {                 if (fL.includes('lightning')) {                    icon = `\x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-zap">\x3Cpolygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2">\x3C/polygon>\x3C/svg>`;                 } else if (fL.includes('% off')) {                    icon = `\x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>`;                 } else if (fL.includes('under') || fL.includes('min ')) {                    icon = `\x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-badge-dollar-sign">\x3Cpath d="M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z">\x3C/path>\x3Cpath d="M16 8h-6a2 2 0 1 0 0 4h4a2 2 0 1 1 0 4H8">\x3C/path>\x3Cpath d="M12 18V6">\x3C/path>\x3C/svg>`;                 }                 html += `\x3Cbutton class="tg-df-carousel-filter-btn" ${logic}>${icon} ${this.escapeHTML(f)}\x3C/button>`;              }           });                      filtersWrap.innerHTML = html;                      const btns = filtersWrap.querySelectorAll('button');           btns.forEach(b => {             b.addEventListener('click', () => {                const type = b.getAttribute('data-type');                if (type === 'custom') {                   const v = b.getAttribute('data-v');                   if (typeof trackElementInteraction === 'function') trackElementInteraction({ id: `filter-custom-${(v||'').toLowerCase().replace(/[^a-z0-9]+/g, '-')}`, name: 'Custom Filter', label: v });                }                if (type === 'all') {                   if (typeof trackElementInteraction === 'function') trackElementInteraction({ id: 'filter-clear-all', name: 'Clear all', label: 'Clear all filters' });                   // reset everything                   btns.forEach(btn => btn.classList.remove('active'));                   b.classList.add('active');                                      // Reset prices                   if (this.priceFilter) this.priceFilter.value = 'all';                   if (this.customPriceMin) this.customPriceMin.value = '';                   if (this.customPriceMax) this.customPriceMax.value = '';                   let dPr = r.pr || 'all';                   if (typeof dPr === 'string' && dPr !== 'all') {                      let prLower = dPr.toLowerCase();                      if (prLower.includes('min') || prLower.includes('over')) {                         let m = dPr.match(/(\d+)/);                         if (m && this.customPriceMin) this.customPriceMin.value = m[1];                      } else if (prLower.includes('max') || prLower.includes('under')) {                         let m = dPr.match(/(\d+)/);                         if (m && this.customPriceMax) this.customPriceMax.value = m[1];                      }                   }                                      let discountAmount = '0';                   if(r.ds && typeof r.ds === 'string') {                      let m = r.ds.match(/(\d+)/);                      if(m) discountAmount = m[1];                   }                   if (this.discountFilter) this.discountFilter.value = discountAmount;                   if (this.offerTypeSelect) this.offerTypeSelect.value = r.ot || '';                   if (this.retailerSelect) this.retailerSelect.value = r.rt || '';                   this.selectedBrands = [];                   if (this.brandDropdown) {                     const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                     chks.forEach(chk => chk.checked = false);                   }                } else {                   const v = b.getAttribute('data-v');                   const fL = v.toLowerCase();                                      let mapRet = ['amazon', 'walmart', 'best buy', 'target', 'john lewis', 'currys', 'argos'];                   const getCategory = (s) => {                      if (s === 'lightning deals' || s === 'amazon deals' || s === 'prime deals') return 'offer';                      if (s.includes('% off')) return 'discount';                      if (s.includes('under') || s.includes('over') || s.includes('min') || s.includes('max')) return 'price';                      if (mapRet.includes(s)) return 'retailer';                      return 'brand';                   };                   const cat = getCategory(fL);                   const wasActive = b.classList.contains('active');                   if (cat !== 'brand') {                      btns.forEach(btn => {                          if (btn === b) return;                          if (btn.getAttribute('data-type') === 'all') return;                          const bV = btn.getAttribute('data-v');                          if (!bV) return;                          if (getCategory(bV.toLowerCase()) === cat) btn.classList.remove('active');                      });                   }                   if (wasActive) b.classList.remove('active');                   else b.classList.add('active');                   let anyActive = Array.from(btns).some(btn => btn !== btns[0] && btn.classList.contains('active'));                   if (!anyActive) {                       btns[0].click();                       return;                   } else {                       btns[0].classList.remove('active');                   }                                      if (this.priceFilter) this.priceFilter.value = 'all';                   if (this.customPriceMin) this.customPriceMin.value = '';                   if (this.customPriceMax) this.customPriceMax.value = '';                   let dPr = r.pr || 'all';                   if (typeof dPr === 'string' && dPr !== 'all') {                      let prLower = dPr.toLowerCase();                      if (prLower.includes('min') || prLower.includes('over')) {                         let m = dPr.match(/(\d+)/);                         if (m && this.customPriceMin) this.customPriceMin.value = m[1];                      } else if (prLower.includes('max') || prLower.includes('under')) {                         let m = dPr.match(/(\d+)/);                         if (m && this.customPriceMax) this.customPriceMax.value = m[1];                      }                   }                                      let discountAmount = '0';                   if(r.ds && typeof r.ds === 'string') {                      let m = r.ds.match(/(\d+)/);                      if(m) discountAmount = m[1];                   }                   if (this.discountFilter) this.discountFilter.value = discountAmount;                   if (this.offerTypeSelect) this.offerTypeSelect.value = r.ot || '';                   if (this.retailerSelect) this.retailerSelect.value = r.rt || '';                   this.selectedBrands = [];                   btns.forEach(btn => {                       if (!btn.classList.contains('active') || btn.getAttribute('data-type') === 'all') return;                       const vv = btn.getAttribute('data-v');                       const vl = vv.toLowerCase();                                              if (vl === 'lightning deals') {                          if (this.offerTypeSelect) this.offerTypeSelect.value = 'amazon_lightning';                       } else if (vl === 'amazon deals' || vl === 'prime deals') {                          if (this.offerTypeSelect) this.offerTypeSelect.value = 'amazon_prime';                       } else if (vl.includes('% off')) {                          let m = vl.match(/(\d+)%/);                          if (m && this.discountFilter) this.discountFilter.value = m[1];                       } else if (vl.includes('under') || vl.includes('max')) {                          let m = vl.match(/(\d+)/);                          if (m && this.customPriceMax) this.customPriceMax.value = m[1];                       } else if (vl.includes('min') || vl.includes('over')) {                          let m = vl.match(/(\d+)/);                          if (m && this.customPriceMin) this.customPriceMin.value = m[1];                       } else {                          let foundR = mapRet.find(x => x === vl);                          if (foundR) {                             let realR = ['Amazon', 'Walmart', 'Best Buy', 'Target', 'John Lewis', 'Currys', 'Argos'].find(x => x.toLowerCase() === vl);                             if (this.retailerSelect) this.retailerSelect.value = realR;                          } else {                             this.selectedBrands.push(vv);                          }                       }                   });                                      if (this.brandDropdown) {                       const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                       chks.forEach(c => c.checked = this.selectedBrands.includes(c.value));                   }                                      if (r.pr && typeof r.pr === 'string') {                       let prL = r.pr.toLowerCase();                       if (prL.includes('under $')) {                           let m = prL.match(/under \$(\d+)/i);                           if (m && this.customPriceMax && !this.customPriceMax.value) this.customPriceMax.value = m[1];                       }                   }                }                                this.fetchDeals(this.currentQuery);             });           });                      // default to highlighting first           btns[0].classList.add('active');        }async fetchDeals(query, append = false) {          if (!append) {             this.showLoading();             this.deals = [];             this.displayLimit = this.getRowsLimit();          } else {             this.displayLimit += this.getRowsLimit();          }                    try {            if (this.getViewMode() === 'savings_squad') {               await this.fetchSavingsSquad(append);            } else {               if (this.isBroadQuery(query)) {                 await this.fetchAdviserDeals(query, append);               } else {                 await this.fetchHawkDeals(query, append);                 if (this.deals.length === 0) {                   await this.fetchAdviserDeals(query, append);                 }               }            }          } catch (error) {            console.warn("[Tom's Guide Widget] Fetch error:", error);            this.showError();          }        }        async fetchSavingsSquad() {          let topArticles = this.airedaleArticles;          if (!topArticles) {            const airedaleUrl = `https://airedale.futurecdn.net/feeds/feed_1776420579726.json?site=tomsguide&articleType=deals&limit=50`;            let res;            try {               res = await fetch(airedaleUrl);            } catch(e) {               try { res = await fetch(`https://airedale.futurecdn.net/feeds/feed_1776420579726.json?site=tomsguide&articleType=deals&limit=50`); } catch (err) { console.warn("Fallback fetch failed", err); return; }            }            if (!res.ok) throw new Error('Airedale API Error');            const articles = await res.json();            topArticles = Array.isArray(articles) ? articles.slice(0, 50) : ((articles.data && Array.isArray(articles.data)) ? articles.data.slice(0, 50) : []);            this.airedaleArticles = topArticles;                        let tagCounts = {};            topArticles.forEach((a) => {              let articleTags = new Set();              if (a.articlecategory && Array.isArray(a.articlecategory)) {                 a.articlecategory.forEach((t) => articleTags.add(t));              }              articleTags.forEach(t => {                 tagCounts[t] = (tagCounts[t] || 0) + 1;              });            });                        this.airedaleTags = Object.keys(tagCounts).sort((a, b) => tagCounts[b] - tagCounts[a]);            this.airedaleTagCounts = tagCounts;          }                    let targetArticles = topArticles;          if (this.activeDealTag) {             const cleanTag = this.activeDealTag.toLowerCase().replace(/&/g, '').replace(/[^a-z0-9]+/g, '-').replace(/-+/g, '-').replace(/^-|-$/g, '');             const encodedTag = encodeURIComponent(cleanTag);             const url = `https://airedale.futurecdn.net/feeds/feed_1776420579726.json?site=tomsguide&articleType=deals&limit=50&articleCategoryHandle=${encodedTag}`;             try {                const res = await fetch(url);                if (res.ok) {                   const articles = await res.json();                   targetArticles = Array.isArray(articles) ? articles.slice(0, 50) : ((articles.data && Array.isArray(articles.data)) ? articles.data.slice(0, 50) : []);                }             } catch(e) {                console.warn("Failed to fetch by activeDealTag", e);             }          }          let extractedDeals = [];          let dynamicBrandsCounts = {};                    targetArticles.forEach((article) => {             if (!article.articlepage) return;                          let pageData = [];             try {                pageData = JSON.parse(article.articlepage[0]);             } catch(e){ console.warn(e); }                          const savingsSquad = pageData.filter((p) => p.type === 'deal' || p.type === 'featured-product');                          savingsSquad.forEach((block, idx) => {                const data = block.data || {};                const isFeatured = block.type === 'featured-product';                                const link = data.link || {};                const priceObj = data.price || {};                const image = data.image || {};                                if (data.brand) {                   data.brand = data.brand.replace(/^\d+\.\s*/, '').trim();                   dynamicBrandsCounts[data.brand] = (dynamicBrandsCounts[data.brand] || 0) + 1;                }                const externalUrl = isFeatured ? data.url : (link.href || null);                let summaryTitle = isFeatured ? (data.name || data.brand) : (data.productName || link.label || article.articlename);                let description = isFeatured ? (data.strapline || '') : (data.text || '');                                if (!isFeatured && !data.productName && data.text) {                   const brSplit = data.text.split(new RegExp('\x3Cbr\\s*\\/?\\x3E', 'i'));                   if (brSplit.length > 1) {                     summaryTitle = brSplit[0].replace(/<[^>]+>/g, '').trim();                     description = brSplit.slice(1).join(' ').replace(/<br\s*\/?>/gi, ' ').replace(/<\/?(p|div)[^>]*>/gi, ' ').replace(/<[^>]+>/g, '').replace(/\s+/g, ' ').trim();                   } else {                     const match = data.text.match(/\x3Cstrong>(.*?)<\/strong>/);                     if (match) {                       summaryTitle = match[1].replace(/<[^>]+>/g, '').trim();                       if (summaryTitle.endsWith(':')) summaryTitle = summaryTitle.slice(0, -1);                     }                   }                }                                let imageUrl = isFeatured ? image.mos : (image.src || null);                if (imageUrl && imageUrl.startsWith('//')) imageUrl = 'https:' + imageUrl;                                description = description.replace(/<br\s*\/?>/gi, ' ').replace(/<\/?(p|div)[^>]*>/gi, ' ').replace(/<[^>]+>/g, '').replace(/\s+/g, ' ').replace(/View Deal$/i, '').trim();                                let merchantName = data.retailer || '';                if (!merchantName && externalUrl) {                   try {                     merchantName = new URL(externalUrl).hostname.replace('www.', '').split('.')[0];                     merchantName = merchantName.charAt(0).toUpperCase() + merchantName.slice(1);                   }catch(e){ console.warn(e); }                }                if (!merchantName) merchantName = 'Retailer';                const q = (this.currentQuery || '').toLowerCase();                const activeTagLogic = (this.activeDealTag || '').toLowerCase();                if (q.length > 2 && q !== activeTagLogic) {                   const searchTarget = `${summaryTitle || ''} ${description || ''}`.toLowerCase();                   if (!searchTarget.includes(q)) return;                }                let rawPrice = 0;                let rawMsrp = 0;                let currencyStr = '$';                if (isFeatured) {                   rawPrice = typeof data.salePrice === 'number' && data.salePrice > 0 ? data.salePrice : (typeof data.price === 'number' ? data.price : 0);                   rawMsrp = typeof data.salePrice === 'number' && typeof data.price === 'number' && data.price > data.salePrice ? data.price : 0;                   currencyStr = data.currency === 'GBP' ? '£' : '$';                } else {                   rawPrice = priceObj.amount ? parseFloat(priceObj.amount) : 0;                   rawMsrp = priceObj.amountWas ? parseFloat(priceObj.amountWas) : 0;                   currencyStr = priceObj.currency === 'GBP' ? '£' : '$';                }                                let savingAmt = 0;                let savingLabel = '';                if (rawPrice > 0 && rawMsrp > rawPrice) {                   savingAmt = parseFloat((rawMsrp - rawPrice).toFixed(2));                   savingLabel = `Save ${currencyStr}${savingAmt}`;                }                                // Apply Brand filter                if (this.selectedBrands && this.selectedBrands.length > 0) {                   const itemBrand = (data.brand || '').toLowerCase();                   const hasMatch = this.selectedBrands.some(sb => sb.toLowerCase() === itemBrand);                   if (!hasMatch) return;                }                // Apply Price filter                let priceFilterVal = null;                const min = this.customPriceMin ? this.customPriceMin.value : '';                const max = this.customPriceMax ? this.customPriceMax.value : '';                if (min || max) {                   priceFilterVal = `${min}_${max}`;                } else if (this.priceFilter && this.priceFilter.value !== 'all') {                   priceFilterVal = this.priceFilter.value;                }                if (priceFilterVal && rawPrice > 0) {                   if (priceFilterVal === 'under50' && rawPrice >= 50) return;                   if (priceFilterVal === 'over50' && rawPrice <= 50) return;                   if (priceFilterVal === 'over30' && rawPrice <= 30) return;                   if (priceFilterVal === 'over500' && rawPrice <= 500) return;                   if (priceFilterVal.includes('_')) {                      const parts = priceFilterVal.split('_');                      const min = parseFloat(parts[0]);                      const max = parseFloat(parts[1]);                      if (!isNaN(min) && rawPrice < min) return;                      if (!isNaN(max) && rawPrice > max) return;                   }                }                // Apply Discount filter                if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {                   const requiredDiscount = parseInt(this.discountFilter.value);                   if (!isNaN(requiredDiscount) && requiredDiscount > 0) {                      if (!rawMsrp || rawMsrp <= rawPrice) return;                      const ratio = Math.round((1 - (rawPrice / rawMsrp)) * 100);                      if (ratio < requiredDiscount) return;                   }                }                                extractedDeals.push({                   id: `airedale-${article.id || Math.random()}-${idx}`,                   url: externalUrl,                   image: imageUrl,                   fallbackImage: imageUrl,                   title: summaryTitle,                   brand: data.brand || '',                   productName: data.productName || '',                   merchant: merchantName,                   rawPrice: rawPrice,                   rawMsrp: rawMsrp,                   price: rawPrice > 0 ? rawPrice.toString() : '',                   msrp: rawMsrp > 0 ? rawMsrp.toString() : '',                   currency: currencyStr,                   isCheckPrice: !rawPrice,                   savingLabel: savingLabel,                   savingType: rawMsrp > rawPrice ? 'amount' : 'none',                   isPrime: false,                   starRating: null,                   description: description,                   text: data.text || ''                });             });          });                    const airedaleBrandsList = Object.keys(dynamicBrandsCounts).map(b => ({              formatted_value: b,              count: dynamicBrandsCounts[b]          })).sort((a,b) => b.count - a.count);                    if (this.getViewMode() === 'savings_squad') {             this.populateBrandDropdown(airedaleBrandsList.slice(0, 15));             if (this.brandFilterWrapper) {                if (airedaleBrandsList.length === 0) {                    this.brandFilterWrapper.style.display = 'none';                } else {                    this.brandFilterWrapper.style.display = 'flex';                }             }          }                    this.deals = extractedDeals;          this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        isBroadQuery(query) {          const q = query.toLowerCase();          const intentModifiers = ['deals', 'best', 'sale', 'under', 'cheap', 'offers', 'discount'];          return intentModifiers.some(term => q.includes(term));        }        async fetchHawkDeals(query, append = false) {          const url = new URL(this.apiUrl);          url.searchParams.append('model_name', query);          const areaCode = this.getAreaCode();          if (areaCode) {            url.searchParams.append('area', areaCode);          }                    if (append && this.deals.length > 0) {            url.searchParams.append('offset', this.deals.length.toString());          }                    if (this.retailerSelect && this.retailerSelect.value) {            url.searchParams.append('filter_merchant_name', this.retailerSelect.value);          }                    if (this.selectedBrands && this.selectedBrands.length > 0) {            url.searchParams.append('filter_label[text_brand]', this.selectedBrands.join(','));          }                    let priceVal = null;          const min = this.customPriceMin ? this.customPriceMin.value : '';          const max = this.customPriceMax ? this.customPriceMax.value : '';          if (min || max) {             priceVal = `${min}_${max}`;          } else if (this.priceFilter && this.priceFilter.value !== 'all') {             priceVal = this.priceFilter.value;          }          if (priceVal) {            if (priceVal === 'under50') {              url.searchParams.append('filter_max_price', '50');            } else if (priceVal === 'over50') {              url.searchParams.append('filter_min_price', '50');            } else if (priceVal === 'over30') {              url.searchParams.append('filter_min_price', '30');            } else if (priceVal === 'over500') {              url.searchParams.append('filter_min_price', '500');            } else if (priceVal.includes('_')) {              const parts = priceVal.split('_');              if (parts[0]) url.searchParams.append('filter_min_price', parts[0]);              if (parts[1]) url.searchParams.append('filter_max_price', parts[1]);            }          }                    if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {            const v = parseInt(this.discountFilter.value);            if (!isNaN(v) && v > 0) {              const ratio = (100 - v) / 100;              url.searchParams.append('min_discount_ratio', ratio.toString());            }          }                    if (this.offerTypeSelect && this.offerTypeSelect.value) {            url.searchParams.append('offer', this.offerTypeSelect.value);          }                    url.searchParams.append('filter_product_types', 'deals');                    url.searchParams.append('rows', this.getRowsLimit().toString());          let response;          try {             response = await fetch(url.toString());          } catch(e) {             if (window.location.protocol === 'file:') {                console.warn("[Tom's Guide Widget] fetch from file:// blocked by local CORS policy, falling back to Adviser mock.");                await this.fetchAdviserDeals(query);                return;             }             console.warn("Hawk fetch failed", e);             this.deals = [];             this.render();             return;          }          if (!response.ok) {            throw new Error('Hawk API Response Error');          }          const rawData = await response.json();          // Safely locate data array from potentially wrapped response          let offers = [];          let modelInfoArray = [];                    let brandFilterData = null;          if (rawData && rawData.widget && rawData.widget.data && Array.isArray(rawData.widget.data.filters)) {             brandFilterData = rawData.widget.data.filters.find(f => f.type === 'label_text_brand');          } else if (rawData && rawData.data && Array.isArray(rawData.data.filters)) {             brandFilterData = rawData.data.filters.find(f => f.type === 'label_text_brand');          }          if (brandFilterData && Array.isArray(brandFilterData.values) && brandFilterData.values.length > 0) {             this.populateBrandDropdown(brandFilterData.values);          } else {             if (this.brandFilterWrapper && this.selectedBrands.length === 0) {                this.brandFilterWrapper.style.display = 'none';             }          }                    if (rawData && rawData.widget && rawData.widget.data) {            if (Array.isArray(rawData.widget.data.offers)) offers = rawData.widget.data.offers;            if (rawData.widget.data.model_info && typeof rawData.widget.data.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.widget.data.model_info) ? rawData.widget.data.model_info : Object.values(rawData.widget.data.model_info);            }          } else if (rawData && rawData.data) {            if (Array.isArray(rawData.data.offers)) offers = rawData.data.offers;            if (rawData.data.model_info && typeof rawData.data.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.data.model_info) ? rawData.data.model_info : Object.values(rawData.data.model_info);            }          } else {            if (Array.isArray(rawData)) offers = rawData;            else if (rawData && Array.isArray(rawData.offers)) offers = rawData.offers;            else if (rawData && rawData.offers && Array.isArray(rawData.offers.offer)) offers = rawData.offers.offer;            else if (rawData && rawData.offers) offers = [].concat(rawData.offers);                        if (rawData && rawData.model_info && typeof rawData.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.model_info) ? rawData.model_info : Object.values(rawData.model_info);            }          }          let modelDetails = {};          modelInfoArray.forEach(m => {            const mId = m.model_id || m.id;            if (mId) {              modelDetails[mId] = {                score: m.score != null ? parseFloat(m.score) : null,                brand: m.brand || null,                parent: (m.parents && Array.isArray(m.parents) && m.parents.length > 0) ? m.parents[0].name : null              };            }          });          offers.forEach(item => {            let data = { ...item };            const mId = data.model_id;            if (mId && modelDetails[mId]) {              data.review_score = modelDetails[mId].score;              data.model_brand = modelDetails[mId].brand;              data.model_parent = modelDetails[mId].parent;            } else {              data.review_score = null;            }                        let itemOffers = [];            if (Array.isArray(item.offers)) itemOffers = item.offers;            else if (Array.isArray(item.offer)) itemOffers = item.offer;            else if (item.offers && typeof item.offers === 'object') itemOffers = [item.offers];            else if (item.offer && typeof item.offer === 'object') itemOffers = [item.offer];            if (itemOffers.length > 0) {              itemOffers.forEach(subItem => {                let subData = { ...item, ...subItem };                const subId = subData.model_id;                if (subId && modelDetails[subId]) {                  subData.review_score = modelDetails[subId].score;                  subData.model_brand = modelDetails[subId].brand;                  subData.model_parent = modelDetails[subId].parent;                } else if (data.review_score != null) {                  subData.review_score = data.review_score;                }                if (subData.merchant && typeof subData.merchant === 'object') {                  subData.merchant_name = subData.merchant.name;                }                this.deals.push(this.extractDealData(subData));              });              return;            }                        if (item.merchant && typeof item.merchant === 'object') {              data.merchant_name = item.merchant.name;            }                        this.deals.push(this.extractDealData(data));          });                    this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        async fetchAdviserDeals(query) {          // ======================================================================          // TODO: ADVISER API REPLACEMENT          // The code below simulates the Adviser API response using mock data.          // Once the real endpoint is ready, remove getAdviserMockData() and           // perform an actual fetch() request similar to fetchHawkDeals().          // Example:          // const area = this.getAreaCode();          // let apiUrl = `https://your-adviser-api.com/search?q=${query}&area=${area}`;          // if (this.priceFilter && this.priceFilter.value !== 'all') {          //   const val = this.priceFilter.value;          //   if (val === 'under50') apiUrl += '&filter_max_price=50';          //   else if (val === '50_100') apiUrl += '&filter_max_price=100';          //   else if (val === '100_200') apiUrl += '&filter_max_price=200';          //   else if (val === '200_500') apiUrl += '&filter_max_price=500';          // }          // const res = await fetch(apiUrl);          // const rawData = await res.json();          // ======================================================================          // Simulating network latency          await new Promise(resolve => setTimeout(resolve, 400));                    const rawData = this.getAdviserMockData();          let offers = [];                    if (rawData && rawData.data && rawData.data.Get && Array.isArray(rawData.data.Get.Deal)) {            offers = rawData.data.Get.Deal;          }                    // Basic client-side filtering for the mock if we want it to react to the query          const q = query.toLowerCase();          const selectedRetailer = (this.retailerSelect && this.retailerSelect.value) ? this.retailerSelect.value.toLowerCase() : null;                    offers.forEach(item => {            const dataObj = item;                        // Apply retailer filter            const itemRetailer = (dataObj.dataRetailer || '').toLowerCase();            if (selectedRetailer && itemRetailer !== selectedRetailer && !itemRetailer.includes(selectedRetailer)) {              return;            }                        // Apply mock price filter            let price = dataObj.dataDiscountedPrice || 0;            if (typeof price === 'string') {              price = parseFloat(price.replace(/[^0-9.]/g, ''));            }            let priceVal = null;            const min = this.customPriceMin ? this.customPriceMin.value : '';            const max = this.customPriceMax ? this.customPriceMax.value : '';            if (min || max) {               priceVal = `${min}_${max}`;            } else if (this.priceFilter && this.priceFilter.value !== 'all') {               priceVal = this.priceFilter.value;            }            if (priceVal) {              if (priceVal === 'under50' && price >= 50) return;              if (priceVal === 'over50' && price <= 50) return;              if (priceVal === 'over30' && price <= 30) return;              if (priceVal === 'over500' && price <= 500) return;              if (priceVal.includes('_')) {                 const parts = priceVal.split('_');                 if (parts[0] && price < parseFloat(parts[0])) return;                 if (parts[1] && price > parseFloat(parts[1])) return;              }            }                        // Map Adviser schema to our widget's expected schema            const mappedData = {              url: dataObj.linkHREF || dataObj.dataLink || '#',              image: dataObj.imageURL || (dataObj.image && dataObj.image.src) || '',              title: dataObj.dataProduct || (dataObj.product && dataObj.product.name) || 'Product Deal',              merchant: dataObj.dataRetailer || 'Retailer',              price: dataObj.dataDiscountedPrice || 0,              currency: dataObj.dataCurrency === 'USD' ? '$' : (dataObj.dataCurrency || '$'),              msrp: dataObj.dataOriginalPrice || null            };                        const titleLow = mappedData.title.toLowerCase();            const merchLow = mappedData.merchant.toLowerCase();                        // Smarter mock filtering            let isMatch = false;            if (q === '' || this.isBroadQuery(q)) {              isMatch = true;            } else if (titleLow.includes(q) || merchLow.includes(q)) {              isMatch = true;            } else if ((q.includes('laptop') || q.includes('mac') || q.includes('pc')) && (titleLow.includes('macbook') || titleLow.includes('laptop'))) {              isMatch = true;            } else if ((q.includes('tv') || q.includes('television')) && (titleLow.includes('tv') || titleLow.includes('oled') || titleLow.includes('qled'))) {              isMatch = true;            } else if ((q.includes('phone') || q.includes('smartphone')) && (titleLow.includes('galaxy') || titleLow.includes('phone'))) {              isMatch = true;            } else if ((q.match(/watch|fitness|run|shoe/)) && (titleLow.includes('forerunner') || titleLow.includes('saucony') || titleLow.includes('watch'))) {              isMatch = true;            }                        if (isMatch) {               this.deals.push(this.extractDealData(mappedData));            }          });                    let rowLimit = this.getRowsLimit();          // Intentionally omitting the slice here to allow "Load More" to work if the API returns more                    this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        getAdviserMockData() {          return {            "data": {              "Get": {                "Deal": [                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 300,                    "dataOriginalPrice": 399,                    "dataProduct": "Samsung Galaxy A36",                    "dataRetailer": "Samsung",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/MqDYsukV3JBG54te6dEs7j.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 14,                    "dataOriginalPrice": 24,                    "dataProduct": "Blink Mini",                    "dataRetailer": "Amazon",                    "imageURL": "http://cdn.mos.cms.futurecdn.net/3JurmAjHsDa5tPdaHAwEV8.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 59,                    "dataOriginalPrice": 99,                    "dataProduct": "Ring Video Doorbell",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/rAh4uR7AsAsALCCLTXnLNJ.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 10,                    "dataOriginalPrice": 599,                    "dataProduct": "MacBook Neo",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/Lg4Dvg68j9SbB5CPNrTEpH.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 749,                    "dataOriginalPrice": 849,                    "dataProduct": "65\\\" Fire TV Omni 4K QLED TV",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/SG34ZWodUkLTxJvMTbjPYR.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 71,                    "dataOriginalPrice": 160,                    "dataProduct": "Saucony Hurricane 24",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/vxf7UD5T2Am7guVzFoFcZ4.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 649,                    "dataOriginalPrice": 749,                    "dataProduct": "Garmin Forerunner 970",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/3GKnEu7CdhtxPMfnPCMCiA.png"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 1049,                    "dataOriginalPrice": 1499,                    "dataProduct": "LG 48\\\" C4 4K OLED TV",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/imvwZV9zoMD6fn9Afuge35.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 1499,                    "dataOriginalPrice": 2199,                    "dataProduct": "Samsung 49\\\" Odyssey Neo G9 4K Gaming Monitor",                    "dataRetailer": "Amazon",                    "imageURL": "http://cdn.mos.cms.futurecdn.net/XWDEJ5dUAE2nhK8k3Jk7k7.png"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 299,                    "dataOriginalPrice": 699,                    "dataProduct": "EGOHOME Black Memory Foam Mattress (queen)",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/hMUemtAejNETLVYxNrktzm.jpg"                  }                ]              }            }          };        }        decodeHTML(html) {          if (!html) return '';          const txt = document.createElement("textarea");          txt.innerHTML = String(html);          return txt.value;        }        extractDealData(item) {          const priceRawStr = String(item.price || item.current_price || '0');          const msrpRawStr = String(item.was_price || item.msrp || item.original_price || '0');          const rawPrice = parseFloat(priceRawStr.replace(/[^\d.]/g, '')) || 0;          const rawMsrp = parseFloat(msrpRawStr.replace(/[^\d.]/g, '')) || 0;          const isCheckPrice = rawPrice === 0 || priceRawStr === '0.00' || priceRawStr === '0';                    let originalImageUrl = item.image || item.image_url || item.product_image || '';          let imageUrl = originalImageUrl;          if ((!imageUrl || isCheckPrice) && item.model_image_url) {             imageUrl = item.model_image_url;             originalImageUrl = imageUrl;          } else if ((!imageUrl || isCheckPrice) && item.model_image) {             imageUrl = item.model_image;             originalImageUrl = imageUrl;          }                    if (imageUrl) {            imageUrl = imageUrl.replace(/-(\d+)-(\d+)(\.[a-z.]+)$/i, '$3');          }                    let fallbackImage = '';          if (originalImageUrl && originalImageUrl !== imageUrl) {             fallbackImage = originalImageUrl;          } else if (item.model_image && item.model_image !== imageUrl) {             fallbackImage = item.model_image;          } else if (item.model_image_url && item.model_image_url !== imageUrl) {             fallbackImage = item.model_image_url;          }                    const rawCurrency = item.currency || item.currency_symbol || '$';                    let savingLabel = item.percentage_saving_label || '';          if (!savingLabel && rawMsrp > rawPrice && rawPrice > 0) {            const pct = Math.round(((rawMsrp - rawPrice) / rawMsrp) * 100);            if (pct > 0) {              savingLabel = `${pct}% OFF`;            }          }                    const isPrime = item.shipping && item.shipping.prime === true;                    let scoreRaw = (item.review_score !== undefined && item.review_score !== null && item.review_score > 0) ? parseFloat(item.review_score) : null;          let starRating = 0;          if (scoreRaw !== null) {            starRating = Math.round((scoreRaw > 10 ? scoreRaw / 20 : scoreRaw / 2) * 2) / 2;          }                    return {            id: item.offer_id || item.link || item.url || item.offer_link || Math.random().toString(),            url: item.link || item.url || item.offer_link || '#',            image: imageUrl,            fallbackImage: fallbackImage,            title: item.name || item.title || item.model_name || item.product_name || 'Unknown Product',            brand: item.brand || '',            productName: item.model_name || item.product_name || item.name || '',            merchant: item.merchant_name || item.merchant || item.retailer || 'Retailer',            price: item.price !== undefined ? String(item.price) : '0.00',            currency: this.decodeHTML(rawCurrency),            msrp: item.was_price || item.msrp || item.original_price || null,            rawPrice: rawPrice,            rawMsrp: rawMsrp,            hasWasPrice: (item.was_price !== undefined && item.was_price !== null),            isCheckPrice: isCheckPrice,            savingLabel: savingLabel,            isPrime: isPrime,            starRating: starRating > 0 ? starRating : null,            modelId: item.model_id || '',            productKey: item.product_key || '',            merchantId: (item.merchant && typeof item.merchant === 'object') ? item.merchant.id || '' : '',            matchId: item.match_id || '',            merchantNetwork: (item.merchant && typeof item.merchant === 'object') ? item.merchant.an || '' : '',            merchantUrl: (item.merchant && typeof item.merchant === 'object') ? item.merchant.url || '' : '',            modelBrand: item.model_brand || item.brand || '',            modelParent: item.model_parent || ''          };        }        sortData() {          const sortVal = this.sortSelect ? this.sortSelect.value : (this.getViewMode() === 'savings_squad' ? 'date_desc' : 'discount_desc');          if (sortVal === 'price_asc') {            this.deals.sort((a, b) => a.rawPrice - b.rawPrice);          } else if (sortVal === 'price_desc') {            this.deals.sort((a, b) => b.rawPrice - a.rawPrice);          } else if (sortVal === 'discount_desc') {            this.deals.sort((a, b) => {              const aDiscount = a.rawMsrp > a.rawPrice ? (a.rawMsrp - a.rawPrice) : 0;              const bDiscount = b.rawMsrp > b.rawPrice ? (b.rawMsrp - b.rawPrice) : 0;              return bDiscount - aDiscount;            });          } else if (sortVal === 'date_desc') {             this.deals.sort((a, b) => {                let dateA = 0;                let dateB = 0;                if (a && a.modifiedDate) {                   const valA = Array.isArray(a.modifiedDate) ? a.modifiedDate[0] : a.modifiedDate;                   dateA = new Date(valA).getTime();                   if (isNaN(dateA)) dateA = 0;                }                if (b && b.modifiedDate) {                   const valB = Array.isArray(b.modifiedDate) ? b.modifiedDate[0] : b.modifiedDate;                   dateB = new Date(valB).getTime();                   if (isNaN(dateB)) dateB = 0;                }                return dateB - dateA;             });          }        }        getFilteredDeals() {          let filteredDeals = [...this.deals];                    if (this.dealModeToggle && this.dealModeToggle.checked) {            filteredDeals = filteredDeals.filter(d => d.hasWasPrice || (d.msrp && d.rawMsrp > d.rawPrice));          }                    return filteredDeals;        }        showLoading() {          const _div = '<' + '/div>';          const skeletonCardHtml = `            \x3Cdiv class="tg-df-card">              \x3Cdiv class="tg-df-card-image-box">                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-img">${_div}              ${_div}              \x3Cdiv class="tg-df-card-body">                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short">${_div}                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text title">${_div}                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text title">${_div}                \x3Cdiv class="tg-df-card-footer mt-auto">                  \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="height:24px;">${_div}                  \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text" style="height:44px; margin-top:8px;">${_div}                ${_div}              ${_div}            ${_div}`;          this.grid.innerHTML = Array(4).fill(skeletonCardHtml).join('');        }        showError() {          const _div = '<' + '/div>';          this.grid.innerHTML = `\x3Cdiv class="tg-df-message">            An error occurred while finding deals. Please check your connection and try again.          ${_div}`;        }        escapeHTML(str) {          if (!str) return '';          return String(str).replace(/[&<>'"]/g, tag => ({              '&': '&', '<': '<', '>': '>', "'": ''', '"': '"'          }[tag] || tag));        }                bindCouponButtons() {          const btns = this.root.querySelectorAll('.tg-df-tag-coupons');          btns.forEach(btn => {            btn.addEventListener('click', (e) => {              e.preventDefault();              e.stopPropagation();              const merchant = btn.getAttribute('data-merchant');              this.openVouchersModal(merchant);            });          });                    const closeBtn = this.root.querySelector('#tg-df-vouchers-close');          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          if (closeBtn) {            closeBtn.onclick = () => this.closeVouchersModal();          }          if (backdrop) {            backdrop.onclick = (e) => {              if (e.target === backdrop) this.closeVouchersModal();            };          }        }                closeVouchersModal() {          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          if (backdrop) backdrop.classList.remove('active');        }                async checkMerchantsCouponsBulk(merchants) {          if (!merchants || merchants.length === 0) return {};          const controller = new AbortController();          const timeoutId = setTimeout(() => controller.abort(), 4000);          try {            const area = this.getAreaCode();            const url = new URL('https://search-api.fie.future.net.uk/widget.php');            url.searchParams.append('model_name', 'Everything');            url.searchParams.append('language', 'en-GB');            if (area) url.searchParams.append('area', area);            url.searchParams.append('combine_product_types', '1');            url.searchParams.append('filter_merchant_name', merchants.join(','));            url.searchParams.append('all_filters', 'false');            url.searchParams.append('exclude_unlabelled', 'false');            url.searchParams.append('include_specs', 'false');            url.searchParams.append('sort', 'voucher');            url.searchParams.append('distinct_merchants', 'natural');            url.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');            url.searchParams.append('rows', '120');            url.searchParams.append('origin', 'widgets-clientside');                        let res; try { res = await fetch(url.toString(), { signal: controller.signal }); } catch (e) { return {}; }            clearTimeout(timeoutId);            if (!res.ok) return {};            const data = await res.json();                        let offers = [];            if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {              offers = data.widget.data.offers;            } else if (data && data.data && Array.isArray(data.data.offers)) {              offers = data.data.offers;            } else if (Array.isArray(data)) {              offers = data;            } else if (data && Array.isArray(data.offers)) {              offers = data.offers;            } else if (data && data.offers && Array.isArray(data.offers.offer)) {              offers = data.offers.offer;            } else if (data && Array.isArray(data.data)) {              offers = data.data;            }                        const foundMerchants = new Set();            offers.forEach(o => {              let mName = o.merchant_name || o.merchant || o.retailer;              if (mName && typeof mName === 'object') mName = mName.name;              if (mName) foundMerchants.add(String(mName).toLowerCase());            });            const resultMap = {};            merchants.forEach(m => {              if (m) resultMap[m] = foundMerchants.has(String(m).toLowerCase());            });            return resultMap;          } catch (e) {            return {};          }        }                async openVouchersModal(merchantName) {          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          const title = this.root.querySelector('#tg-df-vouchers-title');          const content = this.root.querySelector('#tg-df-vouchers-content');                    if (!backdrop || !content) return;                    // HACK: Hide closing tags          const _div = '<' + '/div>';          const _span = '<' + '/span>';          const _a = '<' + '/a>';          const _h4 = '<' + '/h4>';          const _svg = '<' + '/svg>';          const _circle = '<' + '/circle>';          const _polyline = '<' + '/polyline>';          const _rect = '<' + '/rect>';          const _path = '<' + '/path>';                    title.innerText = `${merchantName} Coupons & Deals`;          content.innerHTML = `\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text">${_div}                               \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text">${_div}`;          backdrop.classList.add('active');                    try {            const area = this.getAreaCode();            const url = new URL('https://search-api.fie.future.net.uk/widget.php');            url.searchParams.append('model_name', 'Everything');            url.searchParams.append('language', 'en-GB');            if (area) url.searchParams.append('area', area);            url.searchParams.append('combine_product_types', '1');            url.searchParams.append('filter_merchant_name', merchantName);            url.searchParams.append('all_filters', 'false');            url.searchParams.append('exclude_unlabelled', 'false');            url.searchParams.append('include_specs', 'false');            url.searchParams.append('sort', 'voucher');            url.searchParams.append('distinct_merchants', 'natural');            url.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');            url.searchParams.append('rows', '50');            url.searchParams.append('origin', 'widgets-clientside');                        const res = await fetch(url.toString());            if (!res.ok) throw new Error('API Error');            const data = await res.json();                        let offers = [];            if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {              offers = data.widget.data.offers;            } else if (data && data.data && Array.isArray(data.data.offers)) {              offers = data.data.offers;            } else if (Array.isArray(data)) {              offers = data;            } else if (data && Array.isArray(data.offers)) {              offers = data.offers;            } else if (data && data.offers && Array.isArray(data.offers.offer)) {              offers = data.offers.offer;            } else if (data && Array.isArray(data.data)) {              offers = data.data;            }                        if (offers.length === 0) {              content.innerHTML = `\x3Cdiv class="tg-df-message">No vouchers currently available for ${this.escapeHTML(merchantName)}.${_div}`;              return;            }                        content.innerHTML = offers.map((v, idx) => {              let offerObj = v;              if (v.offers && v.offers.offer) {                offerObj = Array.isArray(v.offers.offer) ? v.offers.offer[0] : v.offers.offer;              } else if (v.offer) {                offerObj = Array.isArray(v.offer) ? v.offer[0] : v.offer;              }              let logoUrl = v.logo_url || offerObj.logo_url || '';              if (!logoUrl && v.merchant) {                if (Array.isArray(v.merchant) && v.merchant.length > 0) logoUrl = v.merchant[0].logo_url || '';                else logoUrl = v.merchant.logo_url || '';              }                            const offerName = offerObj.name || offerObj.title || v.name || v.title || 'Special Offer';              const endTime = offerObj.end_time || v.end_time || '';              const linkUrl = offerObj.link || offerObj.url || v.link || v.url || '#';                            let foundVoucherCode = '';              const findVoucherCode = (obj) => {                if (!obj || typeof obj !== 'object') return;                if (obj.type === 'voucher_code' && obj.display_value) {                  foundVoucherCode = obj.display_value;                  return;                }                if (Array.isArray(obj)) {                  for (const item of obj) {                    findVoucherCode(item);                    if (foundVoucherCode) return;                  }                } else {                  for (const k in obj) {                    if (Object.prototype.hasOwnProperty.call(obj, k)) {                      findVoucherCode(obj[k]);                      if (foundVoucherCode) return;                    }                  }                }              };              findVoucherCode(offerObj);              if (!foundVoucherCode) findVoucherCode(v);                            const voucherCode = foundVoucherCode || offerObj.voucher_code || v.voucher_code || '';              const codeHtml = voucherCode ? `\x3Cspan class="tg-df-voucher-code" data-action="copy-code" data-code="${this.escapeHTML(voucherCode)}" title="Copy to clipboard">                \x3Cspan class="tg-df-voucher-code-text">${this.escapeHTML(voucherCode)}${_span}                \x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-left:6px;flex-shrink:0;" class="tg-df-voucher-copy-icon">                  \x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2">${_rect}                  \x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1">${_path}                ${_svg}              ${_span}` : '';                            const logoHtml = logoUrl                 ? `\x3Cimg src="${this.escapeHTML(logoUrl)}" alt="${this.escapeHTML(offerName)}" class="tg-df-voucher-logo" />`                 : `\x3Cdiv class="tg-df-voucher-logo" style="background:#e2e8f0;">${_div}`;                            let expiryHtml = '';              if (endTime) {                let dStr = endTime;                if (!isNaN(dStr) && String(dStr).length === 10) dStr = Number(dStr) * 1000;                const d = new Date(dStr);                if (!isNaN(d.getTime())) {                  const options = { year: 'numeric', month: 'short', day: 'numeric' };                  expiryHtml = `                    \x3Cdiv class="tg-df-voucher-expiry">                      \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">                        \x3Ccircle cx="12" cy="12" r="10">${_circle}                        \x3Cpolyline points="12 6 12 12 16 14">${_polyline}                      ${_svg}                      Expires ${d.toLocaleDateString(undefined, options)}                    ${_div}`;                }              }              const revenueIdVal = generateRevenueId(linkUrl, offerName, merchantName, null);              const rewrittenLinkUrl = rewriteAffiliateLink(linkUrl, area, revenueIdVal);              return `                \x3Ca href="${this.escapeHTML(rewrittenLinkUrl)}" target="_blank" rel="noopener nofollow" class="tg-df-voucher-item"                  data-action="voucher-click"                  data-product-name="${this.escapeHTML(offerName)}"                  data-merchant-name="${this.escapeHTML(merchantName)}"                  data-analytics-id="${this.escapeHTML(offerObj.offer_id || offerObj.id || v.id || '')}"                  data-price=""                  data-previous-price=""                  data-original-link="${this.escapeHTML(linkUrl)}"                  data-revenue-id="${revenueIdVal}"                  data-index="${idx}"                  data-total="${offers.length}"                  data-in-stock="true"                  data-currency="USD"                  data-model-id="${this.escapeHTML(offerObj.model_id || v.model_id || offerObj.id || v.id || '')}"                  data-merchant-id="${this.escapeHTML(offerObj.merchant_id || offerObj.merchant?.id || '')}"                >                  ${logoHtml}                  \x3Cdiv class="tg-df-voucher-content">                    \x3Ch4 class="tg-df-voucher-title">${this.escapeHTML(offerName)}${_h4}                    ${codeHtml}                    ${expiryHtml}                  ${_div}                ${_a}              `;            }).join('');                        // Attach copy functionality            const copyBtns = content.querySelectorAll('[data-action="copy-code"]');            copyBtns.forEach(btn => {              btn.addEventListener('click', async (e) => {                e.preventDefault();                e.stopPropagation();                                const code = btn.getAttribute('data-code');                if (!code) return;                                try {                  const copyToClipboard = async (text) => {                     if (window.navigator.clipboard && window.isSecureContext) {                        try { await window.navigator.clipboard.writeText(text); return; } catch (e) {}                     }                     const textArea = document.createElement("textarea");                     textArea.value = text;                     textArea.style.position = "fixed";                     document.body.appendChild(textArea);                     textArea.focus();                     textArea.select();                     document.execCommand('copy');                     textArea.remove();                  };                  await copyToClipboard(code);                                    // Visual feedback                  btn.classList.add('copied');                  const textSpan = btn.querySelector('.tg-df-voucher-code-text');                  const iconSvg = btn.querySelector('.tg-df-voucher-copy-icon');                                    const origText = textSpan.innerText;                  const origIcon = iconSvg.innerHTML;                                    textSpan.innerText = 'Copied!';                  iconSvg.innerHTML = `\x3Cpolyline points="20 6 9 17 4 12">${_polyline}`;                                    setTimeout(() => {                    if (btn) {                      btn.classList.remove('copied');                      if (textSpan) textSpan.innerText = origText;                      if (iconSvg) iconSvg.innerHTML = origIcon;                    }                  }, 2000);                                    trackElementInteraction({                    id: 'voucher-code-copy',                    name: 'Copy Voucher Code',                    label: `Copied ${code} for ${merchantName}`                  });                } catch (err) {                  console.warn('Failed to copy text: ', err);                }              });            });            // Attach voucher click tracking            const voucherBtns = content.querySelectorAll('[data-action="voucher-click"]');            voucherBtns.forEach(btn => {              btn.addEventListener('click', (e) => {                if (e.target.closest('[data-action="copy-code"]')) return;                                const productName = btn.getAttribute('data-product-name');                const merchantNameAttr = btn.getAttribute('data-merchant-name');                const productId = btn.getAttribute('data-analytics-id');                const price = parseFloat(btn.getAttribute('data-price')) || null;                const prevPriceStr = btn.getAttribute('data-previous-price');                const previousPrice = prevPriceStr ? parseFloat(prevPriceStr) : null;                const originalLink = btn.getAttribute('data-original-link');                const rewrittenLink = btn.getAttribute('href');                const revenueId = btn.getAttribute('data-revenue-id');                const index = parseInt(btn.getAttribute('data-index'), 10) || 0;                const inStock = btn.getAttribute('data-in-stock') === 'true';                const totalText = btn.getAttribute('data-total');                const totalDeals = parseInt(totalText, 10) || 0;                const productCategoryName = 'deals';                const trackingParams = {                  widgetId: this.widgetId,                  productCategoryName: productCategoryName,                  product: {                    modelId: btn.getAttribute('data-model-id') || null,                    matchId: btn.getAttribute('data-match-id') || null,                    brand: btn.getAttribute('data-model-brand') || null,                    parent: btn.getAttribute('data-model-parent') || null,                    name: productName,                    price: price,                    previousPrice: previousPrice,                    link: rewrittenLink,                    originalLink: originalLink,                    inStock: inStock                  },                  zeroBasedProductIndexOrNull: index,                  totalDealsOrProducts: totalDeals,                   merchant: {                    id: btn.getAttribute('data-merchant-id') || null,                    network: btn.getAttribute('data-merchant-network') || null,                    url: btn.getAttribute('data-merchant-url') || null,                    name: merchantNameAttr                  },                  revenueId: revenueId,                  widgetTypeName: this.widgetTypeName,                  isoCurrencyCode: btn.getAttribute('data-currency') || 'USD'                };                if (typeof trackDealClick === 'function') {                  trackDealClick(trackingParams);                }              });            });                                  } catch (e) {            console.warn(e);            content.innerHTML = `\x3Cdiv class="tg-df-message">Failed to load vouchers.${_div}`;          }        }        render() {          try {            if (this.getViewMode() === 'savings_squad' && this.airedaleTags.length > 0) {              if (this.categoryFilterWrapper) {                 this.categoryFilterWrapper.style.display = 'flex';              }              if (this.categoryFilter) {                 const _option = '<' + '/option>';                 let optionsHtml = `\x3Coption value="all">All Categories${_option}`;                 this.airedaleTags.forEach(tag => {                    const isSelected = this.activeDealTag === tag ? 'selected' : '';                    optionsHtml += `\x3Coption value="${this.escapeHTML(tag)}" ${isSelected}>${this.escapeHTML(tag)} (${this.airedaleTagCounts[tag] || 0})${_option}`;                 });                 this.categoryFilter.innerHTML = optionsHtml;                 this.categoryFilter.value = this.activeDealTag || 'all';              }            } else {               if (this.categoryFilterWrapper) {                  this.categoryFilterWrapper.style.display = 'none';               }            }            const displayDeals = this.getFilteredDeals();          // HACK: Hide closing tags from the CMS HTML sanitizer so it doesn't strip them during in-page injection          const _div = '<' + '/div>';          const _span = '<' + '/span>';          const _a = '<' + '/a>';          const _h3 = '<' + '/h3>';          const _p = '<' + '/p>';          const _strong = '<' + '/strong>';          const _sup = '<' + '/sup>';          const _button = '<' + '/button>';          if (displayDeals.length === 0) {            if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {              if (this.deals.length > 0) {                 this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                  No deals match your selected filters.                ${_div}`;              } else if (this.getViewMode() === 'savings_squad' && this.currentQuery.length <= 2) {                 // Do not show "no exact matches" if query is empty for savings_squad                 this.grid.innerHTML = '';              } else {                 this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                  No exact matches found for "\x3Cstrong>${this.escapeHTML(this.currentQuery)}${_strong}". Try adjusting your search term.                ${_div}`;              }            } else {              this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                Search product or category names to discover the best deals from across the web.              ${_div}`;            }            return;          }          let dealsHtml = displayDeals.slice(0, this.displayLimit).map((deal, index) => {            try {               const currencySym = this.escapeHTML(deal.currency);               const isoCurrencyCode = normalizeCurrency(currencySym);               const escapedPrice = this.escapeHTML(deal.price);               const escapedMsrp = this.escapeHTML(deal.msrp);               const areaCode = this.getAreaCode();                              const revenueId = generateRevenueId(deal.url, deal.title, deal.merchant, null);               const originalLink = deal.url;               const rewrittenLink = rewriteAffiliateLink(deal.url, areaCode, revenueId);                        const productCategoryName = 'deals';            const dataAttr = `              data-action="${deal.isCheckPrice ? 'view-similar-click' : 'deal-click'}"              data-analytics-id="${this.escapeHTML(deal.externalProductId || deal.id || '')}"              data-product-name="${this.escapeHTML(deal.title)}"              data-merchant-name="${this.escapeHTML(deal.merchant)}"              data-price="${deal.rawPrice || ''}"              data-previous-price="${deal.rawMsrp || ''}"              data-original-link="${this.escapeHTML(originalLink)}"              data-revenue-id="${revenueId}"              data-index="${index}"              data-total="${displayDeals.length}"              data-in-stock="${deal.inStock !== false}"              data-currency="${this.escapeHTML(isoCurrencyCode)}"              data-model-id="${this.escapeHTML(deal.modelId || '')}"              data-product-key="${this.escapeHTML(deal.productKey || '')}"              data-merchant-id="${this.escapeHTML(deal.merchantId || '')}"            `;                        let priceGroupHtml = '';            let isSavingsSquadMode = this.getViewMode() === 'savings_squad';            let ctaText = 'View Deal';            let formattedPrice = '';            let msrpHtml = '';                        if (deal.isCheckPrice) {              ctaText = isSavingsSquadMode ? 'View Deal' : 'Check Price';              if (isSavingsSquadMode) {                priceGroupHtml = `                  \x3Cdiv class="tg-df-card-merchant-wrapper">                    \x3Cspan class="tg-df-card-merchant-pill" title="${this.escapeHTML(deal.merchant)}">${this.escapeHTML(deal.merchant)}${_span}                  ${_div}                  \x3Cdiv class="tg-df-card-price-group">                  ${_div}                `;              } else {                priceGroupHtml = `                  \x3Cdiv class="tg-df-card-merchant-wrapper">                    \x3Cspan class="tg-df-card-merchant-pill" title="${this.escapeHTML(deal.merchant)}">${this.escapeHTML(deal.merchant)}${_span}                  ${_div}                  \x3Cdiv class="tg-df-card-price-group">                    \x3Cspan class="tg-df-card-price" style="font-size: 15px; font-weight: 500; font-style: italic;">See price at retailer${_span}                  ${_div}                `;              }            } else {              // Format Price              formattedPrice = escapedPrice.includes(currencySym)                 ? escapedPrice                 : `${currencySym}${escapedPrice}`;                              // Format MSRP              msrpHtml = deal.msrp && deal.rawMsrp > deal.rawPrice                ? `\x3Cspan class="tg-df-card-msrp">${escapedMsrp.includes(currencySym) ? escapedMsrp : currencySym + escapedMsrp}${_span}`                : '';                              priceGroupHtml = `                \x3Cdiv class="tg-df-card-merchant-wrapper">                  \x3Cspan class="tg-df-card-merchant-pill" title="${this.escapeHTML(deal.merchant)}">${this.escapeHTML(deal.merchant)}${_span}                ${_div}                \x3Cdiv class="tg-df-card-price-group">                  ${isSavingsSquadMode ? '' : `                  \x3Cspan class="tg-df-card-price">${formattedPrice}${_span}                  ${msrpHtml}                  `}                ${_div}              `;            }                        const discountBadgeHtml = deal.savingLabel && !deal.isCheckPrice              ? `\x3Cspan class="tg-df-card-discount-badge">${this.escapeHTML(deal.savingLabel)}${_span}`              : '';                          // HACK for CMS            const _button = '<' + '/button>';            const _svg = '<' + '/svg>';            const _path = '<' + '/path>';            const _rect = '<' + '/rect>';            const _circle = '<' + '/circle>';            const _polyline = '<' + '/polyline>';            const _line = '<' + '/line>';                        let badgesHtml = '';            const primeBadge = deal.isPrime ? `              \x3Cspan class="tg-df-tag tg-df-tag-prime">                \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="currentColor">                  \x3Cpath d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z">${_path}                ${_svg} Prime              ${_span}            ` : '';                        const couponsBadge = deal.merchant && deal.merchant.toLowerCase().includes('amazon') ? '' : `              \x3Cdiv class="tg-df-coupon-wrapper" data-merchant="${this.escapeHTML(deal.merchant)}" style="display:inline-flex; align-items:center;">                \x3Cdiv class="tg-df-coupon-spinner">${_div}                \x3Cbutton type="button" class="tg-df-tag tg-df-tag-coupons" data-action="coupons-click" data-merchant="${this.escapeHTML(deal.merchant)}" style="display:none;">                  \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">                    \x3Cpath d="M20.59 13.41l-7.17 7.17a2 2 0 0 1-2.83 0L2 12V2h10l8.59 8.59a2 2 0 0 1 0 2.82z">${_path}                    \x3Cline x1="7" y1="7" x2="7.01" y2="7">${_line}                  ${_svg} Coupons                ${_button}              ${_div}            `;                        // Note: We always add coupons badge if there's a chance, but to allow 3-line titles we check wrapper display state            badgesHtml = `              \x3Cdiv class="tg-df-card-badges">                ${primeBadge}                ${couponsBadge}              ${_div}            `;            const _linearGradient = '<' + '/linearGradient>';            const _polygon = '<' + '/polygon>';            const _stop = '<' + '/stop>';            const _defs = '<' + '/defs>';                        let starHtml = '';            if (deal.starRating) {              let rating = deal.starRating;                            if (rating > 0) {                const fullStars = Math.floor(rating);                const halfStar = (rating - fullStars) >= 0.5 ? 1 : 0;                const emptyStars = Math.max(0, 5 - fullStars - halfStar);                const blue = '#1f69ff'; // Tom's guide brand color from VIEW DEAL button                const gray = '#cbd5e1';                                const starSvgFull = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="${blue}" stroke="${blue}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26">${_polygon}${_svg}`;                                const gradId = 'half_grad_' + Math.floor(Math.random()*1000000);                const starSvgHalf = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" stroke="${blue}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cdefs>\x3ClinearGradient id="${gradId}" x1="0" x2="1" y1="0" y2="0">\x3Cstop offset="50%" stop-color="${blue}">${_stop}\x3Cstop offset="50%" stop-color="transparent">${_stop}${_linearGradient}${_defs}                  \x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26" fill="url(#${gradId})">${_polygon}${_svg}`;                                  const starSvgEmpty = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="${gray}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26">${_polygon}${_svg}`;                                let stars = [];                for (let i=0; i<fullStars; i++) stars.push(starSvgFull);                if (halfStar) stars.push(starSvgHalf);                for (let i=0; i<emptyStars; i++) stars.push(starSvgEmpty);                                starHtml = `\x3Cdiv class="tg-df-card-stars" style="display:flex;align-items:center;margin-bottom:8px;font-size:13px;font-weight:600;color:var(--tg-df-text-muted);">                  \x3Cspan style="margin-right:6px;">Tom's Guide:${_span}                  \x3Cdiv style="display:flex;gap:2px;">                    ${stars.join('')}                  ${_div}                ${_div}`;              }            }            let htmlOutput = '';            if (isSavingsSquadMode) {              htmlOutput += `              \x3Cdiv class="hawk-deal-widget-container tg-df-mobile-only" data-collapsible="true">                ${this.editorMode ? `\x3Cinput type="checkbox" class="tg-df-deal-checkbox" data-id="${this.escapeHTML(deal.id)}" ${this.selectedDeals.has(deal.id) ? 'checked' : ''} style="margin-bottom: 10px;">` : ''}                \x3Cdiv class="hawk-deal-widget-wrap">                  \x3Cdiv class="hawk-deal-widget-image-container">                    \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" rel="sponsored noopener" target="_blank" class="hawk-affiliate-link-deal-widget" ${dataAttr}>                      \x3Cimg ${deal.image ? `src="${this.escapeHTML(deal.image)}"` : ''} alt="${this.escapeHTML(deal.title)}" class="hawk-lazy-image-deal-widget" loading="lazy" width="140" height="160" onerror="${deal.fallbackImage ? `if(!this.dataset.fb) { this.dataset.fb='1'; this.src='${this.escapeHTML(deal.fallbackImage)}'; } else { this.style.opacity='0'; }` : `this.style.opacity='0';`}">                    ${_a}                  ${_div}                  \x3Cdiv class="hawk-deal-widget-text-cta-container">                    \x3Cdiv class="hawk-deal-widget-text-body-container">                      \x3Cdiv class="hawk-deal-widget-text-body-main">                        \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                          ${deal.isCheckPrice ? `                            \x3Cspan class="hawk-deal-widget-title-product-title">${this.escapeHTML(deal.title)}${_span}                          ` : `                            \x3Cspan class="hawk-deal-widget-title-product-title">${deal.brand ? this.escapeHTML(deal.brand) + ' ' : ''}${this.escapeHTML(deal.productName || deal.title || '')}:${_span}                          `}                        ${_a}                        ${!deal.isCheckPrice && deal.rawMsrp && deal.rawMsrp > deal.rawPrice ? `                          \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                            \x3Cspan class="hawk-deal-widget-title-was-price">was ${currencySym}${escapedMsrp}${_span}                          ${_a}                        ` : ''}                        \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                          \x3Cspan class="hawk-deal-widget-title-retailer-price">                            ${!deal.isCheckPrice ? `                              \x3Cspan class="hawk-deal-widget-title-price">now ${formattedPrice}${_span}                              \x3Cspan class="hawk-deal-widget-title-retailer"> at ${this.escapeHTML(deal.merchant)}${_span}                            ` : `                              \x3Cspan class="hawk-deal-widget-title-price">See price at ${this.escapeHTML(deal.merchant)}${_span}                            `}                          ${_span}                        ${_a}                        ${deal.description ? `\x3Cdiv class="hawk-deal-widget-text-body-description">\x3Cp>${this.escapeHTML(deal.description)}${_p}${_div}` : ''}                      ${_div}                    ${_div}                    \x3Cdiv class="hawk-deal-widget-footer">                      \x3Cdiv class="hawk-deal-widget-button-wrapper">                        \x3Cdiv class="hawk-deal-widget-preferred-partner-wrapper">                          \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-deal-button" rel="sponsored noopener" target="_blank" ${dataAttr}>                            \x3Cspan>${deal.isCheckPrice ? 'Check Price' : 'View Deal'}${_span}                          ${_a}                        ${_div}                      ${_div}                    ${_div}                  ${_div}                ${_div}              ${_div}              `;            }            htmlOutput += `              \x3Cdiv class="tg-df-card ${isSavingsSquadMode ? 'tg-df-desktop-only' : ''}">                ${this.editorMode ? `\x3Cinput type="checkbox" class="tg-df-deal-checkbox" data-id="${this.escapeHTML(deal.id)}" ${this.selectedDeals.has(deal.id) ? 'checked' : ''}>` : ''}                \x3Cdiv class="tg-df-card-image-box">                  ${discountBadgeHtml}                  \x3Ca href="${this.escapeHTML(rewrittenLink)}" ${dataAttr} target="_blank" rel="noopener nofollow" style="display: flex; align-items: center; justify-content: center; width: 100%; height: 100%;">                    \x3Cimg ${deal.image ? `src="${this.escapeHTML(deal.image)}"` : ''} alt="${this.escapeHTML(deal.title)}" class="tg-df-card-image" loading="lazy" onerror="${deal.fallbackImage ? `if(!this.dataset.fb) { this.dataset.fb='1'; this.src='${this.escapeHTML(deal.fallbackImage)}'; } else { this.style.opacity='0'; }` : `this.style.opacity='0';`}">                  ${_a}                ${_div}                \x3Cdiv class="tg-df-card-body">                  ${starHtml}                  ${badgesHtml}                  \x3Ch3 class="tg-df-card-title tg-df-custom-savings-squad-title" title="${this.escapeHTML(deal.title)}">                    \x3Ca href="${this.escapeHTML(rewrittenLink)}" disable-tracking="true" target="_blank" rel="noopener nofollow" style="text-decoration: none; color: inherit;">                      ${isSavingsSquadMode                         ? (deal.isCheckPrice                             ? (deal.title && deal.title.includes(':')                                 ? `\x3Cstrong>${this.escapeHTML(deal.title.substring(0, deal.title.indexOf(':') + 1))}${_strong}\x3Cspan style="color: #1f69ff; font-weight: normal;">${this.escapeHTML(deal.title.substring(deal.title.indexOf(':') + 1))}${_span}`                                : this.escapeHTML(deal.title)                              )                             : `\x3Cstrong>${deal.brand ? this.escapeHTML(deal.brand) + ' ' : ''}${this.escapeHTML(deal.productName || deal.title || '')}:${_strong} ${deal.rawMsrp && deal.rawMsrp > deal.rawPrice ? `\x3Cspan style="color: #d0021b; text-decoration: line-through; font-weight: normal; margin-right: 4px;">was ${currencySym}${escapedMsrp}${_span} ` : ''}\x3Cspan style="color: #1f69ff; font-weight: normal;">now ${formattedPrice} at ${this.escapeHTML(deal.merchant)}${_span}`                          )                        : this.escapeHTML(deal.title)                      }                    ${_a}                  ${_h3}                  ${deal.description ? `\x3Cp style="font-size: 13px; color: var(--tg-df-text-muted); margin-bottom: 12px; line-height: 1.4;">${this.escapeHTML(deal.description)}${_p}` : ''}                  \x3Cdiv class="tg-df-card-footer">                    ${priceGroupHtml}                    \x3Ca href="${this.escapeHTML(rewrittenLink)}" ${dataAttr} target="_blank" rel="noopener nofollow" class="tg-df-card-cta ${isSavingsSquadMode ? 'tg-df-cta-savings-squad' : ''}" style="text-decoration: none;">${ctaText}${_a}                  ${_div}                ${_div}              ${_div}            `;                        return htmlOutput;            } catch (e) {               console.log("Error rendering deal in map for index", index, typeof deal === 'object' ? JSON.stringify(deal) : deal, "MSG:", e.message);               return '';            }          }).join('');                    if (displayDeals.length > this.displayLimit || ((this.getViewMode() === 'carousel' || this.getViewMode() === 'auto') && displayDeals.length > 0 && displayDeals.length % ((this.rowsSelect && this.rowsSelect.value) ? parseInt(this.rowsSelect.value, 10) : 12) === 0)) {            if (this.getViewMode() === 'carousel') {               dealsHtml += `                 \x3Cbutton type="button" class="tg-df-load-more-card tg-df-load-more">                   \x3Csvg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-bottom: 8px;">\x3Cpath d="M5 12h14">\x3C/path>\x3Cpath d="m12 5 7 7-7 7">\x3C/path>\x3C/svg>                   Load More                 ${_button}               `;            } else {               dealsHtml += `                 \x3Cdiv style="width: 100%; display: flex; justify-content: center; margin-top: 16px; grid-column: 1 / -1;">                   \x3Cbutton type="button" class="tg-df-tag-outline tg-df-load-more" style="padding: 8px 24px; border-radius: 100px; font-weight: 600; font-size: 14px; cursor: pointer; display: flex; align-items: center;">Load More${_button}                 ${_div}               `;            }          }                    this.grid.innerHTML = dealsHtml;          // Inject JSON-LD          try {            let targetNode = this.hostContainer || document.head;            let jsonLdScript = targetNode.querySelector('#tg-df-json-ld-' + this.widgetId);            if (!jsonLdScript) {                jsonLdScript = document.createElement('script');                jsonLdScript.type = 'application/ld+json';                jsonLdScript.id = 'tg-df-json-ld-' + this.widgetId;                targetNode.appendChild(jsonLdScript);            }            const jsonLdData = {              "@context": "https://schema.org",              "@type": "ItemList",              "itemListElement": displayDeals.slice(0, this.displayLimit).map((deal, index) => {                 let isoCurrency = "USD";                 if (deal.currency === '£') isoCurrency = "GBP";                 else if (deal.currency === '€') isoCurrency = "EUR";                 else if (deal.currency === 'A$') isoCurrency = "AUD";                 else if (deal.currency === 'CA$') isoCurrency = "CAD";                 const areaCode = typeof this.getAreaCode === 'function' ? this.getAreaCode() : 'US';                 const revenueId = typeof generateRevenueId === 'function' ? generateRevenueId(deal.url, deal.title, deal.merchant, null) : '';                 const rewrittenLink = typeof rewriteAffiliateLink === 'function' ? rewriteAffiliateLink(deal.url, areaCode, revenueId) : deal.url;                 return {                   "@type": "ListItem",                   "position": index + 1,                   "item": {                     "@type": "Product",                     "name": deal.title,                     "image": deal.image || "",                     "description": deal.description || "",                     "brand": {                       "@type": "Brand",                       "name": deal.brand || ""                     },                     "offers": {                       "@type": "Offer",                       "priceCurrency": isoCurrency,                       "price": deal.rawPrice || 0,                       "url": rewrittenLink,                       "seller": {                         "@type": "Organization",                         "name": deal.merchant || ""                       }                     }                   }                 };              }).filter(item => item.item.name)            };            jsonLdScript.textContent = JSON.stringify(jsonLdData);          } catch(e) { console.warn("JSON-LD generation failed", e); }                    let gridWrapper = this.grid.parentElement;          if (gridWrapper && gridWrapper.classList.contains('tg-df-grid-wrapper')) {             let rightChevron = gridWrapper.querySelector('.tg-df-carousel-scroll-right');             let leftChevron = gridWrapper.querySelector('.tg-df-carousel-scroll-left');             if (this.getViewMode() === 'carousel') {                 // The observer set up in setupScrollListeners handles visibility.                 if (rightChevron) rightChevron.style.display = 'flex';                 if (leftChevron) leftChevron.style.display = 'none'; // reset correctly             } else {                 if (rightChevron) rightChevron.style.display = 'none';                 if (leftChevron) leftChevron.style.display = 'none';             }          }                    const loadMoreBtn = this.grid.querySelector('.tg-df-load-more');          if (loadMoreBtn) {            loadMoreBtn.addEventListener('click', async () => {              if (typeof trackElementInteraction === 'function') {                trackElementInteraction({ id: 'load-more', name: 'Load more', label: 'Load More Results' });              }              if (displayDeals.length <= this.displayLimit) {                 loadMoreBtn.innerHTML = `                  <svg class="tg-df-spinner" style="width: 16px; height: 16px; display: inline-block; vertical-align: middle; margin-right: 8px;" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" d="M12 2v4m0 12v4M4.93 4.93l2.83 2.83m8.48 8.48l2.83 2.83M2 12h4m12 0h4M4.93 19.07l2.83-2.83m8.48-8.48l2.83-2.83"/></svg>                  Loading...                 `;                 loadMoreBtn.disabled = true;                 await this.fetchDeals(this.currentQuery, true);              } else {                 this.displayLimit += this.getRowsLimit();                 this.render();              }            });          }                      this.bindCouponButtons();            this.checkAndUpdateCoupons();                        // Allow hawklinks.js to discover and rewrite our widget links             // by appending the .article-body class and manually triggering processArticle.            let container = this.root.classList.contains('tg-df-container') ? this.root : this.root.querySelector('.tg-df-container');            if (container && !container.classList.contains('article-body')) {               container.classList.add('article-body');            }            setTimeout(() => {               if (this.grid && !this.grid.classList.contains('article-body')) this.grid.classList.add('article-body');               document.dispatchEvent(new CustomEvent('processArticle', { detail: { element: this.root } }));            }, 50);          } catch(e) {            console.warn("Widget render error", e);          }        }                async checkAndUpdateCoupons() {          const wrappers = Array.from(this.root.querySelectorAll('.tg-df-coupon-wrapper'));          if (wrappers.length === 0) return;                    const merchants = [...new Set(wrappers.map(w => w.getAttribute('data-merchant')).filter(Boolean))];          if (merchants.length === 0) return;          const couponResultsMap = await this.checkMerchantsCouponsBulk(merchants);                    for (const merchant of merchants) {            const hasCoupons = !!couponResultsMap[merchant];            const merchantWrappers = wrappers.filter(w => w.getAttribute('data-merchant') === merchant);            merchantWrappers.forEach(wrapper => {              const spinner = wrapper.querySelector('.tg-df-coupon-spinner');              const btn = wrapper.querySelector('.tg-df-tag-coupons');                            if (spinner) spinner.style.display = 'none';                            if (hasCoupons && btn) {                btn.style.display = 'inline-flex';              } else if (!hasCoupons) {                wrapper.style.display = 'none';              }            });          }        }        updateFloatingCopyBar() {          if (!this.editorBar || !this.editorSelectedCount) return;          if (this.editorMode && this.selectedDeals.size > 0) {            this.editorBar.style.display = 'flex';            this.editorSelectedCount.innerText = this.selectedDeals.size;          } else {            this.editorBar.style.display = 'none';          }        }        async copySelectedDealsToCMS() {           function htmlToSlate(htmlString) {              if (!htmlString) return [{ type: 'paragraph', children: [{ text: '' }] }];              let doc;              if (typeof window !== 'undefined' && window.DOMParser) {                 doc = new DOMParser().parseFromString(htmlString, 'text/html');              } else {                 doc = document.implementation.createHTMLDocument('');                 doc.body.innerHTML = htmlString;              }                            function parseNode(node, marks = {}) {                  if (node.nodeType === 3) {                      const text = node.textContent;                      if (!text) return null;                      return { text: text, ...marks };                  }                  if (node.nodeType === 1) {                      const tagName = node.tagName.toLowerCase();                      if (tagName === 'br') {                          return { type: 'line-break', children: [{ text: '' }] };                      }                      if (tagName === 'p') {                          let children = Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                          if (children.length === 0) children.push({ text: "" });                          return { type: 'paragraph', children };                      }                      if (tagName === 'strong' || tagName === 'b') {                          const newMarks = { ...marks, bold: true };                          return Array.from(node.childNodes).map(child => parseNode(child, newMarks)).flat().filter(Boolean);                      }                      if (tagName === 'em' || tagName === 'i') {                          const newMarks = { ...marks, italic: true };                          return Array.from(node.childNodes).map(child => parseNode(child, newMarks)).flat().filter(Boolean);                      }                      if (tagName === 'a') {                          const href = node.getAttribute('href') || '';                          let children = Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                          if (children.length === 0) children.push({ text: "" });                          return {                              type: 'link',                              url: href,                              isNoFollow: (node.getAttribute('rel') || '').includes('nofollow'),                              isSponsored: (node.getAttribute('rel') || '').includes('sponsored'),                              isOpenNewTab: node.getAttribute('target') === '_blank',                              isPreventDataRewrite: false,                              children: children                          };                      }                      return Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                  }                  return null;              }                            let blocksArray = [];              let currentParagraphChildren = [];              function flushParagraph() {                  if (currentParagraphChildren.length > 0) {                      blocksArray.push({ type: 'paragraph', children: currentParagraphChildren });                      currentParagraphChildren = [];                  }              }              Array.from(doc.body.childNodes).forEach(node => {                  const parsed = parseNode(node, {});                  const parsedItems = Array.isArray(parsed) ? parsed : (parsed ? [parsed] : []);                  parsedItems.forEach(item => {                      if (item.type === 'paragraph') {                          flushParagraph();                          blocksArray.push(item);                      } else {                          currentParagraphChildren.push(item);                      }                  });              });              flushParagraph();              if (blocksArray.length === 0) {                  blocksArray = [{ type: 'paragraph', children: [{ text: '' }] }];              }              return blocksArray;           }           const blocks = [];                      this.editorCopyBtn.innerHTML = '\x3Cspan class="tg-df-coupon-spinner" style="display:inline-block; margin-right:8px; border-top-color:#fff;">' + '<' + '/span> Copying...';           for (const deal of Array.from(this.selectedDeals.values())) {              const url = deal.url;              const merchant = deal.merchant;              const title = deal.title;              const image = deal.image;              const currentPrice = deal.currency + deal.rawPrice;              const wasPrice = deal.hasWasPrice && deal.rawMsrp > deal.rawPrice ? deal.currency + deal.rawMsrp : '';                            let couponsChildren = [];              try {                  const area = this.getAreaCode();                  const apiUrl = new URL('https://search-api.fie.future.net.uk/widget.php');                  apiUrl.searchParams.append('model_name', 'Everything');                  apiUrl.searchParams.append('language', 'en-GB');                  apiUrl.searchParams.append('area', area);                  apiUrl.searchParams.append('combine_product_types', '1');                  apiUrl.searchParams.append('filter_merchant_name', merchant);                  apiUrl.searchParams.append('all_filters', 'false');                  apiUrl.searchParams.append('exclude_unlabelled', 'false');                  apiUrl.searchParams.append('include_specs', 'false');                  apiUrl.searchParams.append('sort', 'voucher');                  apiUrl.searchParams.append('distinct_merchants', 'natural');                  apiUrl.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');                  apiUrl.searchParams.append('rows', '3');                  apiUrl.searchParams.append('origin', 'widgets-clientside');                                    let res; try { res = await fetch(apiUrl.toString()); } catch (e) { return; }                  if (res.ok) {                      const data = await res.json();                      let offers = [];                      if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {                        offers = data.widget.data.offers;                      } else if (data && data.data && Array.isArray(data.data.offers)) {                        offers = data.data.offers;                      }                                            if (offers.length > 0) {                          couponsChildren.push({ text: "Also check out these coupons: ", bold: true });                          offers.slice(0, 3).forEach((offer, idx) => {                              const actualOffer = offer.offer || offer;                              const offerName = actualOffer.name || actualOffer.title || offer.model_name || offer.title || offer.name || 'Coupon';                              const linkUrl = actualOffer.link || actualOffer.url || actualOffer.offer_link || '#';                              couponsChildren.push({ type: "line-break", children: [{ text: "" }] });                              couponsChildren.push({ text: "🎟️ " });                              couponsChildren.push({                                  type: "link",                                  url: linkUrl,                                  isNoFollow: true,                                  isSponsored: false,                                  isOpenNewTab: true,                                  isPreventDataRewrite: false,                                  children: [{ text: offerName, bold: true }]                              });                          });                      }                  }              } catch (err) {                  console.warn('Failed to fetch coupons for', merchant, err);              }              let descriptionValue = [];              if (deal.text) {                 descriptionValue = htmlToSlate(deal.text);              } else {                 const dealDescriptions = [                   `Don't miss out on this fantastic deal for the ${title}. It is currently available at ${merchant} for a highly competitive price.`,                   `We've spotted an excellent price drop on the ${title}. Grab it now at ${merchant} before it's gone.`,                   `The ${title} is currently seeing a generous discount over at ${merchant}. This is a perfect time to buy if you've been holding out.`,                   `If you're in the market for the ${title}, ${merchant} has just the deal for you.`,                   `Score the ${title} for less at ${merchant} right now. This is a rare chance to save big.`,                   `Upgrade your setup with the ${title}, now available at a stellar price via ${merchant}.`                 ];                 const randomDescription = dealDescriptions[Math.floor(Math.random() * dealDescriptions.length)];                 descriptionValue = [                    { type: "paragraph", children: [{ text: randomDescription }] }                 ];              }                            if (couponsChildren.length > 0) {                 let lastBlock = descriptionValue[descriptionValue.length - 1];                 if (lastBlock && lastBlock.type === 'paragraph') {                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children.push({ text: "Also check out these coupons: ", bold: true });                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children = lastBlock.children.concat(couponsChildren);                 } else {                     descriptionValue.push({                         type: "paragraph",                         children: [                             { type: "line-break", children: [{ text: "" }] },                             { type: "line-break", children: [{ text: "" }] },                             { text: "Also check out these coupons: ", bold: true },                             { type: "line-break", children: [{ text: "" }] },                             ...couponsChildren                         ]                     });                 }              }              function normalizeCurrencyToISO(symbol) {                const map = { '£': 'GBP', '$': 'USD', 'A$': 'AUD', 'CA$': 'CAD', '€': 'EUR' };                return map[symbol] || symbol;              }              const isoCurrency = normalizeCurrencyToISO(deal.currency);              blocks.push({                 id: (window.crypto && window.crypto.randomUUID) ? window.crypto.randomUUID() : 'cms-' + Date.now() + Math.random(),                 blockTypeName: "deal",                 excludeFrom: [],                 collapsible: false,                 props: {                    description: {                       value: descriptionValue,                       touched: false,                       validationMessage: ""                    },                    image: {                       value: {                          credit: [{ type: "paragraph", children: [{ text: merchant }] }],                          dateCreated: Date.now(),                          dateModified: Date.now(),                          distribution: [],                          fileSize: 0,                          height: 1000,                          id: deal.id,                          imageRights: "",                          src: image,                          name: title + ".jpg",                          tags: [],                          width: 1000                       },                       touched: false,                       validationMessage: ""                    },                    showDealButton: { value: true, touched: false, validationMessage: "" },                    isPreferredPartner: { value: false, touched: false, validationMessage: "" },                    linkHref: { value: url, touched: false, validationMessage: "" },                    linkLabel: { value: "", touched: false, validationMessage: "" },                    linkIsNoFollow: { value: true, touched: false, validationMessage: "" },                    linkIsSponsored: { value: false, touched: false, validationMessage: "" },                    linkIsOpenNewWindow: { value: true, touched: false, validationMessage: "" },                    customPromoFlags: { value: [], touched: false, validationMessage: "" },                    showStarDeal: { value: false, touched: false, validationMessage: "" },                    savingType: { value: "none", touched: false, validationMessage: "" },                    starDealPromoFlag: { value: "", touched: false, validationMessage: "" },                    showEditorsChoice: { value: false, touched: false, validationMessage: "" },                    editorsChoiceTitle: { value: "", touched: false, validationMessage: "" },                    hawkPriceCurrency: { value: { value: isoCurrency, label: isoCurrency }, touched: false, validationMessage: "" },                    hawkPrice: { value: deal.hasWasPrice ? String(deal.rawMsrp) : String(deal.rawPrice), touched: false, validationMessage: "" },                    hawkSalePrice: { value: String(deal.rawPrice), touched: false, validationMessage: "" },                    lastCheckedPriceDate: { value: "", touched: false, validationMessage: "" },                    hawkModel: { touched: false, validationMessage: "" },                    productId: { value: "", touched: false, validationMessage: "" },                    voucherId: { value: "", touched: false, validationMessage: "" },                    brand: { value: deal.brand || merchant, touched: false, validationMessage: "" },                    productName: { value: title, touched: false, validationMessage: "" },                    label: { value: "", touched: false, validationMessage: "" },                    retailer: { value: merchant, touched: false, validationMessage: "" },                    priceCheckError: false                 },                 failedFetchError: ""              });           }           const payload = {              type: "articleBuilderPages",              data: blocks           };           const jsonStr = JSON.stringify(payload);                      if (navigator.clipboard && navigator.clipboard.writeText) {              navigator.clipboard.writeText(jsonStr).then(() => {                 this.editorCopyBtn.innerHTML = 'Copied!';                 setTimeout(() => {                    this.editorCopyBtn.innerHTML = '\x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2"><' + '/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"><' + '/path><' + '/svg> Copy to CMS';                 }, 2000);              }).catch(err => {                 console.warn('Failed to copy text: ', err);                 alert('Failed to copy deals to clipboard. See console.');              });           } else {              // Fallback              const textArea = document.createElement("textarea");              textArea.value = jsonStr;              document.body.appendChild(textArea);              textArea.focus();              textArea.select();              try {                 document.execCommand('copy');                 this.editorCopyBtn.innerHTML = 'Copied!';                 setTimeout(() => {                    this.editorCopyBtn.innerHTML = '\x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2"><' + '/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"><' + '/path><' + '/svg> Copy to CMS';                 }, 2000);              } catch (err) {                 console.warn('Fallback: Oops, unable to copy', err);                 alert('Fallback: Failed to copy deals to clipboard.');              }              document.body.removeChild(textArea);           }        }      }      // Initialize the Widget      if (document.readyState === 'loading') {        document.addEventListener('DOMContentLoaded', () => new DealsFinderWidget({ rootId: 'signal-deals-finder-root', rootNode: shadowRoot, hostContainer: hostContainer }));      } else {        new DealsFinderWidget({ rootId: 'signal-deals-finder-root', rootNode: shadowRoot, hostContainer: hostContainer });      }    })();  </script></div>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ Best Buy early Labor Day sale: 12 appliance deals I'd shop right now ]]></title>
                                                                                                <dc:content><![CDATA[ <p>We're inching closer to Labor Day – and the big online retailers are starting the celebrations early this year.</p><p>Best Buy has kicked off a massive Labor Day sale, with great deals on a wide-range of home appliances. If you're in need of a new oven, washing machine, microwave, or fridge, now is a fantastic time to take advantage of some really big savings. What's more, these aren't unknown brands – we're talking money off big names like LG, Whirlpool, Frigidaire, and Samsung.</p><p>Below, you'll find my 12 favorite deals from the sale. As ever these deals won't stick around forever, so if you spot something you like, make sure to move fast. </p>        <div class="featured_product_block featured_block_hero" data-id="8d1efdfa-a20c-11f1-beee-4da1049c1516">            <a href="https://www.bestbuy.com/product/whirlpool-1-7-cu-ft-over-the-range-microwave-with-1000-watts-cooking-power-stainless-steel/J3KHVG33QL/sku/6590539" data-model-name="Over-the-Range Microwave" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:133.33%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/mAsdDauZKtMcQ5hSs3bsyD.jpg" alt="Over-the-Range Microwave"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Whirlpool</div>                                        <div class="featured__title">Over-the-Range Microwave</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="8d1efc24-a20c-11f1-9f13-b3e6cff644d3">            <a href="https://www.bestbuy.com/product/lg-1-8-cu-ft-over-the-range-smart-microwave-with-sensor-cooking-and-easyclean-stainless-steel/J7G5658L4Y/sku/6621243" data-model-name="Over-The-Range Smart Microwave" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:133.33%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/WmqXcxaxq44w3RKkEeKx2R.jpg" alt="LG, Lg - 1.8 Cu. Ft. Over-The-Range Smart Microwave With Sensor Cooking and Easyclean - Stainless Steel"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>LG</div>                                        <div class="featured__title">Over-The-Range Smart Microwave</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="8d1efe86-a20c-11f1-8ea3-234473b3b4fc">            <a href="https://www.bestbuy.com/product/insignia-14-0-cu-ft-garage-ready-chest-freezer-white/J2FPJKY9X5/sku/6444379" data-model-name="Garage-Ready Chest Freezer" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:133.33%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/WcPeCTFWpT8EyzsFBkpmMQ.jpg" alt="Insignia, Garage-Ready Chest Freezer"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Insignia</div>                                        <div class="featured__title">Garage-Ready Chest Freezer</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="8d1eff08-a20c-11f1-8630-01e939e2ae37">            <a href="https://www.bestbuy.com/product/whirlpool-24-inch-quiet-dishwasher-with-3rd-rack-stainless-steel/J3KHVG7Z3C/sku/6515791" data-model-name="24-inch Quiet Dishwasher" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:133.33%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/Ve3yyoahWjoeSS5ZCjdMjV.jpg" alt="Whirlpool, 24-inch Quiet Dishwasher"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Whirlpool</div>                                        <div class="featured__title">24-inch Quiet Dishwasher</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="8d1efd14-a20c-11f1-bf28-c904fc90ffa2">            <a href="https://www.bestbuy.com/product/whirlpool-24-dishwasher-with-ai-intelligent-wash-and-47-dba-stainless-steel/J3KHV8ZQ86/sku/6420935" data-model-name="24-inch Dishwasher With AI Intelligent Wash" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:133.33%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/5tFDbbpgcgezRjhrRiL3B4.jpg" alt="Whirlpool, 24-inch Dishwasher With AI Intelligent Wash"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Whirlpool</div>                                        <div class="featured__title">24-inch Dishwasher With AI Intelligent Wash</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="8d1efc92-a20c-11f1-a232-af93ce0c2942">            <a href="https://www.bestbuy.com/product/samsung-5-0-cu-ft-high-efficiency-stackable-smart-front-load-washer-with-steam-and-super-speed-wash-brushed-black/J3ZYG28GS9/sku/6507594" data-model-name="High-Efficiency Stackable Smart Washer" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:133.33%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/dwrwzKHW7i6nWwteUyTGoX.jpg" alt="Samsung, Samsung - 5.0 Cu. Ft. High-Efficiency Stackable Smart Front Load Washer With Steam and Super Speed Wash - Brushed Black"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Samsung</div>                                        <div class="featured__title">High-Efficiency Stackable Smart Washer</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="8d1efbac-a20c-11f1-8c57-0d0dca2678c0">            <a href="https://www.bestbuy.com/product/lg-36-in-counter-depth-max-25-5-cu-ft-french-door-smart-refrigerator-with-ice-plus-printproof-stainless-steel-look/JJ8VPZKRJ8/sku/6642587/openbox?condition=fair" data-model-name="36-inch French Door Smart Refrigerator" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:133.33%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/EycrfJh2Kj8pSyjr4i3H6L.jpg" alt="LG, Lg - 36-In Counter-Depth Max 25.5 Cu. Ft. French Door Smart Refrigerator With Ice Plus - Printproof Stainless Steel Look"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>LG</div>                                        <div class="featured__title">36-inch French Door Smart Refrigerator</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="8d1efabc-a20c-11f1-8299-e58a717638b7">            <a href="https://www.bestbuy.com/product/frigidaire-gallery-30-built-in-single-total-convection-electric-wall-oven-with-stone-baked-pizza-stainless-steel/J3GWLTCQ2Q/sku/6642418" data-model-name="Frigidaire 30" Built-In Electric Wall Oven" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:133.33%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/WtGp6QsnGKMEHWz3gD5uo3.jpg" alt="Frigidaire gallery 30 built in single electric wall oven"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Frigidaire</div>                                        <div class="featured__title">Frigidaire 30" Built-In Electric Wall Oven</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="8d1efd8c-a20c-11f1-b665-2785d3fc88a7">            <a href="https://www.bestbuy.com/product/lg-36-in-wide-27-1-cu-ft-side-by-side-smart-refrigerator-with-craft-ice-stainless-steel/JJ8VPZS938/sku/6468484" data-model-name="Side-by-Side Smart Refrigerator" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:133.33%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/gdFDhkCRfzdxpzmCPwZqC7.jpg" alt="BRAND, LG - 36-in Wide 27.1 Cu. Ft. Side-by-Side Smart Refrigerator with Craft Ice - Stainless Steel"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>LG</div>                                        <div class="featured__title">Side-by-Side Smart Refrigerator</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="8d1efb3e-a20c-11f1-9511-e966c416f26f">            <a href="https://www.bestbuy.com/product/forno-appliances-36-in-wide-6-elements-paolo-5-44-cu-ft-freestanding-electric-true-convection-range-with-warming-zone-silver/JX9PPPQSG7/sku/6639075" data-model-name="36-inch Electric True Convection Range" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:133.33%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/C2mWaSPsxKBoZv7HPnEWuC.jpg" alt="Forno Appliances, Forno Appliances - 36 In. Wide 6 Elements Paolo 5.44 Cu. Ft. Freestanding Electric True Convection Range With Warming Zone - Silver"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Forno Appliances</div>                                        <div class="featured__title">36-inch Electric True Convection Range</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="8d1eff80-a20c-11f1-b5ea-07dfe4f070a9">            <a href="https://www.bestbuy.com/product/lg-30-in-wide-smart-built-in-electric-convection-combination-wall-oven-with-microwave-and-steam-sous-vide-stainless-steel/J7G56587FJ/sku/6534256" data-model-name="30-inch Smart Electric Wall Oven with Microwave" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:133.33%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/V83BzrgyHb2jCyFERQ8q8h.jpg" alt="LG 30-inch Smart Built-In Electric Convection Combination Wall Oven with Microwave"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>LG</div>                                        <div class="featured__title">30-inch Smart Electric Wall Oven with Microwave</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="8d1effee-a20c-11f1-9fef-dd95ad045df0">            <a href="https://www.bestbuy.com/product/lg-studio-30-in-wide-smart-built-in-electric-convection-double-wall-oven-with-air-fry-and-sous-vide-stainless-steel/JJ8VPZ9S67/sku/6479190" data-model-name="30-inch Smart Electric Convection Double Wall Oven" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:133.33%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/xzdHviVGR4ermit9hWBAbn.jpg" alt="BRAND, LG - STUDIO 30-in Wide Smart Built-In Electric Convection Double Wall Oven with Air Fry and Sous Vide - Stainless Steel"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>LG</div>                                        <div class="featured__title">30-inch Smart Electric Convection Double Wall Oven</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/sales-events/best-buy-early-labor-day-sale-12-appliance-deals-id-shop-right-now</link>
                                                                            <description>
                            <![CDATA[ Best Buy is starting the Labor Day sales early. We've picked out 12 of the best deals currently available so you can save big on household appliances. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">AfL2U6zKLoPhq7sBst8H8T</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/8GrxJASggYUYF5gGxrzi4c-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Thu, 27 Aug 2026 14:30:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Sales Events]]></category>
                                                                                                                    <dc:creator><![CDATA[ Will Salmon ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/HpRWP7Mh9ErgRGoTvZBbBJ.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Will Salmon is Tom&#039;s Guide&#039;s Collections Editor, curating advice on the best products to spend your money on. Will has been writing about tech and entertainment for almost 20 years, including stints as GamesRadar+&#039;s Streaming Editor, editing comics website Newsarama, and writing for lots and lots of magazines.&lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/8GrxJASggYUYF5gGxrzi4c-1280-80.jpg">
                                                            <media:credit><![CDATA[Forno Appliances, Samsung, LG, Whirlpool / Edited by Gemini]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[A selection of home appliances on a blue background.]]></media:description>                                                            <media:text><![CDATA[A selection of home appliances on a blue background.]]></media:text>
                                <media:title type="plain"><![CDATA[A selection of home appliances on a blue background.]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/8GrxJASggYUYF5gGxrzi4c-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>We're inching closer to Labor Day – and the big online retailers are starting the celebrations early this year.</p><p>Best Buy has kicked off a massive Labor Day sale, with great deals on a wide-range of home appliances. If you're in need of a new oven, washing machine, microwave, or fridge, now is a fantastic time to take advantage of some really big savings. What's more, these aren't unknown brands – we're talking money off big names like LG, Whirlpool, Frigidaire, and Samsung.</p><p>Below, you'll find my 12 favorite deals from the sale. As ever these deals won't stick around forever, so if you spot something you like, make sure to move fast. </p>        <div class="featured_product_block featured_block_hero" data-id="8d1efdfa-a20c-11f1-beee-4da1049c1516">            <a href="https://www.bestbuy.com/product/whirlpool-1-7-cu-ft-over-the-range-microwave-with-1000-watts-cooking-power-stainless-steel/J3KHVG33QL/sku/6590539" data-model-name="Over-the-Range Microwave" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:133.33%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/mAsdDauZKtMcQ5hSs3bsyD.jpg" alt="Over-the-Range Microwave"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Whirlpool</div>                                        <div class="featured__title">Over-the-Range Microwave</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="8d1efc24-a20c-11f1-9f13-b3e6cff644d3">            <a href="https://www.bestbuy.com/product/lg-1-8-cu-ft-over-the-range-smart-microwave-with-sensor-cooking-and-easyclean-stainless-steel/J7G5658L4Y/sku/6621243" data-model-name="Over-The-Range Smart Microwave" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:133.33%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/WmqXcxaxq44w3RKkEeKx2R.jpg" alt="LG, Lg - 1.8 Cu. Ft. Over-The-Range Smart Microwave With Sensor Cooking and Easyclean - Stainless Steel"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>LG</div>                                        <div class="featured__title">Over-The-Range Smart Microwave</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="8d1efe86-a20c-11f1-8ea3-234473b3b4fc">            <a href="https://www.bestbuy.com/product/insignia-14-0-cu-ft-garage-ready-chest-freezer-white/J2FPJKY9X5/sku/6444379" data-model-name="Garage-Ready Chest Freezer" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:133.33%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/WcPeCTFWpT8EyzsFBkpmMQ.jpg" alt="Insignia, Garage-Ready Chest Freezer"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Insignia</div>                                        <div class="featured__title">Garage-Ready Chest Freezer</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="8d1eff08-a20c-11f1-8630-01e939e2ae37">            <a href="https://www.bestbuy.com/product/whirlpool-24-inch-quiet-dishwasher-with-3rd-rack-stainless-steel/J3KHVG7Z3C/sku/6515791" data-model-name="24-inch Quiet Dishwasher" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:133.33%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/Ve3yyoahWjoeSS5ZCjdMjV.jpg" alt="Whirlpool, 24-inch Quiet Dishwasher"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Whirlpool</div>                                        <div class="featured__title">24-inch Quiet Dishwasher</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="8d1efd14-a20c-11f1-bf28-c904fc90ffa2">            <a href="https://www.bestbuy.com/product/whirlpool-24-dishwasher-with-ai-intelligent-wash-and-47-dba-stainless-steel/J3KHV8ZQ86/sku/6420935" data-model-name="24-inch Dishwasher With AI Intelligent Wash" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:133.33%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/5tFDbbpgcgezRjhrRiL3B4.jpg" alt="Whirlpool, 24-inch Dishwasher With AI Intelligent Wash"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Whirlpool</div>                                        <div class="featured__title">24-inch Dishwasher With AI Intelligent Wash</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="8d1efc92-a20c-11f1-a232-af93ce0c2942">            <a href="https://www.bestbuy.com/product/samsung-5-0-cu-ft-high-efficiency-stackable-smart-front-load-washer-with-steam-and-super-speed-wash-brushed-black/J3ZYG28GS9/sku/6507594" data-model-name="High-Efficiency Stackable Smart Washer" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:133.33%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/dwrwzKHW7i6nWwteUyTGoX.jpg" alt="Samsung, Samsung - 5.0 Cu. Ft. High-Efficiency Stackable Smart Front Load Washer With Steam and Super Speed Wash - Brushed Black"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Samsung</div>                                        <div class="featured__title">High-Efficiency Stackable Smart Washer</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="8d1efbac-a20c-11f1-8c57-0d0dca2678c0">            <a href="https://www.bestbuy.com/product/lg-36-in-counter-depth-max-25-5-cu-ft-french-door-smart-refrigerator-with-ice-plus-printproof-stainless-steel-look/JJ8VPZKRJ8/sku/6642587/openbox?condition=fair" data-model-name="36-inch French Door Smart Refrigerator" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:133.33%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/EycrfJh2Kj8pSyjr4i3H6L.jpg" alt="LG, Lg - 36-In Counter-Depth Max 25.5 Cu. Ft. French Door Smart Refrigerator With Ice Plus - Printproof Stainless Steel Look"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>LG</div>                                        <div class="featured__title">36-inch French Door Smart Refrigerator</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="8d1efabc-a20c-11f1-8299-e58a717638b7">            <a href="https://www.bestbuy.com/product/frigidaire-gallery-30-built-in-single-total-convection-electric-wall-oven-with-stone-baked-pizza-stainless-steel/J3GWLTCQ2Q/sku/6642418" data-model-name="Frigidaire 30" Built-In Electric Wall Oven" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:133.33%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/WtGp6QsnGKMEHWz3gD5uo3.jpg" alt="Frigidaire gallery 30 built in single electric wall oven"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Frigidaire</div>                                        <div class="featured__title">Frigidaire 30" Built-In Electric Wall Oven</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="8d1efd8c-a20c-11f1-b665-2785d3fc88a7">            <a href="https://www.bestbuy.com/product/lg-36-in-wide-27-1-cu-ft-side-by-side-smart-refrigerator-with-craft-ice-stainless-steel/JJ8VPZS938/sku/6468484" data-model-name="Side-by-Side Smart Refrigerator" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:133.33%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/gdFDhkCRfzdxpzmCPwZqC7.jpg" alt="BRAND, LG - 36-in Wide 27.1 Cu. Ft. Side-by-Side Smart Refrigerator with Craft Ice - Stainless Steel"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>LG</div>                                        <div class="featured__title">Side-by-Side Smart Refrigerator</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="8d1efb3e-a20c-11f1-9511-e966c416f26f">            <a href="https://www.bestbuy.com/product/forno-appliances-36-in-wide-6-elements-paolo-5-44-cu-ft-freestanding-electric-true-convection-range-with-warming-zone-silver/JX9PPPQSG7/sku/6639075" data-model-name="36-inch Electric True Convection Range" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:133.33%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/C2mWaSPsxKBoZv7HPnEWuC.jpg" alt="Forno Appliances, Forno Appliances - 36 In. Wide 6 Elements Paolo 5.44 Cu. Ft. Freestanding Electric True Convection Range With Warming Zone - Silver"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Forno Appliances</div>                                        <div class="featured__title">36-inch Electric True Convection Range</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="8d1eff80-a20c-11f1-b5ea-07dfe4f070a9">            <a href="https://www.bestbuy.com/product/lg-30-in-wide-smart-built-in-electric-convection-combination-wall-oven-with-microwave-and-steam-sous-vide-stainless-steel/J7G56587FJ/sku/6534256" data-model-name="30-inch Smart Electric Wall Oven with Microwave" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:133.33%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/V83BzrgyHb2jCyFERQ8q8h.jpg" alt="LG 30-inch Smart Built-In Electric Convection Combination Wall Oven with Microwave"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>LG</div>                                        <div class="featured__title">30-inch Smart Electric Wall Oven with Microwave</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="8d1effee-a20c-11f1-9fef-dd95ad045df0">            <a href="https://www.bestbuy.com/product/lg-studio-30-in-wide-smart-built-in-electric-convection-double-wall-oven-with-air-fry-and-sous-vide-stainless-steel/JJ8VPZ9S67/sku/6479190" data-model-name="30-inch Smart Electric Convection Double Wall Oven" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:133.33%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/xzdHviVGR4ermit9hWBAbn.jpg" alt="BRAND, LG - STUDIO 30-in Wide Smart Built-In Electric Convection Double Wall Oven with Air Fry and Sous Vide - Stainless Steel"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>LG</div>                                        <div class="featured__title">30-inch Smart Electric Convection Double Wall Oven</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ 12 low-cost bathroom accessories under $50 that instantly elevate your space ]]></title>
                                                                                                <dc:content><![CDATA[ <p>Upgrading your bathroom doesn't have to cost the Earth. Sometimes it's just a case of finding the right accessories to make your space feel more homey, and adding a few useful gadgets.</p><p>For this article I've selected 12 items that have practical utility and a touch of straightforward style, so they will fit into almost any bathroom. That means things like toothbrush holders, towel bars, soap trays and more. I've also picked out a few essential  devices, like an electric toothbrush and a scale.</p><p>It's easy for costs to quickly add up, so for that reason I've only picked out budget items: everything here currently costs less than $50 on Amazon, so you're not going to break the bank while filling out your space.</p>        <div class="featured_product_block featured_block_hero" data-id="11c10eb4-9fd2-11f1-8c02-e5b2f99fc6c1">            <a href="https://www.amazon.com/Pedestal-Farmhouse-Bathroom-Decorative-Kitchen/dp/B0C68RBNYL/" data-model-name="Wood Bathroom Tray" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/hDHFBVnvy4w4sgFP5Jd9uS.jpg" alt="Wood Bathroom Tray Farmhouse Decor Kitchen Soap Holder, 8.7"x3.6" Brown"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Zoocatia</div>                                        <div class="featured__title">Wood Bathroom Tray</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="11c10f7c-9fd2-11f1-8bcc-c3a6f23ddff7">            <a href="https://www.amazon.com/Miamolo-Ceramic-Holder-Bathroom-Kitchen/dp/B0D6RMCQZ4/" data-model-name="Ceramic Soap Dish" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/6VDYoWT5SRXA8mB3LvdhTR.jpg" alt="Miamolo Soap Dish, Ceramic Soap Holder Shower Soap Dish for Bar Soap Sponge, Soap Saver Tray for Bathroom Kitchen Sink, White"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Miamolo</div>                                        <div class="featured__title">Ceramic Soap Dish</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="11c1101c-9fd2-11f1-b351-1f7555608df2">            <a href="https://www.amazon.com/Etekcity-Digital-Bathroom-Measure-Tempered/dp/B01HI1W1V4/" data-model-name="Digital Bathroom Scale" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:113.64%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/WHxbz5r9xWBQjGqFDiGk8S.jpg" alt="Etekcity Digital Body Weight Bathroom Scale, 6mm Tempered Glass, 400 Lbs"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Etekcity</div>                                        <div class="featured__title">Digital Bathroom Scale</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="11c110bc-9fd2-11f1-9380-3fc6d7b90074">            <a href="https://www.amazon.com/MSAICOE-Shower-Caddy-Hanging-ShowerHead/dp/B0DLW9YSWT/" data-model-name="Msaicoe Shower Caddy Hanging" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:125.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/kYkeKQ4pYenEcfNpBD3n4R.jpg" alt="Msaicoe Shower Caddy Hanging - Never Rust Shower Hanging Organizer - Aluminum Over the Showerhead Caddy With Soap Basket and 6 Hooks for Razor/sponge (black)"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                                                                <div class="featured__title">Msaicoe Shower Caddy Hanging</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="11c11170-9fd2-11f1-bfa1-cb1e6d040886">            <a href="https://www.amazon.com/JOPOFI-Towel-Bar-Bathroom-Holder/dp/B0GX322K8B/" data-model-name="Jopofi Towel Bar" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/kjVffBiqh5YxwtPjc78n4S.jpg" alt="Jopofi Towel Bar - 23.6 Inch Bathroom Towel Holder - Matte Black"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                                                                <div class="featured__title">Jopofi Towel Bar</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="11c11210-9fd2-11f1-b008-497856f3e4bf">            <a href="https://www.amazon.com/Matani-Bamboo-Diatomite-Toothbrush-Holder/dp/B08GZ3766L/" data-model-name="Matani Bamboo Toothbrush Holder" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/W4CxDcae5986qhoUTJYKKQ.jpg" alt="Matani Bamboo Toothbrush Holder Diatomite Tooth Brush Organizer - Storage Stand for Small Bathroom & Counter - Removable Base & Drain Holes, Water-Absorbent & Quick-Drying (light Grey)"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                                                                <div class="featured__title">Matani Bamboo Toothbrush Holder</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="11c112a6-9fd2-11f1-9cf3-656bef95ed5f">            <a href="https://www.amazon.com/Mounted-Height-Adjustable-Lighted-Magnifying/dp/B0HBQ7D29L/" data-model-name="9''Wall Mounted Makeup Mirror" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/q3c7dK5skcAG3g7xLi9wWP.jpg" alt="9'' 30x/1x Wall Mounted Height Adjustable Lighted Magnifying Makeup Mirror"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>VFD</div>                                        <div class="featured__title">9''Wall Mounted Makeup Mirror</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="11c11332-9fd2-11f1-ad62-9d32127e7e9f">            <a href="https://www.amazon.com/SunnyPoint-Standing-Bathroom-Toilet-Reserve/dp/B07TXSFWNM/" data-model-name="Bathroom Toilet Paper Holder" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:141.24%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/rUmsaVSobV8GUr2XDK6ULP.jpg" alt="Sunnypoint Free Standing Bathroom Toilet Paper Holder Stand With Reserve, Reserve Area Has Enough Space for Jumbo Roll"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>SunnyPoint</div>                                        <div class="featured__title">Bathroom Toilet Paper Holder</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="11c113c8-9fd2-11f1-b28c-bfcf501b7c9a">            <a href="https://www.amazon.com/INIUNIK-Bathroom-Accessory-Set-Accessories/dp/B0F9KSGV66/" data-model-name="Bathroom Accessory Set" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:75.60%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/kfcFMo3itdxbwVydneWwiP.jpg" alt="Iniunik Bathroom Accessory Set, 6 Pieces, Dark Grey"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>INIUNIK</div>                                        <div class="featured__title">Bathroom Accessory Set</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="11c115da-9fd2-11f1-b9a4-3dac70ddd33b">            <a href="https://www.amazon.com/Philips-Norelco-Rechargeable-X3001-90/dp/B0CLWVH384/" data-model-name="Philips Norelco Electric Shaver" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/pAnfsnJKVHQCmWUQ2R56BR.jpg" alt="Philips Norelco 2400 Series Electric Shaver, Deep Black"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                                                                <div class="featured__title">Philips Norelco Electric Shaver</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="11c1147c-9fd2-11f1-add3-2f50384abe74">            <a href="https://www.amazon.com/SUNLY-Touchless-Automatic-Soap-Dispenser/dp/B0FD3K7DDY/" data-model-name="Sunly Touchless Automatic Soap Dispenser " data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:133.93%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/TuofAvYATWUakRtwbHhMSD.jpg" alt="SUNLY, Sunly Touchless Automatic Soap Dispenser"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                                                                <div class="featured__title">Sunly Touchless Automatic Soap Dispenser </div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="11c11526-9fd2-11f1-9e3a-6b28e3452f6c">            <a href="https://www.amazon.com/Oral-B-Black-Pro-1000-Rechargeable/dp/B01AKGRTUM/" data-model-name="Oral-B Pro 1000 Electric Toothbrush" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/TEEr6DCLhLLEK4Y2o7WnuF.jpg" alt="Oral-B Pro 1000 Rechargeable Electric Toothbrush, Black"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                                                                <div class="featured__title">Oral-B Pro 1000 Electric Toothbrush</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/home/home-appliances/12-low-cost-bathroom-accessories-under-usd50-that-instantly-elevate-your-space</link>
                                                                            <description>
                            <![CDATA[ Upgrade your bathroom for less with this selection of affordable accessories and devices– all of which cost less than $50. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">uqaKaPUUAxQrMXbrpzHAB5</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/LMkMUBsEMYwzCCh35a2dpH-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Mon, 24 Aug 2026 19:00:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Home Appliances]]></category>
                                                    <category><![CDATA[Home]]></category>
                                                                                                                    <dc:creator><![CDATA[ Will Salmon ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/HpRWP7Mh9ErgRGoTvZBbBJ.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Will Salmon is Tom&#039;s Guide&#039;s Collections Editor, curating advice on the best products to spend your money on. Will has been writing about tech and entertainment for almost 20 years, including stints as GamesRadar+&#039;s Streaming Editor, editing comics website Newsarama, and writing for lots and lots of magazines.&lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/LMkMUBsEMYwzCCh35a2dpH-1280-80.jpg">
                                                            <media:credit><![CDATA[Miamolo, Zoocatia, Jopofi, Iniunik, Sunly / Edited by Gemini]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[A selection of bathroom products.]]></media:description>                                                            <media:text><![CDATA[A selection of bathroom products.]]></media:text>
                                <media:title type="plain"><![CDATA[A selection of bathroom products.]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/LMkMUBsEMYwzCCh35a2dpH-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Upgrading your bathroom doesn't have to cost the Earth. Sometimes it's just a case of finding the right accessories to make your space feel more homey, and adding a few useful gadgets.</p><p>For this article I've selected 12 items that have practical utility and a touch of straightforward style, so they will fit into almost any bathroom. That means things like toothbrush holders, towel bars, soap trays and more. I've also picked out a few essential  devices, like an electric toothbrush and a scale.</p><p>It's easy for costs to quickly add up, so for that reason I've only picked out budget items: everything here currently costs less than $50 on Amazon, so you're not going to break the bank while filling out your space.</p>        <div class="featured_product_block featured_block_hero" data-id="11c10eb4-9fd2-11f1-8c02-e5b2f99fc6c1">            <a href="https://www.amazon.com/Pedestal-Farmhouse-Bathroom-Decorative-Kitchen/dp/B0C68RBNYL/" data-model-name="Wood Bathroom Tray" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/hDHFBVnvy4w4sgFP5Jd9uS.jpg" alt="Wood Bathroom Tray Farmhouse Decor Kitchen Soap Holder, 8.7"x3.6" Brown"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Zoocatia</div>                                        <div class="featured__title">Wood Bathroom Tray</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="11c10f7c-9fd2-11f1-8bcc-c3a6f23ddff7">            <a href="https://www.amazon.com/Miamolo-Ceramic-Holder-Bathroom-Kitchen/dp/B0D6RMCQZ4/" data-model-name="Ceramic Soap Dish" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/6VDYoWT5SRXA8mB3LvdhTR.jpg" alt="Miamolo Soap Dish, Ceramic Soap Holder Shower Soap Dish for Bar Soap Sponge, Soap Saver Tray for Bathroom Kitchen Sink, White"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Miamolo</div>                                        <div class="featured__title">Ceramic Soap Dish</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="11c1101c-9fd2-11f1-b351-1f7555608df2">            <a href="https://www.amazon.com/Etekcity-Digital-Bathroom-Measure-Tempered/dp/B01HI1W1V4/" data-model-name="Digital Bathroom Scale" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:113.64%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/WHxbz5r9xWBQjGqFDiGk8S.jpg" alt="Etekcity Digital Body Weight Bathroom Scale, 6mm Tempered Glass, 400 Lbs"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Etekcity</div>                                        <div class="featured__title">Digital Bathroom Scale</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="11c110bc-9fd2-11f1-9380-3fc6d7b90074">            <a href="https://www.amazon.com/MSAICOE-Shower-Caddy-Hanging-ShowerHead/dp/B0DLW9YSWT/" data-model-name="Msaicoe Shower Caddy Hanging" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:125.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/kYkeKQ4pYenEcfNpBD3n4R.jpg" alt="Msaicoe Shower Caddy Hanging - Never Rust Shower Hanging Organizer - Aluminum Over the Showerhead Caddy With Soap Basket and 6 Hooks for Razor/sponge (black)"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                                                                <div class="featured__title">Msaicoe Shower Caddy Hanging</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="11c11170-9fd2-11f1-bfa1-cb1e6d040886">            <a href="https://www.amazon.com/JOPOFI-Towel-Bar-Bathroom-Holder/dp/B0GX322K8B/" data-model-name="Jopofi Towel Bar" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/kjVffBiqh5YxwtPjc78n4S.jpg" alt="Jopofi Towel Bar - 23.6 Inch Bathroom Towel Holder - Matte Black"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                                                                <div class="featured__title">Jopofi Towel Bar</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="11c11210-9fd2-11f1-b008-497856f3e4bf">            <a href="https://www.amazon.com/Matani-Bamboo-Diatomite-Toothbrush-Holder/dp/B08GZ3766L/" data-model-name="Matani Bamboo Toothbrush Holder" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/W4CxDcae5986qhoUTJYKKQ.jpg" alt="Matani Bamboo Toothbrush Holder Diatomite Tooth Brush Organizer - Storage Stand for Small Bathroom & Counter - Removable Base & Drain Holes, Water-Absorbent & Quick-Drying (light Grey)"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                                                                <div class="featured__title">Matani Bamboo Toothbrush Holder</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="11c112a6-9fd2-11f1-9cf3-656bef95ed5f">            <a href="https://www.amazon.com/Mounted-Height-Adjustable-Lighted-Magnifying/dp/B0HBQ7D29L/" data-model-name="9''Wall Mounted Makeup Mirror" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/q3c7dK5skcAG3g7xLi9wWP.jpg" alt="9'' 30x/1x Wall Mounted Height Adjustable Lighted Magnifying Makeup Mirror"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>VFD</div>                                        <div class="featured__title">9''Wall Mounted Makeup Mirror</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="11c11332-9fd2-11f1-ad62-9d32127e7e9f">            <a href="https://www.amazon.com/SunnyPoint-Standing-Bathroom-Toilet-Reserve/dp/B07TXSFWNM/" data-model-name="Bathroom Toilet Paper Holder" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:141.24%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/rUmsaVSobV8GUr2XDK6ULP.jpg" alt="Sunnypoint Free Standing Bathroom Toilet Paper Holder Stand With Reserve, Reserve Area Has Enough Space for Jumbo Roll"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>SunnyPoint</div>                                        <div class="featured__title">Bathroom Toilet Paper Holder</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="11c113c8-9fd2-11f1-b28c-bfcf501b7c9a">            <a href="https://www.amazon.com/INIUNIK-Bathroom-Accessory-Set-Accessories/dp/B0F9KSGV66/" data-model-name="Bathroom Accessory Set" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:75.60%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/kfcFMo3itdxbwVydneWwiP.jpg" alt="Iniunik Bathroom Accessory Set, 6 Pieces, Dark Grey"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>INIUNIK</div>                                        <div class="featured__title">Bathroom Accessory Set</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="11c115da-9fd2-11f1-b9a4-3dac70ddd33b">            <a href="https://www.amazon.com/Philips-Norelco-Rechargeable-X3001-90/dp/B0CLWVH384/" data-model-name="Philips Norelco Electric Shaver" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/pAnfsnJKVHQCmWUQ2R56BR.jpg" alt="Philips Norelco 2400 Series Electric Shaver, Deep Black"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                                                                <div class="featured__title">Philips Norelco Electric Shaver</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="11c1147c-9fd2-11f1-add3-2f50384abe74">            <a href="https://www.amazon.com/SUNLY-Touchless-Automatic-Soap-Dispenser/dp/B0FD3K7DDY/" data-model-name="Sunly Touchless Automatic Soap Dispenser " data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:133.93%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/TuofAvYATWUakRtwbHhMSD.jpg" alt="SUNLY, Sunly Touchless Automatic Soap Dispenser"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                                                                <div class="featured__title">Sunly Touchless Automatic Soap Dispenser </div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="11c11526-9fd2-11f1-9e3a-6b28e3452f6c">            <a href="https://www.amazon.com/Oral-B-Black-Pro-1000-Rechargeable/dp/B01AKGRTUM/" data-model-name="Oral-B Pro 1000 Electric Toothbrush" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/TEEr6DCLhLLEK4Y2o7WnuF.jpg" alt="Oral-B Pro 1000 Rechargeable Electric Toothbrush, Black"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                                                                <div class="featured__title">Oral-B Pro 1000 Electric Toothbrush</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ Enter the Vitamix Nano: Could it be the answer to perfectly blended single-serve smoothies? ]]></title>
                                                                                                <dc:content><![CDATA[ <p>Vitamix makes some of the <a href="https://www.tomsguide.com/best-picks/best-blenders">best blenders</a> on the market — our testing at Tom’s Guide consistently proves it — but the brand’s premium price tags often put them out of reach.</p><p>However, that just changed with the launch of the Vitamix Nano. The brand is re-entering the single-serve market with a compact, personal blender design for the health-conscious in mind, and it’s available for <a href="https://www.vitamix.com/us/en_us" target="_blank" rel="nofollow">$199 at Vitamix</a>.</p><h2 id="single-serve-smoothies">Single-serve smoothies</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="bYv4sFXPAXKQ25oCFkmWTc" name="Vitamix Nano" alt="Vitamix Nano" src="https://cdn.mos.cms.futurecdn.net/bYv4sFXPAXKQ25oCFkmWTc.png" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Vitamix)</span></figcaption></figure><p>The compact Nano isn’t designed for big elaborate feasts. Instead, it focuses on the essentials: creating smoothies and frozen drinks with a small footprint that won’t overcrowd your countertop.</p><p>Although you don’t get all the multi-functions of other Vitamix blenders, such as the <a href="https://www.tomsguide.com/home/home-appliances/vitamix-ascent-x2-blender-review">Vitamix Ascent X2</a>, which takes the top spot in our <a href="https://www.tomsguide.com/best-picks/best-blenders">best blenders buying guide</a>, you don’t get short-changed on performance. The Vitamix Nano has a single purpose.</p><div class="product"><a data-dimension112="196edacc-9fac-11f1-a0b9-e9e3c8c2a9ea" data-action="Deal Block" data-label="Nano" data-dimension48="Nano" data-dimension25="$199" href="https://www.vitamix.com/us/en_us/products/nano" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:500px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="qRJet8VAb3tngGTe3hwQ39" name="Vitamix Nano" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/qRJet8VAb3tngGTe3hwQ39.png" mos="" align="middle" fullscreen="" width="500" height="500" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.vitamix.com/us/en_us/products/nano" target="_blank" rel="nofollow" data-dimension112="196edacc-9fac-11f1-a0b9-e9e3c8c2a9ea" data-action="Deal Block" data-label="Nano" data-dimension48="Nano" data-dimension25="$199">Nano: $199</a></strong><br>The Vitamix personal, single-serve blender that thinks while it blends. Select the SmoothiePilot setting, and the blender will automatically adjust the speed and timing to achieve the right texture. Or, opt for the variable speed for a personalized choice.  <a class="view-deal button" href="https://www.vitamix.com/us/en_us/products/nano" target="_blank" rel="nofollow" data-dimension112="196edacc-9fac-11f1-a0b9-e9e3c8c2a9ea" data-action="Deal Block" data-label="Nano" data-dimension48="Nano" data-dimension25="$199">View Deal</a></p></div><h2 id="intelligent-blending">Intelligent blending</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="3NBt4nQV6d8iYABTmherzA" name="Vitamix Nano" alt="Vitamix Nano" src="https://cdn.mos.cms.futurecdn.net/3NBt4nQV6d8iYABTmherzA.png" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Vitamix)</span></figcaption></figure><p>At the heart of the Vitamix Nano is SmoothiePilot — the brand’s first adaptive smoothie feature. So what exactly does that mean? It senses what’s happening inside the cup and automatically selects the optimal blend program, adjusting the speed and duration to deliver a smooth result, whether making a smoothie or frozen cocktail.</p><p>Laura Ostenkamp, vice president of sales and marketing at Vitamix, says, in short, it "blends every time with no guesswork required."</p><p>Does this put an end to pausing mid-blend to check and stir the ingredients, and to finding unexpected lumps in your cocktails? We’ll have to see how it performs once we receive a unit to test. </p><h2 id="the-vitamix-nano-what-do-you-get">The Vitamix Nano: What do you get?</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="ZfwKLjkxXTXkmTGBABPzQc" name="Vitamix Nano" alt="Vitamix Nano" src="https://cdn.mos.cms.futurecdn.net/ZfwKLjkxXTXkmTGBABPzQc.png" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Vitamix)</span></figcaption></figure><p>So what does this compact <strong>20-ounce cup</strong> blender offer, and is it worth paying $199 for the privilege? Vitamix says it comes with a high-powered <strong>1,000-watt motor</strong> and <strong>hardened stainless steel blades</strong> to tackle tough ingredients like ice and frozen fruit. </p><p>What’s more, the technology takes away all the hard work, making the controls simple: select <strong>SmoothiePilot</strong> for a perfectly smooth drink, or select <strong>variable speed</strong> for your preferred texture. </p><p>You also get <strong>two cups with lids</strong>, so you can blend your drinks and go, or keep one in the refrigerator for later.<br><br>Cleaning a blender can be notoriously tricky, but once you’ve made your drink, clean up is easy. According to Vitamix, it <strong>self-cleans in 30 seconds</strong>; just add hot water and a drop of dish soap; there’s no need to disassemble the unit. But, for an easy life, it’s also <strong>dishwasher-safe</strong>. </p><p>And if you’re wondering whether you have enough space for another gadget on your countertop, the Vitamix Nano is mini. It measures just 8.5 inches x 5.5 inches at the base, and stands 15.3 inches tall. </p><p>The only choice you’ll have to make apart from selecting SmoothiePilot or the variable control is whether to buy the white or black version. My money is on the black, although I’d like to see a few punchy candy colors introduced in the future.</p><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h3><ul><li><a href="https://www.tomsguide.com/home/kitchen-dining/vitamix-just-released-an-entry-level-version-of-our-all-time-favorite-blender">Vitamix just released an entry-level version of our all-time favorite blender</a></li><li><a href="https://www.tomsguide.com/home/home-appliances/ninja-blast-max-review">I made smoothies, shakes and pancake batter in Ninja's most powerful portable blender — here's my verdict</a></li><li><a href="https://www.tomsguide.com/home/home-appliances/i-threw-out-my-nutribullet-blender-after-testing-this-beast-personal-blender-heres-why">I threw out my Nutribullet blender after testing this Beast personal blender — here's why</a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/home/kitchen-dining/enter-the-vitamix-nano-could-it-be-the-answer-to-perfectly-blended-single-serve-smoothies</link>
                                                                            <description>
                            <![CDATA[ Vitamix just launched a new personal blender with intelligent tech: Is it worth $199? ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">9o2Ahgvh7Wwc68qQbD48Tk</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/YgkcnUArksceTGzwaftMU3-1280-80.png" type="image/png" length="0"></enclosure>
                                                                        <pubDate>Mon, 24 Aug 2026 13:53:29 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Kitchen & Dining]]></category>
                                                    <category><![CDATA[Home]]></category>
                                                    <category><![CDATA[Home Appliances]]></category>
                                                                                                <author><![CDATA[ camilla.sharman@futurenet.com (Camilla Sharman) ]]></author>                    <dc:creator><![CDATA[ Camilla Sharman ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/nY4nvWzofHKHpvzAqN5LVH.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Camilla is the Homes Staff Writer and covers everything to do with homes and gardens. She has a wealth of editorial experience, mounting over 30 years, and covers news and features, tests products for reviews and compiles buying guides.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;p&gt;Her work has appeared in business and consumer titles, including Ideal Home, Real Homes, House Beautiful, Homebuilding &amp;amp; Renovation, and Kitchen &amp;amp; Bathroom Business. She’s even appeared on the cover of Your Home, writing about her own house renovation.&lt;/p&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;p&gt;Although she’s obsessed with decorating her home, she also enjoys baking and trying out the latest kitchen appliances. But when she’s not inside, you’ll find her pottering about in her yard, tending to her vegetable patch or taking in her prized hydrangeas. She also enjoys keeping fit, and if she&#039;s not on a spin bike trying to keep up with the class, she&#039;ll be in the pool, or trying to perfect her headstand in a yoga class.&lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                <media:content type="image/png" url="https://cdn.mos.cms.futurecdn.net/YgkcnUArksceTGzwaftMU3-1280-80.png">
                                                            <media:credit><![CDATA[Vitamix]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Vitamix Nano in black]]></media:description>                                                            <media:text><![CDATA[Vitamix Nano in black]]></media:text>
                                <media:title type="plain"><![CDATA[Vitamix Nano in black]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/YgkcnUArksceTGzwaftMU3-1280-80.png" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Vitamix makes some of the <a href="https://www.tomsguide.com/best-picks/best-blenders">best blenders</a> on the market — our testing at Tom’s Guide consistently proves it — but the brand’s premium price tags often put them out of reach.</p><p>However, that just changed with the launch of the Vitamix Nano. The brand is re-entering the single-serve market with a compact, personal blender design for the health-conscious in mind, and it’s available for <a href="https://www.vitamix.com/us/en_us" target="_blank" rel="nofollow">$199 at Vitamix</a>.</p><h2 id="single-serve-smoothies">Single-serve smoothies</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="bYv4sFXPAXKQ25oCFkmWTc" name="Vitamix Nano" alt="Vitamix Nano" src="https://cdn.mos.cms.futurecdn.net/bYv4sFXPAXKQ25oCFkmWTc.png" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Vitamix)</span></figcaption></figure><p>The compact Nano isn’t designed for big elaborate feasts. Instead, it focuses on the essentials: creating smoothies and frozen drinks with a small footprint that won’t overcrowd your countertop.</p><p>Although you don’t get all the multi-functions of other Vitamix blenders, such as the <a href="https://www.tomsguide.com/home/home-appliances/vitamix-ascent-x2-blender-review">Vitamix Ascent X2</a>, which takes the top spot in our <a href="https://www.tomsguide.com/best-picks/best-blenders">best blenders buying guide</a>, you don’t get short-changed on performance. The Vitamix Nano has a single purpose.</p><div class="product"><a data-dimension112="196edacc-9fac-11f1-a0b9-e9e3c8c2a9ea" data-action="Deal Block" data-label="Nano" data-dimension48="Nano" data-dimension25="$199" href="https://www.vitamix.com/us/en_us/products/nano" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:500px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="qRJet8VAb3tngGTe3hwQ39" name="Vitamix Nano" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/qRJet8VAb3tngGTe3hwQ39.png" mos="" align="middle" fullscreen="" width="500" height="500" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.vitamix.com/us/en_us/products/nano" target="_blank" rel="nofollow" data-dimension112="196edacc-9fac-11f1-a0b9-e9e3c8c2a9ea" data-action="Deal Block" data-label="Nano" data-dimension48="Nano" data-dimension25="$199">Nano: $199</a></strong><br>The Vitamix personal, single-serve blender that thinks while it blends. Select the SmoothiePilot setting, and the blender will automatically adjust the speed and timing to achieve the right texture. Or, opt for the variable speed for a personalized choice.  <a class="view-deal button" href="https://www.vitamix.com/us/en_us/products/nano" target="_blank" rel="nofollow" data-dimension112="196edacc-9fac-11f1-a0b9-e9e3c8c2a9ea" data-action="Deal Block" data-label="Nano" data-dimension48="Nano" data-dimension25="$199">View Deal</a></p></div><h2 id="intelligent-blending">Intelligent blending</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="3NBt4nQV6d8iYABTmherzA" name="Vitamix Nano" alt="Vitamix Nano" src="https://cdn.mos.cms.futurecdn.net/3NBt4nQV6d8iYABTmherzA.png" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Vitamix)</span></figcaption></figure><p>At the heart of the Vitamix Nano is SmoothiePilot — the brand’s first adaptive smoothie feature. So what exactly does that mean? It senses what’s happening inside the cup and automatically selects the optimal blend program, adjusting the speed and duration to deliver a smooth result, whether making a smoothie or frozen cocktail.</p><p>Laura Ostenkamp, vice president of sales and marketing at Vitamix, says, in short, it "blends every time with no guesswork required."</p><p>Does this put an end to pausing mid-blend to check and stir the ingredients, and to finding unexpected lumps in your cocktails? We’ll have to see how it performs once we receive a unit to test. </p><h2 id="the-vitamix-nano-what-do-you-get">The Vitamix Nano: What do you get?</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="ZfwKLjkxXTXkmTGBABPzQc" name="Vitamix Nano" alt="Vitamix Nano" src="https://cdn.mos.cms.futurecdn.net/ZfwKLjkxXTXkmTGBABPzQc.png" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Vitamix)</span></figcaption></figure><p>So what does this compact <strong>20-ounce cup</strong> blender offer, and is it worth paying $199 for the privilege? Vitamix says it comes with a high-powered <strong>1,000-watt motor</strong> and <strong>hardened stainless steel blades</strong> to tackle tough ingredients like ice and frozen fruit. </p><p>What’s more, the technology takes away all the hard work, making the controls simple: select <strong>SmoothiePilot</strong> for a perfectly smooth drink, or select <strong>variable speed</strong> for your preferred texture. </p><p>You also get <strong>two cups with lids</strong>, so you can blend your drinks and go, or keep one in the refrigerator for later.<br><br>Cleaning a blender can be notoriously tricky, but once you’ve made your drink, clean up is easy. According to Vitamix, it <strong>self-cleans in 30 seconds</strong>; just add hot water and a drop of dish soap; there’s no need to disassemble the unit. But, for an easy life, it’s also <strong>dishwasher-safe</strong>. </p><p>And if you’re wondering whether you have enough space for another gadget on your countertop, the Vitamix Nano is mini. It measures just 8.5 inches x 5.5 inches at the base, and stands 15.3 inches tall. </p><p>The only choice you’ll have to make apart from selecting SmoothiePilot or the variable control is whether to buy the white or black version. My money is on the black, although I’d like to see a few punchy candy colors introduced in the future.</p><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h3><ul><li><a href="https://www.tomsguide.com/home/kitchen-dining/vitamix-just-released-an-entry-level-version-of-our-all-time-favorite-blender">Vitamix just released an entry-level version of our all-time favorite blender</a></li><li><a href="https://www.tomsguide.com/home/home-appliances/ninja-blast-max-review">I made smoothies, shakes and pancake batter in Ninja's most powerful portable blender — here's my verdict</a></li><li><a href="https://www.tomsguide.com/home/home-appliances/i-threw-out-my-nutribullet-blender-after-testing-this-beast-personal-blender-heres-why">I threw out my Nutribullet blender after testing this Beast personal blender — here's why</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ People are mixing coffee with Diet Coke (yes, really) — I'm an ex-barista, and I tried the viral 'fridge cigarette' ]]></title>
                                                                                                <dc:content><![CDATA[ <div  class="fancy-box"><div class="fancy_box-title">The Coffee Lab</div><div class="fancy_box_body"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' ><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="UwFdgr6xkNzHUWjapZThcN" name="smeg edited2" caption="" alt="the smeg emc02 mini pro manual espresso machine in jade green" src="https://cdn.mos.cms.futurecdn.net/UwFdgr6xkNzHUWjapZThcN.jpg" mos="" link="" align="" fullscreen="" width="" height="" attribution="" endorsement="" class="pinterest-pin-exclude"></p></div></div><figcaption itemprop="caption description" class=""><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p class="fancy-box__body-text">I'm Erin, and welcome to the twenty-first episode of <a data-analytics-id="inline-link" href="https://www.tomsguide.com/tag/the-coffee-lab">The Coffee Lab</a>, the series where we forget coffee snobbery. The Coffee Lab is all about making coffee fun. Join me as I help you kickstart your coffee journey!</p></div></div><p>Let me put you onto something weird: the "Fridge cigarette." I've seen this term used to refer to a cold, crisp can of Diet Coke, but recently, another meaning has arisen: Diet Coke + espresso. As director of <a href="https://www.tomsguide.com/tag/the-coffee-lab">The Coffee Lab</a> and coffee nerd, I had to try this out. What do you mean, people are mixing coffee and Diet Coke? How can that possibly taste good?</p><p>To make it, I bought a simple can of Diet Coke and made a shot of espresso using my <a href="https://www.tomsguide.com/home/coffee-makers/sage-breville-bambino-review">Breville Bambino</a>. Then, I mixed them — simple as that. No fiddling with measurements or layering cream on top like Starbucks's Sweet Cream Cold Brew.</p><p>So, is the "Fridge cigarette" worth your time? Let's get into it. If you want me to try out more weird recipes, comment them down below, and I'll be sure to include them in the next Coffee Lab video.</p>                    <div class= "tiktok-wrapper" style="min-height: 750px;"><blockquote class="tiktok-embed" cite="https://www.tiktok.com/@tomsguide/video/7677698671265303822" data-video-id="7677698671265303822" style="max-width: 605px; min-width: 325px;">                        <section>                            <a target="_blank" title="@tomsguide" href="https://www.tiktok.com/@tomsguide">@tomsguide</a>                            <p></p><a target="_blank" title="♬ city lights drift - GIN CUBE" href="https://www.tiktok.com/music/city-lights-drift-7599489479816661009">♬ city lights drift - GIN CUBE</a></section>                    </blockquote></div>                <h2 id="how-to-make-a-39-fridge-cigarette-39">How to make a 'fridge cigarette'</h2><p>As I said earlier, making a fridge cigarette is super easy.</p><section class="howto-block">                    <h3>1. Procure a can of Diet Coke</h3>                    <figure>                            <p class="bordeaux-image-check">                                <img    src="https://cdn.mos.cms.futurecdn.net/Xq5LMnptjfrhuwg3KZCCh9.jpg"                                        alt="a photo of the viral fridge cigarette coffee + diet coke being made"                                        onerror="this.parentNode.replaceChild(window.missingImage(),this)"                                        data-pin-media="https://cdn.mos.cms.futurecdn.net/Xq5LMnptjfrhuwg3KZCCh9.jpg"                                        class="expandable van-old-layout-image">                            </p><div class="credit">(Image: © Erin Bashford)</div></figure>                                    </section><section class="howto-block">                    <h3>2. Pull a shot of espresso</h3>                    <figure>                            <p class="bordeaux-image-check">                                <img    src="https://cdn.mos.cms.futurecdn.net/jRAVgmnzQ5oEMAgJYWXVNb.png"                                        alt="a photo of an espresso made on the breville bambino / sage bambino "                                        onerror="this.parentNode.replaceChild(window.missingImage(),this)"                                        data-pin-media="https://cdn.mos.cms.futurecdn.net/jRAVgmnzQ5oEMAgJYWXVNb.png"                                        class="expandable van-old-layout-image">                            </p><div class="credit">(Image: © Erin Bashford)</div></figure>                                    </section><section class="howto-block">                    <h3>3. Mix them together</h3>                    <figure>                            <p class="bordeaux-image-check">                                <img    src="https://cdn.mos.cms.futurecdn.net/JJfW8FaoLzipNUwyke4Ys9.jpg"                                        alt="a photo of the viral fridge cigarette coffee + diet coke being made"                                        onerror="this.parentNode.replaceChild(window.missingImage(),this)"                                        data-pin-media="https://cdn.mos.cms.futurecdn.net/JJfW8FaoLzipNUwyke4Ys9.jpg"                                        class="expandable van-old-layout-image">                            </p><div class="credit">(Image: © Erin Bashford)</div></figure>                                    </section><h2 id="how-does-it-taste">How does it taste?</h2><p>It doesn't look appealing, but the fridge cigarette actually tastes... good? </p><p>If you like Espresso Martinis, you'll love the fridge cigarette. It took me a moment to identify the flavor — at first I thought Guinness, but then realized that wasn't the specific flavor I was tasting. It's sweet and vanilla-y, with a rich, malty afternote rounding it out.</p><p>I mean, it's not massively shocking. Diet Coke = vanilla. Espresso = coffee. Espresso Martini = vanilla, coffee. All the same flavors are going on here. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:5071px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="dXphpzD79anUdiPYYPbbt9" name="fridge cigarette final" alt="a photo of the viral fridge cigarette coffee + diet coke being made" src="https://cdn.mos.cms.futurecdn.net/dXphpzD79anUdiPYYPbbt9.jpg" mos="" align="middle" fullscreen="" width="5071" height="2852" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Erin Bashford)</span></figcaption></figure><p>What about caffeine content? I mean, if you're super exhausted, this might be a way to bring you back to life. As soon as I drank about half, my hands started shaking, and I was acutely aware of the fluorescent lights in the studio. This isn't a drink I'd recommend if you're sensitive to caffeine. This is only for hardened caffeinators.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-ODqdlX"></div>                            </div>                            <script src="https://kwizly.com/embed/ODqdlX.js" async></script><p>As always, let me know if you have any questions or if there are any other weird coffee drinks you want me to taste-test next. Stay tuned for the next episode of The Coffee Lab, landing at a YouTube, TikTok, and Instagram near you.</p><figure class="inline-layout"><div style="min-height: 400px;"><fw-embed-feed channel="toms_guide" playlist="ojE0pK" mode="row" player_placement="bottom-right"></fw-embed-feed></div></figure><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h3><ul><li><a href="https://www.tomsguide.com/home/coffee-makers/overwhelmed-by-coffee-jargon-here-are-the-5-key-espresso-terms-you-need-to-know"><strong>Overwhelmed by coffee jargon? Here are the 5 key espresso terms you need to know</strong></a></li><li><a href="https://www.tomsguide.com/home/coffee-makers/im-an-ex-starbucks-barista-you-can-make-the-iced-brown-sugar-oatmilk-shaken-espresso-at-home-for-a-fraction-of-the-cost"><strong>I'm an ex-Starbucks barista — you can make the Iced Brown Sugar Oatmilk Shaken Espresso at home for a fraction of the cost</strong></a></li><li><a href="https://www.tomsguide.com/home/coffee-makers/i-tried-lelits-brand-new-entry-level-espresso-machine-and-i-wish-i-had-usd2-000-so-i-could-buy-it"><strong>I tried Lelit's brand-new 'entry-level' espresso machine — and I wish I had $2,000 so I could buy it</strong></a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/home/coffee-makers/people-are-mixing-coffee-with-diet-coke-yes-really-im-an-ex-barista-and-i-tried-the-viral-fridge-cigarette</link>
                                                                            <description>
                            <![CDATA[ On the 21st episode of The Coffee Lab, I'm trying the viral "Fridge Cigarette" coffee cocktail. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">N838JhoZDPfsJuvPKEtoM3</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/rPFq2zqVWgJdfoc8oQK4Sg-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Mon, 24 Aug 2026 05:00:00 +0000</pubDate>                                                                                                                                <updated>Tue, 25 Aug 2026 12:34:06 +0000</updated>
                                                                                                                                            <category><![CDATA[Coffee Makers]]></category>
                                                    <category><![CDATA[Home]]></category>
                                                    <category><![CDATA[Home Appliances]]></category>
                                                    <category><![CDATA[Kitchen & Dining]]></category>
                                                                                                <author><![CDATA[ erin.bashford@futurenet.com (Erin Bashford) ]]></author>                    <dc:creator><![CDATA[ Erin Bashford ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/rLvJvJVZx43hEzSsJy3BpL.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Erin Bashford is a senior reviews writer at Tom’s Guide. She has a Master’s in Broadcast and Digital Journalism from the University of East Anglia and 7 years of experience reviewing music and events for various publications. She has edited publications such as Outline Magazine’s Guide to Norwich, and she has written for a number of music magazines and websites such as Clash Magazine, Outline Magazine and Dork Magazine. She has a strong interest in audio gear and the music world. &lt;/p&gt;&lt;p&gt;As an ex-barista, Erin is passionate about coffee tech. She also loves finding the best cooking hacks and kitchen appliances, including her beloved Instant Pot. &lt;/p&gt;&lt;p&gt;In her spare time, you can find her reading, practising yoga, hiking, writing fantasy novels, or stressing over NYT Games.&lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/rPFq2zqVWgJdfoc8oQK4Sg-1280-80.jpg">
                                                            <media:credit><![CDATA[Erin Bashford]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[a photo of a diet coke with the coffee lab logo]]></media:description>                                                            <media:text><![CDATA[a photo of a diet coke with the coffee lab logo]]></media:text>
                                <media:title type="plain"><![CDATA[a photo of a diet coke with the coffee lab logo]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/rPFq2zqVWgJdfoc8oQK4Sg-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <div  class="fancy-box"><div class="fancy_box-title">The Coffee Lab</div><div class="fancy_box_body"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' ><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="UwFdgr6xkNzHUWjapZThcN" name="smeg edited2" caption="" alt="the smeg emc02 mini pro manual espresso machine in jade green" src="https://cdn.mos.cms.futurecdn.net/UwFdgr6xkNzHUWjapZThcN.jpg" mos="" link="" align="" fullscreen="" width="" height="" attribution="" endorsement="" class="pinterest-pin-exclude"></p></div></div><figcaption itemprop="caption description" class=""><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p class="fancy-box__body-text">I'm Erin, and welcome to the twenty-first episode of <a data-analytics-id="inline-link" href="https://www.tomsguide.com/tag/the-coffee-lab">The Coffee Lab</a>, the series where we forget coffee snobbery. The Coffee Lab is all about making coffee fun. Join me as I help you kickstart your coffee journey!</p></div></div><p>Let me put you onto something weird: the "Fridge cigarette." I've seen this term used to refer to a cold, crisp can of Diet Coke, but recently, another meaning has arisen: Diet Coke + espresso. As director of <a href="https://www.tomsguide.com/tag/the-coffee-lab">The Coffee Lab</a> and coffee nerd, I had to try this out. What do you mean, people are mixing coffee and Diet Coke? How can that possibly taste good?</p><p>To make it, I bought a simple can of Diet Coke and made a shot of espresso using my <a href="https://www.tomsguide.com/home/coffee-makers/sage-breville-bambino-review">Breville Bambino</a>. Then, I mixed them — simple as that. No fiddling with measurements or layering cream on top like Starbucks's Sweet Cream Cold Brew.</p><p>So, is the "Fridge cigarette" worth your time? Let's get into it. If you want me to try out more weird recipes, comment them down below, and I'll be sure to include them in the next Coffee Lab video.</p>                    <div class= "tiktok-wrapper" style="min-height: 750px;"><blockquote class="tiktok-embed" cite="https://www.tiktok.com/@tomsguide/video/7677698671265303822" data-video-id="7677698671265303822" style="max-width: 605px; min-width: 325px;">                        <section>                            <a target="_blank" title="@tomsguide" href="https://www.tiktok.com/@tomsguide">@tomsguide</a>                            <p></p><a target="_blank" title="♬ city lights drift - GIN CUBE" href="https://www.tiktok.com/music/city-lights-drift-7599489479816661009">♬ city lights drift - GIN CUBE</a></section>                    </blockquote></div>                <h2 id="how-to-make-a-39-fridge-cigarette-39">How to make a 'fridge cigarette'</h2><p>As I said earlier, making a fridge cigarette is super easy.</p><section class="howto-block">                    <h3>1. Procure a can of Diet Coke</h3>                    <figure>                            <p class="bordeaux-image-check">                                <img    src="https://cdn.mos.cms.futurecdn.net/Xq5LMnptjfrhuwg3KZCCh9.jpg"                                        alt="a photo of the viral fridge cigarette coffee + diet coke being made"                                        onerror="this.parentNode.replaceChild(window.missingImage(),this)"                                        data-pin-media="https://cdn.mos.cms.futurecdn.net/Xq5LMnptjfrhuwg3KZCCh9.jpg"                                        class="expandable van-old-layout-image">                            </p><div class="credit">(Image: © Erin Bashford)</div></figure>                                    </section><section class="howto-block">                    <h3>2. Pull a shot of espresso</h3>                    <figure>                            <p class="bordeaux-image-check">                                <img    src="https://cdn.mos.cms.futurecdn.net/jRAVgmnzQ5oEMAgJYWXVNb.png"                                        alt="a photo of an espresso made on the breville bambino / sage bambino "                                        onerror="this.parentNode.replaceChild(window.missingImage(),this)"                                        data-pin-media="https://cdn.mos.cms.futurecdn.net/jRAVgmnzQ5oEMAgJYWXVNb.png"                                        class="expandable van-old-layout-image">                            </p><div class="credit">(Image: © Erin Bashford)</div></figure>                                    </section><section class="howto-block">                    <h3>3. Mix them together</h3>                    <figure>                            <p class="bordeaux-image-check">                                <img    src="https://cdn.mos.cms.futurecdn.net/JJfW8FaoLzipNUwyke4Ys9.jpg"                                        alt="a photo of the viral fridge cigarette coffee + diet coke being made"                                        onerror="this.parentNode.replaceChild(window.missingImage(),this)"                                        data-pin-media="https://cdn.mos.cms.futurecdn.net/JJfW8FaoLzipNUwyke4Ys9.jpg"                                        class="expandable van-old-layout-image">                            </p><div class="credit">(Image: © Erin Bashford)</div></figure>                                    </section><h2 id="how-does-it-taste">How does it taste?</h2><p>It doesn't look appealing, but the fridge cigarette actually tastes... good? </p><p>If you like Espresso Martinis, you'll love the fridge cigarette. It took me a moment to identify the flavor — at first I thought Guinness, but then realized that wasn't the specific flavor I was tasting. It's sweet and vanilla-y, with a rich, malty afternote rounding it out.</p><p>I mean, it's not massively shocking. Diet Coke = vanilla. Espresso = coffee. Espresso Martini = vanilla, coffee. All the same flavors are going on here. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:5071px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="dXphpzD79anUdiPYYPbbt9" name="fridge cigarette final" alt="a photo of the viral fridge cigarette coffee + diet coke being made" src="https://cdn.mos.cms.futurecdn.net/dXphpzD79anUdiPYYPbbt9.jpg" mos="" align="middle" fullscreen="" width="5071" height="2852" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Erin Bashford)</span></figcaption></figure><p>What about caffeine content? I mean, if you're super exhausted, this might be a way to bring you back to life. As soon as I drank about half, my hands started shaking, and I was acutely aware of the fluorescent lights in the studio. This isn't a drink I'd recommend if you're sensitive to caffeine. This is only for hardened caffeinators.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-ODqdlX"></div>                            </div>                            <script src="https://kwizly.com/embed/ODqdlX.js" async></script><p>As always, let me know if you have any questions or if there are any other weird coffee drinks you want me to taste-test next. Stay tuned for the next episode of The Coffee Lab, landing at a YouTube, TikTok, and Instagram near you.</p><figure class="inline-layout"><div style="min-height: 400px;"><fw-embed-feed channel="toms_guide" playlist="ojE0pK" mode="row" player_placement="bottom-right"></fw-embed-feed></div></figure><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h3><ul><li><a href="https://www.tomsguide.com/home/coffee-makers/overwhelmed-by-coffee-jargon-here-are-the-5-key-espresso-terms-you-need-to-know"><strong>Overwhelmed by coffee jargon? Here are the 5 key espresso terms you need to know</strong></a></li><li><a href="https://www.tomsguide.com/home/coffee-makers/im-an-ex-starbucks-barista-you-can-make-the-iced-brown-sugar-oatmilk-shaken-espresso-at-home-for-a-fraction-of-the-cost"><strong>I'm an ex-Starbucks barista — you can make the Iced Brown Sugar Oatmilk Shaken Espresso at home for a fraction of the cost</strong></a></li><li><a href="https://www.tomsguide.com/home/coffee-makers/i-tried-lelits-brand-new-entry-level-espresso-machine-and-i-wish-i-had-usd2-000-so-i-could-buy-it"><strong>I tried Lelit's brand-new 'entry-level' espresso machine — and I wish I had $2,000 so I could buy it</strong></a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ I’ve swapped to an induction cooktop from gas — 3 things I love, and 1 thing you need to know ]]></title>
                                                                                                <dc:content><![CDATA[ <p>I’ve been boring everyone in earshot about my new kitchen. It’s been on my wishlist for a couple of years, so I’ve had plenty of time to work out exactly what I want for the cabinets and countertops. But when it came to appliances, there was one non-negotiable that topped the list.</p><p>Having relied on a gas cooktop for nearly 30 years, I was <a href="https://www.tomsguide.com/home/home-appliances/induction-vs-gas-cooktop-which-is-best-for-you">ready to make a swap</a>. I was fed up with food boiling over and cleaning up around the rings and grates. </p><p>So I was more than ready to say goodbye to gas and welcome <a href="https://www.tomsguide.com/home/home-appliances/i-asked-6-culinary-pros-if-its-worth-switching-to-an-induction-cooktop-heres-the-verdict">induction</a> into my kitchen.  </p><p>It’s now one week since my new Hisense Hi8 induction cooktop was fitted (you can see from my images that I’m still working from a makeshift worktop), but in that short time I can honestly say I have no regrets.<br><br>Here I share three things I love and one thing you need to know before buying an induction cooktop.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-W5ryxO"></div>                            </div>                            <script src="https://kwizly.com/embed/W5ryxO.js" async></script><h3 class="article-body__section" id="section-3-things-i-love"><span>3 things I love</span></h3><h2 id="1-precision-cooking">1. Precision cooking</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="o8aL8VudjeXihLTGxPmgE" name="Hisense Hi8 Induction Cooktop" alt="Hisense Hi8 Induction Cooktop" src="https://cdn.mos.cms.futurecdn.net/o8aL8VudjeXihLTGxPmgE.png" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Camilla Sharman)</span></figcaption></figure><p>I was first introduced to <a href="https://www.tomsguide.com/home/I-tried-an-induction-cooktop-3-things-i-learned">induction cooking</a> during a press visit to Smeg’s test kitchen, and was a little nervous to start. I wasn’t sure what to expect, or how easy an induction cooktop would be to use. </p><p>It turns out I had nothing to fear, and apart from taking a few moments to get used to the cooking levels, I found it instinctive.</p><p>I've since tested several portable versions, including <a href="https://www.tomsguide.com/home/home-appliances/i-just-tested-smegs-portable-induction-cooktop-and-its-the-perfect-kitchen-sidekick">Smeg’s portable induction cooktop</a> and <a href="https://www.tomsguide.com/home/kitchen-dining/i-tested-ikeas-portable-induction-cooktop-and-its-a-game-changer-for-small-spaces">Ikea’s budget-friendly portable induction cooktop, </a>and I’ve experienced the same with each one: induction cooking gives you precision.</p><p>Twiddling the knobs on my gas cooktop to get the heat 'just right’ always felt like guesswork, and I was forever having to clean up the mess of boiled-over liquid.  </p><p>The controls on the Hisense induction cooktop make it super easy to get the exact heat you need.  What’s more, because your pans sit directly on the cooktop, without a rack above, heat loss is minimal. </p><h2 id="2-it-39-s-quick">2. It's quick</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="iWFhWSrR9ySymc8xMnb6b5" name="Smeg-Power-Boost-boiling-water.jpg" alt="Power boost function on Smeg Portable Induction Cooktop" src="https://cdn.mos.cms.futurecdn.net/iWFhWSrR9ySymc8xMnb6b5.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>After years of cooking on a gas cooktop, I always relied on an electric kettle to preheat my pasta water. Trying to bring a large pot to a boil from cold on a gas burner felt like it took an eternity. </p><p>Since swapping to induction, I’ve noticed a massive difference in speed, and it hasn’t gone unnoticed by my son, who has taken a sudden interest in this new ‘gadget’. </p><p>Apart from noticing the increased speed when using the normal controls, you can increase the intensity with the power boost — or ‘P’ on the controls. Apart from being a feature on the Hisense induction cooktop, it’s even included within Smeg's portable version.</p><h2 id="3-clean-up-is-easy">3. Clean up is easy</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:3062px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="mieDQ7imd3U3MHiTeroGVF" name="Induction cooktop" alt="Hisense Hi8 induction cooktop" src="https://cdn.mos.cms.futurecdn.net/mieDQ7imd3U3MHiTeroGVF.jpg" mos="" align="middle" fullscreen="" width="3062" height="1722" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Camilla Sharman)</span></figcaption></figure><p>I can forget about spending time after I’ve enjoyed a meal cleaning up my cooktop. The flat surface makes it easy to wipe over. There are no awkward surfaces to work around, and with precision control, there’s less chance of spills and burnt-on messes.</p><p>What’s more, the Hisense Hi8 has a matt finish, so unlike the majority of induction cooktops with shiny surfaces, fingerprint issues are also obsolete.</p><h3 class="article-body__section" id="section-1-thing-to-know"><span>1 thing to know</span></h3><h2 id="you-may-need-to-change-your-pans">You may need to change your pans</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:3000px;"><p class="vanilla-image-block" style="padding-top:56.23%;"><img id="RhPPP4z4s47XPFwfwQRZR6" name="Induction cooktop-icon" alt="Induction cooktop with icon in background" src="https://cdn.mos.cms.futurecdn.net/RhPPP4z4s47XPFwfwQRZR6.jpg" mos="" align="middle" fullscreen="" width="3000" height="1687" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Shutterstock)</span></figcaption></figure><p>I’d been using my previous pans for over 20 years, and they still have plenty of life left in them. However, as they are not induction-friendly, they simply won’t work.</p><p>Induction cooking works by passing an electric current through a coiled copper wire beneath the cooking surface. This creates magnetic energy that interacts with the cookware rather than the cooktop’s surface. For heat to be transferred, your pans need to be magnetic. That means using <a href="https://www.tomsguide.com/home/can-you-use-stainless-steel-pans-on-an-induction-cooktop-heres-what-the-experts-say">stainless steel</a> or <a href="https://www.tomsguide.com/home/does-an-induction-cooktop-work-with-cast-iron-pans-heres-what-the-experts-say">cast iron</a>. Aluminum and copper pans won’t work.</p><p>Today, this isn’t a big issue, as when I was shopping for my new pans, the majority were induction-compatible. But if you’re not sure what to buy, look out for a symbol resembling a coil. And if you're <em>still</em> not sure what to look for, drop me a question in the comments below and I'll be happy to answer.</p><div class="product"><a data-dimension112="004568aa-9d71-11f1-9fc2-77e131a793c7" data-action="Deal Block" data-label="Cookware, set of 6, stainless steel" data-dimension48="Cookware, set of 6, stainless steel" data-dimension25="$59" href="https://www.ikea.com/us/en/p/ikea-365-cookware-set-of-6-stainless-steel-70577908/?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:507px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="v5xMobVMWFvaSFQeBsxnmK" name="IKEA 365+ Cookware, set of 6, stainless steel pans" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/v5xMobVMWFvaSFQeBsxnmK.png" mos="" align="middle" fullscreen="" width="507" height="507" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.ikea.com/us/en/p/ikea-365-cookware-set-of-6-stainless-steel-70577908/?" target="_blank" rel="nofollow" data-dimension112="004568aa-9d71-11f1-9fc2-77e131a793c7" data-action="Deal Block" data-label="Cookware, set of 6, stainless steel" data-dimension48="Cookware, set of 6, stainless steel" data-dimension25="$59">Cookware, set of 6, stainless steel: $59</a></strong><br>IKEA's cookware set is made of stainless steel and is compatible with all cooktops, including induction. The three pans come with a lid and are dishwasher- and oven-safe. <a class="view-deal button" href="https://www.ikea.com/us/en/p/ikea-365-cookware-set-of-6-stainless-steel-70577908/?" target="_blank" rel="nofollow" data-dimension112="004568aa-9d71-11f1-9fc2-77e131a793c7" data-action="Deal Block" data-label="Cookware, set of 6, stainless steel" data-dimension48="Cookware, set of 6, stainless steel" data-dimension25="$59">View Deal</a></p></div><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h3><ul><li><a href="https://www.tomsguide.com/home/does-an-induction-cooktop-work-with-cast-iron-pans-heres-what-the-experts-say">Does an induction cooktop work with cast iron pans? Here’s what the experts say</a></li><li><a href="https://www.tomsguide.com/home/home-appliances/i-switched-to-induction-cooking-heres-why-im-never-going-back">I switched to induction cooking in 2024 — here's why I'm never going back</a></li><li><a href="https://www.tomsguide.com/home/home-appliances/are-you-damaging-your-induction-cooktop-heres-what-you-should-do-to-protect-it">Are you damaging your induction cooktop? Here’s what you should do to protect it</a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/home/kitchen-dining/ive-swapped-to-an-induction-cooktop-from-gas-3-things-i-love-and-1-thing-you-need-to-know</link>
                                                                            <description>
                            <![CDATA[ Why I won’t shut up about my new induction cooktop — can I convert you too? ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">YndmPADhZuE8DmfPcUvh8T</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/js8zPtzd4HtqjF2nCSbPRX-1280-80.png" type="image/png" length="0"></enclosure>
                                                                        <pubDate>Sun, 23 Aug 2026 08:00:00 +0000</pubDate>                                                                                                                                <updated>Mon, 24 Aug 2026 08:24:00 +0000</updated>
                                                                                                                                            <category><![CDATA[Kitchen & Dining]]></category>
                                                    <category><![CDATA[Home Appliances]]></category>
                                                    <category><![CDATA[Home]]></category>
                                                                                                <author><![CDATA[ camilla.sharman@futurenet.com (Camilla Sharman) ]]></author>                    <dc:creator><![CDATA[ Camilla Sharman ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/nY4nvWzofHKHpvzAqN5LVH.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Camilla is the Homes Staff Writer and covers everything to do with homes and gardens. She has a wealth of editorial experience, mounting over 30 years, and covers news and features, tests products for reviews and compiles buying guides.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;p&gt;Her work has appeared in business and consumer titles, including Ideal Home, Real Homes, House Beautiful, Homebuilding &amp;amp; Renovation, and Kitchen &amp;amp; Bathroom Business. She’s even appeared on the cover of Your Home, writing about her own house renovation.&lt;/p&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;p&gt;Although she’s obsessed with decorating her home, she also enjoys baking and trying out the latest kitchen appliances. But when she’s not inside, you’ll find her pottering about in her yard, tending to her vegetable patch or taking in her prized hydrangeas. She also enjoys keeping fit, and if she&#039;s not on a spin bike trying to keep up with the class, she&#039;ll be in the pool, or trying to perfect her headstand in a yoga class.&lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                <media:content type="image/png" url="https://cdn.mos.cms.futurecdn.net/js8zPtzd4HtqjF2nCSbPRX-1280-80.png">
                                                            <media:credit><![CDATA[Hisense]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Hisense Hi8 Induction Cooktop]]></media:description>                                                            <media:text><![CDATA[Hisense Hi8 Induction Cooktop]]></media:text>
                                <media:title type="plain"><![CDATA[Hisense Hi8 Induction Cooktop]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/js8zPtzd4HtqjF2nCSbPRX-1280-80.png" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>I’ve been boring everyone in earshot about my new kitchen. It’s been on my wishlist for a couple of years, so I’ve had plenty of time to work out exactly what I want for the cabinets and countertops. But when it came to appliances, there was one non-negotiable that topped the list.</p><p>Having relied on a gas cooktop for nearly 30 years, I was <a href="https://www.tomsguide.com/home/home-appliances/induction-vs-gas-cooktop-which-is-best-for-you">ready to make a swap</a>. I was fed up with food boiling over and cleaning up around the rings and grates. </p><p>So I was more than ready to say goodbye to gas and welcome <a href="https://www.tomsguide.com/home/home-appliances/i-asked-6-culinary-pros-if-its-worth-switching-to-an-induction-cooktop-heres-the-verdict">induction</a> into my kitchen.  </p><p>It’s now one week since my new Hisense Hi8 induction cooktop was fitted (you can see from my images that I’m still working from a makeshift worktop), but in that short time I can honestly say I have no regrets.<br><br>Here I share three things I love and one thing you need to know before buying an induction cooktop.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-W5ryxO"></div>                            </div>                            <script src="https://kwizly.com/embed/W5ryxO.js" async></script><h3 class="article-body__section" id="section-3-things-i-love"><span>3 things I love</span></h3><h2 id="1-precision-cooking">1. Precision cooking</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="o8aL8VudjeXihLTGxPmgE" name="Hisense Hi8 Induction Cooktop" alt="Hisense Hi8 Induction Cooktop" src="https://cdn.mos.cms.futurecdn.net/o8aL8VudjeXihLTGxPmgE.png" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Camilla Sharman)</span></figcaption></figure><p>I was first introduced to <a href="https://www.tomsguide.com/home/I-tried-an-induction-cooktop-3-things-i-learned">induction cooking</a> during a press visit to Smeg’s test kitchen, and was a little nervous to start. I wasn’t sure what to expect, or how easy an induction cooktop would be to use. </p><p>It turns out I had nothing to fear, and apart from taking a few moments to get used to the cooking levels, I found it instinctive.</p><p>I've since tested several portable versions, including <a href="https://www.tomsguide.com/home/home-appliances/i-just-tested-smegs-portable-induction-cooktop-and-its-the-perfect-kitchen-sidekick">Smeg’s portable induction cooktop</a> and <a href="https://www.tomsguide.com/home/kitchen-dining/i-tested-ikeas-portable-induction-cooktop-and-its-a-game-changer-for-small-spaces">Ikea’s budget-friendly portable induction cooktop, </a>and I’ve experienced the same with each one: induction cooking gives you precision.</p><p>Twiddling the knobs on my gas cooktop to get the heat 'just right’ always felt like guesswork, and I was forever having to clean up the mess of boiled-over liquid.  </p><p>The controls on the Hisense induction cooktop make it super easy to get the exact heat you need.  What’s more, because your pans sit directly on the cooktop, without a rack above, heat loss is minimal. </p><h2 id="2-it-39-s-quick">2. It's quick</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="iWFhWSrR9ySymc8xMnb6b5" name="Smeg-Power-Boost-boiling-water.jpg" alt="Power boost function on Smeg Portable Induction Cooktop" src="https://cdn.mos.cms.futurecdn.net/iWFhWSrR9ySymc8xMnb6b5.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>After years of cooking on a gas cooktop, I always relied on an electric kettle to preheat my pasta water. Trying to bring a large pot to a boil from cold on a gas burner felt like it took an eternity. </p><p>Since swapping to induction, I’ve noticed a massive difference in speed, and it hasn’t gone unnoticed by my son, who has taken a sudden interest in this new ‘gadget’. </p><p>Apart from noticing the increased speed when using the normal controls, you can increase the intensity with the power boost — or ‘P’ on the controls. Apart from being a feature on the Hisense induction cooktop, it’s even included within Smeg's portable version.</p><h2 id="3-clean-up-is-easy">3. Clean up is easy</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:3062px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="mieDQ7imd3U3MHiTeroGVF" name="Induction cooktop" alt="Hisense Hi8 induction cooktop" src="https://cdn.mos.cms.futurecdn.net/mieDQ7imd3U3MHiTeroGVF.jpg" mos="" align="middle" fullscreen="" width="3062" height="1722" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Camilla Sharman)</span></figcaption></figure><p>I can forget about spending time after I’ve enjoyed a meal cleaning up my cooktop. The flat surface makes it easy to wipe over. There are no awkward surfaces to work around, and with precision control, there’s less chance of spills and burnt-on messes.</p><p>What’s more, the Hisense Hi8 has a matt finish, so unlike the majority of induction cooktops with shiny surfaces, fingerprint issues are also obsolete.</p><h3 class="article-body__section" id="section-1-thing-to-know"><span>1 thing to know</span></h3><h2 id="you-may-need-to-change-your-pans">You may need to change your pans</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:3000px;"><p class="vanilla-image-block" style="padding-top:56.23%;"><img id="RhPPP4z4s47XPFwfwQRZR6" name="Induction cooktop-icon" alt="Induction cooktop with icon in background" src="https://cdn.mos.cms.futurecdn.net/RhPPP4z4s47XPFwfwQRZR6.jpg" mos="" align="middle" fullscreen="" width="3000" height="1687" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Shutterstock)</span></figcaption></figure><p>I’d been using my previous pans for over 20 years, and they still have plenty of life left in them. However, as they are not induction-friendly, they simply won’t work.</p><p>Induction cooking works by passing an electric current through a coiled copper wire beneath the cooking surface. This creates magnetic energy that interacts with the cookware rather than the cooktop’s surface. For heat to be transferred, your pans need to be magnetic. That means using <a href="https://www.tomsguide.com/home/can-you-use-stainless-steel-pans-on-an-induction-cooktop-heres-what-the-experts-say">stainless steel</a> or <a href="https://www.tomsguide.com/home/does-an-induction-cooktop-work-with-cast-iron-pans-heres-what-the-experts-say">cast iron</a>. Aluminum and copper pans won’t work.</p><p>Today, this isn’t a big issue, as when I was shopping for my new pans, the majority were induction-compatible. But if you’re not sure what to buy, look out for a symbol resembling a coil. And if you're <em>still</em> not sure what to look for, drop me a question in the comments below and I'll be happy to answer.</p><div class="product"><a data-dimension112="004568aa-9d71-11f1-9fc2-77e131a793c7" data-action="Deal Block" data-label="Cookware, set of 6, stainless steel" data-dimension48="Cookware, set of 6, stainless steel" data-dimension25="$59" href="https://www.ikea.com/us/en/p/ikea-365-cookware-set-of-6-stainless-steel-70577908/?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:507px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="v5xMobVMWFvaSFQeBsxnmK" name="IKEA 365+ Cookware, set of 6, stainless steel pans" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/v5xMobVMWFvaSFQeBsxnmK.png" mos="" align="middle" fullscreen="" width="507" height="507" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.ikea.com/us/en/p/ikea-365-cookware-set-of-6-stainless-steel-70577908/?" target="_blank" rel="nofollow" data-dimension112="004568aa-9d71-11f1-9fc2-77e131a793c7" data-action="Deal Block" data-label="Cookware, set of 6, stainless steel" data-dimension48="Cookware, set of 6, stainless steel" data-dimension25="$59">Cookware, set of 6, stainless steel: $59</a></strong><br>IKEA's cookware set is made of stainless steel and is compatible with all cooktops, including induction. The three pans come with a lid and are dishwasher- and oven-safe. <a class="view-deal button" href="https://www.ikea.com/us/en/p/ikea-365-cookware-set-of-6-stainless-steel-70577908/?" target="_blank" rel="nofollow" data-dimension112="004568aa-9d71-11f1-9fc2-77e131a793c7" data-action="Deal Block" data-label="Cookware, set of 6, stainless steel" data-dimension48="Cookware, set of 6, stainless steel" data-dimension25="$59">View Deal</a></p></div><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h3><ul><li><a href="https://www.tomsguide.com/home/does-an-induction-cooktop-work-with-cast-iron-pans-heres-what-the-experts-say">Does an induction cooktop work with cast iron pans? Here’s what the experts say</a></li><li><a href="https://www.tomsguide.com/home/home-appliances/i-switched-to-induction-cooking-heres-why-im-never-going-back">I switched to induction cooking in 2024 — here's why I'm never going back</a></li><li><a href="https://www.tomsguide.com/home/home-appliances/are-you-damaging-your-induction-cooktop-heres-what-you-should-do-to-protect-it">Are you damaging your induction cooktop? Here’s what you should do to protect it</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ My kitchen is getting a makeover: 5 clever IKEA finds I'm buying from $4 ]]></title>
                                                                                                <dc:content><![CDATA[ <p>There’s no bigger project in your home than renovating a kitchen. It’s a lengthy process even before the fitting starts, and it requires decision after decision.</p><p>But after having spent weeks washing up in the bathtub and wiping plaster dust off my <a href="https://www.tomsguide.com/best-picks/best-cutting-boards">cutting boards</a>, I’ve survived and have finally got to the fun part. I’m now ready to choose all the accessories for my brand-new kitchen. </p><p>But this major project has left a big dent in my bank balance, so I need to find <a href="https://www.tomsguide.com/home/12-ikea-finds-to-double-your-kitchen-space">budget-friendly ways to style and organize the space</a>. That’s why I’m heading to IKEA, and I’ll be putting these five items into my basket to help make my kitchen functional and fun.</p><h2 id="style-on-a-budget">Style on a budget</h2><div class="product"><a data-dimension112="b3b59798-9bd7-11f1-ba00-519fd54c3811" data-action="Deal Block" data-label="FÄRGKLAR Mug" data-dimension48="FÄRGKLAR Mug" data-dimension25="$4" href="https://www.ikea.com/us/en/p/faergklar-mug-light-pink-50604880/" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:563px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="ni9MRt7B2CZvSHoP8TXqdG" name="FÄRGKLAR Mug" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/ni9MRt7B2CZvSHoP8TXqdG.png" mos="" align="middle" fullscreen="" width="563" height="563" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.ikea.com/us/en/p/faergklar-mug-light-pink-50604880/" target="_blank" rel="nofollow" data-dimension112="b3b59798-9bd7-11f1-ba00-519fd54c3811" data-action="Deal Block" data-label="FÄRGKLAR Mug" data-dimension48="FÄRGKLAR Mug" data-dimension25="$4">FÄRGKLAR Mug: $4</a></strong><br>If you think pink kitchen cabinets are a step too far (I nearly did it!), you can still add a touch of pink to your room. I'll be keeping these light pink mugs on an open shelf in my kitchen, rather than behind a closed cabinet. What’s more, if you like the design, you can buy matching items, including an 18-piece dinner set for $69.<a class="view-deal button" href="https://www.ikea.com/us/en/p/faergklar-mug-light-pink-50604880/" target="_blank" rel="nofollow" data-dimension112="b3b59798-9bd7-11f1-ba00-519fd54c3811" data-action="Deal Block" data-label="FÄRGKLAR Mug" data-dimension48="FÄRGKLAR Mug" data-dimension25="$4">View Deal</a></p></div><div class="product"><a data-dimension112="ca866dda-9bd2-11f1-a802-7b3ac17989c3" data-action="Deal Block" data-label="KLIPPKAKTUS Lazy susan" data-dimension48="KLIPPKAKTUS Lazy susan" data-dimension25="$11" href="https://www.ikea.com/us/en/p/klippkaktus-lazy-susan-00569426/" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1400px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="mQhN9p9FceZ7C6RQsnVQCT" name="IKEA Klippkaktus lazy susan" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/mQhN9p9FceZ7C6RQsnVQCT.png" mos="" align="middle" fullscreen="" width="1400" height="1400" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.ikea.com/us/en/p/klippkaktus-lazy-susan-00569426/" target="_blank" rel="nofollow" data-dimension112="ca866dda-9bd2-11f1-a802-7b3ac17989c3" data-action="Deal Block" data-label="KLIPPKAKTUS Lazy susan" data-dimension48="KLIPPKAKTUS Lazy susan" data-dimension25="$11">KLIPPKAKTUS Lazy susan: $11</a></strong><br>Fed up with scrambling through your refrigerator or cabinets to find that sauce? A Lazy Susan is the perfect solution for easy storage. The spinning turntable rotates to make it easier to grab that jar of pickles that’s stuck at the back. I'm going to add IKEA's version to my refrigerator, but this clever gadget works equally well in other kitchen storage scenarios. <a class="view-deal button" href="https://www.ikea.com/us/en/p/klippkaktus-lazy-susan-00569426/" target="_blank" rel="nofollow" data-dimension112="ca866dda-9bd2-11f1-a802-7b3ac17989c3" data-action="Deal Block" data-label="KLIPPKAKTUS Lazy susan" data-dimension48="KLIPPKAKTUS Lazy susan" data-dimension25="$11">View Deal</a></p></div><div class="product"><a data-dimension112="a6f4aa68-9bd6-11f1-b23a-355f4e0cbedf" data-action="Deal Block" data-label="SPJUTLILJA Spice mill, set of 2" data-dimension48="SPJUTLILJA Spice mill, set of 2" data-dimension25="$14.99" href="https://www.ikea.com/us/en/p/spjutlilja-spice-mill-set-of-2-black-light-beige-10624229/" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1500px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="xdYGmFofjNBztzpPRjFCyk" name="IKEA SPJUTLILJA Spice mill, set of 2" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/xdYGmFofjNBztzpPRjFCyk.png" mos="" align="middle" fullscreen="" width="1500" height="1500" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.ikea.com/us/en/p/spjutlilja-spice-mill-set-of-2-black-light-beige-10624229/" target="_blank" rel="nofollow" data-dimension112="a6f4aa68-9bd6-11f1-b23a-355f4e0cbedf" data-action="Deal Block" data-label="SPJUTLILJA Spice mill, set of 2" data-dimension48="SPJUTLILJA Spice mill, set of 2" data-dimension25="$14.99">SPJUTLILJA Spice mill, set of 2: $14.99</a></strong><br>I love grinding fresh peppercorns over my meals, but I daren't put my current grinder on the table. So, when I spotted this striking salt-and-pepper milling set at IKEA, it had to go into my basket. Who said functional couldn’t be fun? The striking vertical black-and-white design will make a statement on your countertop, and at under $15, I think it's one of the reasons people love shopping at IKEA. <a class="view-deal button" href="https://www.ikea.com/us/en/p/spjutlilja-spice-mill-set-of-2-black-light-beige-10624229/" target="_blank" rel="nofollow" data-dimension112="a6f4aa68-9bd6-11f1-b23a-355f4e0cbedf" data-action="Deal Block" data-label="SPJUTLILJA Spice mill, set of 2" data-dimension48="SPJUTLILJA Spice mill, set of 2" data-dimension25="$14.99">View Deal</a></p></div><div class="product"><a data-dimension112="05e2813c-9bd5-11f1-ad4c-b7d72814a22e" data-action="Deal Block" data-label="APTITLIG Butcher block" data-dimension48="APTITLIG Butcher block" data-dimension25="$24.99" href="https://www.ikea.com/us/en/p/aptitlig-butcher-block-bamboo-00233429/" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1400px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="eBJwY3KbwK6M9H36wzWUgX" name="IKEA Aptitlig butcher block" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/eBJwY3KbwK6M9H36wzWUgX.png" mos="" align="middle" fullscreen="" width="1400" height="1400" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.ikea.com/us/en/p/aptitlig-butcher-block-bamboo-00233429/" target="_blank" rel="nofollow" data-dimension112="05e2813c-9bd5-11f1-ad4c-b7d72814a22e" data-action="Deal Block" data-label="APTITLIG Butcher block" data-dimension48="APTITLIG Butcher block" data-dimension25="$24.99">APTITLIG Butcher block: $24.99</a></strong><br>I never manage with small chopping boards, so this large butcher's block is perfect for chopping large quantities of fruits and vegetables. The bamboo board measures 17 ¾ x 14 ¼  x 1 ¼," and has a groove running around the edge to stop juices from spilling onto your countertop. To keep mine looking pristine, I’ll be coating it with food-safe mineral oil to extend its life.<a class="view-deal button" href="https://www.ikea.com/us/en/p/aptitlig-butcher-block-bamboo-00233429/" target="_blank" rel="nofollow" data-dimension112="05e2813c-9bd5-11f1-ad4c-b7d72814a22e" data-action="Deal Block" data-label="APTITLIG Butcher block" data-dimension48="APTITLIG Butcher block" data-dimension25="$24.99">View Deal</a></p></div><div class="product"><a data-dimension112="46d5b5f4-9bdc-11f1-acc3-f1a29d5bafb3" data-action="Deal Block" data-label="KLIPPFISK Frying pan, 9 1/2 inch" data-dimension48="KLIPPFISK Frying pan, 9 1/2 inch" data-dimension25="$29.99" href="https://www.ikea.com/us/en/p/klippfisk-frying-pan-non-stick-coating-wood-dark-gray-blue-90602501/#content" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1500px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="wnYbZjdBraNtr4x8riKz69" name="IKEA KLIPPFISK frying pan" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/wnYbZjdBraNtr4x8riKz69.png" mos="" align="middle" fullscreen="" width="1500" height="1500" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.ikea.com/us/en/p/klippfisk-frying-pan-non-stick-coating-wood-dark-gray-blue-90602501/#content" target="_blank" rel="nofollow" data-dimension112="46d5b5f4-9bdc-11f1-acc3-f1a29d5bafb3" data-action="Deal Block" data-label="KLIPPFISK Frying pan, 9 1/2 inch" data-dimension48="KLIPPFISK Frying pan, 9 1/2 inch" data-dimension25="$29.99">KLIPPFISK Frying pan, 9 1/2 inch: $29.99</a></strong><br>Having swapped my gas cooktop for an induction one, I’ve had to change all my pots and pans to induction-friendly ones. This modern frying pan in blue-grey cast aluminum has two spouts, a non-stick coating and a beautiful rubberwood handle, plus it's compatible with all cooktops. If you’d prefer a larger version, you can opt for the 11-inch pan.<a class="view-deal button" href="https://www.ikea.com/us/en/p/klippfisk-frying-pan-non-stick-coating-wood-dark-gray-blue-90602501/#content" target="_blank" rel="nofollow" data-dimension112="46d5b5f4-9bdc-11f1-acc3-f1a29d5bafb3" data-action="Deal Block" data-label="KLIPPFISK Frying pan, 9 1/2 inch" data-dimension48="KLIPPFISK Frying pan, 9 1/2 inch" data-dimension25="$29.99">View Deal</a></p></div><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h3><ul><li><a href="https://www.tomsguide.com/home/kitchen-dining/you-dont-need-an-appliance-garage-ive-been-using-this-usd29-ikea-classic-for-years-and-it-keeps-my-gadgets-neatly-stowed-away">You don’t need an appliance garage — I’ve been using this $29 IKEA classic for years, and it keeps my gadgets neatly stowed away</a></li><li><a href="https://www.tomsguide.com/home/kitchen-dining/ikeas-stackable-food-storage-containers-just-doubled-my-kitchen-counter-space-and-they-only-cost-usd14">IKEA’s stackable food storage containers just doubled my kitchen counter space, and they only cost $14</a></li><li><a href="https://www.tomsguide.com/home/kitchen-dining/i-tested-ikeas-portable-induction-cooktop-and-its-a-game-changer-for-small-spaces">I tested IKEA's portable induction cooktop — and it's a game changer for small spaces</a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/home/my-kitchen-is-getting-a-makeover-5-clever-ikea-finds-im-buying-from-usd4</link>
                                                                            <description>
                            <![CDATA[ I’m currently renovating my kitchen on a budget and here are 5 IKEA items I’m adding to my basket. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">uNcQNQMkjZNcFy2yspsAy7</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/qg5Z6rnAaTsHSyK9TWXmTN-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Sat, 22 Aug 2026 13:00:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Home]]></category>
                                                    <category><![CDATA[Kitchen & Dining]]></category>
                                                    <category><![CDATA[Home Appliances]]></category>
                                                                                                <author><![CDATA[ camilla.sharman@futurenet.com (Camilla Sharman) ]]></author>                    <dc:creator><![CDATA[ Camilla Sharman ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/nY4nvWzofHKHpvzAqN5LVH.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Camilla is the Homes Staff Writer and covers everything to do with homes and gardens. She has a wealth of editorial experience, mounting over 30 years, and covers news and features, tests products for reviews and compiles buying guides.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;p&gt;Her work has appeared in business and consumer titles, including Ideal Home, Real Homes, House Beautiful, Homebuilding &amp;amp; Renovation, and Kitchen &amp;amp; Bathroom Business. She’s even appeared on the cover of Your Home, writing about her own house renovation.&lt;/p&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;p&gt;Although she’s obsessed with decorating her home, she also enjoys baking and trying out the latest kitchen appliances. But when she’s not inside, you’ll find her pottering about in her yard, tending to her vegetable patch or taking in her prized hydrangeas. She also enjoys keeping fit, and if she&#039;s not on a spin bike trying to keep up with the class, she&#039;ll be in the pool, or trying to perfect her headstand in a yoga class.&lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/qg5Z6rnAaTsHSyK9TWXmTN-1280-80.jpg">
                                                            <media:credit><![CDATA[Tom&#039;s Guide]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[An closeup exterior shot of an IKEA store.]]></media:description>                                                            <media:text><![CDATA[An closeup exterior shot of an IKEA store.]]></media:text>
                                <media:title type="plain"><![CDATA[An closeup exterior shot of an IKEA store.]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/qg5Z6rnAaTsHSyK9TWXmTN-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>There’s no bigger project in your home than renovating a kitchen. It’s a lengthy process even before the fitting starts, and it requires decision after decision.</p><p>But after having spent weeks washing up in the bathtub and wiping plaster dust off my <a href="https://www.tomsguide.com/best-picks/best-cutting-boards">cutting boards</a>, I’ve survived and have finally got to the fun part. I’m now ready to choose all the accessories for my brand-new kitchen. </p><p>But this major project has left a big dent in my bank balance, so I need to find <a href="https://www.tomsguide.com/home/12-ikea-finds-to-double-your-kitchen-space">budget-friendly ways to style and organize the space</a>. That’s why I’m heading to IKEA, and I’ll be putting these five items into my basket to help make my kitchen functional and fun.</p><h2 id="style-on-a-budget">Style on a budget</h2><div class="product"><a data-dimension112="b3b59798-9bd7-11f1-ba00-519fd54c3811" data-action="Deal Block" data-label="FÄRGKLAR Mug" data-dimension48="FÄRGKLAR Mug" data-dimension25="$4" href="https://www.ikea.com/us/en/p/faergklar-mug-light-pink-50604880/" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:563px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="ni9MRt7B2CZvSHoP8TXqdG" name="FÄRGKLAR Mug" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/ni9MRt7B2CZvSHoP8TXqdG.png" mos="" align="middle" fullscreen="" width="563" height="563" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.ikea.com/us/en/p/faergklar-mug-light-pink-50604880/" target="_blank" rel="nofollow" data-dimension112="b3b59798-9bd7-11f1-ba00-519fd54c3811" data-action="Deal Block" data-label="FÄRGKLAR Mug" data-dimension48="FÄRGKLAR Mug" data-dimension25="$4">FÄRGKLAR Mug: $4</a></strong><br>If you think pink kitchen cabinets are a step too far (I nearly did it!), you can still add a touch of pink to your room. I'll be keeping these light pink mugs on an open shelf in my kitchen, rather than behind a closed cabinet. What’s more, if you like the design, you can buy matching items, including an 18-piece dinner set for $69.<a class="view-deal button" href="https://www.ikea.com/us/en/p/faergklar-mug-light-pink-50604880/" target="_blank" rel="nofollow" data-dimension112="b3b59798-9bd7-11f1-ba00-519fd54c3811" data-action="Deal Block" data-label="FÄRGKLAR Mug" data-dimension48="FÄRGKLAR Mug" data-dimension25="$4">View Deal</a></p></div><div class="product"><a data-dimension112="ca866dda-9bd2-11f1-a802-7b3ac17989c3" data-action="Deal Block" data-label="KLIPPKAKTUS Lazy susan" data-dimension48="KLIPPKAKTUS Lazy susan" data-dimension25="$11" href="https://www.ikea.com/us/en/p/klippkaktus-lazy-susan-00569426/" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1400px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="mQhN9p9FceZ7C6RQsnVQCT" name="IKEA Klippkaktus lazy susan" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/mQhN9p9FceZ7C6RQsnVQCT.png" mos="" align="middle" fullscreen="" width="1400" height="1400" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.ikea.com/us/en/p/klippkaktus-lazy-susan-00569426/" target="_blank" rel="nofollow" data-dimension112="ca866dda-9bd2-11f1-a802-7b3ac17989c3" data-action="Deal Block" data-label="KLIPPKAKTUS Lazy susan" data-dimension48="KLIPPKAKTUS Lazy susan" data-dimension25="$11">KLIPPKAKTUS Lazy susan: $11</a></strong><br>Fed up with scrambling through your refrigerator or cabinets to find that sauce? A Lazy Susan is the perfect solution for easy storage. The spinning turntable rotates to make it easier to grab that jar of pickles that’s stuck at the back. I'm going to add IKEA's version to my refrigerator, but this clever gadget works equally well in other kitchen storage scenarios. <a class="view-deal button" href="https://www.ikea.com/us/en/p/klippkaktus-lazy-susan-00569426/" target="_blank" rel="nofollow" data-dimension112="ca866dda-9bd2-11f1-a802-7b3ac17989c3" data-action="Deal Block" data-label="KLIPPKAKTUS Lazy susan" data-dimension48="KLIPPKAKTUS Lazy susan" data-dimension25="$11">View Deal</a></p></div><div class="product"><a data-dimension112="a6f4aa68-9bd6-11f1-b23a-355f4e0cbedf" data-action="Deal Block" data-label="SPJUTLILJA Spice mill, set of 2" data-dimension48="SPJUTLILJA Spice mill, set of 2" data-dimension25="$14.99" href="https://www.ikea.com/us/en/p/spjutlilja-spice-mill-set-of-2-black-light-beige-10624229/" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1500px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="xdYGmFofjNBztzpPRjFCyk" name="IKEA SPJUTLILJA Spice mill, set of 2" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/xdYGmFofjNBztzpPRjFCyk.png" mos="" align="middle" fullscreen="" width="1500" height="1500" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.ikea.com/us/en/p/spjutlilja-spice-mill-set-of-2-black-light-beige-10624229/" target="_blank" rel="nofollow" data-dimension112="a6f4aa68-9bd6-11f1-b23a-355f4e0cbedf" data-action="Deal Block" data-label="SPJUTLILJA Spice mill, set of 2" data-dimension48="SPJUTLILJA Spice mill, set of 2" data-dimension25="$14.99">SPJUTLILJA Spice mill, set of 2: $14.99</a></strong><br>I love grinding fresh peppercorns over my meals, but I daren't put my current grinder on the table. So, when I spotted this striking salt-and-pepper milling set at IKEA, it had to go into my basket. Who said functional couldn’t be fun? The striking vertical black-and-white design will make a statement on your countertop, and at under $15, I think it's one of the reasons people love shopping at IKEA. <a class="view-deal button" href="https://www.ikea.com/us/en/p/spjutlilja-spice-mill-set-of-2-black-light-beige-10624229/" target="_blank" rel="nofollow" data-dimension112="a6f4aa68-9bd6-11f1-b23a-355f4e0cbedf" data-action="Deal Block" data-label="SPJUTLILJA Spice mill, set of 2" data-dimension48="SPJUTLILJA Spice mill, set of 2" data-dimension25="$14.99">View Deal</a></p></div><div class="product"><a data-dimension112="05e2813c-9bd5-11f1-ad4c-b7d72814a22e" data-action="Deal Block" data-label="APTITLIG Butcher block" data-dimension48="APTITLIG Butcher block" data-dimension25="$24.99" href="https://www.ikea.com/us/en/p/aptitlig-butcher-block-bamboo-00233429/" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1400px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="eBJwY3KbwK6M9H36wzWUgX" name="IKEA Aptitlig butcher block" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/eBJwY3KbwK6M9H36wzWUgX.png" mos="" align="middle" fullscreen="" width="1400" height="1400" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.ikea.com/us/en/p/aptitlig-butcher-block-bamboo-00233429/" target="_blank" rel="nofollow" data-dimension112="05e2813c-9bd5-11f1-ad4c-b7d72814a22e" data-action="Deal Block" data-label="APTITLIG Butcher block" data-dimension48="APTITLIG Butcher block" data-dimension25="$24.99">APTITLIG Butcher block: $24.99</a></strong><br>I never manage with small chopping boards, so this large butcher's block is perfect for chopping large quantities of fruits and vegetables. The bamboo board measures 17 ¾ x 14 ¼  x 1 ¼," and has a groove running around the edge to stop juices from spilling onto your countertop. To keep mine looking pristine, I’ll be coating it with food-safe mineral oil to extend its life.<a class="view-deal button" href="https://www.ikea.com/us/en/p/aptitlig-butcher-block-bamboo-00233429/" target="_blank" rel="nofollow" data-dimension112="05e2813c-9bd5-11f1-ad4c-b7d72814a22e" data-action="Deal Block" data-label="APTITLIG Butcher block" data-dimension48="APTITLIG Butcher block" data-dimension25="$24.99">View Deal</a></p></div><div class="product"><a data-dimension112="46d5b5f4-9bdc-11f1-acc3-f1a29d5bafb3" data-action="Deal Block" data-label="KLIPPFISK Frying pan, 9 1/2 inch" data-dimension48="KLIPPFISK Frying pan, 9 1/2 inch" data-dimension25="$29.99" href="https://www.ikea.com/us/en/p/klippfisk-frying-pan-non-stick-coating-wood-dark-gray-blue-90602501/#content" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1500px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="wnYbZjdBraNtr4x8riKz69" name="IKEA KLIPPFISK frying pan" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/wnYbZjdBraNtr4x8riKz69.png" mos="" align="middle" fullscreen="" width="1500" height="1500" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.ikea.com/us/en/p/klippfisk-frying-pan-non-stick-coating-wood-dark-gray-blue-90602501/#content" target="_blank" rel="nofollow" data-dimension112="46d5b5f4-9bdc-11f1-acc3-f1a29d5bafb3" data-action="Deal Block" data-label="KLIPPFISK Frying pan, 9 1/2 inch" data-dimension48="KLIPPFISK Frying pan, 9 1/2 inch" data-dimension25="$29.99">KLIPPFISK Frying pan, 9 1/2 inch: $29.99</a></strong><br>Having swapped my gas cooktop for an induction one, I’ve had to change all my pots and pans to induction-friendly ones. This modern frying pan in blue-grey cast aluminum has two spouts, a non-stick coating and a beautiful rubberwood handle, plus it's compatible with all cooktops. If you’d prefer a larger version, you can opt for the 11-inch pan.<a class="view-deal button" href="https://www.ikea.com/us/en/p/klippfisk-frying-pan-non-stick-coating-wood-dark-gray-blue-90602501/#content" target="_blank" rel="nofollow" data-dimension112="46d5b5f4-9bdc-11f1-acc3-f1a29d5bafb3" data-action="Deal Block" data-label="KLIPPFISK Frying pan, 9 1/2 inch" data-dimension48="KLIPPFISK Frying pan, 9 1/2 inch" data-dimension25="$29.99">View Deal</a></p></div><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h3><ul><li><a href="https://www.tomsguide.com/home/kitchen-dining/you-dont-need-an-appliance-garage-ive-been-using-this-usd29-ikea-classic-for-years-and-it-keeps-my-gadgets-neatly-stowed-away">You don’t need an appliance garage — I’ve been using this $29 IKEA classic for years, and it keeps my gadgets neatly stowed away</a></li><li><a href="https://www.tomsguide.com/home/kitchen-dining/ikeas-stackable-food-storage-containers-just-doubled-my-kitchen-counter-space-and-they-only-cost-usd14">IKEA’s stackable food storage containers just doubled my kitchen counter space, and they only cost $14</a></li><li><a href="https://www.tomsguide.com/home/kitchen-dining/i-tested-ikeas-portable-induction-cooktop-and-its-a-game-changer-for-small-spaces">I tested IKEA's portable induction cooktop — and it's a game changer for small spaces</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ The Nespresso machine coffee lovers rave about is back down to just AU$88 right now ]]></title>
                                                                                                <dc:content><![CDATA[ <p>Mastering the perfect cup of coffee can be tricky, especially if you're a total newbie to the world of espresso machines. That's where the <a href="https://www.tomsguide.com/home/coffee-makers/ive-reviewed-countless-espresso-machines-this-year-but-theres-only-one-you-need-to-buy">best fully automatic coffee makers</a> come in, and one brand that simply excels in this category is Nespresso. </p><p>If pulling the perfect shot or calculating the grind size yourself is simply too much hassle, then a machine like Nespresso's Vertuo Pop could be the right fit for you. By removing the complexities of coffee bean selection and the excessive cleaning that comes with owning a manual machine, Nespresso's capsule system takes the guesswork out of barista-made cups at home, providing consistent cups with the simple touch of a button. </p><p>And right now, Nespresso's Vertuo Pop machine is down to just AU$88 — that's 62% off RRP. This price is exclusive to the <a href="https://www.amazon.com.au/DeLonghi-Nespresso-Single-Serve-Centrifusion-Technology/dp/B0BSV6MRM6" target="_blank">Pacific Blue</a>, <a href="https://www.amazon.com.au/dp/B0GMGFK12S" target="_blank">Lilac</a>, <a href="https://www.amazon.com.au/dp/B0BYSKJBYL" target="_blank">Coconut White</a> and <a href="https://www.amazon.com.au/Nespresso-DeLonghi-centrifusion-technology-Liquorice/dp/B0BSV5WCZV" target="_blank">Liquorice Black</a> colourways on Amazon. You'll also need to act fast to score this stunning coffee machine, though — this deal’s only available while stocks last.</p><div class="product"><a data-dimension112="8f2cd3fa-9d03-11f1-b7cf-cf3dd5cd0c03" data-action="Deal Block" data-label="Vertuo Pop" data-dimension48="Vertuo Pop" data-dimension25="$88" href="https://www.amazon.com.au/DeLonghi-Nespresso-Single-Serve-Centrifusion-Technology/dp/B0BSV6MRM6" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:500px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="H4VttYx8gH79ubjYe8yC2j" name="delonghi-nespresso-vertuo-pop-env90a-cap-aa4d1ae7-d0ce-41e0-b2a4-3a92ab59ff06.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/H4VttYx8gH79ubjYe8yC2j.jpg" mos="" align="middle" fullscreen="" width="500" height="500" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>Now 62% off, the Nespresso Vertuo Pop machine is hard to pass up at an incredible AU$88. With one-touch convenience, you can brew up to four different cup sizes from a range of great Nespresso coffee pods. You'll also receive a 12-pack of coffee capsule samples to try. Available in <a href="https://www.amazon.com.au/DeLonghi-Nespresso-Single-Serve-Centrifusion-Technology/dp/B0BSV6MRM6" target="_blank" data-dimension112="8f2cd3fa-9d03-11f1-b7cf-cf3dd5cd0c03" data-action="Deal Block" data-label="Vertuo Pop" data-dimension48="Vertuo Pop" data-dimension25="$88">Pacific Blue</a>, <a href="https://www.amazon.com.au/dp/B0GMGFK12S" target="_blank">Lilac</a>, <a href="https://www.amazon.com.au/dp/B0BYSKJBYL" target="_blank">Coconut White</a> and <a href="https://www.amazon.com.au/Nespresso-DeLonghi-centrifusion-technology-Liquorice/dp/B0BSV5WCZV" target="_blank">Liquorice Black</a> colourways.<a class="view-deal button" href="https://www.amazon.com.au/DeLonghi-Nespresso-Single-Serve-Centrifusion-Technology/dp/B0BSV6MRM6" target="_blank" rel="nofollow" data-dimension112="8f2cd3fa-9d03-11f1-b7cf-cf3dd5cd0c03" data-action="Deal Block" data-label="Vertuo Pop" data-dimension48="Vertuo Pop" data-dimension25="$88">View Deal</a></p></div><p>It's worth noting that this machine is rather fuss-free, and it's as simple as plugging it in, filling the water tank and hitting the button before sipping on your first brew. More often than not though, standalone Nespresso machines come with a sample pack of pods to try, but they don't always include a milk frother or extras to get your perfect sip sorted. </p><p>That said, plenty of Nespresso Vertuo models are sold in bundles, which include Nespresso's Aeroccino3 milk frother and, in some cases, a Nespresso-branded mug or tumbler. </p><p>If your budget can stretch to AU$179, you might want to consider nabbing the <a href="https://www.amazon.com.au/Nespresso-Single-Serve-Cappuccino-Centrifusion-Technology/dp/B0DXQ72F2X">Nespresso Vertuo Pop and the Aeroccino 3 milk frother</a>, with all the bells and whistles, in a fun Candy Pink bundle. This bundle also has the viral <a href="https://www.nespresso.com/au/en/order/accessories/original/iced-coffee-tumbler">Nespresso Travel Tumbler</a>, which typically retails at AU$42, and a fun canvas carry bag. </p><p>Not a fan of the Vertuo Pop's design? You might like the latest Vertuo model, the Up, which is discounted to <a href="https://www.amazon.com.au/DeLonghi-Nespresso-Vertuo-Aeroccino-ENV200-WAE/dp/B0GQB1KPVB/">AU$299 in White or Grey colourways</a>. The Up also includes the Aeroccino milk frother and the sample pods. </p><p>I've popped both deals below if you're ready to upgrade your morning routine with this one-touch convenience. </p>        <div class="featured_product_block featured_block_hero" data-id="8f2cd4e0-9d03-11f1-aa1e-0535c0d3e846">            <a href="https://www.amazon.com.au/Nespresso-Single-Serve-Cappuccino-Centrifusion-Technology/dp/B0DXQ72F2X" data-model-name="Nespresso Vertuo Pop and Aeroccino 3 Welcome Set (Candy Pink)" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/QakBSCJBqXzjp68m9nSru4.jpg" alt="De'longhi Nespresso Vertuo Pop and Aeroccino 3 Env90.ae, Capsule Coffee Machine, Single-Serve Pod Coffee and Cappuccino Machine, 4 Cup Sizes, Centrifusion Technology, Welcome Set Included, Candy Pink"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Nespresso</div>                                        <div class="featured__title">Nespresso Vertuo Pop and Aeroccino 3 Welcome Set (Candy Pink)</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="8f2cd54e-9d03-11f1-87be-3b8258d94185">            <a href="https://www.amazon.com.au/DeLonghi-Nespresso-Vertuo-Aeroccino-ENV200-WAE/dp/B0GQB1KPVB/" data-model-name="Vertuo Up with Aeroccino milk frother" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/EQrMFEGQVxCHHRg6pZGbx4.jpg" alt="De'longhi Nespresso Vertuo Up – Capsule Coffee Machine With Aeroccino Milk Frother, 7 Cup Sizes, Fast Heat-Up, 1.4l Water Tank, Creations Mode, Compact Design, White (env200.wae)"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Nespresso</div>                                        <div class="featured__title">Vertuo Up with Aeroccino milk frother</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/home/coffee-makers/the-nespresso-machine-coffee-lovers-rave-about-is-back-down-to-just-aud88-right-now</link>
                                                                            <description>
                            <![CDATA[ Need a new Nespresso? Consider the coveted Nespresso Vertuo Pop, now just AU$88 on Amazon. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">3JXh3cRehDKcvozHkNa5VT</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/k8gAfTMvyp3QTaVGqyqR5T-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Fri, 21 Aug 2026 03:23:35 +0000</pubDate>                                                                                                                                <updated>Fri, 21 Aug 2026 03:23:53 +0000</updated>
                                                                                                                                            <category><![CDATA[Coffee Makers]]></category>
                                                    <category><![CDATA[Home]]></category>
                                                    <category><![CDATA[Home Appliances]]></category>
                                                    <category><![CDATA[Kitchen & Dining]]></category>
                                                                                                <author><![CDATA[ lucy.scotting@futurenet.com (Lucy Scotting) ]]></author>                    <dc:creator><![CDATA[ Lucy Scotting ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/UC9ncAYxkmJ5ipHEyX44ri.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Lucy Scotting is a staff writer for Tom’s Guide Australia, primarily covering lifestyle, streaming and internet-related news. Lucy started her career writing for HR and staffing industry publications, with articles covering emerging tech, business and finance.&lt;/p&gt;&lt;p&gt;In her spare time, Lucy can be found watching sci-fi movies, working on her dystopian fiction novel (in progress since 2017) or hanging out with her dog, Fletcher. If she’s not found doing any of the above, she’s likely on her next adventure to a new city, country, or continent. &lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/k8gAfTMvyp3QTaVGqyqR5T-1280-80.jpg">
                                                            <media:credit><![CDATA[Future]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Nespresso Pop]]></media:description>                                                            <media:text><![CDATA[Nespresso Pop]]></media:text>
                                <media:title type="plain"><![CDATA[Nespresso Pop]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/k8gAfTMvyp3QTaVGqyqR5T-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Mastering the perfect cup of coffee can be tricky, especially if you're a total newbie to the world of espresso machines. That's where the <a href="https://www.tomsguide.com/home/coffee-makers/ive-reviewed-countless-espresso-machines-this-year-but-theres-only-one-you-need-to-buy">best fully automatic coffee makers</a> come in, and one brand that simply excels in this category is Nespresso. </p><p>If pulling the perfect shot or calculating the grind size yourself is simply too much hassle, then a machine like Nespresso's Vertuo Pop could be the right fit for you. By removing the complexities of coffee bean selection and the excessive cleaning that comes with owning a manual machine, Nespresso's capsule system takes the guesswork out of barista-made cups at home, providing consistent cups with the simple touch of a button. </p><p>And right now, Nespresso's Vertuo Pop machine is down to just AU$88 — that's 62% off RRP. This price is exclusive to the <a href="https://www.amazon.com.au/DeLonghi-Nespresso-Single-Serve-Centrifusion-Technology/dp/B0BSV6MRM6" target="_blank">Pacific Blue</a>, <a href="https://www.amazon.com.au/dp/B0GMGFK12S" target="_blank">Lilac</a>, <a href="https://www.amazon.com.au/dp/B0BYSKJBYL" target="_blank">Coconut White</a> and <a href="https://www.amazon.com.au/Nespresso-DeLonghi-centrifusion-technology-Liquorice/dp/B0BSV5WCZV" target="_blank">Liquorice Black</a> colourways on Amazon. You'll also need to act fast to score this stunning coffee machine, though — this deal’s only available while stocks last.</p><div class="product"><a data-dimension112="8f2cd3fa-9d03-11f1-b7cf-cf3dd5cd0c03" data-action="Deal Block" data-label="Vertuo Pop" data-dimension48="Vertuo Pop" data-dimension25="$88" href="https://www.amazon.com.au/DeLonghi-Nespresso-Single-Serve-Centrifusion-Technology/dp/B0BSV6MRM6" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:500px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="H4VttYx8gH79ubjYe8yC2j" name="delonghi-nespresso-vertuo-pop-env90a-cap-aa4d1ae7-d0ce-41e0-b2a4-3a92ab59ff06.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/H4VttYx8gH79ubjYe8yC2j.jpg" mos="" align="middle" fullscreen="" width="500" height="500" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>Now 62% off, the Nespresso Vertuo Pop machine is hard to pass up at an incredible AU$88. With one-touch convenience, you can brew up to four different cup sizes from a range of great Nespresso coffee pods. You'll also receive a 12-pack of coffee capsule samples to try. Available in <a href="https://www.amazon.com.au/DeLonghi-Nespresso-Single-Serve-Centrifusion-Technology/dp/B0BSV6MRM6" target="_blank" data-dimension112="8f2cd3fa-9d03-11f1-b7cf-cf3dd5cd0c03" data-action="Deal Block" data-label="Vertuo Pop" data-dimension48="Vertuo Pop" data-dimension25="$88">Pacific Blue</a>, <a href="https://www.amazon.com.au/dp/B0GMGFK12S" target="_blank">Lilac</a>, <a href="https://www.amazon.com.au/dp/B0BYSKJBYL" target="_blank">Coconut White</a> and <a href="https://www.amazon.com.au/Nespresso-DeLonghi-centrifusion-technology-Liquorice/dp/B0BSV5WCZV" target="_blank">Liquorice Black</a> colourways.<a class="view-deal button" href="https://www.amazon.com.au/DeLonghi-Nespresso-Single-Serve-Centrifusion-Technology/dp/B0BSV6MRM6" target="_blank" rel="nofollow" data-dimension112="8f2cd3fa-9d03-11f1-b7cf-cf3dd5cd0c03" data-action="Deal Block" data-label="Vertuo Pop" data-dimension48="Vertuo Pop" data-dimension25="$88">View Deal</a></p></div><p>It's worth noting that this machine is rather fuss-free, and it's as simple as plugging it in, filling the water tank and hitting the button before sipping on your first brew. More often than not though, standalone Nespresso machines come with a sample pack of pods to try, but they don't always include a milk frother or extras to get your perfect sip sorted. </p><p>That said, plenty of Nespresso Vertuo models are sold in bundles, which include Nespresso's Aeroccino3 milk frother and, in some cases, a Nespresso-branded mug or tumbler. </p><p>If your budget can stretch to AU$179, you might want to consider nabbing the <a href="https://www.amazon.com.au/Nespresso-Single-Serve-Cappuccino-Centrifusion-Technology/dp/B0DXQ72F2X">Nespresso Vertuo Pop and the Aeroccino 3 milk frother</a>, with all the bells and whistles, in a fun Candy Pink bundle. This bundle also has the viral <a href="https://www.nespresso.com/au/en/order/accessories/original/iced-coffee-tumbler">Nespresso Travel Tumbler</a>, which typically retails at AU$42, and a fun canvas carry bag. </p><p>Not a fan of the Vertuo Pop's design? You might like the latest Vertuo model, the Up, which is discounted to <a href="https://www.amazon.com.au/DeLonghi-Nespresso-Vertuo-Aeroccino-ENV200-WAE/dp/B0GQB1KPVB/">AU$299 in White or Grey colourways</a>. The Up also includes the Aeroccino milk frother and the sample pods. </p><p>I've popped both deals below if you're ready to upgrade your morning routine with this one-touch convenience. </p>        <div class="featured_product_block featured_block_hero" data-id="8f2cd4e0-9d03-11f1-aa1e-0535c0d3e846">            <a href="https://www.amazon.com.au/Nespresso-Single-Serve-Cappuccino-Centrifusion-Technology/dp/B0DXQ72F2X" data-model-name="Nespresso Vertuo Pop and Aeroccino 3 Welcome Set (Candy Pink)" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/QakBSCJBqXzjp68m9nSru4.jpg" alt="De'longhi Nespresso Vertuo Pop and Aeroccino 3 Env90.ae, Capsule Coffee Machine, Single-Serve Pod Coffee and Cappuccino Machine, 4 Cup Sizes, Centrifusion Technology, Welcome Set Included, Candy Pink"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Nespresso</div>                                        <div class="featured__title">Nespresso Vertuo Pop and Aeroccino 3 Welcome Set (Candy Pink)</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="8f2cd54e-9d03-11f1-87be-3b8258d94185">            <a href="https://www.amazon.com.au/DeLonghi-Nespresso-Vertuo-Aeroccino-ENV200-WAE/dp/B0GQB1KPVB/" data-model-name="Vertuo Up with Aeroccino milk frother" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/EQrMFEGQVxCHHRg6pZGbx4.jpg" alt="De'longhi Nespresso Vertuo Up – Capsule Coffee Machine With Aeroccino Milk Frother, 7 Cup Sizes, Fast Heat-Up, 1.4l Water Tank, Creations Mode, Compact Design, White (env200.wae)"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Nespresso</div>                                        <div class="featured__title">Vertuo Up with Aeroccino milk frother</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ People are putting aluminum foil in their washing machines — I asked an appliance expert if it’s safe ]]></title>
                                                                                                <dc:content><![CDATA[ <p>It’s part of my job as a homes writer to spot viral household hacks and share my thoughts on whether they work. So, when I read about putting aluminum foil balls in a washing machine, I was instantly on high alert.</p><p>Firstly, I’m thinking, what is it supposed to do, and secondly, I’m wondering whether it’s safe.</p><p>Apparently, placing a rolled-up ball of aluminum foil in your washing machine and <a href="https://www.tomsguide.com/us/best-clothes-dryers,review-6225.html">clothes dryer</a> helps reduce static. But does it actually work?</p><h2 id="a-silver-ball-of-magic">A silver ball of magic</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:4272px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="wjF22X282MtrgrXk33H5e7" name="shutterstock_41469406.jpg" alt="aluminum foil on wooden surface" src="https://cdn.mos.cms.futurecdn.net/wjF22X282MtrgrXk33H5e7.jpg" mos="" align="middle" fullscreen="" width="4272" height="2403" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Shutterstock)</span></figcaption></figure><p><a href="https://www.tomsguide.com/how-to/7-surprising-uses-for-aluminum-foil">Aluminum foil has many surprising uses</a> beyond covering food. It can be used as a <a href="https://www.tomsguide.com/home/gardening/gardeners-are-being-urged-to-put-aluminum-foil-in-their-yard-right-now-and-you-might-be-surprised-why">pest deterrent in your yard</a>, to <a href="https://www.tomsguide.com/opinion/i-just-beat-the-heat-with-a-dollar2-roll-of-aluminum-foil-heres-how">cool your home</a>, and even to <a href="https://www.tomsguide.com/us/aluminum-foil-wi-fi-extension,news-26097.html">boost your Wi-Fi signal</a>. Now we’re being told it can help with the laundry — and I need all the help I can get!</p><p>But I’ve recently purchased a new <a href="https://www.tomsguide.com/us/best-washing-machines,review-6208.html">washing machine</a>, so I’d be reluctant to try this laundry hack without knowing whether it’s safe to follow. I don’t want to ruin my new appliance.</p><p>So, what does throwing a rolled-up ball of aluminum foil into your washing machine do? Apparently, it helps reduce static, preventing clingy garments. Is it time to say goodbye to your usual clothes softener and dryer sheets?</p><h2 id="how-to-use-aluminum-foil-in-your-washing-machine">How to use aluminum foil in your washing machine</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="QpAPuFbKgDBLZHbnX2knYg" name="Aluminum foil in washing machine" alt="Ball of aluminum foil in washing machine" src="https://cdn.mos.cms.futurecdn.net/QpAPuFbKgDBLZHbnX2knYg.png" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Camilla Sharman)</span></figcaption></figure><p>The laundry hack involves scrunching a ball of aluminum foil about 2-3 inches in diameter and adding it to your washing machine and dryer. The same ball can be used for several loads. However, when I explored the hack further, I discovered it’s only really helpful when drying your laundry. </p><p>According to the<a href="https://www.soapboxlr.com/blog/posts/reduce-static-cling-naturally-the-aluminum-foil-ball-trick/" target="_blank"> Laundry Room</a>, the idea arose to solve the problem of static cling as an eco-friendly alternative to single-use products such as dryer sheets. </p><p>It reports, “Aluminum works by discharging electricity that builds up in the dryer. When clothes tumble around in the dryer, friction causes them to generate static electricity. The aluminum foil acts as a conductor that absorbs the charge, preventing the clothes from clinging together.”</p><p>And it adds, “Unlike dryer sheets, which coat clothes in a thin layer of chemicals, aluminum foil simply neutralizes the static without leaving any residue.”</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-W0RKRX"></div>                            </div>                            <script src="https://kwizly.com/embed/W0RKRX.js" async></script><h2 id="the-expert-s-take-is-it-safe">The expert's take: Is it safe?</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:5990px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="LrW2oMHDP87f69SFxpEVME" name="Main.jpg" alt="A close up of a clothes dryer's drum with dry clothes" src="https://cdn.mos.cms.futurecdn.net/LrW2oMHDP87f69SFxpEVME.jpg" mos="" align="middle" fullscreen="" width="5990" height="3369" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Shutterstock)</span></figcaption></figure><p>To get some answers I spoke with Michelle Feng, the marketing manager at <a href="https://uk.hisense.com/">Hisense</a>, and I asked whether it’s safe to use aluminum foil in your washing machine.</p><p>“Putting a tightly compressed aluminum foil ball in a washing machine for the duration of a cycle is unlikely to pose a significant risk, but I wouldn’t recommend doing it routinely,” said Feng.</p><p>The main claim behind this “hack” is that aluminum can help reduce static as fabrics rub together, but Feng noted that static buildup is much less of an issue during a wash cycle because clothes are immersed in water much of the time, allowing electrical charge to dissipate.</p><p>Feng shared that this claim is more relevant to a tumble dryer, where fabrics rub together in hot, dry conditions. But she said there is little evidence that aluminum foil balls actually reduce static.</p><p>So would the appliance manufacturer recommend that people follow this tip?</p><p>“Given the lack of a demonstrated benefit, we wouldn’t recommend the hack,” Feng said. “There is also no need to introduce an aluminum ball into the machine when there are potential downsides, such as the foil breaking apart, loose pieces reaching the filter or drainage system, or sharp edges catching on delicate fabrics.”</p><p>I'd be interested in reading your thoughts on this laundry hack and whether you have tried it. Please leave your comments below.</p><div class="product"><a data-dimension112="46ec79de-9bbd-11f1-8eae-ef264326fb34" data-action="Deal Block" data-label="Smart Pet Pro Washer and Dryer" data-dimension48="Smart Pet Pro Washer and Dryer" data-dimension25="$998" href="https://www.pcrichard.com/maytag-pet-pro-27-in-7.4-cu-ft-smart-stackable-electric-dryer-with-sensor-dry-sanitize-and-steam-cycle-midnight-steel/MED7020RF.html?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:800px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="SkAvGUqExVDa5yAXoth2CV" name="Maytag dryer" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/SkAvGUqExVDa5yAXoth2CV.jpg" mos="" align="middle" fullscreen="" width="800" height="800" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.pcrichard.com/maytag-pet-pro-27-in-7.4-cu-ft-smart-stackable-electric-dryer-with-sensor-dry-sanitize-and-steam-cycle-midnight-steel/MED7020RF.html?" target="_blank" rel="nofollow" data-dimension112="46ec79de-9bbd-11f1-8eae-ef264326fb34" data-action="Deal Block" data-label="Smart Pet Pro Washer and Dryer" data-dimension48="Smart Pet Pro Washer and Dryer" data-dimension25="$998">Smart Pet Pro Washer and Dryer: was $1166 now $998</a></strong><br>Maytag's Pet Pro Washer and Dryer is recommended as the best clothes dryer overall in our buying guide. This front-loading machine has a 5 cu. ft. capacity, 12 cycles and a pet pro filter. What's more, it's also compatible with Alexa and Google Assistant.<a class="view-deal button" href="https://www.pcrichard.com/maytag-pet-pro-27-in-7.4-cu-ft-smart-stackable-electric-dryer-with-sensor-dry-sanitize-and-steam-cycle-midnight-steel/MED7020RF.html?" target="_blank" rel="nofollow" data-dimension112="46ec79de-9bbd-11f1-8eae-ef264326fb34" data-action="Deal Block" data-label="Smart Pet Pro Washer and Dryer" data-dimension48="Smart Pet Pro Washer and Dryer" data-dimension25="$998">View Deal</a></p></div><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h3><ul><li><a href="https://www.tomsguide.com/home/home-appliances/dont-make-this-laundry-mistake-experts-share-how-much-laundry-detergent-to-use-for-the-best-wash">Don’t make this laundry mistake — experts share how much laundry detergent to use for the best wash</a></li><li><a href="https://www.tomsguide.com/home/5-big-laundry-mistakes-youre-probably-making-and-how-to-avoid-them">5 big laundry mistakes you're probably making and how to avoid them</a></li><li><a href="https://www.tomsguide.com/home/why-are-my-clothes-turning-gray-laundry-experts-reveal-5-tips-to-keep-your-whites-bright">Why are my clothes turning gray? Laundry experts reveal 5 tips to keep your whites bright</a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/home/people-are-putting-aluminum-foil-in-their-washing-machines-i-asked-an-appliance-expert-if-its-safe</link>
                                                                            <description>
                            <![CDATA[ The truth about the aluminum foil laundry hack — is it a genius trick or a disaster? ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">FXB83FEaoNVc7idsisps2k</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/XGiTDdhHznTKVPjztYzpq-1280-80.png" type="image/png" length="0"></enclosure>
                                                                        <pubDate>Wed, 19 Aug 2026 11:45:59 +0000</pubDate>                                                                                                                                <updated>Wed, 19 Aug 2026 17:58:48 +0000</updated>
                                                                                                                                            <category><![CDATA[Home]]></category>
                                                    <category><![CDATA[Home Appliances]]></category>
                                                                                                <author><![CDATA[ camilla.sharman@futurenet.com (Camilla Sharman) ]]></author>                    <dc:creator><![CDATA[ Camilla Sharman ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/nY4nvWzofHKHpvzAqN5LVH.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Camilla is the Homes Staff Writer and covers everything to do with homes and gardens. She has a wealth of editorial experience, mounting over 30 years, and covers news and features, tests products for reviews and compiles buying guides.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;p&gt;Her work has appeared in business and consumer titles, including Ideal Home, Real Homes, House Beautiful, Homebuilding &amp;amp; Renovation, and Kitchen &amp;amp; Bathroom Business. She’s even appeared on the cover of Your Home, writing about her own house renovation.&lt;/p&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;p&gt;Although she’s obsessed with decorating her home, she also enjoys baking and trying out the latest kitchen appliances. But when she’s not inside, you’ll find her pottering about in her yard, tending to her vegetable patch or taking in her prized hydrangeas. She also enjoys keeping fit, and if she&#039;s not on a spin bike trying to keep up with the class, she&#039;ll be in the pool, or trying to perfect her headstand in a yoga class.&lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                <media:content type="image/png" url="https://cdn.mos.cms.futurecdn.net/XGiTDdhHznTKVPjztYzpq-1280-80.png">
                                                            <media:credit><![CDATA[Future / Camilla Sharman]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Putting ball of aluminum foil in washing machine]]></media:description>                                                            <media:text><![CDATA[Putting ball of aluminum foil in washing machine]]></media:text>
                                <media:title type="plain"><![CDATA[Putting ball of aluminum foil in washing machine]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/XGiTDdhHznTKVPjztYzpq-1280-80.png" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>It’s part of my job as a homes writer to spot viral household hacks and share my thoughts on whether they work. So, when I read about putting aluminum foil balls in a washing machine, I was instantly on high alert.</p><p>Firstly, I’m thinking, what is it supposed to do, and secondly, I’m wondering whether it’s safe.</p><p>Apparently, placing a rolled-up ball of aluminum foil in your washing machine and <a href="https://www.tomsguide.com/us/best-clothes-dryers,review-6225.html">clothes dryer</a> helps reduce static. But does it actually work?</p><h2 id="a-silver-ball-of-magic">A silver ball of magic</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:4272px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="wjF22X282MtrgrXk33H5e7" name="shutterstock_41469406.jpg" alt="aluminum foil on wooden surface" src="https://cdn.mos.cms.futurecdn.net/wjF22X282MtrgrXk33H5e7.jpg" mos="" align="middle" fullscreen="" width="4272" height="2403" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Shutterstock)</span></figcaption></figure><p><a href="https://www.tomsguide.com/how-to/7-surprising-uses-for-aluminum-foil">Aluminum foil has many surprising uses</a> beyond covering food. It can be used as a <a href="https://www.tomsguide.com/home/gardening/gardeners-are-being-urged-to-put-aluminum-foil-in-their-yard-right-now-and-you-might-be-surprised-why">pest deterrent in your yard</a>, to <a href="https://www.tomsguide.com/opinion/i-just-beat-the-heat-with-a-dollar2-roll-of-aluminum-foil-heres-how">cool your home</a>, and even to <a href="https://www.tomsguide.com/us/aluminum-foil-wi-fi-extension,news-26097.html">boost your Wi-Fi signal</a>. Now we’re being told it can help with the laundry — and I need all the help I can get!</p><p>But I’ve recently purchased a new <a href="https://www.tomsguide.com/us/best-washing-machines,review-6208.html">washing machine</a>, so I’d be reluctant to try this laundry hack without knowing whether it’s safe to follow. I don’t want to ruin my new appliance.</p><p>So, what does throwing a rolled-up ball of aluminum foil into your washing machine do? Apparently, it helps reduce static, preventing clingy garments. Is it time to say goodbye to your usual clothes softener and dryer sheets?</p><h2 id="how-to-use-aluminum-foil-in-your-washing-machine">How to use aluminum foil in your washing machine</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="QpAPuFbKgDBLZHbnX2knYg" name="Aluminum foil in washing machine" alt="Ball of aluminum foil in washing machine" src="https://cdn.mos.cms.futurecdn.net/QpAPuFbKgDBLZHbnX2knYg.png" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Camilla Sharman)</span></figcaption></figure><p>The laundry hack involves scrunching a ball of aluminum foil about 2-3 inches in diameter and adding it to your washing machine and dryer. The same ball can be used for several loads. However, when I explored the hack further, I discovered it’s only really helpful when drying your laundry. </p><p>According to the<a href="https://www.soapboxlr.com/blog/posts/reduce-static-cling-naturally-the-aluminum-foil-ball-trick/" target="_blank"> Laundry Room</a>, the idea arose to solve the problem of static cling as an eco-friendly alternative to single-use products such as dryer sheets. </p><p>It reports, “Aluminum works by discharging electricity that builds up in the dryer. When clothes tumble around in the dryer, friction causes them to generate static electricity. The aluminum foil acts as a conductor that absorbs the charge, preventing the clothes from clinging together.”</p><p>And it adds, “Unlike dryer sheets, which coat clothes in a thin layer of chemicals, aluminum foil simply neutralizes the static without leaving any residue.”</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-W0RKRX"></div>                            </div>                            <script src="https://kwizly.com/embed/W0RKRX.js" async></script><h2 id="the-expert-s-take-is-it-safe">The expert's take: Is it safe?</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:5990px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="LrW2oMHDP87f69SFxpEVME" name="Main.jpg" alt="A close up of a clothes dryer's drum with dry clothes" src="https://cdn.mos.cms.futurecdn.net/LrW2oMHDP87f69SFxpEVME.jpg" mos="" align="middle" fullscreen="" width="5990" height="3369" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Shutterstock)</span></figcaption></figure><p>To get some answers I spoke with Michelle Feng, the marketing manager at <a href="https://uk.hisense.com/">Hisense</a>, and I asked whether it’s safe to use aluminum foil in your washing machine.</p><p>“Putting a tightly compressed aluminum foil ball in a washing machine for the duration of a cycle is unlikely to pose a significant risk, but I wouldn’t recommend doing it routinely,” said Feng.</p><p>The main claim behind this “hack” is that aluminum can help reduce static as fabrics rub together, but Feng noted that static buildup is much less of an issue during a wash cycle because clothes are immersed in water much of the time, allowing electrical charge to dissipate.</p><p>Feng shared that this claim is more relevant to a tumble dryer, where fabrics rub together in hot, dry conditions. But she said there is little evidence that aluminum foil balls actually reduce static.</p><p>So would the appliance manufacturer recommend that people follow this tip?</p><p>“Given the lack of a demonstrated benefit, we wouldn’t recommend the hack,” Feng said. “There is also no need to introduce an aluminum ball into the machine when there are potential downsides, such as the foil breaking apart, loose pieces reaching the filter or drainage system, or sharp edges catching on delicate fabrics.”</p><p>I'd be interested in reading your thoughts on this laundry hack and whether you have tried it. Please leave your comments below.</p><div class="product"><a data-dimension112="46ec79de-9bbd-11f1-8eae-ef264326fb34" data-action="Deal Block" data-label="Smart Pet Pro Washer and Dryer" data-dimension48="Smart Pet Pro Washer and Dryer" data-dimension25="$998" href="https://www.pcrichard.com/maytag-pet-pro-27-in-7.4-cu-ft-smart-stackable-electric-dryer-with-sensor-dry-sanitize-and-steam-cycle-midnight-steel/MED7020RF.html?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:800px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="SkAvGUqExVDa5yAXoth2CV" name="Maytag dryer" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/SkAvGUqExVDa5yAXoth2CV.jpg" mos="" align="middle" fullscreen="" width="800" height="800" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.pcrichard.com/maytag-pet-pro-27-in-7.4-cu-ft-smart-stackable-electric-dryer-with-sensor-dry-sanitize-and-steam-cycle-midnight-steel/MED7020RF.html?" target="_blank" rel="nofollow" data-dimension112="46ec79de-9bbd-11f1-8eae-ef264326fb34" data-action="Deal Block" data-label="Smart Pet Pro Washer and Dryer" data-dimension48="Smart Pet Pro Washer and Dryer" data-dimension25="$998">Smart Pet Pro Washer and Dryer: was $1166 now $998</a></strong><br>Maytag's Pet Pro Washer and Dryer is recommended as the best clothes dryer overall in our buying guide. This front-loading machine has a 5 cu. ft. capacity, 12 cycles and a pet pro filter. What's more, it's also compatible with Alexa and Google Assistant.<a class="view-deal button" href="https://www.pcrichard.com/maytag-pet-pro-27-in-7.4-cu-ft-smart-stackable-electric-dryer-with-sensor-dry-sanitize-and-steam-cycle-midnight-steel/MED7020RF.html?" target="_blank" rel="nofollow" data-dimension112="46ec79de-9bbd-11f1-8eae-ef264326fb34" data-action="Deal Block" data-label="Smart Pet Pro Washer and Dryer" data-dimension48="Smart Pet Pro Washer and Dryer" data-dimension25="$998">View Deal</a></p></div><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h3><ul><li><a href="https://www.tomsguide.com/home/home-appliances/dont-make-this-laundry-mistake-experts-share-how-much-laundry-detergent-to-use-for-the-best-wash">Don’t make this laundry mistake — experts share how much laundry detergent to use for the best wash</a></li><li><a href="https://www.tomsguide.com/home/5-big-laundry-mistakes-youre-probably-making-and-how-to-avoid-them">5 big laundry mistakes you're probably making and how to avoid them</a></li><li><a href="https://www.tomsguide.com/home/why-are-my-clothes-turning-gray-laundry-experts-reveal-5-tips-to-keep-your-whites-bright">Why are my clothes turning gray? Laundry experts reveal 5 tips to keep your whites bright</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ SharkNinja’s AquaReach just reinvented wet-dry vacs with an extendable wand ]]></title>
                                                                                                <dc:content><![CDATA[ <p>SharkNinja, known for making some of the <a href="https://www.tomsguide.com/best-picks/best-vacuum-cleaners" target="_blank">best vacuums</a>, has launched AquaReach — a 2-in-1 wet-and-dry vacuum and mop designed to go far beyond cleaning floors.</p><p>Inspired by social media cleaning hacks to reach places that standard floor cleaners cannot, the $399 AquaReach goes beyond the ordinary core-cleaning capabilities. Apart from the standard floor cleaner design, AquaReach includes an extendible wand to reach elevated surfaces and tight spaces.</p><h2 id="aquareach-tackles-more-messes-in-one">AquaReach tackles more messes in one</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="KCs6ndvL8HcSuYiDVcyY4j" name="SharkNinja AquaReach" alt="SharkNinja AquaReach" src="https://cdn.mos.cms.futurecdn.net/KCs6ndvL8HcSuYiDVcyY4j.png" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: SharkNinja)</span></figcaption></figure><p>Consumers have shared countless cleaning hacks, some of which Tom’s Guide has covered:<a href="https://www.tomsguide.com/home/i-found-this-vacuuming-hack-on-tiktok-and-my-baseboards-have-never-looked-cleaner"> wrapping dryers sheets around vacuum nozzles</a>, taping microfiber cloths to cleaning tools, and inventing DIY workarounds to get the job done. </p><p>SharkNinja says those videos weren’t just clever hacks; they revealed an unmet need that vacuums hadn’t addressed.</p><p>“People weren’t creating cleaning hacks because they wanted to — they were creating them because they had to,” says Petra Oman, VP of Marketing at SharkNinja in a press release. “They showed us what was missing. </p><p>“AquaReach was built around the way people were already cleaning, combining vacuuming, mopping and extended reach so they can tackle more of the mess in one routine.”</p><p>I’m thinking one tool that does multiple jobs cuts down chore time — you’re no longer having to improvise or pick up another appliance to get a job done.</p><div class="product"><a data-dimension112="c485d0ae-9af3-11f1-ba84-531ed1f63ab6" data-action="Deal Block" data-label="AquaReach Vacuum Mop" data-dimension48="AquaReach Vacuum Mop" data-dimension25="$399" href="https://www.sharkninja.com/shark-aquareach-vacuum-mop/WD551.html" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:577px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="LhLaDzp36nwUeMWhiVTXfM" name="SharkNinja AquaReach" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/LhLaDzp36nwUeMWhiVTXfM.png" mos="" align="middle" fullscreen="" width="577" height="577" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.sharkninja.com/shark-aquareach-vacuum-mop/WD551.html" target="_blank" rel="nofollow" data-dimension112="c485d0ae-9af3-11f1-ba84-531ed1f63ab6" data-action="Deal Block" data-label="AquaReach Vacuum Mop" data-dimension48="AquaReach Vacuum Mop" data-dimension25="$399">AquaReach Vacuum Mop: $399</a></strong><br>Shark's latest vacuum mop goes beyond the floor, cleaning both wet and dry messes. Designed for hard surfaces, it offers both powerful suction and mopping simultaneously, with a 40-minute runtime.<a class="view-deal button" href="https://www.sharkninja.com/shark-aquareach-vacuum-mop/WD551.html" target="_blank" rel="nofollow" data-dimension112="c485d0ae-9af3-11f1-ba84-531ed1f63ab6" data-action="Deal Block" data-label="AquaReach Vacuum Mop" data-dimension48="AquaReach Vacuum Mop" data-dimension25="$399">View Deal</a></p></div><h2 id="cleaning-messes-beyond-the-floor">Cleaning messes beyond the floor</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="KQcH8L3KrSvW9XjhtheNrG" name="SharkNinja AquaReach" alt="SharkNinja AquaReach" src="https://cdn.mos.cms.futurecdn.net/KQcH8L3KrSvW9XjhtheNrG.png" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Shutterstock)</span></figcaption></figure><p>We all know that real-life messes don’t stay on the floor. Food splatters on cabinet fronts, and grime builds around toilet bases. Life happens, and messes aren’t just dry. </p><p>That’s why SharkNinja has combined a wet and dry vacuum to tackle what we all face every day.  With the AquaReach, the brushroll rotates continuously, working with a powerful jet of cleaning solution to loosen and scrub stuck-on debris, while Shark's powerful suction lifts away dirt and dirty liquid simultaneously. </p><p>And when you need to clean up more than just the floor, the<strong> integrated extendable wand</strong> offers the same vacuuming and mopping power with more flexibility. </p><p>What's more, the appliance comes with two specialized tools — a <strong>stain scrubber</strong> and <strong>detailer mop</strong>. With a targeted spray and powerful suction, the<strong> </strong>stain scrubber is designed to remove stuck-on messes from the floor, baseboards, window sills, behind toilets and bathtub ledges. Meanwhile, the detailer mop reaches under furniture, along edges and into tight corners.</p><p>And while cleaning your floors, the brush roll is continuously refreshed — preventing dirty water and debris from redistributing a mess on your floors. That’s thanks to the dual-tank system, which keeps clear and dirty water separate, and an on-dock rinse cycle that flushes the brush roll after every use. </p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-eGRoEX"></div>                            </div>                            <script src="https://kwizly.com/embed/eGRoEX.js" async></script><h2 id="and-for-an-even-better-clean">And for an even better clean...</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:7667px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="MuJ7tNejzKrbueAvD2T5Dc" name="SharkNinja AquaReach" alt="SharkNinja AquaReach" src="https://cdn.mos.cms.futurecdn.net/MuJ7tNejzKrbueAvD2T5Dc.png" mos="" align="middle" fullscreen="" width="7667" height="4313" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: SharkNinja)</span></figcaption></figure><p>SharkNinja hasn’t just launched one new appliance; you can also choose the <strong>AquaReach Pro</strong>. What’s the difference? The Pro version has the additional Total Self-Cleaning and Drying System, and its Self-Sanitizing dock rinses the brushroll and dries it with heated air up to 160°F. According to SharkNinja, this helps reduce odors and eliminate 99.9% of bacteria from the brushroll. </p><p>It also offers an <strong>edge-optimization nozzle</strong> that cleans closer to baseboards and edges, and an <strong>LED reveal beam</strong> that illuminates hidden dust, crumbs and other debris.</p><p>But you do have to pay more for the AquaReach Pro, which is available for <a href="https://www.sharkninja.com/shark-aquareach-pro-vacuum-mop/WD563.html" target="_blank" rel="nofollow">$529 direct from SharkNinja.</a></p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="FwyEiDpiXpiXcjQDvvj8bE" name="SharkNinja AquaReach" alt="SharkNinja AquaReach" src="https://cdn.mos.cms.futurecdn.net/FwyEiDpiXpiXcjQDvvj8bE.png" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: SharkNinja)</span></figcaption></figure><p>We're still waiting to get our hands on SharkNinja’s newest appliance, but I'm eager to put it up against <a href="https://www.tomsguide.com/home/tineco-floor-one-s6-review">Tineco's Floor One S6 </a>wet and dry vacuum and <a href="https://www.tomsguide.com/home/home-appliances/eureka-rapidwash-new730bk-floor-cleaner-review">Eureka's RapidWash Floor Cleaner</a>, to see if the additional wand is a worthy extra.</p><div class="product"><a data-dimension112="c485d162-9af3-11f1-af67-1df5cacdc946" data-action="Deal Block" data-label="AquaReach Pro Vacuum Mop with Mop Pads Kit" data-dimension48="AquaReach Pro Vacuum Mop with Mop Pads Kit" data-dimension25="$529" href="https://www.sharkninja.com/shark-aquareach-pro-vacuum-mop/WD563.html" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:643px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="YSKwL6fkPK2XE7GUf2SfCY" name="SharkNinja AquaReach Pro" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/YSKwL6fkPK2XE7GUf2SfCY.png" mos="" align="middle" fullscreen="" width="643" height="643" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.sharkninja.com/shark-aquareach-pro-vacuum-mop/WD563.html" target="_blank" rel="nofollow" data-dimension112="c485d162-9af3-11f1-af67-1df5cacdc946" data-action="Deal Block" data-label="AquaReach Pro Vacuum Mop with Mop Pads Kit" data-dimension48="AquaReach Pro Vacuum Mop with Mop Pads Kit" data-dimension25="$529">AquaReach Pro Vacuum Mop with Mop Pads Kit: $529</a></strong><br>SharkNinja's AquaReach Pro offers all the functionality of the standard version, plus a sanitizing dock and an extra 10-minute runtime. <a class="view-deal button" href="https://www.sharkninja.com/shark-aquareach-pro-vacuum-mop/WD563.html" target="_blank" rel="nofollow" data-dimension112="c485d162-9af3-11f1-af67-1df5cacdc946" data-action="Deal Block" data-label="AquaReach Pro Vacuum Mop with Mop Pads Kit" data-dimension48="AquaReach Pro Vacuum Mop with Mop Pads Kit" data-dimension25="$529">View Deal</a></p></div><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h3><ul><li><a href="https://www.tomsguide.com/home/how-choose-the-right-type-of-vacuum-cleaner">How to choose the right vacuum cleaner — 7 things to consider</a></li><li><a href="https://www.tomsguide.com/home/i-tried-this-weird-vacuum-cleaning-hack-to-keep-my-home-smelling-fresh-but-does-it-work">I tried this weird vacuum cleaning hack to keep my home smelling fresh — but does it work?</a></li><li><a href="https://www.tomsguide.com/home/keep-your-wet-and-dry-vacuum-running-like-new-with-these-5-easy-steps">Keep your wet and dry vacuum running like new with these 7 easy steps</a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/home/home-appliances/sharkninjas-new-aquareach-wet-dry-vacuum-cleans-up</link>
                                                                            <description>
                            <![CDATA[ Meet Shark’s AquaReach. This extendable wet-dry vacuum was built for wall-to-wall cleaning. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">RqffUEp4KpvFebbYLZ64QK</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/YPLWZLKCeu3pExUK8jmE6K-1280-80.png" type="image/png" length="0"></enclosure>
                                                                        <pubDate>Tue, 18 Aug 2026 15:20:51 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Home Appliances]]></category>
                                                    <category><![CDATA[Home]]></category>
                                                                                                <author><![CDATA[ camilla.sharman@futurenet.com (Camilla Sharman) ]]></author>                    <dc:creator><![CDATA[ Camilla Sharman ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/nY4nvWzofHKHpvzAqN5LVH.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Camilla is the Homes Staff Writer and covers everything to do with homes and gardens. She has a wealth of editorial experience, mounting over 30 years, and covers news and features, tests products for reviews and compiles buying guides.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;p&gt;Her work has appeared in business and consumer titles, including Ideal Home, Real Homes, House Beautiful, Homebuilding &amp;amp; Renovation, and Kitchen &amp;amp; Bathroom Business. She’s even appeared on the cover of Your Home, writing about her own house renovation.&lt;/p&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;p&gt;Although she’s obsessed with decorating her home, she also enjoys baking and trying out the latest kitchen appliances. But when she’s not inside, you’ll find her pottering about in her yard, tending to her vegetable patch or taking in her prized hydrangeas. She also enjoys keeping fit, and if she&#039;s not on a spin bike trying to keep up with the class, she&#039;ll be in the pool, or trying to perfect her headstand in a yoga class.&lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                <media:content type="image/png" url="https://cdn.mos.cms.futurecdn.net/YPLWZLKCeu3pExUK8jmE6K-1280-80.png">
                                                            <media:credit><![CDATA[SharkNinja]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[SharkNinja AquaReach]]></media:description>                                                            <media:text><![CDATA[SharkNinja AquaReach]]></media:text>
                                <media:title type="plain"><![CDATA[SharkNinja AquaReach]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/YPLWZLKCeu3pExUK8jmE6K-1280-80.png" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>SharkNinja, known for making some of the <a href="https://www.tomsguide.com/best-picks/best-vacuum-cleaners" target="_blank">best vacuums</a>, has launched AquaReach — a 2-in-1 wet-and-dry vacuum and mop designed to go far beyond cleaning floors.</p><p>Inspired by social media cleaning hacks to reach places that standard floor cleaners cannot, the $399 AquaReach goes beyond the ordinary core-cleaning capabilities. Apart from the standard floor cleaner design, AquaReach includes an extendible wand to reach elevated surfaces and tight spaces.</p><h2 id="aquareach-tackles-more-messes-in-one">AquaReach tackles more messes in one</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="KCs6ndvL8HcSuYiDVcyY4j" name="SharkNinja AquaReach" alt="SharkNinja AquaReach" src="https://cdn.mos.cms.futurecdn.net/KCs6ndvL8HcSuYiDVcyY4j.png" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: SharkNinja)</span></figcaption></figure><p>Consumers have shared countless cleaning hacks, some of which Tom’s Guide has covered:<a href="https://www.tomsguide.com/home/i-found-this-vacuuming-hack-on-tiktok-and-my-baseboards-have-never-looked-cleaner"> wrapping dryers sheets around vacuum nozzles</a>, taping microfiber cloths to cleaning tools, and inventing DIY workarounds to get the job done. </p><p>SharkNinja says those videos weren’t just clever hacks; they revealed an unmet need that vacuums hadn’t addressed.</p><p>“People weren’t creating cleaning hacks because they wanted to — they were creating them because they had to,” says Petra Oman, VP of Marketing at SharkNinja in a press release. “They showed us what was missing. </p><p>“AquaReach was built around the way people were already cleaning, combining vacuuming, mopping and extended reach so they can tackle more of the mess in one routine.”</p><p>I’m thinking one tool that does multiple jobs cuts down chore time — you’re no longer having to improvise or pick up another appliance to get a job done.</p><div class="product"><a data-dimension112="c485d0ae-9af3-11f1-ba84-531ed1f63ab6" data-action="Deal Block" data-label="AquaReach Vacuum Mop" data-dimension48="AquaReach Vacuum Mop" data-dimension25="$399" href="https://www.sharkninja.com/shark-aquareach-vacuum-mop/WD551.html" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:577px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="LhLaDzp36nwUeMWhiVTXfM" name="SharkNinja AquaReach" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/LhLaDzp36nwUeMWhiVTXfM.png" mos="" align="middle" fullscreen="" width="577" height="577" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.sharkninja.com/shark-aquareach-vacuum-mop/WD551.html" target="_blank" rel="nofollow" data-dimension112="c485d0ae-9af3-11f1-ba84-531ed1f63ab6" data-action="Deal Block" data-label="AquaReach Vacuum Mop" data-dimension48="AquaReach Vacuum Mop" data-dimension25="$399">AquaReach Vacuum Mop: $399</a></strong><br>Shark's latest vacuum mop goes beyond the floor, cleaning both wet and dry messes. Designed for hard surfaces, it offers both powerful suction and mopping simultaneously, with a 40-minute runtime.<a class="view-deal button" href="https://www.sharkninja.com/shark-aquareach-vacuum-mop/WD551.html" target="_blank" rel="nofollow" data-dimension112="c485d0ae-9af3-11f1-ba84-531ed1f63ab6" data-action="Deal Block" data-label="AquaReach Vacuum Mop" data-dimension48="AquaReach Vacuum Mop" data-dimension25="$399">View Deal</a></p></div><h2 id="cleaning-messes-beyond-the-floor">Cleaning messes beyond the floor</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="KQcH8L3KrSvW9XjhtheNrG" name="SharkNinja AquaReach" alt="SharkNinja AquaReach" src="https://cdn.mos.cms.futurecdn.net/KQcH8L3KrSvW9XjhtheNrG.png" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Shutterstock)</span></figcaption></figure><p>We all know that real-life messes don’t stay on the floor. Food splatters on cabinet fronts, and grime builds around toilet bases. Life happens, and messes aren’t just dry. </p><p>That’s why SharkNinja has combined a wet and dry vacuum to tackle what we all face every day.  With the AquaReach, the brushroll rotates continuously, working with a powerful jet of cleaning solution to loosen and scrub stuck-on debris, while Shark's powerful suction lifts away dirt and dirty liquid simultaneously. </p><p>And when you need to clean up more than just the floor, the<strong> integrated extendable wand</strong> offers the same vacuuming and mopping power with more flexibility. </p><p>What's more, the appliance comes with two specialized tools — a <strong>stain scrubber</strong> and <strong>detailer mop</strong>. With a targeted spray and powerful suction, the<strong> </strong>stain scrubber is designed to remove stuck-on messes from the floor, baseboards, window sills, behind toilets and bathtub ledges. Meanwhile, the detailer mop reaches under furniture, along edges and into tight corners.</p><p>And while cleaning your floors, the brush roll is continuously refreshed — preventing dirty water and debris from redistributing a mess on your floors. That’s thanks to the dual-tank system, which keeps clear and dirty water separate, and an on-dock rinse cycle that flushes the brush roll after every use. </p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-eGRoEX"></div>                            </div>                            <script src="https://kwizly.com/embed/eGRoEX.js" async></script><h2 id="and-for-an-even-better-clean">And for an even better clean...</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:7667px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="MuJ7tNejzKrbueAvD2T5Dc" name="SharkNinja AquaReach" alt="SharkNinja AquaReach" src="https://cdn.mos.cms.futurecdn.net/MuJ7tNejzKrbueAvD2T5Dc.png" mos="" align="middle" fullscreen="" width="7667" height="4313" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: SharkNinja)</span></figcaption></figure><p>SharkNinja hasn’t just launched one new appliance; you can also choose the <strong>AquaReach Pro</strong>. What’s the difference? The Pro version has the additional Total Self-Cleaning and Drying System, and its Self-Sanitizing dock rinses the brushroll and dries it with heated air up to 160°F. According to SharkNinja, this helps reduce odors and eliminate 99.9% of bacteria from the brushroll. </p><p>It also offers an <strong>edge-optimization nozzle</strong> that cleans closer to baseboards and edges, and an <strong>LED reveal beam</strong> that illuminates hidden dust, crumbs and other debris.</p><p>But you do have to pay more for the AquaReach Pro, which is available for <a href="https://www.sharkninja.com/shark-aquareach-pro-vacuum-mop/WD563.html" target="_blank" rel="nofollow">$529 direct from SharkNinja.</a></p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="FwyEiDpiXpiXcjQDvvj8bE" name="SharkNinja AquaReach" alt="SharkNinja AquaReach" src="https://cdn.mos.cms.futurecdn.net/FwyEiDpiXpiXcjQDvvj8bE.png" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: SharkNinja)</span></figcaption></figure><p>We're still waiting to get our hands on SharkNinja’s newest appliance, but I'm eager to put it up against <a href="https://www.tomsguide.com/home/tineco-floor-one-s6-review">Tineco's Floor One S6 </a>wet and dry vacuum and <a href="https://www.tomsguide.com/home/home-appliances/eureka-rapidwash-new730bk-floor-cleaner-review">Eureka's RapidWash Floor Cleaner</a>, to see if the additional wand is a worthy extra.</p><div class="product"><a data-dimension112="c485d162-9af3-11f1-af67-1df5cacdc946" data-action="Deal Block" data-label="AquaReach Pro Vacuum Mop with Mop Pads Kit" data-dimension48="AquaReach Pro Vacuum Mop with Mop Pads Kit" data-dimension25="$529" href="https://www.sharkninja.com/shark-aquareach-pro-vacuum-mop/WD563.html" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:643px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="YSKwL6fkPK2XE7GUf2SfCY" name="SharkNinja AquaReach Pro" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/YSKwL6fkPK2XE7GUf2SfCY.png" mos="" align="middle" fullscreen="" width="643" height="643" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.sharkninja.com/shark-aquareach-pro-vacuum-mop/WD563.html" target="_blank" rel="nofollow" data-dimension112="c485d162-9af3-11f1-af67-1df5cacdc946" data-action="Deal Block" data-label="AquaReach Pro Vacuum Mop with Mop Pads Kit" data-dimension48="AquaReach Pro Vacuum Mop with Mop Pads Kit" data-dimension25="$529">AquaReach Pro Vacuum Mop with Mop Pads Kit: $529</a></strong><br>SharkNinja's AquaReach Pro offers all the functionality of the standard version, plus a sanitizing dock and an extra 10-minute runtime. <a class="view-deal button" href="https://www.sharkninja.com/shark-aquareach-pro-vacuum-mop/WD563.html" target="_blank" rel="nofollow" data-dimension112="c485d162-9af3-11f1-af67-1df5cacdc946" data-action="Deal Block" data-label="AquaReach Pro Vacuum Mop with Mop Pads Kit" data-dimension48="AquaReach Pro Vacuum Mop with Mop Pads Kit" data-dimension25="$529">View Deal</a></p></div><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h3><ul><li><a href="https://www.tomsguide.com/home/how-choose-the-right-type-of-vacuum-cleaner">How to choose the right vacuum cleaner — 7 things to consider</a></li><li><a href="https://www.tomsguide.com/home/i-tried-this-weird-vacuum-cleaning-hack-to-keep-my-home-smelling-fresh-but-does-it-work">I tried this weird vacuum cleaning hack to keep my home smelling fresh — but does it work?</a></li><li><a href="https://www.tomsguide.com/home/keep-your-wet-and-dry-vacuum-running-like-new-with-these-5-easy-steps">Keep your wet and dry vacuum running like new with these 7 easy steps</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ Moccamaster vs Simply Good Coffee — which premium coffee machine makes a better brew? Here's what I think ]]></title>
                                                                                                <dc:content><![CDATA[ <div  class="fancy-box"><div class="fancy_box-title">The Coffee Lab</div><div class="fancy_box_body"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' ><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="UwFdgr6xkNzHUWjapZThcN" name="smeg edited2" caption="" alt="the smeg emc02 mini pro manual espresso machine in jade green" src="https://cdn.mos.cms.futurecdn.net/UwFdgr6xkNzHUWjapZThcN.jpg" mos="" link="" align="" fullscreen="" width="" height="" attribution="" endorsement="" class="pinterest-pin-exclude"></p></div></div><figcaption itemprop="caption description" class=""><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p class="fancy-box__body-text">I'm Erin, and welcome to the twentieth episode of <a data-analytics-id="inline-link" href="https://www.tomsguide.com/tag/the-coffee-lab">The Coffee Lab</a>, the series where we forget coffee snobbery. The Coffee Lab is all about making coffee fun. Join me as I help you kickstart your coffee journey!</p></div></div><p>Anyone who knows anything about coffee has heard of Moccamaster. The Moccamaster (specifically the <a href="https://www.tomsguide.com/home/coffee-makers/technivorm-moccamaster-kgbv-select-review">KBGV Select</a>) is the most famous drip machine in the world, and there's very little competition. Few brands can go head-to-head with Technivorm's industrial, hardy stalwart, arguably the <a href="https://www.tomsguide.com/home/coffee-makers/best-coffee-makers">best coffee maker</a> of all time.</p><p>Mostly unchanged since its 1969 release, the Moccamaster does what many other coffee brands wish their flagship could: it has the best reputation in coffee. Whether this is from the industry-leading after-purchase care or the indestructible machine itself, I'm not sure. But people seriously love this thing. It's irrefutably "cult". </p><p>So enter the zippy young upstart — <a href="https://www.tomsguide.com/home/coffee-makers/simply-good-coffee-plastic-free-brewer-review">Simply Good Coffee Plastic-Free Brewer.</a> This model launched at the end of last year and was rolled out in 2026. What's the Plastic-Free Brewer got that the Moccamaster hasn't then? Well, the clue's in the name — it's not about what it <em>has</em>, but what it <em>hasn't</em>. Simply Good Coffee uses zero plastic in the brewing process. </p><p>Sure, this is all well and good — but what about taste? Let's find out which one makes a better brew. </p><h2 id="moccamaster-kbgv-select-amp-simply-good-coffee-plastic-free-brewer-what-39-s-the-difference">Moccamaster KBGV Select & Simply Good Coffee Plastic-Free Brewer: What's the difference?</h2><div class="product"><a data-dimension112="fd9c53d6-958f-11f1-9d02-bd0b05d941b8" data-action="Deal Block" data-label="Plastic-Free Brewer" data-dimension48="Plastic-Free Brewer" data-dimension25="$479" href="https://www.amazon.com/dp/B0FLYM8986" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1500px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="kBwcCTJrsdvHBBcz4LZYMa" name="Plastic-Free Brewer" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/kBwcCTJrsdvHBBcz4LZYMa.jpg" mos="" align="middle" fullscreen="" width="1500" height="1500" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>The Simply Good Plastic-Free Brewer measures 13.7 x 7.8 x 14.6 inches, uses a #4 cone, and can brew up to 8 cups of coffee at a time.<a class="view-deal button" href="https://www.amazon.com/dp/B0FLYM8986" target="_blank" rel="nofollow" data-dimension112="fd9c53d6-958f-11f1-9d02-bd0b05d941b8" data-action="Deal Block" data-label="Plastic-Free Brewer" data-dimension48="Plastic-Free Brewer" data-dimension25="$479">View Deal</a></p></div><p>While at their cores, the Moccamaster KBGV Select and the Simply Good Coffee Plastic-Free Brewers are both drip/filter coffee machines, there are a few key differences. </p><p>These differences reside in two main areas: design and accreditation. </p><p>Obviously, the SGC Plastic-Free Brewer is that: plastic-free (well, low plastic). No hot water touches plastic anywhere in the brewing process — but it does have medical-grade silicone tubing in the water lines. Even so, I don't class this as "plastic" as it's not the kind of polymer that leaches into water or breaks down over time. </p><p>The SGC has plastic on the exterior to prevent burns. Seriously, imagine if it were completely steel. You'd need to go to the ER if you accidentally brush up against it after brewing. </p><p>Now, the Moccamaster KBGV Select has a plastic filter basket and a plastic destratification tube in the carafe. I personally don't mind this plastic — Technivorm (which makes Moccamaster) is a Dutch company, and the EU has seriously strict regulations on plastic. It's high-quality, non-leaching, BPA-and PFA-free — all the adjectives.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:5242px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="DgfM3CL3QY7sPZLVG2N8xP" name="moccamaster and SGC machines" alt="the moccamaster and simply good coffee plastic-free brewer side by side" src="https://cdn.mos.cms.futurecdn.net/DgfM3CL3QY7sPZLVG2N8xP.jpg" mos="" align="middle" fullscreen="" width="5242" height="2948" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Erin Bashford)</span></figcaption></figure><p>So what else separates them? The SCA (Specialty Coffee Association) accreditation. Now, I don't think this is the be-all and end-all. There are more important things than an SCA accreditation. Taste, feel, emotional connection, secret ghosts inhabiting your coffee maker — whatever floats your boat (stews your brew? No. That's terrible. A career in stand-up comedy is clearly not for me). </p><p>If you do care about SCA accreditations, as I know a lot of coffee lovers do, you'll be more inclined to go with the Moccamaster. The KBGV Select has been SCA-accredited since the latter's advent in 2017, but the Simply Good Coffee Plastic-Free Brewer isn't yet accredited. </p><h2 id="moccamaster-kbgv-select-amp-simply-good-coffee-plastic-free-brewer-so-how-does-it-taste">Moccamaster KBGV Select & Simply Good Coffee Plastic-Free Brewer: So how does it taste?</h2><div class="product"><a data-dimension112="fd9c546c-958f-11f1-aa8e-e9f94f358517" data-action="Deal Block" data-label="Moccamaster KBGV Select" data-dimension48="Moccamaster KBGV Select" data-dimension25="$369" href="https://www.amazon.com/Moccamaster-53941-Select-10-Cup-Polished/dp/B093DYPBYR" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2297px;"><p class="vanilla-image-block" style="padding-top:108.84%;"><img id="ViCKNPMdH4jYKkGFaBFznF" name="moccamaster_sorbet_deal" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/ViCKNPMdH4jYKkGFaBFznF.jpg" mos="" align="middle" fullscreen="" width="2297" height="2500" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Moccamaster-53941-Select-10-Cup-Polished/dp/B093DYPBYR" target="_blank" rel="nofollow" data-dimension112="fd9c546c-958f-11f1-aa8e-e9f94f358517" data-action="Deal Block" data-label="Moccamaster KBGV Select" data-dimension48="Moccamaster KBGV Select" data-dimension25="$369">Moccamaster KBGV Select: $369</a></strong><br>There's a reason why the <a href="https://www.tomsguide.com/home/coffee-makers/technivorm-moccamaster-kgbv-select-review">Moccamaster</a> is so revered in the coffee world: it seriously is that good. It's super easy to use, SCA-accredited (for both full-batch and half-batch), and makes full-bodied-but-not-bitter coffee.  </p><p><strong>Warranty check:</strong> 5 years as standard and <em>lifetime repairs</em>.<a class="view-deal button" href="https://www.amazon.com/Moccamaster-53941-Select-10-Cup-Polished/dp/B093DYPBYR" target="_blank" rel="nofollow" data-dimension112="fd9c546c-958f-11f1-aa8e-e9f94f358517" data-action="Deal Block" data-label="Moccamaster KBGV Select" data-dimension48="Moccamaster KBGV Select" data-dimension25="$369">View Deal</a></p></div><p>The Moccamaster KBGV Select and Simply Good Coffee Plastic-Free Brewer both make a rich, comforting, delicious brew with zero silt or bitterness. I would have no qualms recommending either of these machines for serious coffee lovers or newcomers alike.</p><p>There are a few main differences in flavor, though. Take a look at these two photos. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:4342px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="Lri4XF5esj9TcvyXhPfFcE" name="moccamaster vs simply good coffee" alt="moccamaster and simply good coffee plastic-free coffee maker coffee side by side" src="https://cdn.mos.cms.futurecdn.net/Lri4XF5esj9TcvyXhPfFcE.jpg" mos="" align="middle" fullscreen="" width="4342" height="2442" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="caption-text">Left: Moccamaster | Right: SGC </span><span class="credit" itemprop="copyrightHolder">(Image credit: Erin Bashford)</span></figcaption></figure><p>The SGC Plastic-Free Brewer has a "Bloom" function, whereas the Moccamaster does not. In simple terms, this function steeps the coffee in water before pushing more water through for a full brew. This allows the coffee to grow more complex and can bring out nuanced flavors in the beans. </p><p>As a result, the SGC flavor is a little more juicy and what I would describe as "coffee-snob" territory. The Moccamaster tastes divine, don't get me wrong, but it brews a cup I would associate with "I'm a real coffee drinker because I drink my coffee black" memes. </p><p>I know people take water distribution seriously, so here's a comparison shot of the Moccamaster and Simply Good Coffee Plastic-Free Brewer filter baskets post-brew. </p><figure role="gallery"><figure><img src="https://cdn.mos.cms.futurecdn.net/2PYZV6Mf64zFtbGEE8WAwn.jpg" alt="funnelling on drip coffee makers" /><figcaption>Moccamaster<small role="credit">Erin Bashford</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/Hd4eCZDAGuMT6sq8FbSRwn.jpg" alt="funnelling on drip coffee makers" /><figcaption>Simply Good Coffee<small role="credit">Erin Bashford</small></figcaption></figure></figure><p>Honestly, there's no better or worse here. Both machines brew a delicious cup. I would be happy with either of these in my apartment. The Moccamaster is pure, classic coffee, and the SCG is a little more pure, classic coffee wearing a beanie hat and a flannel. </p><p>I would choose the Moccamaster over the SCG purely for the lifetime repairs (and, well, because the SCG isn't actually sold in the U.K. yet), but you wouldn't be disappointed with either.</p><p>Which brew appeals to you? Moccamaster or SGC? Let me know in the comments and stay tuned for next Monday's The Coffee Lab, on TikTok, Instagram, and YouTube. </p><figure class="inline-layout"><div style="min-height: 400px;"><fw-embed-feed channel="toms_guide" playlist="ojE0pK" mode="row" player_placement="bottom-right"></fw-embed-feed></div></figure><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h3><ul><li><a href="https://www.tomsguide.com/home/coffee-makers/overwhelmed-by-coffee-jargon-here-are-the-5-key-espresso-terms-you-need-to-know">Overwhelmed by coffee jargon? Here are the 5 key espresso terms you need to know</a></li><li><a href="https://www.tomsguide.com/home/coffee-makers/im-an-ex-starbucks-barista-you-can-make-the-iced-brown-sugar-oatmilk-shaken-espresso-at-home-for-a-fraction-of-the-cost">I'm an ex-Starbucks barista — you can make the Iced Brown Sugar Oatmilk Shaken Espresso at home for a fraction of the cost</a></li><li><a href="https://www.tomsguide.com/home/coffee-makers/i-tried-lelits-brand-new-entry-level-espresso-machine-and-i-wish-i-had-usd2-000-so-i-could-buy-it">I tried Lelit's brand-new 'entry-level' espresso machine — and I wish I had $2,000 so I could buy it</a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/home/coffee-makers/moccamaster-vs-simply-good-coffee-which-premium-coffee-machine-makes-a-better-brew-heres-what-i-think</link>
                                                                            <description>
                            <![CDATA[ On the 20th episode of The Coffee Lab, I'm putting two drip machines head-to-head to see which comes out on top. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">85HH9v8CSFSeopCSVAKNoS</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/CG6SfkgJb6hQFNGVxxyvRP-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Mon, 17 Aug 2026 15:12:13 +0000</pubDate>                                                                                                                                <updated>Mon, 24 Aug 2026 09:55:29 +0000</updated>
                                                                                                                                            <category><![CDATA[Coffee Makers]]></category>
                                                    <category><![CDATA[Home]]></category>
                                                    <category><![CDATA[Home Appliances]]></category>
                                                    <category><![CDATA[Kitchen & Dining]]></category>
                                                                                                <author><![CDATA[ erin.bashford@futurenet.com (Erin Bashford) ]]></author>                    <dc:creator><![CDATA[ Erin Bashford ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/rLvJvJVZx43hEzSsJy3BpL.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Erin Bashford is a senior reviews writer at Tom’s Guide. She has a Master’s in Broadcast and Digital Journalism from the University of East Anglia and 7 years of experience reviewing music and events for various publications. She has edited publications such as Outline Magazine’s Guide to Norwich, and she has written for a number of music magazines and websites such as Clash Magazine, Outline Magazine and Dork Magazine. She has a strong interest in audio gear and the music world. &lt;/p&gt;&lt;p&gt;As an ex-barista, Erin is passionate about coffee tech. She also loves finding the best cooking hacks and kitchen appliances, including her beloved Instant Pot. &lt;/p&gt;&lt;p&gt;In her spare time, you can find her reading, practising yoga, hiking, writing fantasy novels, or stressing over NYT Games.&lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/CG6SfkgJb6hQFNGVxxyvRP-1280-80.jpg">
                                                            <media:credit><![CDATA[Tom&#039;s Guide]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[a side by side composition of the moccamaster kgbv select vs simply good coffee plastic free brewer]]></media:description>                                                            <media:text><![CDATA[a side by side composition of the moccamaster kgbv select vs simply good coffee plastic free brewer]]></media:text>
                                <media:title type="plain"><![CDATA[a side by side composition of the moccamaster kgbv select vs simply good coffee plastic free brewer]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/CG6SfkgJb6hQFNGVxxyvRP-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <div  class="fancy-box"><div class="fancy_box-title">The Coffee Lab</div><div class="fancy_box_body"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' ><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="UwFdgr6xkNzHUWjapZThcN" name="smeg edited2" caption="" alt="the smeg emc02 mini pro manual espresso machine in jade green" src="https://cdn.mos.cms.futurecdn.net/UwFdgr6xkNzHUWjapZThcN.jpg" mos="" link="" align="" fullscreen="" width="" height="" attribution="" endorsement="" class="pinterest-pin-exclude"></p></div></div><figcaption itemprop="caption description" class=""><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p class="fancy-box__body-text">I'm Erin, and welcome to the twentieth episode of <a data-analytics-id="inline-link" href="https://www.tomsguide.com/tag/the-coffee-lab">The Coffee Lab</a>, the series where we forget coffee snobbery. The Coffee Lab is all about making coffee fun. Join me as I help you kickstart your coffee journey!</p></div></div><p>Anyone who knows anything about coffee has heard of Moccamaster. The Moccamaster (specifically the <a href="https://www.tomsguide.com/home/coffee-makers/technivorm-moccamaster-kgbv-select-review">KBGV Select</a>) is the most famous drip machine in the world, and there's very little competition. Few brands can go head-to-head with Technivorm's industrial, hardy stalwart, arguably the <a href="https://www.tomsguide.com/home/coffee-makers/best-coffee-makers">best coffee maker</a> of all time.</p><p>Mostly unchanged since its 1969 release, the Moccamaster does what many other coffee brands wish their flagship could: it has the best reputation in coffee. Whether this is from the industry-leading after-purchase care or the indestructible machine itself, I'm not sure. But people seriously love this thing. It's irrefutably "cult". </p><p>So enter the zippy young upstart — <a href="https://www.tomsguide.com/home/coffee-makers/simply-good-coffee-plastic-free-brewer-review">Simply Good Coffee Plastic-Free Brewer.</a> This model launched at the end of last year and was rolled out in 2026. What's the Plastic-Free Brewer got that the Moccamaster hasn't then? Well, the clue's in the name — it's not about what it <em>has</em>, but what it <em>hasn't</em>. Simply Good Coffee uses zero plastic in the brewing process. </p><p>Sure, this is all well and good — but what about taste? Let's find out which one makes a better brew. </p><h2 id="moccamaster-kbgv-select-amp-simply-good-coffee-plastic-free-brewer-what-39-s-the-difference">Moccamaster KBGV Select & Simply Good Coffee Plastic-Free Brewer: What's the difference?</h2><div class="product"><a data-dimension112="fd9c53d6-958f-11f1-9d02-bd0b05d941b8" data-action="Deal Block" data-label="Plastic-Free Brewer" data-dimension48="Plastic-Free Brewer" data-dimension25="$479" href="https://www.amazon.com/dp/B0FLYM8986" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1500px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="kBwcCTJrsdvHBBcz4LZYMa" name="Plastic-Free Brewer" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/kBwcCTJrsdvHBBcz4LZYMa.jpg" mos="" align="middle" fullscreen="" width="1500" height="1500" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>The Simply Good Plastic-Free Brewer measures 13.7 x 7.8 x 14.6 inches, uses a #4 cone, and can brew up to 8 cups of coffee at a time.<a class="view-deal button" href="https://www.amazon.com/dp/B0FLYM8986" target="_blank" rel="nofollow" data-dimension112="fd9c53d6-958f-11f1-9d02-bd0b05d941b8" data-action="Deal Block" data-label="Plastic-Free Brewer" data-dimension48="Plastic-Free Brewer" data-dimension25="$479">View Deal</a></p></div><p>While at their cores, the Moccamaster KBGV Select and the Simply Good Coffee Plastic-Free Brewers are both drip/filter coffee machines, there are a few key differences. </p><p>These differences reside in two main areas: design and accreditation. </p><p>Obviously, the SGC Plastic-Free Brewer is that: plastic-free (well, low plastic). No hot water touches plastic anywhere in the brewing process — but it does have medical-grade silicone tubing in the water lines. Even so, I don't class this as "plastic" as it's not the kind of polymer that leaches into water or breaks down over time. </p><p>The SGC has plastic on the exterior to prevent burns. Seriously, imagine if it were completely steel. You'd need to go to the ER if you accidentally brush up against it after brewing. </p><p>Now, the Moccamaster KBGV Select has a plastic filter basket and a plastic destratification tube in the carafe. I personally don't mind this plastic — Technivorm (which makes Moccamaster) is a Dutch company, and the EU has seriously strict regulations on plastic. It's high-quality, non-leaching, BPA-and PFA-free — all the adjectives.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:5242px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="DgfM3CL3QY7sPZLVG2N8xP" name="moccamaster and SGC machines" alt="the moccamaster and simply good coffee plastic-free brewer side by side" src="https://cdn.mos.cms.futurecdn.net/DgfM3CL3QY7sPZLVG2N8xP.jpg" mos="" align="middle" fullscreen="" width="5242" height="2948" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Erin Bashford)</span></figcaption></figure><p>So what else separates them? The SCA (Specialty Coffee Association) accreditation. Now, I don't think this is the be-all and end-all. There are more important things than an SCA accreditation. Taste, feel, emotional connection, secret ghosts inhabiting your coffee maker — whatever floats your boat (stews your brew? No. That's terrible. A career in stand-up comedy is clearly not for me). </p><p>If you do care about SCA accreditations, as I know a lot of coffee lovers do, you'll be more inclined to go with the Moccamaster. The KBGV Select has been SCA-accredited since the latter's advent in 2017, but the Simply Good Coffee Plastic-Free Brewer isn't yet accredited. </p><h2 id="moccamaster-kbgv-select-amp-simply-good-coffee-plastic-free-brewer-so-how-does-it-taste">Moccamaster KBGV Select & Simply Good Coffee Plastic-Free Brewer: So how does it taste?</h2><div class="product"><a data-dimension112="fd9c546c-958f-11f1-aa8e-e9f94f358517" data-action="Deal Block" data-label="Moccamaster KBGV Select" data-dimension48="Moccamaster KBGV Select" data-dimension25="$369" href="https://www.amazon.com/Moccamaster-53941-Select-10-Cup-Polished/dp/B093DYPBYR" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2297px;"><p class="vanilla-image-block" style="padding-top:108.84%;"><img id="ViCKNPMdH4jYKkGFaBFznF" name="moccamaster_sorbet_deal" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/ViCKNPMdH4jYKkGFaBFznF.jpg" mos="" align="middle" fullscreen="" width="2297" height="2500" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Moccamaster-53941-Select-10-Cup-Polished/dp/B093DYPBYR" target="_blank" rel="nofollow" data-dimension112="fd9c546c-958f-11f1-aa8e-e9f94f358517" data-action="Deal Block" data-label="Moccamaster KBGV Select" data-dimension48="Moccamaster KBGV Select" data-dimension25="$369">Moccamaster KBGV Select: $369</a></strong><br>There's a reason why the <a href="https://www.tomsguide.com/home/coffee-makers/technivorm-moccamaster-kgbv-select-review">Moccamaster</a> is so revered in the coffee world: it seriously is that good. It's super easy to use, SCA-accredited (for both full-batch and half-batch), and makes full-bodied-but-not-bitter coffee.  </p><p><strong>Warranty check:</strong> 5 years as standard and <em>lifetime repairs</em>.<a class="view-deal button" href="https://www.amazon.com/Moccamaster-53941-Select-10-Cup-Polished/dp/B093DYPBYR" target="_blank" rel="nofollow" data-dimension112="fd9c546c-958f-11f1-aa8e-e9f94f358517" data-action="Deal Block" data-label="Moccamaster KBGV Select" data-dimension48="Moccamaster KBGV Select" data-dimension25="$369">View Deal</a></p></div><p>The Moccamaster KBGV Select and Simply Good Coffee Plastic-Free Brewer both make a rich, comforting, delicious brew with zero silt or bitterness. I would have no qualms recommending either of these machines for serious coffee lovers or newcomers alike.</p><p>There are a few main differences in flavor, though. Take a look at these two photos. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:4342px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="Lri4XF5esj9TcvyXhPfFcE" name="moccamaster vs simply good coffee" alt="moccamaster and simply good coffee plastic-free coffee maker coffee side by side" src="https://cdn.mos.cms.futurecdn.net/Lri4XF5esj9TcvyXhPfFcE.jpg" mos="" align="middle" fullscreen="" width="4342" height="2442" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="caption-text">Left: Moccamaster | Right: SGC </span><span class="credit" itemprop="copyrightHolder">(Image credit: Erin Bashford)</span></figcaption></figure><p>The SGC Plastic-Free Brewer has a "Bloom" function, whereas the Moccamaster does not. In simple terms, this function steeps the coffee in water before pushing more water through for a full brew. This allows the coffee to grow more complex and can bring out nuanced flavors in the beans. </p><p>As a result, the SGC flavor is a little more juicy and what I would describe as "coffee-snob" territory. The Moccamaster tastes divine, don't get me wrong, but it brews a cup I would associate with "I'm a real coffee drinker because I drink my coffee black" memes. </p><p>I know people take water distribution seriously, so here's a comparison shot of the Moccamaster and Simply Good Coffee Plastic-Free Brewer filter baskets post-brew. </p><figure role="gallery"><figure><img src="https://cdn.mos.cms.futurecdn.net/2PYZV6Mf64zFtbGEE8WAwn.jpg" alt="funnelling on drip coffee makers" /><figcaption>Moccamaster<small role="credit">Erin Bashford</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/Hd4eCZDAGuMT6sq8FbSRwn.jpg" alt="funnelling on drip coffee makers" /><figcaption>Simply Good Coffee<small role="credit">Erin Bashford</small></figcaption></figure></figure><p>Honestly, there's no better or worse here. Both machines brew a delicious cup. I would be happy with either of these in my apartment. The Moccamaster is pure, classic coffee, and the SCG is a little more pure, classic coffee wearing a beanie hat and a flannel. </p><p>I would choose the Moccamaster over the SCG purely for the lifetime repairs (and, well, because the SCG isn't actually sold in the U.K. yet), but you wouldn't be disappointed with either.</p><p>Which brew appeals to you? Moccamaster or SGC? Let me know in the comments and stay tuned for next Monday's The Coffee Lab, on TikTok, Instagram, and YouTube. </p><figure class="inline-layout"><div style="min-height: 400px;"><fw-embed-feed channel="toms_guide" playlist="ojE0pK" mode="row" player_placement="bottom-right"></fw-embed-feed></div></figure><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h3><ul><li><a href="https://www.tomsguide.com/home/coffee-makers/overwhelmed-by-coffee-jargon-here-are-the-5-key-espresso-terms-you-need-to-know">Overwhelmed by coffee jargon? Here are the 5 key espresso terms you need to know</a></li><li><a href="https://www.tomsguide.com/home/coffee-makers/im-an-ex-starbucks-barista-you-can-make-the-iced-brown-sugar-oatmilk-shaken-espresso-at-home-for-a-fraction-of-the-cost">I'm an ex-Starbucks barista — you can make the Iced Brown Sugar Oatmilk Shaken Espresso at home for a fraction of the cost</a></li><li><a href="https://www.tomsguide.com/home/coffee-makers/i-tried-lelits-brand-new-entry-level-espresso-machine-and-i-wish-i-had-usd2-000-so-i-could-buy-it">I tried Lelit's brand-new 'entry-level' espresso machine — and I wish I had $2,000 so I could buy it</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ This Nutribullet blender costs less than $100 and performs exceptionally well — as long as you can deal with some wind ]]></title>
                                                                                                <dc:content><![CDATA[ <p>I’m a firm believer that having one of the <a href="https://www.tomsguide.com/best-picks/best-blenders">best blenders</a> is the easiest way to level up your cooking at home, and squeeze in some extra nutrients. That means you need a blender that can cope with even the toughest ingredients. The Nutribullet Power Core does just that. </p><p>The Power Core costs less than $100, yet provides incredibly impressive performance and is easy to use. The large capacity means you can work in large batches, and the maintenance of the blender is really simple too. </p><p>Unfortunately, it’s extremely loud, and the motor creates a lot of airflow in your workspace. The limited speed settings could also put some users off, but I think it’s more than enough for home use. To find out more, you can keep reading this full Nutribullet Power core review. </p><h2 class="article-body__section" id="section-nutribullet-power-core-review-specs"><span>Nutribullet Power Core review: Specs</span></h2><div ><table><tbody><tr><td class="firstcol " ><p><strong>Price</strong></p></td><td  ><p><a href="https://www.amazon.com/nutribullet-Smoothies-Full-Size-Countertop-NBF70100/dp/B0GL4XLTDQ" target="_blank" rel="nofollow">$99</a> / <a href="https://www.amazon.co.uk/nutribullet-Blender-Pitcher-Automatic-Smoothie/dp/B0H1R8NX9J" target="_blank" rel="nofollow">£99</a></p></td></tr><tr><td class="firstcol " ><p><strong>Dimensions</strong></p></td><td  ><p>15.5 x 7.8 x 7.5 inches</p></td></tr><tr><td class="firstcol " ><p><strong>Weight</strong></p></td><td  ><p>7.5 pounds</p></td></tr><tr><td class="firstcol " ><p><strong>Capacity</strong></p></td><td  ><p>72 fluid ounces</p></td></tr><tr><td class="firstcol " ><p><strong>Power</strong></p></td><td  ><p>1400W (U.S.) / 1200W (U.K.)</p></td></tr><tr><td class="firstcol " ><p><strong>Blending speeds</strong></p></td><td  ><p>3 and pulse</p></td></tr><tr><td class="firstcol " ><p><strong>Blending presets</strong></p></td><td  ><p>Smoothie</p></td></tr></tbody></table></div><h2 class="article-body__section" id="section-nutribullet-power-core-review-price-availability"><span>Nutribullet Power Core review: Price & availability</span></h2><p>The Nutribullet Power Core is available from <a href="https://www.amazon.com/nutribullet-Smoothies-Full-Size-Countertop-NBF70100/dp/B0GL4XLTDQ" target="_blank" rel="nofollow">Amazon U.S. for $99</a> and <a href="https://www.amazon.co.uk/nutribullet-Blender-Pitcher-Automatic-Smoothie/dp/B0H1R8NX9J" target="_blank" rel="nofollow">Amazon U.K. for £99</a>. This is an incredibly affordable blender, but that's not unheard of from Nutribullet. In fact, they make some of the most affordable high-performance blenders, including the <a href="https://www.tomsguide.com/home/home-appliances/nutribullet-smart-touch-blender-review">Nutribullet Smart Touch</a> for $99 and the <a href="https://www.tomsguide.com/home/home-appliances/nutribullet-pro-900W-blender-review">Nutribullet Pro 900W</a> for $84. </p><p>If you want the option of smaller capacity blends, look at the <a href="https://www.tomsguide.com/home/home-appliances/ninja-detect-power-pro-with-blendsense-review">Ninja Detect Power Pro with BlendSense</a> for $179, which, like the Power Core, holds 72 ounces but comes with a 24-ounce single-serve cup. </p><p>For more control over blend speeds, check out the <a href="https://www.tomsguide.com/home/home-appliances/tribest-backspin-blender-review">Tribest Backspin</a> for $499, which has 12 speeds, or the <a href="https://www.tomsguide.com/home/home-appliances/vitamix-ascent-x2-blender-review">Vitamix Ascent X2</a> for $549 with 10 variable speeds. In short, if you want more control, you need to pay more because you only get three speeds with the Nutribullet Power Core. That said, for everyday use, this is enough. </p><h2 class="article-body__section" id="section-nutribullet-power-core-review-design"><span>Nutribullet Power Core review: Design </span></h2><p>The Nutribullet Power Core is a blender that will look good in any kitchen. It only comes in matte black, so if color matching all your appliances is a dealbreaker for you, this may not be the one (unless everything you own is black). But for most people, the simplistic design will be a win. </p><p>The jug has measurements up the side, so I found it easy to measure my ingredients as I went. The lid also has a small measuring cap that can be removed to add more ingredients, such as seasonings, as you blend. This was great for making things like dips. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1919px;"><p class="vanilla-image-block" style="padding-top:56.28%;"><img id="kP3FLQZCqDVLaVwqyCLXzZ" name="Nutribullet Power Core" alt="Nutribullet Power Core photographed in front of a blue background" src="https://cdn.mos.cms.futurecdn.net/kP3FLQZCqDVLaVwqyCLXzZ.jpg" mos="" align="middle" fullscreen="" width="1919" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>Because of the large handle, the jug is very easy to hold and pour even when it’s full and heavy. Also, the spout makes pouring accurate, and I didn’t have any issues with spilled smoothies. </p><p>The blender uses a six-point stainless steel blade, and this was very effective even on tough ingredients like dates and seeds.</p><h3 id="controls-2">Controls</h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="CWworxgkKos3cgNgPQqg3a" name="Nutribullet Power Core" alt="Nutribullet Power Core photographed in front of a blue background" src="https://cdn.mos.cms.futurecdn.net/CWworxgkKos3cgNgPQqg3a.jpg" mos="" align="middle" fullscreen="" width="1920" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The Nutribullet Power Core is very easy to use. All of the button controls are at the front of the machine, and since it’s so cheap, it’s very basic. For me, this is great because I don’t think blending needs to be complicated. </p><p>The power button is in the middle, and to the left you’ll find a smoothie preset and a pulse button. To the right, there are three buttons for low, medium, and high-speed blending. </p><h2 class="article-body__section" id="section-nutribullet-power-core-review-blending-performance"><span>Nutribullet Power Core review: Blending performance</span></h2><p>To test the blending performance of the Nutribullet Power Core, I carried out my usual tests and made a smoothie, sorbet, and hummus. When blending, the noise level reached a high of 101 decibels. This is around the volume you can expect from a lawnmower, and according to <a href="https://www.hearusa.com/hearing-loss/causes/decibels/">Hearing Loss USA</a>, “anything above 85 decibels can damage the small hair cells in your ears and affect your hearing health.” </p><p>This is <em>very</em> loud, even for a large blender. In comparison, the Vitamix Ascent X2 reaches about 81 decibels. I would seriously recommend using a pair of <a href="https://www.tomsguide.com/audio/earbuds/these-earplugs-are-designed-for-concerts-but-ive-found-another-use-for-them-now-i-dont-leave-the-house-without-my-loops">Loop earplugs</a> if you’re using this blender often.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.20%;"><img id="4CHHm4o6isXADQUxbzekRa" name="Nutribullet Power Core" alt="Nutribullet Power Core photographed in front of a blue background" src="https://cdn.mos.cms.futurecdn.net/4CHHm4o6isXADQUxbzekRa.jpg" mos="" align="middle" fullscreen="" width="1920" height="1079" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>That’s not the only thing — the motor base also creates a lot of wind. If it wasn’t for the powerful suction cups keeping it stable on my countertop, I’m pretty sure this thing would have taken flight. It blew around containers and papers on my countertop, which was just plain annoying. </p><p>Also, since the jug is so big, it would have been great to have a tamper so ingredients could be directed toward the blades when it wasn’t as full. I ended up having to push the sides down with a spoon intermittently.</p><h3 id="smoothie">Smoothie</h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:5712px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="Yx8BSDmT3RpN2MoKJuNWk9" name="Nutribullet Power Core" alt="Smoothie made using the Nutribullet Power Core" src="https://cdn.mos.cms.futurecdn.net/Yx8BSDmT3RpN2MoKJuNWk9.jpg" mos="" align="middle" fullscreen="" width="5712" height="3213" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>I added a bag of berry smoothie mix, dates, sunflower seeds and oat milk to the blender and used the smoothie preset for blending. This did a great job of quickly dealing with frozen ingredients and mincing the sunflower seeds finely. </p><p>I was most impressed by how the blender handled the dates, as their naturally sticky texture often clogs blender blades and leaves chunks behind. There was some texture from the fruit seeds, but I was left with a smooth drink, and the blades didn’t clog. For $99, this is an extremely impressive blender.</p><h3 id="sorbet">Sorbet</h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:5712px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="RiQarmCSAhDEpr4Bv77du9" name="Nutribullet Power Core" alt="Mango sorbet made using the Nutribullet Power Core" src="https://cdn.mos.cms.futurecdn.net/RiQarmCSAhDEpr4Bv77du9.jpg" mos="" align="middle" fullscreen="" width="5712" height="3213" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>Next, I blended up a sorbet. This allowed me to see how the blender would perform with frozen ingredients without adding liquid. I added a bag of frozen mango that had been thawed for 10 minutes. I used the medium-speed setting, stopping to push the mango down from the sides intermittently. </p><p>Since this is a thicker consistency than the smoothie, I spent a lot of time getting the mixture off the side walls of the blender. The mixture was mostly smooth with a few rogue chunks of mango, but it was good enough for what I needed.</p><h3 id="hummus">Hummus</h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:5712px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="dxaPyVGwDLaBSespdhjwa9" name="Nutribullet Power Core" alt="Hummus made using the Nutribullet Power Core" src="https://cdn.mos.cms.futurecdn.net/dxaPyVGwDLaBSespdhjwa9.jpg" mos="" align="middle" fullscreen="" width="5712" height="3213" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>Finally, I whipped up a quick hummus — and I mean <em>quick</em>. I added two cans of chickpeas, lemon juice and some seasonings to the blender and used the pulse setting as I slowly added extra virgin olive oil. This only took a couple of minutes.  </p><p>I was very impressed with the results. I had a mostly smooth dip with only a few whole chickpeas. For the price, I couldn’t ask for more.</p><h2 class="article-body__section" id="section-nutribullet-power-core-review-storage-maintenance"><span>Nutribullet Power Core review: Storage & maintenance</span></h2><p>Taking care of the Nutribullet Power Core couldn’t be simpler. Everything is dishwasher-safe apart from the motor base. This meant I could just pop the whole jug and lid into the dishwasher and give the motor base a quick wipe down with a cloth. To clean the jug by hand, use detergent and a soft sponge, but be very careful with the blades at the bottom. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.20%;"><img id="K6vubQHZCbZMFXRgnjznNa" name="Nutribullet Power Core" alt="Nutribullet Power Core photographed in front of a blue background" src="https://cdn.mos.cms.futurecdn.net/K6vubQHZCbZMFXRgnjznNa.jpg" mos="" align="middle" fullscreen="" width="1920" height="1079" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>You need to be prepared for it to take up a lot of space on your countertop, or potentially a whole shelf in your cupboard. It measures 15.5 x 7.8 x 7.5 inches and weighs 7.5 pounds. The 72-ounce jug detaches from the motor base for cleaning and easier storage. </p><h2 class="article-body__section" id="section-nutribullet-power-core-review-verdict"><span>Nutribullet Power Core review: Verdict</span></h2><p>The Nutribullet Power Core is an incredibly affordable blender that delivers impressive performance for under $100. This easy-to-use blender made mixing up large batches of my favorite smoothies, sorbets, and dips an absolute breeze. It completely blended even the toughest ingredients like dates, seeds and frozen fruit, leaving no chunks behind. It’s a must if you need a big blender on a budget, and it’s dishwasher-safe, so very easy to maintain. </p><p>However, you’ll need to protect your hearing with some earplugs because it gets incredibly noisy. I’d argue it’s louder than should be possible for a blender. The motor also generates a lot of air, making the surrounding workspace insanely windy. </p><p>With only three speeds, some users may feel limited, but for casual blenders, this is more than enough. For reliable and impressive results on a budget, this blender is a great choice. </p> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/home/kitchen-dining/nutribullet-power-core-review</link>
                                                                            <description>
                            <![CDATA[ The Nutribullet Power Core is an impressive blender that costs less than $100, but the loud noise and airflow could be a dealbreaker for some. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">mutaAbz7ednBaVZYNh4T9P</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/QQDRojUGqyx6LZJjVhLeBa-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Fri, 14 Aug 2026 15:08:37 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Kitchen & Dining]]></category>
                                                    <category><![CDATA[Home]]></category>
                                                    <category><![CDATA[Home Appliances]]></category>
                                                                                                <author><![CDATA[ ashley.thieme@futurenet.com (Ashley Thieme) ]]></author>                    <dc:creator><![CDATA[ Ashley Thieme ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/3AWovHjApwuNrSGRS6WBcL.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Ashley Thieme is a staff writer on the Reviews team at Tom’s Guide where she tests out the latest tech so you can know what’s going to be worth your time and money. She has a master’s degree in Magazine Journalism and a bachelor’s degree in Journalism, Media and Sociology from Cardiff University. She has bylines in titles including Women’s Health UK, sharing the latest health and wellness news stories, and Virgin Radio UK, providing the latest entertainment news and working on celebrity interviews. She has experience reporting on a variety of topics including music, literature, motorsport, entertainment and health. In previously published work, she has reviewed live music events, books, and wellness products. She values the importance of tech enhancing your life rather than taking over, and as a music fanatic, she is always looking for the best way to listen to new music releases. Discovering the top audio equipment that enhances sound quality and provides optimum comfort is what Ashley does best. In her spare time, Ashley enjoys hitting her reading goals on Goodreads by getting into the latest novels with a cup of tea as well as getting out in the Welsh mountains for a good hike on the weekend.&lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/QQDRojUGqyx6LZJjVhLeBa-1280-80.jpg">
                                                            <media:credit><![CDATA[Tom&#039;s Guide]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Nutribullet Power Core photographed in front of a blue background]]></media:description>                                                            <media:text><![CDATA[Nutribullet Power Core photographed in front of a blue background]]></media:text>
                                <media:title type="plain"><![CDATA[Nutribullet Power Core photographed in front of a blue background]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/QQDRojUGqyx6LZJjVhLeBa-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>I’m a firm believer that having one of the <a href="https://www.tomsguide.com/best-picks/best-blenders">best blenders</a> is the easiest way to level up your cooking at home, and squeeze in some extra nutrients. That means you need a blender that can cope with even the toughest ingredients. The Nutribullet Power Core does just that. </p><p>The Power Core costs less than $100, yet provides incredibly impressive performance and is easy to use. The large capacity means you can work in large batches, and the maintenance of the blender is really simple too. </p><p>Unfortunately, it’s extremely loud, and the motor creates a lot of airflow in your workspace. The limited speed settings could also put some users off, but I think it’s more than enough for home use. To find out more, you can keep reading this full Nutribullet Power core review. </p><h2 class="article-body__section" id="section-nutribullet-power-core-review-specs"><span>Nutribullet Power Core review: Specs</span></h2><div ><table><tbody><tr><td class="firstcol " ><p><strong>Price</strong></p></td><td  ><p><a href="https://www.amazon.com/nutribullet-Smoothies-Full-Size-Countertop-NBF70100/dp/B0GL4XLTDQ" target="_blank" rel="nofollow">$99</a> / <a href="https://www.amazon.co.uk/nutribullet-Blender-Pitcher-Automatic-Smoothie/dp/B0H1R8NX9J" target="_blank" rel="nofollow">£99</a></p></td></tr><tr><td class="firstcol " ><p><strong>Dimensions</strong></p></td><td  ><p>15.5 x 7.8 x 7.5 inches</p></td></tr><tr><td class="firstcol " ><p><strong>Weight</strong></p></td><td  ><p>7.5 pounds</p></td></tr><tr><td class="firstcol " ><p><strong>Capacity</strong></p></td><td  ><p>72 fluid ounces</p></td></tr><tr><td class="firstcol " ><p><strong>Power</strong></p></td><td  ><p>1400W (U.S.) / 1200W (U.K.)</p></td></tr><tr><td class="firstcol " ><p><strong>Blending speeds</strong></p></td><td  ><p>3 and pulse</p></td></tr><tr><td class="firstcol " ><p><strong>Blending presets</strong></p></td><td  ><p>Smoothie</p></td></tr></tbody></table></div><h2 class="article-body__section" id="section-nutribullet-power-core-review-price-availability"><span>Nutribullet Power Core review: Price & availability</span></h2><p>The Nutribullet Power Core is available from <a href="https://www.amazon.com/nutribullet-Smoothies-Full-Size-Countertop-NBF70100/dp/B0GL4XLTDQ" target="_blank" rel="nofollow">Amazon U.S. for $99</a> and <a href="https://www.amazon.co.uk/nutribullet-Blender-Pitcher-Automatic-Smoothie/dp/B0H1R8NX9J" target="_blank" rel="nofollow">Amazon U.K. for £99</a>. This is an incredibly affordable blender, but that's not unheard of from Nutribullet. In fact, they make some of the most affordable high-performance blenders, including the <a href="https://www.tomsguide.com/home/home-appliances/nutribullet-smart-touch-blender-review">Nutribullet Smart Touch</a> for $99 and the <a href="https://www.tomsguide.com/home/home-appliances/nutribullet-pro-900W-blender-review">Nutribullet Pro 900W</a> for $84. </p><p>If you want the option of smaller capacity blends, look at the <a href="https://www.tomsguide.com/home/home-appliances/ninja-detect-power-pro-with-blendsense-review">Ninja Detect Power Pro with BlendSense</a> for $179, which, like the Power Core, holds 72 ounces but comes with a 24-ounce single-serve cup. </p><p>For more control over blend speeds, check out the <a href="https://www.tomsguide.com/home/home-appliances/tribest-backspin-blender-review">Tribest Backspin</a> for $499, which has 12 speeds, or the <a href="https://www.tomsguide.com/home/home-appliances/vitamix-ascent-x2-blender-review">Vitamix Ascent X2</a> for $549 with 10 variable speeds. In short, if you want more control, you need to pay more because you only get three speeds with the Nutribullet Power Core. That said, for everyday use, this is enough. </p><h2 class="article-body__section" id="section-nutribullet-power-core-review-design"><span>Nutribullet Power Core review: Design </span></h2><p>The Nutribullet Power Core is a blender that will look good in any kitchen. It only comes in matte black, so if color matching all your appliances is a dealbreaker for you, this may not be the one (unless everything you own is black). But for most people, the simplistic design will be a win. </p><p>The jug has measurements up the side, so I found it easy to measure my ingredients as I went. The lid also has a small measuring cap that can be removed to add more ingredients, such as seasonings, as you blend. This was great for making things like dips. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1919px;"><p class="vanilla-image-block" style="padding-top:56.28%;"><img id="kP3FLQZCqDVLaVwqyCLXzZ" name="Nutribullet Power Core" alt="Nutribullet Power Core photographed in front of a blue background" src="https://cdn.mos.cms.futurecdn.net/kP3FLQZCqDVLaVwqyCLXzZ.jpg" mos="" align="middle" fullscreen="" width="1919" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>Because of the large handle, the jug is very easy to hold and pour even when it’s full and heavy. Also, the spout makes pouring accurate, and I didn’t have any issues with spilled smoothies. </p><p>The blender uses a six-point stainless steel blade, and this was very effective even on tough ingredients like dates and seeds.</p><h3 id="controls-2">Controls</h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="CWworxgkKos3cgNgPQqg3a" name="Nutribullet Power Core" alt="Nutribullet Power Core photographed in front of a blue background" src="https://cdn.mos.cms.futurecdn.net/CWworxgkKos3cgNgPQqg3a.jpg" mos="" align="middle" fullscreen="" width="1920" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The Nutribullet Power Core is very easy to use. All of the button controls are at the front of the machine, and since it’s so cheap, it’s very basic. For me, this is great because I don’t think blending needs to be complicated. </p><p>The power button is in the middle, and to the left you’ll find a smoothie preset and a pulse button. To the right, there are three buttons for low, medium, and high-speed blending. </p><h2 class="article-body__section" id="section-nutribullet-power-core-review-blending-performance"><span>Nutribullet Power Core review: Blending performance</span></h2><p>To test the blending performance of the Nutribullet Power Core, I carried out my usual tests and made a smoothie, sorbet, and hummus. When blending, the noise level reached a high of 101 decibels. This is around the volume you can expect from a lawnmower, and according to <a href="https://www.hearusa.com/hearing-loss/causes/decibels/">Hearing Loss USA</a>, “anything above 85 decibels can damage the small hair cells in your ears and affect your hearing health.” </p><p>This is <em>very</em> loud, even for a large blender. In comparison, the Vitamix Ascent X2 reaches about 81 decibels. I would seriously recommend using a pair of <a href="https://www.tomsguide.com/audio/earbuds/these-earplugs-are-designed-for-concerts-but-ive-found-another-use-for-them-now-i-dont-leave-the-house-without-my-loops">Loop earplugs</a> if you’re using this blender often.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.20%;"><img id="4CHHm4o6isXADQUxbzekRa" name="Nutribullet Power Core" alt="Nutribullet Power Core photographed in front of a blue background" src="https://cdn.mos.cms.futurecdn.net/4CHHm4o6isXADQUxbzekRa.jpg" mos="" align="middle" fullscreen="" width="1920" height="1079" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>That’s not the only thing — the motor base also creates a lot of wind. If it wasn’t for the powerful suction cups keeping it stable on my countertop, I’m pretty sure this thing would have taken flight. It blew around containers and papers on my countertop, which was just plain annoying. </p><p>Also, since the jug is so big, it would have been great to have a tamper so ingredients could be directed toward the blades when it wasn’t as full. I ended up having to push the sides down with a spoon intermittently.</p><h3 id="smoothie">Smoothie</h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:5712px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="Yx8BSDmT3RpN2MoKJuNWk9" name="Nutribullet Power Core" alt="Smoothie made using the Nutribullet Power Core" src="https://cdn.mos.cms.futurecdn.net/Yx8BSDmT3RpN2MoKJuNWk9.jpg" mos="" align="middle" fullscreen="" width="5712" height="3213" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>I added a bag of berry smoothie mix, dates, sunflower seeds and oat milk to the blender and used the smoothie preset for blending. This did a great job of quickly dealing with frozen ingredients and mincing the sunflower seeds finely. </p><p>I was most impressed by how the blender handled the dates, as their naturally sticky texture often clogs blender blades and leaves chunks behind. There was some texture from the fruit seeds, but I was left with a smooth drink, and the blades didn’t clog. For $99, this is an extremely impressive blender.</p><h3 id="sorbet">Sorbet</h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:5712px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="RiQarmCSAhDEpr4Bv77du9" name="Nutribullet Power Core" alt="Mango sorbet made using the Nutribullet Power Core" src="https://cdn.mos.cms.futurecdn.net/RiQarmCSAhDEpr4Bv77du9.jpg" mos="" align="middle" fullscreen="" width="5712" height="3213" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>Next, I blended up a sorbet. This allowed me to see how the blender would perform with frozen ingredients without adding liquid. I added a bag of frozen mango that had been thawed for 10 minutes. I used the medium-speed setting, stopping to push the mango down from the sides intermittently. </p><p>Since this is a thicker consistency than the smoothie, I spent a lot of time getting the mixture off the side walls of the blender. The mixture was mostly smooth with a few rogue chunks of mango, but it was good enough for what I needed.</p><h3 id="hummus">Hummus</h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:5712px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="dxaPyVGwDLaBSespdhjwa9" name="Nutribullet Power Core" alt="Hummus made using the Nutribullet Power Core" src="https://cdn.mos.cms.futurecdn.net/dxaPyVGwDLaBSespdhjwa9.jpg" mos="" align="middle" fullscreen="" width="5712" height="3213" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>Finally, I whipped up a quick hummus — and I mean <em>quick</em>. I added two cans of chickpeas, lemon juice and some seasonings to the blender and used the pulse setting as I slowly added extra virgin olive oil. This only took a couple of minutes.  </p><p>I was very impressed with the results. I had a mostly smooth dip with only a few whole chickpeas. For the price, I couldn’t ask for more.</p><h2 class="article-body__section" id="section-nutribullet-power-core-review-storage-maintenance"><span>Nutribullet Power Core review: Storage & maintenance</span></h2><p>Taking care of the Nutribullet Power Core couldn’t be simpler. Everything is dishwasher-safe apart from the motor base. This meant I could just pop the whole jug and lid into the dishwasher and give the motor base a quick wipe down with a cloth. To clean the jug by hand, use detergent and a soft sponge, but be very careful with the blades at the bottom. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.20%;"><img id="K6vubQHZCbZMFXRgnjznNa" name="Nutribullet Power Core" alt="Nutribullet Power Core photographed in front of a blue background" src="https://cdn.mos.cms.futurecdn.net/K6vubQHZCbZMFXRgnjznNa.jpg" mos="" align="middle" fullscreen="" width="1920" height="1079" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>You need to be prepared for it to take up a lot of space on your countertop, or potentially a whole shelf in your cupboard. It measures 15.5 x 7.8 x 7.5 inches and weighs 7.5 pounds. The 72-ounce jug detaches from the motor base for cleaning and easier storage. </p><h2 class="article-body__section" id="section-nutribullet-power-core-review-verdict"><span>Nutribullet Power Core review: Verdict</span></h2><p>The Nutribullet Power Core is an incredibly affordable blender that delivers impressive performance for under $100. This easy-to-use blender made mixing up large batches of my favorite smoothies, sorbets, and dips an absolute breeze. It completely blended even the toughest ingredients like dates, seeds and frozen fruit, leaving no chunks behind. It’s a must if you need a big blender on a budget, and it’s dishwasher-safe, so very easy to maintain. </p><p>However, you’ll need to protect your hearing with some earplugs because it gets incredibly noisy. I’d argue it’s louder than should be possible for a blender. The motor also generates a lot of air, making the surrounding workspace insanely windy. </p><p>With only three speeds, some users may feel limited, but for casual blenders, this is more than enough. For reliable and impressive results on a budget, this blender is a great choice. </p>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ Don't let summer end — Ninja pizza ovens, blenders and coolers are up to 42% off at Amazon ]]></title>
                                                                                                <dc:content><![CDATA[ <p>Amazon is closing out the summer with a bunch of Ninja appliance deals. Whether you're hoping to extend grilling season into the fall, want to keep enjoying delicious smoothies, or even improve your knife skills while cooking — there are some discounts here that you definitely don't want to miss.</p><p>I've been searching the sale and have found <a href="https://www.amazon.com/stores/page/471F718E-0761-48DF-ABAF-0FC6590C695B" target="_blank" rel="nofollow">up to 30% off Ninja appliances</a>. I've listed all my favorites below, so keep scrolling to check them out.</p><h3 class="article-body__section" id="section-quick-links"><span>Quick Links</span></h3><ul><li><a href="https://www.amazon.com/stores/page/471F718E-0761-48DF-ABAF-0FC6590C695B" target="_blank" rel="nofollow"><strong>shop all Ninja deals at Amazon</strong></a></li><li><strong>Ninja Blast Max: </strong><a href="https://www.amazon.com/dp/B0GX2SD3K6?" target="_blank" rel="nofollow"><strong>was $99 now $69</strong></a><strong></strong></li><li><strong>Ninja Iced Coffee Maker: </strong><a href="https://www.amazon.com/Ninja-Specialty-Single-Serve-Compatible-PB055ABL/dp/B0C25Y15TL" target="_blank" rel="nofollow"><strong>was $129 now $99</strong></a></li><li><strong>Ninja Crispi 4-in-1 Portable Glass Air Fryer: </strong><a href="https://www.amazon.com/Ninja-Microwave-Dishwasher-Containers-FN101GY/dp/B0DDDD8WD6?" target="_blank" rel="nofollow"><strong>was $179 now $159</strong></a></li><li><strong>Ninja 10-Pc German Steel Knife Set: </strong><a href="https://www.amazon.com/dp/B0H2NLCZBQ" target="_blank" rel="nofollow"><strong>was $249 now $199</strong></a></li><li><strong>Ninja Woodfire Oven & Smoker: </strong><a href="https://www.amazon.com/Ninja-Woodfire-Technology-terracotta-OO101/dp/B0C6BQVDX3/" target="_blank" rel="nofollow"><strong>was $399 now $279</strong></a></li><li><strong>Ninja Luxe Café Premier: </strong><a href="https://www.amazon.com/dp/B0FGDTHY1Y" target="_blank" rel="nofollow"><strong>now $599</strong></a></li></ul><h3 class="article-body__section" id="section-ninja-deals"><span>Ninja Deals</span></h3><div class="product"><a data-dimension112="9ae6da84-96fe-11f1-a330-f9d854e50872" data-action="Deal Block" data-label="Blast Max" data-dimension48="Blast Max" data-dimension25="$69" href="https://www.amazon.com/dp/B0GX2SD3K6?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1216px;"><p class="vanilla-image-block" style="padding-top:123.36%;"><img id="9Q4QY399FaozAFUt4j8dTW" name="ninja-blast-max-portable-blender--twist--bb517479-54ce-4a77-974c-58e2f44dde33.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/9Q4QY399FaozAFUt4j8dTW.jpg" mos="" align="middle" fullscreen="" width="1216" height="1500" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>The Ninja Blast Max is capable of taking on any challenge you throw at it, including crushing ice and blitzing berries to make yummy smoothies. It comes with multiple blend settings to make sure your blender is using the right level of power for the task at hand, and the compact size means it’s a great option for anyone with a small kitchen. <a class="view-deal button" href="https://www.amazon.com/dp/B0GX2SD3K6?" target="_blank" rel="nofollow" data-dimension112="9ae6da84-96fe-11f1-a330-f9d854e50872" data-action="Deal Block" data-label="Blast Max" data-dimension48="Blast Max" data-dimension25="$69">View Deal</a></p></div><div class="product"><a data-dimension112="9ae6dae8-96fe-11f1-af0b-bffac6dd08f7" data-action="Deal Block" data-label="Belgian Waffle Maker" data-dimension48="Belgian Waffle Maker" data-dimension25="$79" href="https://www.amazon.com/Ninja-BW1001-NeverStick-Precision-Pour-Chef-curated/dp/B0B358VDZJ/ref=" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1614px;"><p class="vanilla-image-block" style="padding-top:86.00%;"><img id="XofzJVhShmZ3kcVxuocQvB" name="Ninja Belgian Waffle Maker" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/XofzJVhShmZ3kcVxuocQvB.png" mos="" align="middle" fullscreen="" width="1614" height="1388" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Ninja-BW1001-NeverStick-Precision-Pour-Chef-curated/dp/B0B358VDZJ/ref=" target="_blank" rel="nofollow" data-dimension112="9ae6dae8-96fe-11f1-af0b-bffac6dd08f7" data-action="Deal Block" data-label="Belgian Waffle Maker" data-dimension48="Belgian Waffle Maker" data-dimension25="$79">Belgian Waffle Maker: was $99 now $79</a></strong><br>Weekend brunch just got an upgrade. This vertical waffle maker has five shade settings so everyone gets their waffle exactly how they like it, plus a specialty setting for high-sugar batters like brownies (yes, really). The precision-pour cup takes the guesswork out of measuring, and audible alerts mean no more burnt disasters. Pair it with the Ninja CREAMi for the ultimate breakfast-dessert combo. <a class="view-deal button" href="https://www.amazon.com/Ninja-BW1001-NeverStick-Precision-Pour-Chef-curated/dp/B0B358VDZJ/ref=" target="_blank" rel="nofollow" data-dimension112="9ae6dae8-96fe-11f1-af0b-bffac6dd08f7" data-action="Deal Block" data-label="Belgian Waffle Maker" data-dimension48="Belgian Waffle Maker" data-dimension25="$79">View Deal</a></p></div><div class="product"><a data-dimension112="9ae6db42-96fe-11f1-bc49-877570370827" data-action="Deal Block" data-label="Pods & Grounds Specialty Single-Serve Iced Coffee Maker" data-dimension48="Pods & Grounds Specialty Single-Serve Iced Coffee Maker" data-dimension25="$99" href="https://www.amazon.com/Ninja-Specialty-Single-Serve-Compatible-PB055ABL/dp/B0C25Y15TL" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:679px;"><p class="vanilla-image-block" style="padding-top:99.56%;"><img id="4uiaRXRKY8Go6F4ZpM7UdA" name="Ninja coffee" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/4uiaRXRKY8Go6F4ZpM7UdA.jpg" mos="" align="middle" fullscreen="" width="679" height="676" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Ninja-Specialty-Single-Serve-Compatible-PB055ABL/dp/B0C25Y15TL" target="_blank" rel="nofollow" data-dimension112="9ae6db42-96fe-11f1-bc49-877570370827" data-action="Deal Block" data-label="Pods & Grounds Specialty Single-Serve Iced Coffee Maker" data-dimension48="Pods & Grounds Specialty Single-Serve Iced Coffee Maker" data-dimension25="$99">Pods & Grounds Specialty Single-Serve Iced Coffee Maker: was $129 now $99</a></strong><br>This stylish Ninja coffee maker comes in a gorgeous Sage colorway and is now on sale for $30 off. Whether you prefer pods or grounds, this device makes tasty brews in 7 sizes (6-oz. to 24-oz) and has a built-in, fold-away milk frother!<a class="view-deal button" href="https://www.amazon.com/Ninja-Specialty-Single-Serve-Compatible-PB055ABL/dp/B0C25Y15TL" target="_blank" rel="nofollow" data-dimension112="9ae6db42-96fe-11f1-bc49-877570370827" data-action="Deal Block" data-label="Pods & Grounds Specialty Single-Serve Iced Coffee Maker" data-dimension48="Pods & Grounds Specialty Single-Serve Iced Coffee Maker" data-dimension25="$99">View Deal</a></p></div><div class="product"><a data-dimension112="9ae6dba6-96fe-11f1-abb4-4baee8b836fa" data-action="Deal Block" data-label="NeverClog Cold Press Juicer" data-dimension48="NeverClog Cold Press Juicer" data-dimension25="$129" href="https://www.amazon.com/dp/B0DPXNR6YS" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:522px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="pKMqdL3azKMYSNwdTHk4m9" name="Ninja Never Clog" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/pKMqdL3azKMYSNwdTHk4m9.jpg" mos="" align="middle" fullscreen="" width="522" height="522" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0DPXNR6YS" target="_blank" rel="nofollow" data-dimension112="9ae6dba6-96fe-11f1-abb4-4baee8b836fa" data-action="Deal Block" data-label="NeverClog Cold Press Juicer" data-dimension48="NeverClog Cold Press Juicer" data-dimension25="$129">NeverClog Cold Press Juicer: was $149 now $129</a></strong><br>Create healthy juices from the comforts of your home with the Ninja Cold Press Juicer Pro. It features a powerful high torque motor and includes two one-touch programs that make it easy to operate. We also like that it has a pulp control that allows you to customize your juice with pulp or without.<a class="view-deal button" href="https://www.amazon.com/dp/B0DPXNR6YS" target="_blank" rel="nofollow" data-dimension112="9ae6dba6-96fe-11f1-abb4-4baee8b836fa" data-action="Deal Block" data-label="NeverClog Cold Press Juicer" data-dimension48="NeverClog Cold Press Juicer" data-dimension25="$129">View Deal</a></p></div><div class="product"><a data-dimension112="9ae6dc00-96fe-11f1-a154-9dead241a500" data-action="Deal Block" data-label="Mega Kitchen System" data-dimension48="Mega Kitchen System" data-dimension25="$179" href="https://www.amazon.com/dp/B00939I7EK" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1676px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="sWibiMn9jcqpLxyQRazy6f" name="Ninja Amazon 2.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/sWibiMn9jcqpLxyQRazy6f.jpg" mos="" align="middle" fullscreen="" width="1676" height="1676" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B00939I7EK" target="_blank" rel="nofollow" data-dimension112="9ae6dc00-96fe-11f1-a154-9dead241a500" data-action="Deal Block" data-label="Mega Kitchen System" data-dimension48="Mega Kitchen System" data-dimension25="$179">Mega Kitchen System: was $219 now $179</a></strong><br>Leave all the multi-tasking in the kitchen to one appliance with this Ninja blender. With four functions for smoothies, processing, dough, drinks and more it will quickly become your go-to kitchen appliance. With this ultimate appliance, you’ll be enjoying fresh, healthy drinks, homemade bread and sweet bakes.<a class="view-deal button" href="https://www.amazon.com/dp/B00939I7EK" target="_blank" rel="nofollow" data-dimension112="9ae6dc00-96fe-11f1-a154-9dead241a500" data-action="Deal Block" data-label="Mega Kitchen System" data-dimension48="Mega Kitchen System" data-dimension25="$179">View Deal</a></p></div><div class="product"><a data-dimension112="9ae6dc5a-96fe-11f1-9b25-51898ea4d818" data-action="Deal Block" data-label="Crispi 4-in-1 Portable Glass Air Fryer" data-dimension48="Crispi 4-in-1 Portable Glass Air Fryer" data-dimension25="$159" href="https://www.amazon.com/Ninja-Microwave-Dishwasher-Containers-FN101GY/dp/B0DDDD8WD6?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:679px;"><p class="vanilla-image-block" style="padding-top:85.86%;"><img id="zNkXNCVYCubXhCRwjaoGPj" name="Ninjs Crispi" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/zNkXNCVYCubXhCRwjaoGPj.jpg" mos="" align="middle" fullscreen="" width="679" height="583" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Ninja-Microwave-Dishwasher-Containers-FN101GY/dp/B0DDDD8WD6?" target="_blank" rel="nofollow" data-dimension112="9ae6dc5a-96fe-11f1-9b25-51898ea4d818" data-action="Deal Block" data-label="Crispi 4-in-1 Portable Glass Air Fryer" data-dimension48="Crispi 4-in-1 Portable Glass Air Fryer" data-dimension25="$159">Crispi 4-in-1 Portable Glass Air Fryer: was $179 now $159</a></strong><br>The Ninja Crispi is one of Ninja's most interesting recent releases. It features a removable cooking lid and interchangeable glass containers to cook meals of a range of sizes. In our <a href="https://www.tomsguide.com/home/air-fryers/ninja-crispi-air-fryer-review">Ninja Crispi review</a>, it earned a well-deserved 4.5 stars.  <a class="view-deal button" href="https://www.amazon.com/Ninja-Microwave-Dishwasher-Containers-FN101GY/dp/B0DDDD8WD6?" target="_blank" rel="nofollow" data-dimension112="9ae6dc5a-96fe-11f1-9b25-51898ea4d818" data-action="Deal Block" data-label="Crispi 4-in-1 Portable Glass Air Fryer" data-dimension48="Crispi 4-in-1 Portable Glass Air Fryer" data-dimension25="$159">View Deal</a></p></div><div class="product"><a data-dimension112="9ae6dcbe-96fe-11f1-8347-05248dfd47f6" data-action="Deal Block" data-label="FrostVault Go 24-Can Backpack Soft Cooler with Cold Dry Zone" data-dimension48="FrostVault Go 24-Can Backpack Soft Cooler with Cold Dry Zone" data-dimension25="$179" href="https://www.amazon.com/Ninja-FrostVaultTM-Backpack-Cooler-Storage/dp/B0GSHG5THD" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:540px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="bcxdGXf8PnyrQEezzPCfXb" name="Ninja FrostVault.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/bcxdGXf8PnyrQEezzPCfXb.jpg" mos="" align="middle" fullscreen="" width="540" height="540" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Ninja-FrostVaultTM-Backpack-Cooler-Storage/dp/B0GSHG5THD" target="_blank" rel="nofollow" data-dimension112="9ae6dcbe-96fe-11f1-8347-05248dfd47f6" data-action="Deal Block" data-label="FrostVault Go 24-Can Backpack Soft Cooler with Cold Dry Zone" data-dimension48="FrostVault Go 24-Can Backpack Soft Cooler with Cold Dry Zone" data-dimension25="$179">FrostVault Go 24-Can Backpack Soft Cooler with Cold Dry Zone: was $199 now $179</a></strong><br>The FrostVault Go is a super convenient backpack cooler from Ninja. It's available in two sizes — this deal is for the 24-can version. It has a Chillseal Lid for maximum ice retention and a Cold Dry Zone to keep food separate and at a food-safe temperature, to ensure its freshness.<a class="view-deal button" href="https://www.amazon.com/Ninja-FrostVaultTM-Backpack-Cooler-Storage/dp/B0GSHG5THD" target="_blank" rel="nofollow" data-dimension112="9ae6dcbe-96fe-11f1-8347-05248dfd47f6" data-action="Deal Block" data-label="FrostVault Go 24-Can Backpack Soft Cooler with Cold Dry Zone" data-dimension48="FrostVault Go 24-Can Backpack Soft Cooler with Cold Dry Zone" data-dimension25="$179">View Deal</a></p></div><div class="product"><a data-dimension112="9ae6dd18-96fe-11f1-97f5-8b56233f0907" data-action="Deal Block" data-label="10-Pc German Steel Knife Set" data-dimension48="10-Pc German Steel Knife Set" data-dimension25="$219" href="https://www.amazon.com/dp/B0H2NLCZBQ" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1368px;"><p class="vanilla-image-block" style="padding-top:109.65%;"><img id="juwy9ZiNjzvb7g4oTRTTT4" name="10-Pc German Steel Knife Set" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/juwy9ZiNjzvb7g4oTRTTT4.jpg" mos="" align="middle" fullscreen="" width="1368" height="1500" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0H2NLCZBQ" target="_blank" rel="nofollow" data-dimension112="9ae6dd18-96fe-11f1-97f5-8b56233f0907" data-action="Deal Block" data-label="10-Pc German Steel Knife Set" data-dimension48="10-Pc German Steel Knife Set" data-dimension25="$219">10-Pc German Steel Knife Set: was $249 now $219</a></strong><br>This 10-piece knife set from Ninja provides all the knives you need to cut, chop and dice your food. It also features a built-in knife sharpener, so you never have an excuse to use a blunt knife again — it'll keep them sharp for 10+ years.<a class="view-deal button" href="https://www.amazon.com/dp/B0H2NLCZBQ" target="_blank" rel="nofollow" data-dimension112="9ae6dd18-96fe-11f1-97f5-8b56233f0907" data-action="Deal Block" data-label="10-Pc German Steel Knife Set" data-dimension48="10-Pc German Steel Knife Set" data-dimension25="$219">View Deal</a></p></div><div class="product"><a data-dimension112="c39b8028-96ff-11f1-98e3-63e3970b16f9" data-action="Deal Block" data-label="Double Oven, 12-in-1 DCT401" data-dimension48="Double Oven, 12-in-1 DCT401" data-dimension25="$219" href="https://www.amazon.com/Ninja-DCT401-FlavorSeal-Convection-Stainless/dp/B0BRQS5BH6" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:875px;"><p class="vanilla-image-block" style="padding-top:85.60%;"><img id="LQBDeKyzWKbLWRQgh54YmA" name="Double Oven, 12-in-1 DCT401" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/LQBDeKyzWKbLWRQgh54YmA.jpg" mos="" align="middle" fullscreen="" width="875" height="749" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Ninja-DCT401-FlavorSeal-Convection-Stainless/dp/B0BRQS5BH6" target="_blank" rel="nofollow" data-dimension112="c39b8028-96ff-11f1-98e3-63e3970b16f9" data-action="Deal Block" data-label="Double Oven, 12-in-1 DCT401" data-dimension48="Double Oven, 12-in-1 DCT401" data-dimension25="$219">Double Oven, 12-in-1 DCT401: was $379 now $219</a></strong><br>We couldn’t recommend this toaster oven more. Although it has since been replaced by a newer model, the DCT401 is a previous winner on our list of the <a href="https://www.tomsguide.com/best-picks/best-toaster-ovens">best toaster ovens</a>. We love that it divides into two ovens you can access separately via the FlexDoor, so you can cook two things at once. There are 12 functions overall, including toast, bake, whole roast, air fry, convection and pizza — meaning you can cook pretty much anything in there however you like.<a class="view-deal button" href="https://www.amazon.com/Ninja-DCT401-FlavorSeal-Convection-Stainless/dp/B0BRQS5BH6" target="_blank" rel="nofollow" data-dimension112="c39b8028-96ff-11f1-98e3-63e3970b16f9" data-action="Deal Block" data-label="Double Oven, 12-in-1 DCT401" data-dimension48="Double Oven, 12-in-1 DCT401" data-dimension25="$219">View Deal</a></p></div><div class="product"><a data-dimension112="9ae6dd72-96fe-11f1-88b3-e97212624547" data-action="Deal Block" data-label="Foodi XL Pro Air Fry Oven, 10-in-1" data-dimension48="Foodi XL Pro Air Fry Oven, 10-in-1" data-dimension25="$229" href="https://www.amazon.com/Ninja-DT201-Countertop-Convection-Dehydrate/dp/B08BXX69K4" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1500px;"><p class="vanilla-image-block" style="padding-top:75.80%;"><img id="sFc44K8P9eTgsrZ4Kc25oB" name="Foodi XL Pro Air Fry Oven, 10-in-1" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/sFc44K8P9eTgsrZ4Kc25oB.jpg" mos="" align="middle" fullscreen="" width="1500" height="1137" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Ninja-DT201-Countertop-Convection-Dehydrate/dp/B08BXX69K4" target="_blank" rel="nofollow" data-dimension112="9ae6dd72-96fe-11f1-88b3-e97212624547" data-action="Deal Block" data-label="Foodi XL Pro Air Fry Oven, 10-in-1" data-dimension48="Foodi XL Pro Air Fry Oven, 10-in-1" data-dimension25="$229">Foodi XL Pro Air Fry Oven, 10-in-1: was $379 now $229</a></strong><br>39% off is one of the biggest Ninja discounts you'll find right now. While this XL air fryer/oven takes up a lot of space, it offers plenty of cooking functions and perfect cooking results every time. <a class="view-deal button" href="https://www.amazon.com/Ninja-DT201-Countertop-Convection-Dehydrate/dp/B08BXX69K4" target="_blank" rel="nofollow" data-dimension112="9ae6dd72-96fe-11f1-88b3-e97212624547" data-action="Deal Block" data-label="Foodi XL Pro Air Fry Oven, 10-in-1" data-dimension48="Foodi XL Pro Air Fry Oven, 10-in-1" data-dimension25="$229">View Deal</a></p></div><div class="product"><a data-dimension112="9ae6ddd6-96fe-11f1-a3e0-737367858cbe" data-action="Deal Block" data-label="Woodfire Oven & Smoker" data-dimension48="Woodfire Oven & Smoker" data-dimension25="$279" href="https://www.amazon.com/Ninja-Woodfire-Technology-terracotta-OO101/dp/B0C6BQVDX3/" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1500px;"><p class="vanilla-image-block" style="padding-top:90.20%;"><img id="C5KWDYUzjspNSP6tT8AAQP" name="81IeXOFExqL._AC_SL1500_.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/C5KWDYUzjspNSP6tT8AAQP.jpg" mos="" align="middle" fullscreen="" width="1500" height="1353" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>The Ninja Woodfire Oven & Smoker is a favorite with the Tom's Guide team. It makes amazing pizzas, smoked wings and many things in between. It's perfect to keep the summer vibes going all year long with delicious dishes.<a class="view-deal button" href="https://www.amazon.com/Ninja-Woodfire-Technology-terracotta-OO101/dp/B0C6BQVDX3/" target="_blank" rel="nofollow" data-dimension112="9ae6ddd6-96fe-11f1-a3e0-737367858cbe" data-action="Deal Block" data-label="Woodfire Oven & Smoker" data-dimension48="Woodfire Oven & Smoker" data-dimension25="$279">View Deal</a></p></div><div class="product"><a data-dimension112="9ae6de30-96fe-11f1-93b8-cf7bb06625b2" data-action="Deal Block" data-label="Luxe Café Premier" data-dimension48="Luxe Café Premier" data-dimension25="$599" href="https://www.amazon.com/dp/B0FGDTHY1Y" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:541px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="HcnQ36qmUJg5VJidxsJ76X" name="Ninja Luxe Cafe.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/HcnQ36qmUJg5VJidxsJ76X.jpg" mos="" align="middle" fullscreen="" width="541" height="541" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>It's not on sale, but the Ninja Luxe Café Premier is just that good. This 3-in-1 coffee machine brews quality espresso, drip coffee, and fast cold brew using its Barista Assist technology, an integrated grinder, and weight-based dosing. Plus, it makes creating pro-level microfoam easy, thanks to its Dual Froth system. Our reviewer called it "the best beginner-friendly espresso machine I’ve ever tested" in our <a href="https://www.tomsguide.com/home/ninja-luxe-cafe-premier-series-espresso-machine-review" data-dimension112="9ae6de30-96fe-11f1-93b8-cf7bb06625b2" data-action="Deal Block" data-label="Luxe Café Premier" data-dimension48="Luxe Café Premier" data-dimension25="$599">Ninja Luxe Café coffee maker review</a>.<a class="view-deal button" href="https://www.amazon.com/dp/B0FGDTHY1Y" target="_blank" rel="nofollow" data-dimension112="9ae6de30-96fe-11f1-93b8-cf7bb06625b2" data-action="Deal Block" data-label="Luxe Café Premier" data-dimension48="Luxe Café Premier" data-dimension25="$599">View Deal</a></p></div><div class="vizualizer-embed"><div class="tg-df-widget-host" data-widget-config="?search=Home+Appliances&brands=Ninja%2CShark&min_discount_ratio=0.95&offer_type=all&view_mode=carousel&widget_title=Top+Deals+Handpicked+by+Our+Editors&widget_subtitle=Discover+the+best+discounts+currently+available%2C+curated+daily+by+the+Tom%27s+Guide+Savings+Squad.&bg_color=light_blue" data-vizualizer-embed="true"></div>    <script>    /**     * Tom's Guide Deals Finder - Vanilla JS Encapsulated Engine     */    (function() {      // --- Freyr Analytics Adapter ---      function initAnalytics() {        window.dataLayer = window.dataLayer || [];        window.googletag = window.googletag || {};        window.googletag.cmd = window.googletag.cmd || [];        window.hawk = window.hawk || { analytics: { freyr: [] } };        window.hawk.analytics = window.hawk.analytics || { freyr: [] };        window.hawk.analytics.freyr = window.hawk.analytics.freyr || [];        window.freyr = window.freyr || { cmd: [] };        const scriptSrc = 'https://freyr.futurecdn.net/freyr.js';        const hostname = typeof window !== 'undefined' ? window.location.hostname : '';        const isTestEnv = typeof window.navigator !== 'undefined' && (window.navigator.webdriver || window.navigator.userAgent.includes('Headless'));        const shouldSendRealAnalytics = !isTestEnv && hostname && hostname !== 'localhost' && hostname !== '127.0.0.1' && !hostname.includes('run.app');        if (shouldSendRealAnalytics && !document.querySelector(`script[src="${scriptSrc}"]`)) {          const script = document.createElement('script');          script.src = scriptSrc;          script.async = true;          document.head.appendChild(script);        }      }      function storeEventForDebug(name, data) {        if (!window.hawk || !window.hawk.analytics || !window.hawk.analytics.freyr) return;        window.hawk.analytics.freyr.push({ name, data });        try {          if (typeof window !== 'undefined' && window.localStorage) {            window.localStorage.setItem("hawk", JSON.stringify(window.hawk));          }        } catch (e) {          // Ignore storage issues        }        try {          window.dispatchEvent(new CustomEvent("hawk-analytics-update"));        } catch (e) {}      }      function sendToFreyr(eventName, data) {        if (typeof window === 'undefined') return;        window.freyr = window.freyr || { cmd: [] };        window.freyr.cmd.push(() => {          if (window.freyr && window.freyr.pushAndUpdate) {            window.freyr.pushAndUpdate(eventName, data);          }        });      }      function sendEvent(event, skip = false) {        try {          storeEventForDebug(event.name, event.data);          if (!skip) {            sendToFreyr(event.name, event.data);          }        } catch (e) {          // Ensure tracking errors don't surface to the user        }      }      function getCookie(name) {        try {          const match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));          return match ? match[2] : null;        } catch (e) {          return null;        }      }      function normalizeCurrency(symbol) {        const map = {          '£': 'GBP',          '$': 'USD',          'A$': 'AUD',          'CA$': 'CAD',          '€': 'EUR'        };        return map[symbol] || symbol;      }      function trackElementInteraction(props) {        sendEvent({          name: 'elementInteraction',          data: {            element: {              action: props.action || "click",              id: props.id || undefined,              class: props.class || undefined,              name: props.name || undefined,              text: props.text || undefined,              label: props.label || undefined,              container: props.container || undefined,              url: props.url || undefined,              articleId: props.articleId || undefined            }          }        });      }      function generateRevenueId(url, productName, merchantName, modelId) {        const str = `${window.location.href}|${productName}|${merchantName}|${modelId || ''}|${new Date().toDateString()}|tomsguide`;        let hash = 0;        for (let i = 0; i < str.length; i++) {          const char = str.charCodeAt(i);          hash = ((hash << 5) - hash) + char;          hash = hash & hash;        }        let numericStr = Math.abs(hash).toString();        while (numericStr.length < 19) {          numericStr += Math.floor(Math.random() * 10).toString();        }        return numericStr.substring(0, 19);      }      function rewriteAffiliateLink(url, territory, revenueId) {        if (!url) return url;        const t = (territory || 'gb').toLowerCase();        return url.replace(/hawk-custom-tracking/g, `tomsguide-${t}-${revenueId}`);      }      function trackHawkEvent(params) {        const { clickType, widgetId, productCategoryName, product, productsArray, zeroBasedProductIndexOrNull, totalDealsOrProducts, areaClicked, merchant, revenueId, isoCurrencyCode, queryName, widgetTypeName } = params;        const data = {          event: "hawkEvent",          category: "Affiliates",          affiliate: {            action: {              type: clickType,              id: widgetId,              event: clickType === "appeared" ? "viewed" : "Click from",              timestamp: Date.now()            },            component: {              flag: "Editor",              product: productCategoryName || "deals",              category: `Signal Deal Finder ${widgetTypeName || "Carousel"} widget`,              type: clickType === "appeared" ? "review" : "signal product",              label: queryName || (product ? (product.name || "") : ""),              index: zeroBasedProductIndexOrNull === null || zeroBasedProductIndexOrNull === undefined ? -1 : zeroBasedProductIndexOrNull,              linkCount: totalDealsOrProducts || 0,              blockLayout: "",              areaClicked: areaClicked || ""            }          },          products: productsArray || (product && merchant ? [            {              product: {                primary: {                  id: product.id || product.matchId || null,                  name: product.name,                  type: "deal",                  price: product.price,                  previousPrice: product.previousPrice || null,                  currency: isoCurrencyCode || "USD",                  preorder: false,                  labels: [],                  link: product.link,                  originalLink: product.originalLink || null,                  revenueId: revenueId || null,                  startTime: null,                  endTime: null,                  voucherCode: null,                  voucherAudience: null,                  voucherPercentageSaving: null,                  voucherMoneySaving: null,                  voucherType: null,                  offerExclusive: false,                  offerScope: null,                  globalId: product.globalId || null,                  inStock: product.inStock !== false,                  contractProvider: null,                  contractMinutes: null,                  contractTexts: null,                  contractData: null,                  contractLength: null,                  contractMonthlyPrice: null,                  contractCurrency: isoCurrencyCode || "USD"                }              },              merchant: {                id: merchant.id || null,                name: merchant.name,                url: merchant.url || null,                network: merchant.network || null              },              model: {                id: product.modelId || null,                brand: product.brand || null,                name: product.name,                parent: product.parent || null              }            }          ] : []),          reviews: [],          _clear: true,          "gtm.uniqueEventId": Date.now() % 10000        };        sendEvent({ name: 'hawkEvent', data });      }      function trackDealClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Product Card" });      }      function trackViewSimilarClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Product Card View Similar" });      }      function trackPriceComparisonClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Price Comparison" });      }      function trackReviewClick(params) {        trackHawkEvent({ ...params, clickType: "review", areaClicked: "Signal Product Card Review Link" });      }      function trackShare(params) {        trackHawkEvent({ ...params, clickType: "share", areaClicked: "Signal Product Card Share" });      }      function trackDealsAppeared(widgetId, deals, revenueId, currency, queryName, widgetTypeName) {         if (!deals || deals.length === 0) return;                  const productsArray = deals.slice(0, 50).map((deal) => {            let voucherPct = null;            let rawPrice = parseFloat(deal.rawPrice) || parseFloat(deal.price) || null;            let rawMsrp = parseFloat(deal.rawMsrp) || parseFloat(deal.msrp) || null;            if (rawMsrp > rawPrice && rawPrice > 0) {              voucherPct = Math.round((1 - (rawPrice / rawMsrp)) * 100);            }            let numId = null;            if (deal.externalProductId && !isNaN(parseInt(deal.externalProductId))) {              numId = parseInt(deal.externalProductId);            } else if (deal.id && !isNaN(parseInt(deal.id))) {              numId = parseInt(deal.id);            } else {              numId = deal.matchId || null;            }            return {              product: {                primary: {                  id: numId,                  name: deal.productName || deal.title || "",                  type: "deal",                  price: rawPrice,                  previousPrice: rawMsrp,                  currency: currency || 'USD',                  preorder: false,                  labels: deal.modelBrand || deal.brand ? [                     { type: "brand", value: deal.modelBrand || deal.brand }                  ] : [],                  link: deal.url,                  originalLink: deal.url,                  revenueId: revenueId || null,                  startTime: null,                  endTime: null,                  voucherCode: null,                  voucherAudience: null,                  voucherPercentageSaving: voucherPct,                  voucherMoneySaving: null,                  voucherType: null,                  offerExclusive: false,                  offerScope: null,                  globalId: deal.productKey || null,                  inStock: deal.inStock !== false,                  contractProvider: null,                  contractMinutes: null,                  contractTexts: null,                  contractData: null,                  contractLength: null,                  contractMonthlyPrice: null,                  contractCurrency: currency || 'USD'                }              },              merchant: {                id: deal.merchantId ? parseInt(deal.merchantId) : null,                name: deal.merchant || "Retailer",                url: deal.merchantUrl || null,                network: deal.merchantNetwork || null              },              model: {                id: deal.modelId ? parseInt(deal.modelId) : null,                brand: deal.modelBrand || deal.brand || null,                name: deal.productName || deal.title || "",                parent: deal.modelParent || null              }            };         });                  trackHawkEvent({             clickType: "appeared",             widgetId: widgetId,             productCategoryName: "deals",             zeroBasedProductIndexOrNull: null,             totalDealsOrProducts: deals.length,             productsArray: productsArray,             queryName: queryName,             widgetTypeName: widgetTypeName         });      }      // 1. Setup Shadow DOM Sandbox      const currentScript = document.currentScript;      let hostContainer = null;      let template = null;            if (currentScript) {        let prev = currentScript.previousElementSibling;        while (prev) {          if (prev.tagName === 'TEMPLATE' && prev.classList.contains('tg-df-widget-template')) {            template = prev;          } else if (prev.tagName === 'DIV' && prev.classList.contains('tg-df-widget-host') && !prev.hasAttribute('data-initialized')) {            hostContainer = prev;            break;          }          prev = prev.previousElementSibling;        }      }            // Fallbacks in case script is deferred      if (!hostContainer) {        const hosts = document.querySelectorAll('.tg-df-widget-host:not([data-initialized])');        if (hosts.length > 0) hostContainer = hosts[0];      }            // Safely embedded template for CMS environments      const rawTemplate = `  \x3Cstyle>    /* --- Shadow DOM Base Reset --- */    *, *::before, *::after {      box-sizing: border-box;    }    img, picture, svg, video {      max-width: 100%;      height: auto;      display: block;    }    /*       1. Scoped CSS for Tom's Guide Deals Widget       All classes are prefixed with \`tg-df-\` to prevent CMS style leakage.    */    .tg-df-container {      container-type: inline-size;      container-name: tg-df;      --tg-df-blue: #1F69FF;      --tg-df-blue-hover: #004d8c;      --tg-df-text: #222222;      --tg-df-text-muted: #555555;      --tg-df-bg: #ffffff;      --tg-df-bg-secondary: #f4f4f4;      --tg-df-border: #e2e8f0;      font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;      color: var(--tg-df-text);      background-color: transparent;       width: 100%;      max-width: 1200px;      margin: 0 auto;      padding-bottom: 24px;    }    .tg-df-container *, .tg-df-container *::before, .tg-df-container *::after {      margin: 0;      padding: 0;      box-sizing: border-box;    }    .tg-df-container img {      border: none;      margin: 0;      padding: 0;    }    .tg-df-container a {      text-decoration: none;      color: inherit;    }    /*       2. Search & Filter Bar    */    .tg-df-controls {      display: flex;      flex-direction: column;      align-items: center;      gap: 20px;      margin-bottom: 32px;      width: 100%;    }    .tg-df-top-bar {      display: flex;      width: 100%;      max-width: 760px;      gap: 12px;      align-items: center;    }    .tg-df-search-wrapper {      position: relative;      flex: 1;      width: 100%;      box-shadow: 0 8px 24px rgba(0,0,0,0.06);      border-radius: 40px;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      z-index: 100;    }    .tg-df-autocomplete-dropdown {      position: absolute;      top: calc(100% + 4px);      left: 0;      right: 0;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 12px;      box-shadow: 0 8px 32px rgba(0,0,0,0.12);      max-height: 300px;      overflow-y: auto;      z-index: 200;      display: none;    }    .tg-df-autocomplete-dropdown.active {      display: block;    }    .tg-df-autocomplete-item {      padding: 12px 24px;      cursor: pointer;      font-size: 14px;      color: var(--tg-df-text);      transition: background 0.1s ease;    }    .tg-df-autocomplete-item:hover {      background: var(--tg-df-bg-secondary);    }    .tg-df-search-input {      width: 100%;      padding: 16px 64px 16px 24px;      font-size: 16px;      border: 2px solid transparent;      border-radius: 40px;      outline: none;      transition: border-color 0.2s ease, box-shadow 0.2s ease;      color: var(--tg-df-text);      background: transparent;    }    .tg-df-search-input:focus {      border-color: transparent;      box-shadow: 0 0 0 3px rgba(0, 108, 196, 0.15);    }    .tg-df-search-input::placeholder {      color: #999999;    }        .tg-df-search-btn {      position: absolute;      right: 8px;      top: 50%;      transform: translateY(-50%);      width: 40px;      height: 40px;      border-radius: 50%;      background: #222;      border: none;      display: flex;      align-items: center;      justify-content: center;      cursor: pointer;      transition: background 0.2s ease;    }        .tg-df-search-btn:hover {      background: #000;    }    .tg-df-search-icon {      width: 16px;      height: 16px;      fill: #fff;    }    .tg-df-settings-wrapper {      position: relative;    }        .tg-df-settings-btn {      width: 48px;      height: 48px;      border-radius: 50%;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      box-shadow: 0 4px 12px rgba(0,0,0,0.04);      display: flex;      align-items: center;      justify-content: center;      cursor: pointer;      transition: all 0.2s ease;      color: var(--tg-df-text-muted);      flex-shrink: 0;    }    .tg-df-settings-btn:hover {      background: var(--tg-df-bg-secondary);      border-color: #0000ff;      color: var(--tg-df-text);    }    .tg-df-settings-btn svg {      width: 24px;      height: 24px;      fill: currentColor;    }    .tg-df-settings-dropdown {      position: absolute;      top: calc(100% + 8px);      right: 0;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 12px;      box-shadow: 0 8px 32px rgba(0,0,0,0.12);      width: 280px;      padding: 20px;      display: none;      z-index: 100;      flex-direction: column;      gap: 20px;    }    .tg-df-settings-dropdown.active {      display: flex;    }        .tg-df-settings-dropdown-backdrop {      display: none;      position: fixed;      inset: 0;      z-index: 99;    }        .tg-df-settings-dropdown-backdrop.active {      display: block;    }    .tg-df-setting-item {      display: flex;      flex-direction: column;      gap: 10px;    }    .tg-df-setting-label {      font-size: 11px;      font-weight: 700;      color: var(--tg-df-text-muted);      text-transform: uppercase;      letter-spacing: 0.5px;    }        .tg-df-region-select {        padding: 10px 12px;        border-radius: 8px;        border: 1px solid var(--tg-df-border);        font-size: 15px;        outline: none;        background: var(--tg-df-bg-secondary);        color: var(--tg-df-text);        cursor: pointer;        width: 100%;    }    .tg-df-toggle {        position: relative;        display: inline-block;        width: 44px;        height: 24px;        flex-shrink: 0;    }    .tg-df-toggle input {        opacity: 0;        width: 0;        height: 0;    }    .tg-df-slider {        position: absolute;        cursor: pointer;        top: 0; left: 0; right: 0; bottom: 0;        background-color: #ccc;        transition: .2s;        border-radius: 24px;    }    .tg-df-slider:before {        position: absolute;        content: "";        height: 18px;        width: 18px;        left: 3px;        bottom: 3px;        background-color: white;        transition: .2s;        border-radius: 50%;    }    .tg-df-toggle input:checked + .tg-df-slider {        background-color: #1F69FF;    }    .tg-df-toggle input:checked + .tg-df-slider:before {        transform: translateX(20px);    }    .tg-df-dl-row {        flex-direction: row;        align-items: center;        justify-content: space-between;    }    .tg-df-dl-row-text {        font-size: 14px;        font-weight: 600;        color: var(--tg-df-text);    }    .tg-df-dl-row-subtext {        font-size: 12px;        font-weight: 400;        line-height: 1.3;        color: var(--tg-df-text-muted);        margin-top: 4px;        display: block;    }    .tg-df-filters {      display: flex;      gap: 12px;      justify-content: center;      flex-wrap: wrap;    }    .tg-df-sort-wrapper {      position: relative;      display: flex;      align-items: center;    }        .tg-df-sort-icon {      position: absolute;      left: 14px;      width: 14px;      height: 14px;      fill: var(--tg-df-text-muted);      pointer-events: none;    }    .tg-df-sort-select, .tg-df-filter-select {      padding: 10px 36px 10px 38px;      font-size: 14px;      border: 1px solid var(--tg-df-border);      border-radius: 100px;      outline: none;      appearance: none;      background-color: var(--tg-df-bg-secondary);      background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 12 12'%3E%3Cpath fill='%23555555' d='M6 8L1 3h10z'/%3E%3C/svg%3E");      background-repeat: no-repeat;      background-position: right 14px center;      color: var(--tg-df-text);      cursor: pointer;      font-weight: 500;      transition: all 0.2s ease;    }        .tg-df-price-input::-webkit-outer-spin-button,    .tg-df-price-input::-webkit-inner-spin-button {      -webkit-appearance: none;      margin: 0;    }    .tg-df-price-input {      -moz-appearance: textfield;    }    .tg-df-sort-select:hover, .tg-df-filter-select:hover {      background-color: #e2e8f0;    }    .tg-df-multiselect-container {      position: relative;    }        .tg-df-multiselect-trigger {      display: block;      background: #fff;      user-select: none;      width: 100%;      overflow: hidden;      white-space: nowrap;      text-overflow: ellipsis;    }        .tg-df-multiselect-dropdown {      display: none;      position: absolute;      top: calc(100% + 4px);      left: 0;      width: 100%;      min-width: 220px;      max-height: 300px;      overflow-y: auto;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 8px;      box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);      z-index: 100;      padding: 8px 0;    }    .tg-df-multiselect-dropdown.active {      display: block;    }    .tg-df-ms-option {      padding: 8px 16px;      display: flex;      align-items: center;      gap: 8px;      cursor: pointer;      font-size: 14px;    }    .tg-df-ms-option:hover {      background-color: var(--tg-df-bg-secondary);    }        .tg-df-ms-option input {      cursor: pointer;      accent-color: #1f69ff;    }    .tg-df-sort-select:focus, .tg-df-filter-select:focus {      border-color: #0000ff;      box-shadow: 0 0 0 3px rgba(0, 0, 255, 0.2);      background-color: var(--tg-df-bg);    }    /*       3. Deal Grid Layout    */    .tg-df-grid.tg-df-grid-auto {      padding-top: 24px;    }    .tg-df-grid, .tg-df-grid.layout-grid {      display: grid;      grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));      gap: 10px;    }    .tg-df-grid.layout-row {      grid-template-columns: 1fr;      gap: 16px;    }        .tg-df-grid.layout-row .tg-df-card {      flex-direction: row;      align-items: stretch;      height: auto;      box-shadow: none;      border-bottom: 1px solid var(--tg-df-border);    }    .tg-df-grid.layout-row .tg-df-card:hover {      box-shadow: none;    }    .tg-df-grid.layout-row .tg-df-card-image-box {      width: 140px;      min-width: 140px;      aspect-ratio: 3/4;      border-right: none;      padding: 16px 16px 16px 32px;    }    .tg-df-grid.layout-row .tg-df-card-body {      padding: 16px;      justify-content: space-between;    }    .tg-df-grid.layout-row .tg-df-card-title {      font-size: 15px;      margin-bottom: 16px;    }    .tg-df-grid.layout-row .tg-df-card-stars { margin-bottom: 8px; }    .tg-df-grid.layout-row .tg-df-card-footer {      flex-direction: column;      align-items: flex-start;      gap: 0;    }    .tg-df-grid.layout-row .tg-df-card-merchant-pill {      margin-bottom: 4px;    }    .tg-df-grid.layout-row .tg-df-card-price-group {      margin-bottom: 8px;    }    .tg-df-grid.layout-row .tg-df-price-group {      width: auto;    }    .tg-df-grid.layout-row .tg-df-card-cta {      width: 100%;      max-width: 200px;      padding: 10px 24px;      font-size: 13px;      flex-shrink: 0;      text-align: center;      justify-content: center;    }    /*       4. Deal Card Design    */    .tg-df-card {      position: relative;      display: flex;      flex-direction: column;      background-color: #ffffff;      border-radius: 0;      overflow: hidden;      transition: transform 0.2s ease, box-shadow 0.2s ease;      text-decoration: none;      color: inherit;      height: 100%;      box-shadow: 0 0 16px rgba(0, 0, 0, 0.08);      border: 1px solid var(--tg-df-border);    }    .tg-df-card:hover {      box-shadow: 0 0 24px rgba(0, 0, 0, 0.12);    }    .tg-df-card-image-box {      width: 100%;      aspect-ratio: 3/4;      background-color: #f8f8f8;      display: flex;      align-items: center;      justify-content: center;      position: relative;      overflow: hidden;      padding: 32px;      flex: 0 0 auto;    }    .tg-df-card-image {      max-width: 100%;      max-height: 100%;      width: auto;      height: auto;      object-fit: contain;      mix-blend-mode: multiply; /* Helps white background images blend into secondary bg */      transition: transform 0.3s ease;    }    .tg-df-card:hover .tg-df-card-image {      transform: scale(1.05); /* Zoom in on hover */    }    .tg-df-card-discount-badge {      position: absolute;      top: 12px;      left: 12px;      background: #dc2626; /* Red */      color: #ffffff;      padding: 6px 8px;      font-size: 11px;      font-weight: 500;      text-transform: uppercase;      letter-spacing: 0.5px;      border-radius: 0;      z-index: 10;    }        .tg-df-card-merchant-pill {      display: block;      padding: 0;      font-size: 11px;      font-weight: 600;      text-transform: uppercase;      letter-spacing: 0.5px;      border-radius: 0;      color: var(--tg-df-text-muted);      margin-bottom: 8px;      white-space: nowrap;      overflow: hidden;      text-overflow: ellipsis;    }    .tg-df-card-body {      padding: 16px;      display: flex;      flex-direction: column;      flex-grow: 1;      min-width: 0;    }    .tg-df-card-badges {      display: flex;      flex-wrap: wrap;      gap: 6px;      margin-bottom: 8px;    }    .tg-df-tag {      display: inline-flex;      align-items: center;      padding: 4px 6px;      font-size: 11px;      font-weight: 700;      text-transform: uppercase;      border-radius: 4px;      gap: 4px;    }    .tg-df-tag-prime {      background-color: #00A8E1;      color: #fff;    }    .tg-df-tag-coupons {      background-color: #f1f5f9;      color: #334155;      border: 1px solid #cbd5e1;      cursor: pointer;      transition: background-color 0.2s;    }    .tg-df-tag-coupons:hover {      background-color: #e2e8f0;    }        .tg-df-tag-outline {      background-color: #f1f5f9;      color: #334155;      border: 1px solid #cbd5e1;      cursor: pointer;      transition: background-color 0.2s;    }    .tg-df-tag-outline:hover {      background-color: #e2e8f0;    }        @keyframes tg-df-spin {      0% { transform: rotate(0deg); }      100% { transform: rotate(360deg); }    }    .tg-df-coupon-spinner {      border: 2px solid #e2e8f0;      border-top: 2px solid #3b82f6;      border-radius: 50%;      width: 14px;      height: 14px;      animation: tg-df-spin 1s linear infinite;      margin: 4px 8px;      display: inline-block;    }        /* Vouchers Modal */    .tg-df-modal-backdrop {      position: fixed;      top: 0; left: 0; right: 0; bottom: 0;      background: rgba(0,0,0,0.5);      z-index: 10000;      display: flex;      align-items: center;      justify-content: center;      opacity: 0;      pointer-events: none;      transition: opacity 0.3s;    }    .tg-df-modal-backdrop.active {      opacity: 1;      pointer-events: auto;    }    .tg-df-modal {      background: #fff;      border-radius: 12px;      width: 90%;      max-width: 400px;      max-height: 80vh;      display: flex;      flex-direction: column;      box-shadow: 0 10px 40px rgba(0,0,0,0.2);      transform: translateY(20px);      transition: transform 0.3s;    }    .tg-df-modal-backdrop.active .tg-df-modal {      transform: translateY(0);    }    .tg-df-modal-header {      padding: 16px;      border-bottom: 1px solid #e2e8f0;      display: flex;      align-items: center;      justify-content: space-between;    }    .tg-df-modal-title {      font-size: 16px;      font-weight: 600;      margin: 0;    }    .tg-df-modal-close {      background: none;      border: none;      cursor: pointer;      padding: 4px;      color: #64748b;    }    .tg-df-modal-body {      padding: 16px;      overflow-y: auto;    }    .tg-df-voucher-item {      padding: 12px;      border: 1px dashed #cbd5e1;      border-radius: 8px;      margin-bottom: 10px;      background: #f8fafc;      display: flex;      align-items: center;      gap: 12px;      text-decoration: none;      color: inherit;      transition: background-color 0.2s, border-color 0.2s;    }    .tg-df-voucher-item:hover {      background: #f1f5f9;      border-color: #94a3b8;    }    .tg-df-voucher-item:last-child {      margin-bottom: 0;    }    .tg-df-voucher-logo {      width: 48px;      height: 48px;      object-fit: contain;      border-radius: 4px;      background: #fff;      border: 1px solid #e2e8f0;      flex-shrink: 0;    }    .tg-df-voucher-content {      flex: 1;      min-width: 0;    }    .tg-df-voucher-title {      font-size: 14px;      font-weight: 600;      margin: 0 0 4px 0;      line-height: 1.3;      color: #0f172a;    }    .tg-df-voucher-expiry {      font-size: 12px;      color: #64748b;      display: flex;      align-items: center;      gap: 4px;      margin-top: 6px;    }    .tg-df-voucher-code {      display: inline-flex;      align-items: center;      background: #f1f5f9;      border: 1px dashed #cbd5e1;      padding: 6px 10px;      font-family: monospace;      font-weight: 700;      font-size: 14px;      color: #0f172a;      border-radius: 4px;      margin-top: 8px;      cursor: pointer;      transition: all 0.2s ease;    }    .tg-df-voucher-code:hover {      background: #e2e8f0;      border-color: #94a3b8;    }    .tg-df-voucher-code.copied {      background: #ecfdf5;      border-color: #10b981;      color: #10b981;    }    .tg-df-voucher-cta {      display: inline-block;      margin-top: 8px;      font-size: 13px;      font-weight: 600;      color: #2563eb;      text-decoration: none;    }    .tg-df-card-title {      font-size: 15px;      font-weight: 400;      line-height: 1.4;      margin: 0 0 12px 0;      color: var(--tg-df-text);      display: -webkit-box;      -webkit-line-clamp: 2;      -webkit-box-orient: vertical;      overflow: hidden;    }    .tg-df-card-footer {      margin-top: auto;      display: flex;      flex-direction: column;      width: 100%;    }    .tg-df-card-price-group {      display: flex;      flex-direction: row;      align-items: center;      gap: 8px;      margin-bottom: 12px;    }    .tg-df-card-price {      font-size: 16px;      font-weight: 700;      color: #dc2626; /* Red price */      line-height: 1;    }        .tg-df-card-msrp {      font-size: 13px;      color: var(--tg-df-text-muted);      text-decoration: line-through;    }    .tg-df-container .tg-df-card-cta {      display: flex;      align-items: center;      justify-content: center;      width: 100%;      box-sizing: border-box;      background-color: #1f69ff;      color: #ffffff;      font-size: 12px;      font-weight: 700;      text-transform: uppercase;      letter-spacing: 0.5px;      padding: 12px 16px;      border-radius: 0;      border: none;      cursor: pointer;      transition: background-color 0.2s ease;    }    .tg-df-card:hover .tg-df-card-cta,    .tg-df-card-cta:hover {      background-color: #1555cc;    }    .tg-df-container .tg-df-card-cta.tg-df-cta-savings-squad {      background-color: #3c8d0d;    }    .tg-df-card:hover .tg-df-card-cta.tg-df-cta-savings-squad,    .tg-df-card-cta.tg-df-cta-savings-squad:hover {      background-color: #2b6509;    }    /*       5. State & Skeleton Styles    */    .tg-df-message {      grid-column: 1 / -1;      text-align: center;      padding: 48px 24px;      color: var(--tg-df-text-muted);      font-size: 16px;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 8px;    }    @keyframes tg-df-shimmer {      0% { background-position: -200% 0; }      100% { background-position: 200% 0; }    }    .tg-df-skeleton {      background: linear-gradient(90deg, var(--tg-df-bg-secondary) 25%, #e2e8f0 50%, var(--tg-df-bg-secondary) 75%);      background-size: 200% 100%;      animation: tg-df-shimmer 1.5s infinite;      border-radius: 4px;    }    .tg-df-skeleton-img {      width: 100%;      height: 100%;      position: absolute;      top: 0; left: 0;    }        .tg-df-skeleton-text {      height: 16px;      margin-bottom: 8px;      width: 100%;    }    .tg-df-skeleton-text.short { width: 40%; }    .tg-df-skeleton-text.title { height: 20px; margin-bottom: 16px; }    /* Editor Floating Bar & Elements */    .tg-df-editor-bar {      position: sticky;      top: 0;      z-index: 1000;      background: #111827;      color: #fff;      padding: 12px 16px;      border-radius: 8px;      margin-bottom: 16px;      display: flex;      align-items: center;      justify-content: space-between;      box-shadow: 0 4px 12px rgba(0,0,0,0.15);    }    .tg-df-editor-bar-text {      font-weight: 600;      font-size: 14px;    }    .tg-df-editor-copy-btn {      background: #10b981;      color: #fff;      padding: 6px 16px;      border: none;      border-radius: 4px;      font-weight: 600;      cursor: pointer;      display: flex;      align-items: center;      font-size: 13px;    }    .tg-df-editor-copy-btn:hover { background: #059669; }        .tg-df-deal-checkbox {      position: absolute;      top: 12px;      right: 12px;      z-index: 10;      width: 20px;      height: 20px;      cursor: pointer;      pointer-events: auto;    }    /*       6. Mobile List View (Stacks into a cleaner horizontal row/list)    */    @container tg-df (max-width: 599px) {      .tg-df-controls {        padding: 0 16px;      }            .tg-df-top-bar {        width: 100%;      }            .tg-df-settings-dropdown {        position: fixed;        top: auto;        bottom: 0;        left: 0;        right: 0;        width: 100%;        border-radius: 20px 20px 0 0;        padding: 24px;        box-shadow: 0 -8px 32px rgba(0,0,0,0.15);        z-index: 1000;        border: none;        border-top: 1px solid var(--tg-df-border);      }            .tg-df-settings-dropdown-backdrop.active {        background: rgba(0,0,0,0.4);      }            .tg-df-search-wrapper {        box-shadow: 0 0 16px rgba(0,0,0,0.08);      }            .tg-df-filters {        width: calc(100% + 32px);        margin: 0 -16px;        padding: 0 16px 4px 16px;        display: flex;        justify-content: flex-start;        gap: 8px;        flex-wrap: nowrap;        overflow-x: auto;        -webkit-overflow-scrolling: touch;        scrollbar-width: none;      }      .tg-df-filters::after {        content: "";        display: block;        flex: 0 0 8px;      }      .tg-df-filters::-webkit-scrollbar {        display: none;      }            .tg-df-sort-wrapper {        flex: 0 0 max(42%, 130px);        min-width: 0;      }      .tg-df-sort-wrapper.tg-df-price-range-wrapper {        flex: 0 0 auto;        min-width: max-content;      }            .tg-df-sort-select, .tg-df-filter-select {        width: 100%;        text-align: left;        padding: 10px 24px 10px 32px;        background-position: right 8px center;        text-overflow: ellipsis;        white-space: nowrap;        overflow: hidden;      }      .tg-df-sort-icon {        left: 10px;      }      .tg-df-grid:not(.layout-grid):not(.layout-row),      .tg-df-grid.layout-row {        grid-template-columns: 1fr;        gap: 16px;      }            .tg-df-grid.tg-df-grid-auto {        padding-top: 24px;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card,      .tg-df-grid.layout-row .tg-df-card {        flex-direction: row;        align-items: stretch;        height: auto;        box-shadow: none; /* simple line on mobile if preferred, or keep */        border-bottom: 1px solid var(--tg-df-border);      }      .tg-df-grid.tg-df-grid-auto .tg-df-card:hover,      .tg-df-grid.layout-row .tg-df-card:hover {        box-shadow: none;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-image-box,      .tg-df-grid.layout-row .tg-df-card-image-box {        width: 120px;        min-width: 120px;        aspect-ratio: 3/4;        border-right: none;        padding: 12px;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-body,      .tg-df-grid.layout-row .tg-df-card-body {        padding: 12px;        justify-content: space-between;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-title,      .tg-df-grid.layout-row .tg-df-card-title {        font-size: 14px;        margin-bottom: 12px;        -webkit-line-clamp: 3;      }      /* Single column mobile grid override */      .tg-df-grid.layout-grid {        grid-template-columns: 1fr;        gap: 16px;      }      .tg-df-grid.layout-grid .tg-df-card-image-box {        padding: 12px;      }      .tg-df-grid.layout-grid .tg-df-card-body {        padding: 10px;      }      .tg-df-grid.layout-grid .tg-df-card-title {        font-size: 13px;        -webkit-line-clamp: 3;        margin-bottom: 8px;      }      .tg-df-grid.layout-grid .tg-df-card-price {        font-size: 14px;      }            .tg-df-card-footer {        flex-direction: column;        align-items: stretch;        gap: 0;        width: 100%;        min-width: 0;      }      .tg-df-card-merchant-pill {        margin-bottom: 4px;      }      .tg-df-card-price-group {        flex: 1 1 auto;        margin-bottom: 8px;      }      .tg-df-card-price {        font-size: 16px;      }      .tg-df-card-msrp {        display: block;       }      .tg-df-grid.layout-row .tg-df-card-cta,      .tg-df-container .tg-df-card-cta {        width: 100%;        max-width: none;        min-width: 0;        box-sizing: border-box;        padding: 8px 16px;        font-size: 12px;        flex: 0 0 auto;        text-align: center;        white-space: normal;        line-height: 1.2;      }    }    .tg-df-container.is-carousel {      min-height: 760px;      background-color: #E7F0FF;      padding: 0 0 24px 0;      border-radius: 24px;    }    .tg-df-container.is-carousel.hide-header-details {      min-height: 480px;    }    /*       7. Carousel View Mode    */    .tg-df-container .tg-df-carousel-host {      /* Layout is now handled by container wrapper */    }    .tg-df-container .tg-df-carousel-eyebrow {      color: #1F69FF;      font-weight: 700;      font-size: 14px;      text-transform: uppercase;      letter-spacing: 1px;      padding: 24px 16px 0 16px;      display: none;    }    .tg-df-container .tg-df-carousel-query-title {      color: #011535;      font-size: 28px;      font-weight: 600;      padding: 0 16px 24px 16px;      line-height: 1.2;      display: none;    }    .tg-df-container .tg-df-carousel-blue-box {      background-color: transparent;      border-radius: 0;      padding: 24px 24px 0 24px;      margin: 0;      color: #1F69FF;          position: relative;      overflow: hidden;    }    .tg-df-container .tg-df-carousel-bg-circle-1 {      display: none;    }    .tg-df-container .tg-df-carousel-bg-circle-2 {      display: none;    }    .tg-df-container .tg-df-carousel-bg-circle-3 {      display: none;    }    .tg-df-container .tg-df-carousel-box-content {      position: relative;      z-index: 10;    }    .tg-df-container .tg-df-carousel-box-eyebrow {      background-color: transparent;      color: #1F69FF;      font-weight: 700;      font-size: 14px;      text-transform: uppercase;      letter-spacing: 1px;      display: inline-block;      padding: 0;      border-radius: 0;    }    .tg-df-container .tg-df-carousel-box-title {      font-size: 28px;      font-weight: 600;      line-height: 1.2;      margin-top: 8px;      color: #1e293b;    }    .tg-df-container .tg-df-countdown-wrapper {      position: absolute;      top: 0;      right: 0;      display: flex;      flex-direction: column;      align-items: flex-end;      gap: 12px;      transform: scale(0.67);      transform-origin: top right;    }    .tg-df-container .tg-df-countdown-title {      font-size: 16px;      text-align: center;      width: 100%;      font-weight: 600;      color: #011535;      margin: 0;    }    .tg-df-container .tg-df-countdown-blocks {      display: flex;      gap: 16px;    }    .tg-df-container .tg-df-countdown-item {      display: flex;      flex-direction: column;      align-items: center;      gap: 4px;    }    .tg-df-container .tg-df-countdown-box {      width: 59px;      height: 59px;      background: #03FE9E;      border-radius: 15px;      display: flex;      align-items: center;      justify-content: center;    }    .tg-df-container .tg-df-countdown-num {      font-family: 'Inter', sans-serif;      font-weight: 700;      font-size: 20px;      line-height: normal;      color: #011535;    }    .tg-df-container .tg-df-countdown-label {      font-family: 'Inter', sans-serif;      font-weight: 500;      font-size: 16px;      line-height: normal;      color: #1e293b;      text-transform: uppercase;    }    .tg-df-container .tg-df-carousel-box-subtitle {      font-size: 16px;      margin-top: 8px;      font-weight: 300;      color: #1e293b;      line-height: 24px;    }    .tg-df-container .tg-df-carousel-roundels-wrapper {      position: relative;      margin-top: 24px;      margin-left: -24px;      margin-right: -24px;    }    .tg-df-container .tg-df-carousel-roundels {      display: flex;      gap: 16px;      overflow-x: auto;            scrollbar-width: none;      padding-top: 12px;      padding-bottom: 24px;      padding-left: 24px;      padding-right: 24px;      margin-left: 0;      margin-right: 0;    }        .tg-df-container .tg-df-carousel-scroll-left,    .tg-df-container .tg-df-carousel-scroll-right {      position: absolute;      top: 50%;      transform: translateY(-50%);      height: 36px;      width: 36px;      display: flex;      align-items: center;      justify-content: center;      border-radius: 50%;      background-color: #ffffff;      border: 1px solid #e2e8f0;      box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);      color: #1F69FF;      cursor: pointer;      transition: all 0.2s;      margin-top: -4px;      z-index: 20;    }    .tg-df-container .tg-df-carousel-scroll-left { left: 8px; }    .tg-df-container .tg-df-carousel-scroll-right { right: 8px; }    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-left { left: 0px; }    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-right { right: 0px; }    .tg-df-carousel-filters-outer { margin-left: -24px; margin-right: -24px; padding-left: 24px; padding-right: 24px; }    @container tg-df (max-width: 599px) { .tg-df-carousel-filters-outer { margin-left: -16px; margin-right: -16px; padding-left: 16px; padding-right: 16px; } }        .tg-df-container .tg-df-carousel-scroll-left:hover,    .tg-df-container .tg-df-carousel-scroll-right:hover {      background-color: #f8fafc;      border-color: #cbd5e1;    }        .tg-df-carousel-roundels-wrapper .tg-df-carousel-scroll-left,    .tg-df-carousel-roundels-wrapper .tg-df-carousel-scroll-right,    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-left,    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-right {      background-color: rgba(255, 255, 255, 0.4);      border: none;      box-shadow: none;      backdrop-filter: blur(4px);      -webkit-backdrop-filter: blur(4px);    }    .tg-df-carousel-roundels-wrapper .tg-df-carousel-scroll-left { left: 0; }    .tg-df-carousel-roundels-wrapper .tg-df-carousel-scroll-right { right: 0; }    .tg-df-grid-wrapper .tg-df-carousel-scroll-left { left: 0; }    .tg-df-grid-wrapper .tg-df-carousel-scroll-right { right: 0; }        .tg-df-carousel-roundels-wrapper .tg-df-carousel-scroll-left:hover,    .tg-df-carousel-roundels-wrapper .tg-df-carousel-scroll-right:hover {      background-color: rgba(255, 255, 255, 0.6);      border: none;    }    .tg-df-container .tg-df-carousel-roundels::-webkit-scrollbar {      display: none;    }    .tg-df-container .tg-df-carousel-roundels::after {      content: "";      flex: 0 0 32px;    }    .tg-df-container .tg-df-roundel {      display: flex;      flex-direction: column;      align-items: center;      gap: 8px;      cursor: pointer;      min-width: 120px;      flex-shrink: 0;    }    .tg-df-container .tg-df-roundel-img-box {      width: 120px;      height: 120px;      border-radius: 50%;      background: white;      display: flex;      align-items: center;      justify-content: center;      overflow: hidden;      box-shadow: 0px 3px 14px 0px rgba(30, 41, 59, 0.08);      transition: box-shadow 0.2s;    }    .tg-df-container .tg-df-roundel:hover .tg-df-roundel-img-box {      box-shadow: 0 0 0 2px #E7F0FF, 0 0 0 4px #1F69FF;    }    .tg-df-container .tg-df-roundel.active .tg-df-roundel-img-box {      box-shadow: 0 0 0 2px #E7F0FF, 0 0 0 4px #1F69FF;    }    .tg-df-container .tg-df-roundel:hover .tg-df-roundel-img-box img {      transform: scale(1.08);    }    .tg-df-container .tg-df-roundel-img-box img {      width: 100%;      height: 100%;      object-fit: contain;      padding: 10px;      box-sizing: border-box;      transition: transform 0.3s ease;    }    .tg-df-container .tg-df-roundel-label {      font-size: 13px;      font-weight: 400;      color: #1e293b;      text-align: center;      transition: font-weight 0.2s;    }    .tg-df-container .tg-df-roundel.active .tg-df-roundel-label {      font-weight: 700;    }    .tg-df-container .tg-df-carousel-filters-label {      font-size: 16px;      font-weight: 400;      color: #1e293b;      white-space: nowrap;      margin-right: 4px;    }    .tg-df-container .tg-df-carousel-filters-wrap {      display: flex;      align-items: center;      flex-wrap: nowrap;      gap: 8px;      margin-top: 8px;      overflow-x: auto;      scrollbar-width: none;      -webkit-overflow-scrolling: touch;      padding-bottom: 8px;      margin-left: -24px;      margin-right: -24px;      padding-left: 24px;      padding-right: 24px;    }    .tg-df-container .tg-df-carousel-filters-wrap::-webkit-scrollbar {      display: none;    }        .tg-df-container .tg-df-carousel-filter-btn img,    .tg-df-container .tg-df-carousel-filter-btn picture {      height: 20px;      width: 20px;      object-fit: contain;      object-position: center;      display: inline-flex;      align-items: center;      justify-content: center;      margin-right: 6px;    }    .tg-df-container .tg-df-carousel-filter-btn picture img {      margin-right: 0;      height: 100%;      width: 100%;    }    .tg-df-container .tg-df-carousel-filter-btn img.active-img,    .tg-df-container .tg-df-carousel-filter-btn picture:has(.active-img) {      display: none;    }    .tg-df-container .tg-df-carousel-filter-btn:hover img.inactive-img,    .tg-df-container .tg-df-carousel-filter-btn.active img.inactive-img,    .tg-df-container .tg-df-carousel-filter-btn:hover picture:has(.inactive-img),    .tg-df-container .tg-df-carousel-filter-btn.active picture:has(.inactive-img) {      display: none;    }    .tg-df-container .tg-df-carousel-filter-btn:hover img.active-img,    .tg-df-container .tg-df-carousel-filter-btn.active img.active-img,    .tg-df-container .tg-df-carousel-filter-btn:hover picture:has(.active-img),    .tg-df-container .tg-df-carousel-filter-btn.active picture:has(.active-img) {      display: inline-flex;    }    .tg-df-container .tg-df-carousel-filter-btn {      background: #ffffff;      border: 2px solid #1e293b;      color: #1e293b;      border-radius: 24px;      padding: 6px 16px;      font-size: 14px;      font-weight: 600;      cursor: pointer;      transition: all 0.2s;      flex-shrink: 0;      white-space: nowrap;      display: inline-flex;      align-items: center;      justify-content: center;      min-height: 36px;      box-sizing: border-box;    }    .tg-df-container .tg-df-carousel-filter-btn svg {      margin-right: 6px;    }    .tg-df-container .tg-df-carousel-filter-btn:hover {      background: #1e293b;      color: white;      border-color: #1e293b;    }    .tg-df-container .tg-df-carousel-filter-btn.active {      background: #1e293b;      color: white;      border-color: #1e293b;    }        .tg-df-grid.carousel-compact {      display: flex;      flex-wrap: nowrap;      overflow-x: auto;      gap: 16px;      padding: 16px 24px;      align-items: stretch;      scrollbar-width: none;    }    .tg-df-grid.carousel-compact::after {      content: "";      flex: 0 0 32px;    }    .tg-df-grid-wrapper {      position: relative;    }    .tg-df-grid.carousel-compact::-webkit-scrollbar {      display: none;    }    .tg-df-grid.carousel-compact .tg-df-load-more-card {      flex: 0 0 auto;      width: 100px;      border-radius: 15px;      box-shadow: 0 0 16px rgba(0,0,0,0.08);      border: 2px solid #1e293b;      background: white;      color: #1e293b;      display: flex;      flex-direction: column;      justify-content: center;      align-items: center;      font-weight: 600;      font-size: 14px;      cursor: pointer;      padding: 16px;      text-align: center;      transition: all 0.2s;    }    .tg-df-grid.carousel-compact .tg-df-load-more-card:hover {      background: #1e293b;      color: white;    }    .tg-df-grid.carousel-compact .tg-df-card {      flex: 0 0 auto;      width: 200px;      min-height: auto;      height: auto;      display: flex;      flex-direction: column;      border-radius: 15px;      border: none;      box-shadow: 0 0 16px rgba(0,0,0,0.08);      overflow: visible;    }    .tg-df-grid.carousel-compact .tg-df-card-image-box {      padding: 12px;      background-color: transparent;      border-radius: 15px 15px 0 0;      height: 130px;    }    .tg-df-grid.carousel-compact .tg-df-card-image {      mix-blend-mode: normal;    }    .tg-df-grid.carousel-compact .tg-df-card-discount-badge {      border-radius: 0;      top: 0px;      left: 0px;      padding: 4px 8px;      font-size: 11px;    }    .tg-df-grid.carousel-compact .tg-df-card-body {      padding: 8px 12px 12px 12px;    }    .tg-df-grid.carousel-compact .tg-df-card-title {      font-size: 14px;      font-weight: 400;      -webkit-line-clamp: 2;      margin-bottom: 8px;      color: #011535;    }    .tg-df-grid.carousel-compact .tg-df-card-body:not(:has(.tg-df-card-stars)):not(:has(.tg-df-tag-prime)):not(:has(.tg-df-coupon-wrapper:not([style*="none"]))) > .tg-df-card-title,    .tg-df-grid.carousel-compact .tg-df-card-body:not(:has(.tg-df-card-stars)):has(> .tg-df-card-title:first-child) > .tg-df-card-title {      -webkit-line-clamp: 3;    }    .tg-df-grid.carousel-compact .tg-df-card-cta {      border-radius: 5px;      padding: 8px 10px;      margin-top: 4px;      background-color: #1F69FF;    }    .tg-df-grid.carousel-compact .tg-df-card-price-group {      margin-bottom: 2px;    }    .tg-df-grid.carousel-compact .tg-df-card-merchant-pill {      margin-bottom: 2px;    }    @container tg-df (max-width: 599px) {      .tg-df-container .tg-df-carousel-blue-box-title {        font-size: 24px;      }      .tg-df-container .tg-df-countdown-title {        display: none;      }      .tg-df-container .tg-df-countdown-wrapper {        position: absolute;        top: 0;        right: 0;        align-items: flex-end;        transform: scale(0.45);        transform-origin: top right;      }      .tg-df-container .tg-df-roundel {        min-width: 88px;      }      .tg-df-container .tg-df-roundel-img-box {        width: 88px;        height: 88px;      }    }    /* REPLICA BLOCK STYLES */    .tg-df-grid.layout-replica-2 { grid-template-columns: repeat(2, 1fr) !important; gap: 20px; }    .tg-df-grid.layout-replica-1 { grid-template-columns: 1fr !important; gap: 20px; }        .tg-df-container .hawk-deal-widget-container { border-bottom: 1px solid #e5e7eb; display: flex; flex-direction: column; margin: 0; padding: 20px 0; box-sizing: border-box; font-family: inherit; }    .tg-df-container .hawk-deal-widget-wrap { display: flex; flex-direction: row; align-items: flex-start; width: 100%; gap: 24px; }    .tg-df-container .hawk-deal-widget-image-container { display: flex; flex-shrink: 0; justify-content: center; width: 160px; height: 160px; align-items: center; background: white; margin-bottom: 0px; }    .tg-df-container .hawk-deal-widget-title-product-title { color: #111827; font-size: 18px; font-weight: 700; line-height: 1.4; display: inline; }    .tg-df-container .hawk-deal-widget-title-price { font-size: 18px; font-weight: 700; line-height: 1.4; white-space: nowrap; color: #2563eb; }    .tg-df-container .hawk-deal-widget-title-price-now { font-weight: 700; }    .tg-df-container .hawk-deal-widget-title-retailer-price:hover { text-decoration: underline; }    .tg-df-container .hawk-deal-widget-title-retailer { font-size: 18px; font-weight: 700; line-height: 1.4; color: #2563eb; }    .tg-df-container .hawk-deal-widget-title-was-price { color: #dc2626; font-size: 16px; font-weight: 500; line-height: 1.4; text-decoration: line-through; white-space: nowrap; margin-left: 8px; margin-right: 8px; }    .tg-df-container .hawk-deal-widget-text-body-container { position: relative; width: 100%; box-sizing: border-box; }    .tg-df-container .hawk-deal-widget-text-body-main { font-size: 16px; width: 100%; margin-bottom: 12px; }    .tg-df-container .hawk-deal-widget-text-body-description { display: block; font-size: 15px; margin-top: 12px; color: #4b5563; line-height: 1.6; }    .tg-df-container .hawk-deal-widget-text-body-description p { margin: 0; line-height: 1.6; }    .tg-df-container .hawk-deal-widget-text-cta-container { display: flex; flex-direction: column; gap: 12px; width: 100%; flex: 1; min-width: 0; box-sizing: border-box; }    .tg-df-container .hawk-deal-widget-footer { display: flex; justify-content: flex-end; width: 100%; margin-top: auto; }    .tg-df-container .hawk-deal-widget-button-wrapper { display: flex; flex-direction: column; align-items: flex-end; justify-content: flex-end; width: 100%; }    .tg-df-container .hawk-deal-widget-preferred-partner-wrapper { display: flex; flex-direction: row; }        @container tg-df (min-width: 600px) {      .tg-df-mobile-only { display: none !important; }    }    @container tg-df (max-width: 599px) {      .tg-df-desktop-only { display: none !important; }      .tg-df-grid.layout-replica-2 { grid-template-columns: 1fr !important; }      .tg-df-grid.savings-squad-cards { grid-template-columns: 1fr !important; display: flex; flex-direction: column; }    }    .tg-df-grid.savings-squad-cards .tg-df-card-title {      -webkit-line-clamp: unset !important;      display: block !important;      overflow: visible !important;    }    @container tg-df (max-width: 500px) {      .tg-df-container .hawk-deal-widget-wrap { display: block; }      .tg-df-container .hawk-deal-widget-image-container { display: block; float: left; margin: 0 16px 8px 0; width: 120px; max-width: 120px; height: auto; align-items: normal; justify-content: normal; }      .tg-df-container .hawk-deal-widget-text-cta-container { display: block; text-align: left; }      .tg-df-container .hawk-deal-widget-footer { display: block; margin-top: 16px; clear: both; width: 100%; }      .tg-df-container .hawk-deal-widget-button-wrapper { display: block; width: 100%; }      .tg-df-container .hawk-deal-widget-button-wrapper .hawk-deal-widget-preferred-partner-wrapper { display: block; width: 100%; }      .tg-df-container .hawk-affiliate-link-deal-button { box-sizing: border-box !important; display: flex !important; max-width: none !important; width: 100% !important; margin: 0 !important; }    }        .tg-df-container .hawk-affiliate-link-deal-button {       align-items: center; background-color: #5aaf0b; box-sizing: border-box; color: #ffffff !important; display: flex; font-size: 14px; font-weight: 700; justify-content: center; letter-spacing: 0.5px; line-height: 1; min-width: 160px; padding: 14px 24px; text-align: center; text-decoration: none; text-transform: uppercase; width: 100%; word-break: normal; border-radius: 4px; border: 0; transition: background-color 0.2s;     }    .tg-df-container .hawk-affiliate-link-deal-button:hover { background-color: #4a9109; text-decoration: none; }    .tg-df-container .hawk-lazy-image-deal-widget { display: block; height: auto; margin: auto; max-height: 160px; max-width: 100%; mix-blend-mode: multiply; object-fit: contain; }    .tg-df-container .hawk-deal-widget-text-cta-container a { color: #2563eb; text-decoration: none; display: inline; }    .tg-df-container .hawk-deal-widget-text-cta-container a:hover { text-decoration: underline; }    .tg-df-container .hawk-deal-widget-text-cta-container a:has(.hawk-deal-widget-title-product-title) { color: #111827; }    .tg-df-container .hawk-deal-widget-text-cta-container a:hover .hawk-deal-widget-title-product-title,    .tg-df-container .hawk-deal-widget-text-cta-container a:hover .hawk-deal-widget-title-retailer-price { text-decoration: underline; }  \x3C/style>  \x3C!-- Widget Container --\x3E  \x3Cdiv class="tg-df-container" id="signal-deals-finder-root">    \x3C!-- Editor Floating Bar --\x3E    \x3Cdiv class="tg-df-editor-bar" id="tg-df-editor-bar" style="display:none;">      \x3Cdiv class="tg-df-editor-bar-text" style="display: flex; align-items: center;">        \x3Cspan id="tg-df-selected-count">0\x3C/span>\x26nbsp;Deals Selected        \x3Cbutton class="tg-df-editor-clear-btn" id="tg-df-editor-clear" type="button" style="margin-left: 12px; font-size: 13px; color: #9ca3af; background: none; border: none; cursor: pointer; text-decoration: underline;">Clear All\x3C/button>      \x3C/div>      \x3Cbutton class="tg-df-editor-copy-btn" id="tg-df-editor-copy" type="button">        \x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2">\x3C/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1">\x3C/path>\x3C/svg>        Copy to CMS      \x3C/button>    \x3C/div>    \x3Cdiv class="tg-df-carousel-host" id="tg-df-carousel-host" style="display: none;">      \x3Cdiv class="tg-df-carousel-eyebrow">DEAL FINDER\x3C/div>      \x3Cdiv class="tg-df-carousel-query-title" id="tg-df-carousel-title-label">Best Deals\x3C/div>            \x3Cdiv class="tg-df-carousel-blue-box">        \x3Cdiv class="tg-df-carousel-bg-circle-1" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-bg-circle-2" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-bg-circle-3" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-box-content">          \x3Cdiv class="tg-df-countdown-wrapper" id="tg-df-countdown-wrapper" style="display:none;">            \x3Cdiv class="tg-df-countdown-title" id="tg-df-countdown-title">Prime Day starts in\x3C/div>            \x3Cdiv class="tg-df-countdown-blocks">              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-days">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">DAYS\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-hrs">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">HRS\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-min">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">MIN\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-sec">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">SEC\x3C/div>\x3C/div>            \x3C/div>          \x3C/div>          \x3Cdiv class="tg-df-carousel-box-eyebrow">DEAL FINDER\x3C/div>          \x3Cdiv class="tg-df-carousel-box-title">Find Deals Fast\x3C/div>          \x3Cdiv class="tg-df-carousel-box-subtitle">The latest deals from the biggest retailers, all in one place\x3C/div>                    \x3Cdiv class="tg-df-carousel-roundels-wrapper">          \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-roundels').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>          \x3Cdiv class="tg-df-carousel-roundels">            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>          \x3C/div>          \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" onclick="this.parentElement.querySelector('.tg-df-carousel-roundels').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>        \x3C/div>        \x3Cdiv class="tg-df-carousel-filters-outer" style="position: relative;">          \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-filters-wrap').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>          \x3Cdiv class="tg-df-carousel-filters-wrap">                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="0">All\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-ot="amazon_lightning">              \x3Cimg src="https://cdn.mos.cms.futurecdn.net/HqAui7w97ft2NPqBtQ5r38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/yWPQ5yyQRhUwVKzGwYbh38-600-100.png" class="active-img" alt="" /> Lightning deals\x3C/button>            \x3Cbutton class="tg-df-carousel-filter-btn" data-ot="amazon_prime">              \x3Cimg src="https://cdn.mos.cms.futurecdn.net/fwoVXvL79turN3Ph535m38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/u75QjVpt3w2EsMimJiRo38-600-100.png" class="active-img" alt="" /> Prime deals\x3C/button>            \x3Cbutton class="tg-df-carousel-filter-btn" data-d="10">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 10% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="15">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 15% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="25">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 25% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-pr="under50">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-badge-dollar-sign">\x3Cpath d="M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z">\x3C/path>\x3Cpath d="M16 8h-6a2 2 0 1 0 0 4h4a2 2 0 1 1 0 4H8">\x3C/path>\x3Cpath d="M12 18V6">\x3C/path>\x3C/svg>            Under $50\x3C/button>        \x3C/div>        \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-filters-wrap').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>      \x3C/div>    \x3C/div>    \x3C/div>      \x3C!-- Search & Filter Controls --\x3E    \x3Cdiv class="tg-df-controls" id="tg-df-controls" style="display:flex;">      \x3Cdiv class="tg-df-top-bar">        \x3Cdiv class="tg-df-search-wrapper">          \x3Cinput type="text" class="tg-df-search-input" placeholder="Search for deals, products, or brands...">          \x3Cbutton type="button" class="tg-df-search-btn" aria-label="Search">              \x3Csvg class="tg-df-search-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">                \x3Cpath d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/>              \x3C/svg>          \x3C/button>          \x3Cdiv class="tg-df-autocomplete-dropdown" id="tg-df-autocomplete">\x3C/div>        \x3C/div>                \x3Cdiv class="tg-df-settings-wrapper">          \x3Cbutton type="button" class="tg-df-settings-btn" aria-label="Settings" id="tg-df-settings-toggle">            \x3Csvg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="20" height="20">                \x3Cpath d="M19.14 12.94c.04-.3.06-.61.06-.94 0-.32-.02-.64-.06-.94l2.03-1.58c.18-.14.23-.41.12-.61l-1.92-3.32c-.12-.22-.37-.29-.59-.22l-2.39.96c-.5-.38-1.03-.7-1.62-.94l-.36-2.54c-.04-.24-.24-.41-.48-.41h-3.84c-.24 0-.43.17-.47.41l-.36 2.54c-.59.24-1.13.57-1.62.94l-2.39-.96c-.22-.08-.47 0-.59.22L2.73 8.87c-.12.21-.08.47.12.61l2.03 1.58c-.05.3-.09.63-.09.94s.02.64.06.94l-2.03 1.58c-.18.14-.23.41-.12.61l1.92 3.32c.12.22.37.29.59.22l2.39-.96c.5.38 1.03.7 1.62.94l.36 2.54c.05.24.24.41.48.41h3.84c.24 0 .43-.17.47-.41l.36-2.54c.59-.24 1.13-.56 1.62-.94l2.39.96c.22.08.47 0 .59-.22l1.92-3.32c.12-.22.07-.49-.12-.61l-2.01-1.58zM12 15.6c-1.98 0-3.6-1.62-3.6-3.6s1.62-3.6 3.6-3.6 3.6 1.62 3.6 3.6-1.62 3.6-3.6 3.6z"/>            \x3C/svg>          \x3C/button>          \x3Cdiv class="tg-df-settings-dropdown-backdrop" id="tg-df-settings-backdrop">\x3C/div>          \x3Cdiv class="tg-df-settings-dropdown" id="tg-df-settings-panel">            \x3Cdiv class="tg-df-setting-item">              \x3Clabel class="tg-df-setting-label">Search Region\x3C/label>              \x3Cselect class="tg-df-region-select" id="tg-df-region-select">                \x3Coption value="auto">🌍 Auto-detect\x3C/option>                \x3Coption value="US">🇺🇸 United States (US)\x3C/option>                \x3Coption value="GB">🇬🇧 United Kingdom (UK)\x3C/option>                \x3Coption value="CA">🇨🇦 Canada (CA)\x3C/option>                \x3Coption value="AU">🇦🇺 Australia (AU)\x3C/option>                \x3Coption value="DE">🇩🇪 Germany (DE)\x3C/option>                \x3Coption value="FR">🇫🇷 France (FR)\x3C/option>                \x3Coption value="IT">🇮🇹 Italy (IT)\x3C/option>              \x3C/select>            \x3C/div>            \x3Cdiv class="tg-df-setting-item">              \x3Clabel class="tg-df-setting-label">Retailer\x3C/label>              \x3Cselect class="tg-df-region-select" id="tg-df-retailer-select">                \x3Coption value="">All Retailers\x3C/option>                \x3Coption value="Amazon">Amazon\x3C/option>                \x3Coption value="Walmart">Walmart\x3C/option>                \x3Coption value="Best Buy">Best Buy\x3C/option>                \x3Coption value="Target">Target\x3C/option>                \x3Coption value="John Lewis">John Lewis\x3C/option>                \x3Coption value="Currys">Currys\x3C/option>                \x3Coption value="Argos">Argos\x3C/option>              \x3C/select>            \x3C/div>            \x3Cdiv class="tg-df-setting-item">              \x3Clabel class="tg-df-setting-label">Offer Type\x3C/label>              \x3Cselect class="tg-df-region-select" id="tg-df-offer-type-select">                \x3Coption value="">All Offers\x3C/option>                \x3Coption value="amazon_prime">Amazon Prime\x3C/option>                \x3Coption value="recommended_promo">Recommended Promo\x3C/option>                \x3Coption value="amazon_lightning">Amazon Lightning Deal\x3C/option>              \x3C/select>            \x3C/div>            \x3Cdiv class="tg-df-setting-item">              \x3Clabel class="tg-df-setting-label">Result Count\x3C/label>              \x3Cselect class="tg-df-region-select" id="tg-df-rows-select">                \x3Coption value="3">3 Items\x3C/option>                \x3Coption value="4">4 Items\x3C/option>                \x3Coption value="6">6 Items\x3C/option>                \x3Coption value="12" selected>12 Items\x3C/option>                \x3Coption value="24">24 Items\x3C/option>                \x3Coption value="48">48 Items\x3C/option>              \x3C/select>            \x3C/div>            \x3Cdiv class="tg-df-setting-item tg-df-dl-row">              \x3Cdiv>                \x3Cspan class="tg-df-dl-row-text">Deal Mode\x3C/span>                \x3Cspan class="tg-df-dl-row-subtext">Only show products with active offers or previous prices (was_price)\x3C/span>              \x3C/div>              \x3Clabel class="tg-df-toggle">                \x3Cinput type="checkbox" id="tg-df-deal-mode">                \x3Cspan class="tg-df-slider">\x3C/span>              \x3C/label>            \x3C/div>            \x3Cdiv class="tg-df-setting-item tg-df-dl-row">              \x3Cdiv>                \x3Cspan class="tg-df-dl-row-text">Editor Mode\x3C/span>                \x3Cspan class="tg-df-dl-row-subtext">Enable multi-select to copy deals to CMS\x3C/span>              \x3C/div>              \x3Clabel class="tg-df-toggle">                \x3Cinput type="checkbox" id="tg-df-editor-mode">                \x3Cspan class="tg-df-slider">\x3C/span>              \x3C/label>            \x3C/div>            \x3Cdiv class="tg-df-setting-item">              \x3Clabel class="tg-df-setting-label">View Mode\x3C/label>              \x3Cselect class="tg-df-region-select" id="tg-df-view-mode-select">                \x3Coption value="auto">Auto Collection\x3C/option>                \x3Coption value="carousel">Carousel\x3C/option>                \x3Coption value="savings_squad">Savings Squad\x3C/option>                \x3Coption value="grid">Grid (Columns)\x3C/option>                \x3Coption value="row">Row (List)\x3C/option>              \x3C/select>            \x3C/div>          \x3C/div>        \x3C/div>      \x3C/div>      \x3Cdiv class="tg-df-filters">        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-category-filter-wrapper" style="display: none;">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-category-filter" aria-label="Category">            \x3Coption value="all">All Categories\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper tg-df-multiselect-container" id="tg-df-brand-filter-wrapper" style="display:none;">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M4.25 5.61C6.27 8.2 10 13 10 13v6c0 .55.45 1 1 1h2c.55 0 1-.45 1-1v-6s3.72-4.8 5.74-7.39A.998.998 0 0 0 18.95 4H5.04c-.83 0-1.3.95-.79 1.61z"/>          \x3C/svg>          \x3Cdiv class="tg-df-filter-select tg-df-multiselect-trigger" id="tg-df-brand-trigger" tabindex="0">            Any Brand          \x3C/div>          \x3Cdiv class="tg-df-multiselect-dropdown" id="tg-df-brand-dropdown">            \x3C!-- Populated via script --\x3E          \x3C/div>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M9 3L5 6.99h3V14h2V6.99h3L9 3zm7 14.01V10h-2v7.01h-3L15 21l4-3.99h-3z"/>          \x3C/svg>          \x3Cselect class="tg-df-sort-select" aria-label="Sort Deals">            \x3Coption value="date_desc">Newest First\x3C/option>            \x3Coption value="best_match">Sort by: Match\x3C/option>            \x3Coption value="price_asc">Price Low to High\x3C/option>            \x3Coption value="price_desc">Price High to Low\x3C/option>            \x3Coption value="discount_desc">Biggest Discount\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper tg-df-price-range-wrapper" id="tg-df-custom-price-wrapper" style="display: flex; align-items:center; justify-content:center; padding: 10px 20px; gap: 8px; border: 1px solid var(--tg-df-border); border-radius: 100px; background-color: var(--tg-df-bg);">          \x3Cspan style="font-size:14px; font-weight:500; color:var(--tg-df-text-primary);">Price\x3C/span>          \x3Cinput type="number" class="tg-df-price-input" id="tg-df-custom-price-min" placeholder="Min" style="width: 48px; background: transparent; border: none; color: var(--tg-df-text-primary); outline: none; font-size: 14px; text-align: center; padding: 0;">          \x3Cspan style="color:var(--tg-df-text-muted)">-\x3C/span>          \x3Cinput type="number" class="tg-df-price-input" id="tg-df-custom-price-max" placeholder="Max" style="width: 48px; background: transparent; border: none; color: var(--tg-df-text-primary); outline: none; font-size: 14px; text-align: center; padding: 0;">        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-legacy-price-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58.55 0 1.05-.22 1.41-.59l7-7c.37-.36.59-.86.59-1.41 0-.55-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-price-filter" aria-label="Filter Prices">            \x3Coption value="all">All Prices\x3C/option>            \x3Coption value="under50">Under $50\x3C/option>            \x3Coption value="50_100">$50 - $100\x3C/option>            \x3Coption value="100_200">$100 - $200\x3C/option>            \x3Coption value="200_500">$200 - $500\x3C/option>            \x3Coption value="over500">Over $500\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-discount-filter-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">            \x3Cpath d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58.55 0 1.05-.22 1.41-.59l7-7c.37-.36.59-.86.59-1.41 0-.55-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-discount-filter" aria-label="Discount Amount">            \x3Coption value="all">Any discount\x3C/option>            \x3Coption value="5">Min 5%\x3C/option>            \x3Coption value="10">Min 10%\x3C/option>            \x3Coption value="15">Min 15%\x3C/option>            \x3Coption value="20">Min 20%\x3C/option>            \x3Coption value="25">Min 25%\x3C/option>            \x3Coption value="30">Min 30%\x3C/option>            \x3Coption value="40">Min 40%\x3C/option>            \x3Coption value="50">Min 50%\x3C/option>            \x3Coption value="60">Min 60%\x3C/option>            \x3Coption value="70">Min 70%\x3C/option>          \x3C/select>        \x3C/div>      \x3C/div>    \x3C/div>    \x3C!-- Deals Grid Wrapper --\x3E    \x3Cdiv class="tg-df-grid-wrapper tg-df-carousel-cards-wrapper" id="tg-df-grid-wrapper">      \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('#tg-df-grid').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>      \x3Cdiv class="tg-df-grid" id="tg-df-grid">        \x3C!-- Content populated by JavaScript --\x3E      \x3C/div>      \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" style="display:none;" onclick="this.parentElement.querySelector('#tg-df-grid').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>    \x3C/div>        \x3C!-- Vouchers Modal --\x3E    \x3Cdiv class="tg-df-modal-backdrop" id="tg-df-vouchers-modal">      \x3Cdiv class="tg-df-modal">        \x3Cdiv class="tg-df-modal-header">          \x3Ch3 class="tg-df-modal-title" id="tg-df-vouchers-title">Available Coupons & Deals\x3C/h3>          \x3Cbutton class="tg-df-modal-close" id="tg-df-vouchers-close">            \x3Csvg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">              \x3Cline x1="18" y1="6" x2="6" y2="18">\x3C/line>              \x3Cline x1="6" y1="6" x2="18" y2="18">\x3C/line>            \x3C/svg>          \x3C/button>        \x3C/div>        \x3Cdiv class="tg-df-modal-body" id="tg-df-vouchers-content">          \x3C!-- Vouchers injected here --\x3E        \x3C/div>      \x3C/div>    \x3C/div>  \x3C/div>`;      if (!template) {        template = document.createElement('template');        template.innerHTML = rawTemplate;      }      let shadowRoot = null;      if (hostContainer && template) {        hostContainer.setAttribute('data-initialized', 'true');        shadowRoot = hostContainer.attachShadow({ mode: 'open' });        shadowRoot.appendChild(template.content.cloneNode(true));      }      class DealsFinderWidget {        constructor(config) {          this.rootNode = config.rootNode || document;          this.hostContainer = config.hostContainer || null;          this.rootId = config.rootId || 'signal-deals-finder-root';          this.root = this.rootNode.querySelector('#' + this.rootId);          if (!this.root) return;          this.widgetId = (window.crypto && window.crypto.randomUUID) ? window.crypto.randomUUID() : 'widget-' + Date.now() + '-' + Math.random().toString(36).slice(2);          this.grid = this.root.querySelector('#tg-df-grid');          this.tagsContainer = this.root.querySelector('#tg-df-tags-container');          this.categoryFilter = this.root.querySelector('#tg-df-category-filter');          this.categoryFilterWrapper = this.root.querySelector('#tg-df-category-filter-wrapper');          this.searchInput = this.root.querySelector('.tg-df-search-input');          this.autocompleteDropdown = this.root.querySelector('#tg-df-autocomplete');          this.sortSelect = this.root.querySelector('.tg-df-sort-select');          this.searchBtn = this.root.querySelector('.tg-df-search-btn');                    this.settingsToggle = this.root.querySelector('#tg-df-settings-toggle');          this.settingsPanel = this.root.querySelector('#tg-df-settings-panel');          this.settingsBackdrop = this.root.querySelector('#tg-df-settings-backdrop');          this.regionSelect = this.root.querySelector('#tg-df-region-select');          this.retailerSelect = this.root.querySelector('#tg-df-retailer-select');          this.offerTypeSelect = this.root.querySelector('#tg-df-offer-type-select');          this.viewModeSelect = this.root.querySelector('#tg-df-view-mode-select');          this.rowsSelect = this.root.querySelector('#tg-df-rows-select');          this.dealModeToggle = this.root.querySelector('#tg-df-deal-mode');          this.editorModeToggle = this.root.querySelector('#tg-df-editor-mode');          this.priceFilter = this.root.querySelector('#tg-df-price-filter');          this.discountFilter = this.root.querySelector('#tg-df-discount-filter');                    this.editorBar = this.root.querySelector('#tg-df-editor-bar');          this.editorSelectedCount = this.root.querySelector('#tg-df-selected-count');          this.editorCopyBtn = this.root.querySelector('#tg-df-editor-copy');          this.editorClearBtn = this.root.querySelector('#tg-df-editor-clear');                    this.apiUrl = 'https://search-api.fie.future.net.uk/widget.php';          this.deals = [];          this.displayLimit = 12;          this.airedaleArticles = null;          this.airedaleTags = [];          this.airedaleTagCounts = {};          this.activeDealTag = null;          this.selectedBrands = [];          this.currentQuery = '';          this.editorMode = this.hostContainer ? this.hostContainer.hasAttribute('data-editor-mode') : false;          this.viewModeOverride = this.hostContainer ? this.hostContainer.getAttribute('data-view-mode') : null;          this.selectedDeals = new Map();                    this.brandFilterWrapper = this.root.querySelector('#tg-df-brand-filter-wrapper');          this.brandTrigger = this.root.querySelector('#tg-df-brand-trigger');          this.brandDropdown = this.root.querySelector('#tg-df-brand-dropdown');                    this.customPriceWrapper = this.root.querySelector('#tg-df-custom-price-wrapper');          this.customPriceMin = this.root.querySelector('#tg-df-custom-price-min');          this.customPriceMax = this.root.querySelector('#tg-df-custom-price-max');          this.legacyPriceWrapper = this.root.querySelector('#tg-df-legacy-price-wrapper');          this.discountFilterWrapper = this.root.querySelector('#tg-df-discount-filter-wrapper');          this.initResizeObserver();          this.init();            if (['carousel', 'carousel-compact', 'auto', 'grid', 'row'].includes(this.getViewMode())) { this.loadCarouselSpreadsheet(); }        }        getViewMode() {          if (this.viewModeOverride && (!this.editorMode || !this.viewModeSelect)) {            return this.viewModeOverride;          }          return (this.viewModeSelect && this.viewModeSelect.value) ? this.viewModeSelect.value : (this.viewModeOverride || 'auto');        }        applyLayoutMode() {          if (!this.grid) return;          const mode = this.getViewMode();          this.grid.classList.remove('layout-row', 'layout-grid', 'tg-df-grid-auto', 'carousel-compact', 'layout-replica-1', 'layout-replica-2');                    const carouselHost = this.root.querySelector('#tg-df-carousel-host');          const controlsDiv = this.root.querySelector('#tg-df-controls');          if (mode === 'carousel' || mode === 'auto' || mode === 'grid' || mode === 'row') {             if (mode === 'carousel') this.grid.classList.add('carousel-compact');             if (carouselHost) carouselHost.style.display = 'block';             if (controlsDiv) controlsDiv.style.display = 'none';             if (this.root.classList.contains('tg-df-container') && mode === 'carousel') {               this.root.classList.add('is-carousel');             } else if (this.root.classList.contains('tg-df-container')) {               this.root.classList.remove('is-carousel');             }          } else {             if (carouselHost) carouselHost.style.display = 'none';             if (controlsDiv) controlsDiv.style.display = 'flex';             if (this.root.classList.contains('tg-df-container')) {               this.root.classList.remove('is-carousel');             }          }          if (mode === 'grid') {            this.grid.classList.add('layout-grid');          } else if (mode === 'row') {            this.grid.classList.add('layout-row');          } else if (mode === 'savings_squad') {            this.grid.classList.add('tg-df-grid-auto', 'savings-squad-cards');          } else if (mode !== 'carousel') {            this.grid.classList.add('tg-df-grid-auto');          }                    const settingsWrapper = this.root.querySelector('.tg-df-settings-wrapper');          if (settingsWrapper) {            settingsWrapper.style.display = mode === 'auto' ? 'none' : 'block';          }          if (this.customPriceWrapper) {             this.customPriceWrapper.style.display = mode === 'auto' ? 'flex' : 'none';          }          if (this.legacyPriceWrapper) {             this.legacyPriceWrapper.style.display = mode === 'auto' ? 'none' : 'flex';          }          if (this.discountFilterWrapper) {             this.discountFilterWrapper.style.display = mode === 'auto' ? 'none' : 'flex';          }        }        initResizeObserver() {          try {            if (window.parent === window) return;          } catch (e) {            // cross origin frame check threw          }          const emitHeight = () => {            try {              const height = document.documentElement.scrollHeight || document.body.scrollHeight;              const msg = { type: 'embed-size', height: height };              if (window.parent && window.parent !== window) {                window.parent.postMessage(msg, '*');                window.parent.postMessage(JSON.stringify({ ...msg, sentinel: 'amp' }), '*');              }            } catch (e) {}          };                    if (window.ResizeObserver) {            try {              const ro = new ResizeObserver(() => emitHeight());              ro.observe(document.body);              if (this.root) ro.observe(this.root);            } catch(e){ console.warn(e); }          }          window.addEventListener('resize', emitHeight);          setTimeout(emitHeight, 300);        }        initCountdown() {          this.cdWrapper = this.root.querySelector('#tg-df-countdown-wrapper');                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          this.showCountdown = params.get('show_countdown') === 'true';          const showHeaderDetails = params.get('show_header_details') !== 'false';          const eyebrow = this.root.querySelector('.tg-df-carousel-box-eyebrow');          const title = this.root.querySelector('.tg-df-carousel-box-title');          const subtitle = this.root.querySelector('.tg-df-carousel-box-subtitle');          if (!showHeaderDetails) {            let containerElement = this.root.classList.contains('tg-df-container') ? this.root : this.root.querySelector('.tg-df-container');            if (containerElement) containerElement.classList.add('hide-header-details');            if (eyebrow) eyebrow.style.display = 'none';            if (title) title.style.display = 'none';            if (subtitle) subtitle.style.display = 'none';          }          if (!this.cdWrapper) return;          this.cdTitle = this.root.querySelector('#tg-df-countdown-title');          this.cdDays = this.root.querySelector('#tg-df-cd-days');          this.cdHrs = this.root.querySelector('#tg-df-cd-hrs');          this.cdMin = this.root.querySelector('#tg-df-cd-min');          this.cdSec = this.root.querySelector('#tg-df-cd-sec');          this.updateCountdown();          this.cdInterval = setInterval(() => this.updateCountdown(), 1000);        }        updateCountdown() {          if (!this.cdWrapper) return;          if (!this.showCountdown) {            this.cdWrapper.style.display = 'none';            return;          }          const area = this.getAreaCode();          let offset = '-04:00';          if (['DE', 'FR', 'IT', 'ES', 'NL'].includes(area)) {             offset = '+02:00';          } else if (['GB', 'IE', 'UK'].includes(area)) {             offset = '+01:00';          }          const startTime = new Date('2026-06-23T00:00:00' + offset).getTime();          const endTime = new Date('2026-06-26T00:00:00' + offset).getTime();          const now = Date.now();          let targetTime = 0;          if (now < startTime) {             targetTime = startTime;             if (this.cdTitle) this.cdTitle.textContent = 'Prime Day starts in';             this.cdWrapper.style.display = 'flex';          } else if (now < endTime) {             targetTime = endTime;             if (this.cdTitle) this.cdTitle.textContent = 'Prime Day ends in';             this.cdWrapper.style.display = 'flex';          } else {             this.cdWrapper.style.display = 'none';             if (this.cdInterval) clearInterval(this.cdInterval);             return;          }          const diff = Math.max(0, targetTime - now);          const d = Math.floor(diff / (1000 * 60 * 60 * 24));          const h = Math.floor((diff / (1000 * 60 * 60)) % 24);          const m = Math.floor((diff / 1000 / 60) % 60);          const s = Math.floor((diff / 1000) % 60);          if (this.cdDays) this.cdDays.textContent = d;          if (this.cdHrs) this.cdHrs.textContent = h;          if (this.cdMin) this.cdMin.textContent = m;          if (this.cdSec) this.cdSec.textContent = s;        }        init() {          this.initCountdown();          try {            initAnalytics();          } catch (e) {            console.warn('Deals Widget Analytics Error:', e);          }                    this.bindEvents();                    let initialQuery = '';                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          let initialViewMode = params.get('view_mode');          if (!params.has('search') && !params.has('q') && !params.has('query') && initialViewMode !== 'savings_squad') {             initialQuery = 'Everything';             if (this.discountFilter && !params.has('min_discount_ratio')) {               this.discountFilter.value = '5';             }          }          const website = params.get('website') || 'tomsguide';          this.website = website;          if (website === 'techradar') {            const squadHeader = this.root.querySelector('.tg-df-savings-squad-header');            if (squadHeader) {               const pic = squadHeader.querySelector('picture');               if (pic) pic.style.display = 'none';            }            const style = document.createElement('style');            style.innerHTML = `              .tg-df-container .hawk-affiliate-link-deal-button, .tg-df-container .tg-df-card-cta { background-color: #5DAF08 !important; }              .tg-df-container .hawk-affiliate-link-deal-button:hover, .tg-df-container .tg-df-card-cta:hover { background-color: #4a8c06 !important; }            `;            this.root.appendChild(style);          }                    if (this.regionSelect) {            this.regionSelect.value = params.get('region') || 'auto';            this.updatePriceDropdownCurrency();          }                    if (this.retailerSelect && params.has('retailer')) {            this.retailerSelect.value = params.get('retailer');          }                    if (params.has('brands')) {            const b = params.get('brands');            if (b) {              this.selectedBrands = b.split(',');            }          }                    if (this.offerTypeSelect && params.has('offer_type')) {            this.offerTypeSelect.value = params.get('offer_type');          }          if (params.has('bg_color')) {            const bg = params.get('bg_color');            if (bg === 'white') {              this.root.style.setProperty('background-color', '#ffffff', 'important');            } else if (bg === 'transparent') {              this.root.style.setProperty('background-color', 'transparent', 'important');            } else if (bg === 'light_blue') {              this.root.style.setProperty('background-color', '#E7F0FF', 'important');            }          } else {             this.root.style.removeProperty('background-color');          }                    if (params.has('view_mode')) {            if (this.viewModeSelect) {              this.viewModeSelect.value = params.get('view_mode');            } else {              this.viewModeOverride = params.get('view_mode');            }          }          if (this.rowsSelect && params.has('rows')) {            this.rowsSelect.value = params.get('rows');          }          if (params.has('price')) {            const priceVal = params.get('price');            if (this.priceFilter) {               // Try assigning it directly to select. If it's not present implicitly ignores               this.priceFilter.value = priceVal;            }            if (priceVal.includes('_')) {               const parts = priceVal.split('_');               if (this.customPriceMin && parts[0]) this.customPriceMin.value = parts[0];               if (this.customPriceMax && parts[1]) this.customPriceMax.value = parts[1];            }          }          if (this.discountFilter && params.has('min_discount_ratio')) {            // Need to convert back from ratio (e.g. 0.8) to select value (e.g. "20")            const ratioStr = params.get('min_discount_ratio');            const ratioFloat = parseFloat(ratioStr);            if (!isNaN(ratioFloat)) {               const percentage = Math.round((1 - ratioFloat) * 100);               this.discountFilter.value = percentage.toString();            }          }          if (this.sortSelect) {            this.sortSelect.value = params.get('sort') || 'discount_desc';          }          if (this.dealModeToggle && params.has('deal_mode')) {            this.dealModeToggle.checked = params.get('deal_mode') === 'true' || params.get('deal_mode') === '1';          }                    // Re-apply layout after params have updated control values          this.applyLayoutMode();                    if (params.get('search')) {            initialQuery = params.get('search');          } else if (params.get('q')) {            initialQuery = params.get('q');          } else if (params.get('query')) {            initialQuery = params.get('query');          }                    this.currentQuery = initialQuery;          if (this.searchInput) {            this.searchInput.value = this.currentQuery;          }                    if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {            this.fetchDeals(this.currentQuery);          } else {            this.render();          }        }        updatePriceDropdownCurrency() {          if (!this.priceFilter || !this.regionSelect) return;          const currencySymbols = {            'US': '$',            'GB': '£',            'CA': '$CA',            'AU': '$AU',            'DE': '€',            'FR': '€',            'IT': '€',          };          const area = this.getAreaCode();          const cur = currencySymbols[area || 'US'] || '$';                    const options = this.priceFilter.options;          for (let i = 0; i < options.length; i++) {            const opt = options[i];            if (opt.value === 'all') {              opt.innerText = 'All Prices';            } else if (opt.value === 'under50') {              opt.innerText = `Under ${cur}50`;            } else if (opt.value === '50_100') {              opt.innerText = `${cur}50 - ${cur}100`;            } else if (opt.value === '100_200') {              opt.innerText = `${cur}100 - ${cur}200`;            } else if (opt.value === '200_500') {              opt.innerText = `${cur}200 - ${cur}500`;            } else if (opt.value === 'over500') {              opt.innerText = `Over ${cur}500`;            }          }        }        populateBrandDropdown(values) {          if (!this.brandDropdown || !this.brandFilterWrapper) return;          this.brandFilterWrapper.style.display = 'flex'; // show the wrapper                    let html = '';          const allChecked = this.selectedBrands.length === 0 ? 'checked' : '';          const _div = '<' + '/div>';          const _span = '<' + '/span>';          html += `\x3Cdiv class="tg-df-ms-option">\x3Cinput type="checkbox" value="" ${allChecked} class="tg-df-brand-chk"> Any Brand${_div}`;                    values.forEach(v => {             if (!v.formatted_value || v.formatted_value === 'Any Brand') return;             const isChecked = this.selectedBrands.includes(v.formatted_value) ? 'checked' : '';             html += `\x3Cdiv class="tg-df-ms-option">\x3Cinput type="checkbox" value="${this.escapeHTML(v.formatted_value)}" ${isChecked} class="tg-df-brand-chk"> ${this.escapeHTML(v.formatted_value)} \x3Cspan style="color:var(--tg-df-text-muted);font-size:12px">(${v.count || 0})${_span}${_div}`;          });                    this.brandDropdown.innerHTML = html;                    // Re-bind listeners          const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');          chks.forEach(chk => {            chk.addEventListener('change', (e) => {              const val = e.target.value;              if (val === '') {                this.selectedBrands = [];              } else {                if (e.target.checked) {                   if (!this.selectedBrands.includes(val)) this.selectedBrands.push(val);                } else {                   this.selectedBrands = this.selectedBrands.filter(b => b !== val);                }              }                            if (this.selectedBrands.length === 0) {                 this.brandTrigger.innerText = 'Any Brand';              } else if (this.selectedBrands.length === 1) {                 this.brandTrigger.innerText = this.selectedBrands[0];              } else {                 this.brandTrigger.innerText = `${this.selectedBrands.length} Brands selected`;              }                            // Only call API if changed from UI interactions              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                 this.updateURLParams();                 this.fetchDeals(this.currentQuery);              }            });          });                    // Update button text on load          if (this.selectedBrands.length === 0) {             this.brandTrigger.innerText = 'Any Brand';          } else if (this.selectedBrands.length === 1) {             this.brandTrigger.innerText = this.selectedBrands[0];          } else {             this.brandTrigger.innerText = `${this.selectedBrands.length} Brands selected`;          }        }        updateURLParams() {          const url = new URL(window.location);          if (this.currentQuery && this.currentQuery !== 'Gaming laptops') {            url.searchParams.set('q', this.currentQuery);          } else {            url.searchParams.delete('q');            url.searchParams.delete('search');            url.searchParams.delete('query');          }                    if (this.regionSelect && this.regionSelect.value !== 'auto') {            url.searchParams.set('region', this.regionSelect.value);          } else {            url.searchParams.delete('region');          }                    if (this.retailerSelect && this.retailerSelect.value) {            url.searchParams.set('retailer', this.retailerSelect.value);          } else {            url.searchParams.delete('retailer');          }                    if (this.selectedBrands && this.selectedBrands.length > 0) {            url.searchParams.set('brands', this.selectedBrands.join(','));          } else {            url.searchParams.delete('brands');          }                    if (this.offerTypeSelect && this.offerTypeSelect.value) {            url.searchParams.set('offer_type', this.offerTypeSelect.value);          } else {            url.searchParams.delete('offer_type');          }                    if (this.viewModeSelect && this.viewModeSelect.value !== 'auto') {            url.searchParams.set('view_mode', this.viewModeSelect.value);          } else {            url.searchParams.delete('view_mode');          }                    if (this.rowsSelect && this.rowsSelect.value !== '12') {            url.searchParams.set('rows', this.rowsSelect.value);          } else {            url.searchParams.delete('rows');          }                    const min = this.customPriceMin ? this.customPriceMin.value : '';          const max = this.customPriceMax ? this.customPriceMax.value : '';          if (min || max) {             url.searchParams.set('price', `${min}_${max}`);          } else if (this.priceFilter && this.priceFilter.value !== 'all') {            url.searchParams.set('price', this.priceFilter.value);          } else {            url.searchParams.delete('price');          }                    if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {            const v = parseInt(this.discountFilter.value);            if (!isNaN(v) && v > 0) {               const ratio = (100 - v) / 100;               url.searchParams.set('min_discount_ratio', ratio.toString());            }          } else {            url.searchParams.delete('min_discount_ratio');          }                    if (this.sortSelect && this.sortSelect.value !== 'discount_desc') {            url.searchParams.set('sort', this.sortSelect.value);          } else {            url.searchParams.delete('sort');          }                    if (this.dealModeToggle && this.dealModeToggle.checked) {            url.searchParams.set('deal_mode', 'true');          } else {            url.searchParams.delete('deal_mode');          }                    window.history.replaceState({}, '', url);        }        bindEvents() {          const roundels = this.root.querySelectorAll('.tg-df-carousel-cat.original-hardcoded');          roundels.forEach(r => {             r.addEventListener('click', () => {                const q = r.getAttribute('data-query');                const pr = r.getAttribute('data-pr');                if (typeof trackHawkEvent !== 'undefined') {                     trackHawkEvent({                         clickType: "CC",                         widgetId: this.widgetId,                         productCategoryName: "deals",                         zeroBasedProductIndexOrNull: null,                         totalDealsOrProducts: null,                         areaClicked: "Category Roundel",                         revenueId: this.revenueId,                         isoCurrencyCode: typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD',                         queryName: q,                         widgetTypeName: this.widgetTypeName                     });                 }                this.currentQuery = q;                const label = this.root.querySelector('#tg-df-carousel-title-label');                if (label) label.textContent = 'Best ' + q;                if (this.priceFilter) this.priceFilter.value = pr || 'all';                if (this.discountFilter) this.discountFilter.value = '5';                if (this.searchInput) this.searchInput.value = q;                                roundels.forEach(ro => ro.classList.remove('active'));                r.classList.add('active');                this.fetchDeals(this.currentQuery);             });          });          const discBtns = this.root.querySelectorAll('.tg-df-carousel-filter-btn');          discBtns.forEach(b => {             b.addEventListener('click', () => {                const d = b.getAttribute('data-d');                const pr = b.getAttribute('data-pr');                const ot = b.getAttribute('data-ot');                let label = b.innerText ? b.innerText.trim() : '';                let filterType = 'unknown';                let filterVal = 'unknown';                if (d !== null) { filterType = 'discount'; filterVal = d; }                else if (pr !== null) { filterType = 'price'; filterVal = pr; }                else if (ot !== null) { filterType = 'offertype'; filterVal = ot; }                if (typeof trackElementInteraction === 'function') trackElementInteraction({ id: `filter-${filterType}-${filterVal}`, name: 'Filter Button', label: label });                                if (d !== null) {                   if (this.discountFilter) this.discountFilter.value = this.discountFilter.value === d ? '0' : d;                } else if (pr !== null) {                   if (this.priceFilter) this.priceFilter.value = this.priceFilter.value === pr ? 'all' : pr;                } else if (ot !== null) {                   if (this.offerTypeSelect) this.offerTypeSelect.value = this.offerTypeSelect.value === ot ? 'all' : ot;                } else {                   if (this.discountFilter) this.discountFilter.value = '0';                   if (this.priceFilter) this.priceFilter.value = 'all';                   if (this.offerTypeSelect) this.offerTypeSelect.value = 'all';                }                if (d === null && pr === null && ot === null && b.getAttribute("data-type") !== "custom") {                   discBtns.forEach(ro => ro.classList.remove('active'));                   b.classList.add('active');                } else if (b.getAttribute("data-type") !== "custom") {                   // Only operate on hardcoded buttons (those without data-type)                   discBtns.forEach(ro => {                      if (!ro.getAttribute('data-d') && !ro.getAttribute('data-pr') && !ro.getAttribute('data-ot') && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active');                   });                                      let makeActive = true;                   if (d !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-d') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   } else if (pr !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-pr') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   } else if (ot !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-ot') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   }                                      if (makeActive) b.classList.add('active');                                      // Check if anything is active, if not activate "All"                   let anyActive = false;                   discBtns.forEach(ro => { if (ro.classList.contains('active') && ro.getAttribute('data-type') !== 'custom') anyActive = true; });                   if (!anyActive) {                       discBtns.forEach(ro => { if (!ro.getAttribute('data-d') && !ro.getAttribute('data-pr') && !ro.getAttribute('data-ot') && ro.getAttribute('data-type') !== 'custom') ro.classList.add('active'); });                   }                }                                this.fetchDeals(this.currentQuery);             });          });          if (this.brandTrigger && this.brandDropdown) {            this.brandTrigger.addEventListener('click', () => {              this.brandDropdown.classList.toggle('active');            });            document.addEventListener('click', (e) => {              if (this.brandFilterWrapper && !e.composedPath().includes(this.brandFilterWrapper)) {                this.brandDropdown.classList.remove('active');              }            });          }          let debounceTimer;          if(this.searchInput) {            this.searchInput.addEventListener('input', (e) => {              clearTimeout(debounceTimer);              const query = e.target.value.trim();              this.currentQuery = query;              if (this.getViewMode() === 'savings_squad' && this.autocompleteDropdown && this.airedaleTags && query.length > 0) {                 const matches = this.airedaleTags.filter(t => t.toLowerCase().includes(query.toLowerCase()) && t.toLowerCase() !== query.toLowerCase()).slice(0, 5);                 if (matches.length > 0) {                    this.autocompleteDropdown.innerHTML = matches.map(m => `\x3Cdiv class="tg-df-autocomplete-item" data-tag="${this.escapeHTML(m)}">${this.escapeHTML(m)}<` + `/div>`).join('');                    this.autocompleteDropdown.classList.add('active');                 } else {                    this.autocompleteDropdown.classList.remove('active');                 }              } else if (this.autocompleteDropdown) {                 this.autocompleteDropdown.classList.remove('active');              }              debounceTimer = setTimeout(() => {                this.updateURLParams();                if (query.length > 2) {                  this.fetchDeals(query);                } else if (query.length === 0) {                  this.deals = [];                  this.render();                }              }, 400);            });            this.searchInput.addEventListener('keypress', (e) => {              if (e.key === 'Enter') {                if (this.autocompleteDropdown) this.autocompleteDropdown.classList.remove('active');                clearTimeout(debounceTimer);                const query = e.target.value.trim();                this.currentQuery = query;                this.activeDealTag = null;                trackElementInteraction({ id: 'search-submit', name: 'Ask', label: 'Ask (main search)', text: query });                this.updateURLParams();                if (query.length > 2 || (this.getViewMode() === 'savings_squad')) {                   this.fetchDeals(query);                }              }            });          }          if (this.autocompleteDropdown) {             this.autocompleteDropdown.addEventListener('click', (e) => {                const item = e.target.closest('.tg-df-autocomplete-item');                if (item) {                   const tag = item.getAttribute('data-tag');                   this.currentQuery = tag;                   if (this.searchInput) this.searchInput.value = tag;                   this.activeDealTag = tag;                   this.autocompleteDropdown.classList.remove('active');                   this.updateURLParams();                   this.fetchDeals(tag);                }             });             document.addEventListener('click', (e) => {               if (this.autocompleteDropdown && this.searchInput && !e.composedPath().includes(this.searchInput) && !e.composedPath().includes(this.autocompleteDropdown)) {                 this.autocompleteDropdown.classList.remove('active');               }             });          }          if (this.searchBtn) {            this.searchBtn.addEventListener('click', () => {              if (this.autocompleteDropdown) this.autocompleteDropdown.classList.remove('active');              clearTimeout(debounceTimer);              const query = this.searchInput.value.trim();              trackElementInteraction({ id: 'search-submit', name: 'Ask', label: 'Ask (main search)', text: query });              this.activeDealTag = null;              this.currentQuery = query;              this.updateURLParams();              if (query.length > 2 || (this.getViewMode() === 'savings_squad')) {                 this.fetchDeals(query);              }            });          }          if(this.sortSelect) this.sortSelect.addEventListener('change', () => {            trackElementInteraction({ id: `sort-option-${this.sortSelect.value}`, name: 'Sort', label: `Sort: ${this.sortSelect.options[this.sortSelect.selectedIndex].text}` });            this.updateURLParams();            if (this.deals.length > 0) {              this.sortData();              this.render();            }          });                    const priceFilter = this.root.querySelector('#tg-df-price-filter');          if (priceFilter) {            this.priceFilter = priceFilter;            this.priceFilter.addEventListener('change', () => {              trackElementInteraction({ id: `filter-price-${this.priceFilter.value}`, name: 'Price', label: this.priceFilter.options[this.priceFilter.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }            });          }          const updateCustomPrice = () => {             this.updateURLParams();             if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);             } else {                this.render();             }          };          if (this.customPriceMin) {             this.customPriceMin.addEventListener('change', updateCustomPrice);             this.customPriceMin.addEventListener('keypress', (e) => {                if (e.key === 'Enter') updateCustomPrice();             });          }          if (this.customPriceMax) {             this.customPriceMax.addEventListener('change', updateCustomPrice);             this.customPriceMax.addEventListener('keypress', (e) => {                if (e.key === 'Enter') updateCustomPrice();             });          }          const discountFilter = this.root.querySelector('#tg-df-discount-filter');          if (discountFilter) {            this.discountFilter = discountFilter;            this.discountFilter.addEventListener('change', () => {              trackElementInteraction({ id: `filter-discount-${this.discountFilter.value}`, name: 'Discount', label: this.discountFilter.options[this.discountFilter.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }            });          }          if (this.categoryFilter) {            this.categoryFilter.addEventListener('change', (e) => {               const val = e.target.value === 'all' ? null : e.target.value;               this.activeDealTag = val;               this.fetchSavingsSquad();            });          }                    if (this.settingsToggle) {            this.settingsToggle.addEventListener('click', () => {              const o = this.settingsPanel.classList.toggle('active');              this.settingsBackdrop.classList.toggle('active');              if (o) trackElementInteraction({ id: 'filter-open', name: 'Filters', label: 'Open filters' });            });          }                    if (this.settingsBackdrop) {            this.settingsBackdrop.addEventListener('click', () => {              this.settingsPanel.classList.remove('active');              this.settingsBackdrop.classList.remove('active');            });          }                    if (this.regionSelect) {            this.regionSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-region-${this.regionSelect.value}`, name: 'Region', label: this.regionSelect.options[this.regionSelect.selectedIndex].text });              this.updateURLParams();              this.updatePriceDropdownCurrency();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.retailerSelect) {            this.retailerSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-merchant-${this.retailerSelect.value}`, name: 'Retailer', label: this.retailerSelect.options[this.retailerSelect.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.offerTypeSelect) {            this.offerTypeSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-offertype-${this.offerTypeSelect.value}`, name: 'Offer Type', label: this.offerTypeSelect.options[this.offerTypeSelect.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.viewModeSelect) {            this._prevViewMode = this.viewModeSelect.value;            this.viewModeSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-viewmode-${this.viewModeSelect.value}`, name: 'View Mode', label: this.viewModeSelect.options[this.viewModeSelect.selectedIndex].text });                            // Reset all active toggles and filters to prevent config carry-over              this.selectedBrands = [];              if (this.brandTrigger) this.brandTrigger.innerText = 'Select Brands';              if (this.brandDropdown) {                const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                chks.forEach(chk => { chk.checked = false; });              }              if (this.priceFilter) this.priceFilter.value = 'all';              if (this.customPriceMin) this.customPriceMin.value = '';              if (this.customPriceMax) this.customPriceMax.value = '';              if (this.sortSelect) this.sortSelect.value = this.viewModeSelect.value === 'savings_squad' ? 'date_desc' : 'discount_desc';              if (this.discountFilter) this.discountFilter.value = '0';              if (this.retailerSelect) this.retailerSelect.value = '';              if (this.offerTypeSelect) this.offerTypeSelect.value = '';              if (this.rowsSelect) this.rowsSelect.value = '12';              if (this.categoryFilter) this.categoryFilter.value = 'all';              this.activeDealTag = null;              this.updateURLParams();              this.applyLayoutMode();                            if (this.getViewMode() === 'savings_squad' || this._prevViewMode === 'savings_squad') {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }              this._prevViewMode = this.viewModeSelect.value;            });          }                    if (this.rowsSelect) {            this.rowsSelect.addEventListener('change', () => {              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.dealModeToggle) {            this.dealModeToggle.addEventListener('change', () => {              this.updateURLParams();              this.render();            });          }          if (this.editorModeToggle) {             this.editorModeToggle.addEventListener('change', (e) => {                this.editorMode = e.target.checked;                this.render();                this.updateFloatingCopyBar();             });          }          if (this.editorCopyBtn) {             this.editorCopyBtn.addEventListener('click', () => {                this.copySelectedDealsToCMS();             });          }          if (this.editorClearBtn) {             this.editorClearBtn.addEventListener('click', () => {                this.selectedDeals.clear();                this.render();                this.updateFloatingCopyBar();             });          }          if (this.grid) {            this.grid.addEventListener('change', (e) => {               if (e.target.classList.contains('tg-df-deal-checkbox')) {                  const dealId = e.target.getAttribute('data-id');                  if (e.target.checked) {                     const dealObj = this.deals.find(d => d.id === dealId);                     if (dealObj) this.selectedDeals.set(dealId, dealObj);                  } else {                     this.selectedDeals.delete(dealId);                  }                  this.updateFloatingCopyBar();               }            });            this.grid.addEventListener('click', (e) => {              const dealCard = e.target.closest('[data-action="deal-click"]');              const similarCard = e.target.closest('[data-action="view-similar-click"]');              const cardLink = dealCard || similarCard;              if (cardLink) {                const productName = cardLink.getAttribute('data-product-name');                const merchantName = cardLink.getAttribute('data-merchant-name');                const productId = cardLink.getAttribute('data-analytics-id');                const price = parseFloat(cardLink.getAttribute('data-price')) || null;                const prevPriceStr = cardLink.getAttribute('data-previous-price');                const previousPrice = prevPriceStr ? parseFloat(prevPriceStr) : null;                const originalLink = cardLink.getAttribute('data-original-link');                const rewrittenLink = cardLink.getAttribute('href');                const revenueId = cardLink.getAttribute('data-revenue-id');                const index = parseInt(cardLink.getAttribute('data-index'), 10) || 0;                const inStock = cardLink.getAttribute('data-in-stock') === 'true';                const totalText = cardLink.getAttribute('data-total');                const totalDeals = parseInt(totalText, 10) || 0;                const productCategoryName = 'deals';                const trackingParams = {                  widgetId: this.widgetId,                  productCategoryName: productCategoryName,                  product: {                    modelId: cardLink.getAttribute('data-model-id') || null,                    matchId: cardLink.getAttribute('data-match-id') || null,                    brand: cardLink.getAttribute('data-model-brand') || null,                    parent: cardLink.getAttribute('data-model-parent') || null,                    name: productName,                    price: price,                    previousPrice: previousPrice,                    link: rewrittenLink,                    originalLink: originalLink,                    inStock: inStock                  },                  zeroBasedProductIndexOrNull: index,                  totalDealsOrProducts: totalDeals,                   merchant: {                    id: cardLink.getAttribute('data-merchant-id') || null,                    network: cardLink.getAttribute('data-merchant-network') || null,                    url: cardLink.getAttribute('data-merchant-url') || null,                    name: merchantName                  },                  revenueId: revenueId,                  widgetTypeName: this.widgetTypeName,                  isoCurrencyCode: normalizeCurrency(this.escapeHTML(cardLink.getAttribute('data-currency') || '$'))                };                if (dealCard) {                  trackDealClick(trackingParams);                } else {                  trackViewSimilarClick(trackingParams);                }              }              const couponsBtn = e.target.closest('[data-action="coupons-click"]');              if (couponsBtn) {                trackElementInteraction({                  id: 'product-card-show-coupons',                  name: 'Coupons',                  label: `Product card coupons: ${couponsBtn.getAttribute('data-merchant')}`                });              }            });          }          this.setupScrollListeners();        }        setupScrollListeners() {          const containers = [             this.root.querySelector('.tg-df-carousel-roundels'),             this.root.querySelector('.tg-df-carousel-filters-wrap'),             this.root.querySelector('#tg-df-grid')          ];                    containers.forEach(container => {             if (!container) return;                          const checkScroll = () => {                if (!container.parentElement) return;                const leftBtn = container.parentElement.querySelector('.tg-df-carousel-scroll-left');                const rightBtn = container.parentElement.querySelector('.tg-df-carousel-scroll-right');                                if (leftBtn) {                   if (container.scrollLeft <= 5) leftBtn.style.display = 'none';                   else leftBtn.style.display = 'flex';                }                                if (rightBtn) {                   if (container.scrollWidth <= container.clientWidth) {                       rightBtn.style.display = 'none';                   } else if (container.scrollLeft >= container.scrollWidth - container.clientWidth - 5) {                       rightBtn.style.display = 'none';                   } else {                       rightBtn.style.display = 'flex';                   }                }             };                          container.addEventListener('scroll', checkScroll);             checkScroll();                          window.addEventListener('resize', checkScroll);                          const observer = new MutationObserver(checkScroll);             observer.observe(container, { childList: true, subtree: true, characterData: false });          });        }        get widgetTypeName() {          const mode = this.viewModeSelect ? this.viewModeSelect.value : (this.viewModeOverride || 'auto');          switch(mode) {              case 'carousel': return 'Carousel';              case 'savings_squad': return 'Savings Squad';              case 'grid': return 'Grid';              case 'row': return 'Row';              default: return 'Auto Collection';          }        }        getRowsLimit() {          if (this.rowsSelect && this.rowsSelect.value) return parseInt(this.rowsSelect.value, 10);          let configSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {             configSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {             configSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(configSource);          if (params.has('rows')) return parseInt(params.get('rows'), 10) || 12;          return 12;        }        getAreaCode() {          if (this.regionSelect && this.regionSelect.value) {            if (this.regionSelect.value === 'auto') return null;            return this.regionSelect.value;          }          let area = null;          try {            const locale = window.navigator.language || window.navigator.userLanguage;            if (locale && locale.includes('-')) {              area = locale.split('-')[1].toUpperCase();            } else if (locale && locale.length === 2) {              if (locale.toUpperCase() === 'EN') { area = 'US'; }              else { area = locale.toUpperCase(); }            }          } catch (e) { /* Ignore */ }                    // Map to known valid options or fallback to US          const valid = ['US', 'GB', 'CA', 'AU', 'DE', 'FR', 'IT'];          if (area === 'UK') area = 'GB';          if (valid.includes(area)) {             return area;          }          return 'US';        }                async loadCarouselSpreadsheet() {          try {              const parseCSVRow = (str) => {                  let result = [], cur = '', inQuotes = false;                  for (let i = 0; i < str.length; i++) {                      let char = str[i];                      if (inQuotes) {                          if (char === '"') {                              if (str[i + 1] === '"') { cur += '"'; i++; }                              else { inQuotes = false; }                          } else { cur += char; }                      } else {                          if (char === '"') { inQuotes = true; }                          else if (char === ',') { result.push(cur); cur = ''; }                          else { cur += char; }                      }                  }                  result.push(cur); return result;              };              const parseCSV = (str) => {                  const rows = []; let curRow = '', inQuotes = false;                  for (let i = 0; i < str.length; i++) {                      let char = str[i];                      if (char === '"') inQuotes = !inQuotes;                      if ((char === '\n' || char === '\r') && !inQuotes) {                          if (char === '\r' && str[i+1] === '\n') i++;                          if (curRow) rows.push(parseCSVRow(curRow));                          curRow = '';                      } else { curRow += char; }                  }                  if (curRow) rows.push(parseCSVRow(curRow));                  return rows;              };              const preloadedCSV = decodeURIComponent(escape(atob("LCwxLDIsMyw0LDUsNiw3LDgsOSwxMCwxMSwxMiwxMywxNCwxNQ0KUm91bmRlbCB0ZXh0LEFsbCxUVnMsRm9vdHdlYXIsQXBwYXJlbCxNYXR0cmVzZXMsQXBwbGlhbmNlcyxXZWFyYWJsZSB0ZWNoLEhlYWRwaG9uZXMsU21hcnQgSG9tZSxTcGVha2VycyxMYXB0b3BzLFRhYmxldHMsQ29tcHV0aW5nLFBob25lcyxHYW1pbmcsTGVnbw0KUm91bmRlbCBpbWFnZSxodHRwczovL3d3dy50b21zZ3VpZGUuY29tL3Byb2R1Y3RzL2Nhcm91c2VsL2FpLnBuZyxodHRwczovL3d3dy50b21zZ3VpZGUuY29tL3Byb2R1Y3RzL2Nhcm91c2VsL3R2cy5wbmcsaHR0cHM6Ly9pbWFnZXMuZmllLmZ1dHVyZWNkbi5uZXQvcHJvZHVjdHMvN2IzYTIyNGIwNzk2M2M2MjdiNmI5MDliZDc4MzM4MzZlMDJmZjgxOS5qcGcud2VicCxodHRwczovL2ltYWdlcy5maWUuZnV0dXJlY2RuLm5ldC9wcm9kdWN0cy84NGRhYzVkNDhlZDJkNDQ4NTU5ZWJhNjdhY2U4MzE0Y2M2N2NjZDk0LmpwZy53ZWJwLGh0dHBzOi8vd3d3LnRvbXNndWlkZS5jb20vcHJvZHVjdHMvY2Fyb3VzZWwvbWF0dHJlc3Nlcy5wbmcsaHR0cHM6Ly9pbWFnZXMuZmllLmZ1dHVyZWNkbi5uZXQvcHJvZHVjdHMvNzY4ZTk3Y2ViMDcxODAxZmFlMjA5MTBkMDgyMGIxNmY3NDdhZjkzOS5qcGcud2VicCxodHRwczovL3d3dy50b21zZ3VpZGUuY29tL3Byb2R1Y3RzL2Nhcm91c2VsL3dlbGxuZXNzLnBuZyxodHRwczovL3d3dy50b21zZ3VpZGUuY29tL3Byb2R1Y3RzL2Nhcm91c2VsL2hlYWRwaG9uZXMuanBnLGh0dHBzOi8vaW1hZ2VzLmZpZS5mdXR1cmVjZG4ubmV0L3Byb2R1Y3RzLzg5NTM1YmVlYmUyMGRiYmQ0YTM0NmQ2ZDZiZGZlOTFkOGE4ODRhMjEuanBnLndlYnAsaHR0cHM6Ly93d3cudG9tc2d1aWRlLmNvbS9wcm9kdWN0cy9jYXJvdXNlbC9hdWRpby5qcGcsaHR0cHM6Ly93d3cudG9tc2d1aWRlLmNvbS9wcm9kdWN0cy9jYXJvdXNlbC9sYXB0b3BzLmpwZyxodHRwczovL2ltYWdlcy5maWUuZnV0dXJlY2RuLm5ldC9wcm9kdWN0cy8yMzk3NTY0ZWQ3YTVmZjk0N2U5YjZiMzBlNTRmNDc0OTRiODQxZjg5LmpwZy53ZWJwLGh0dHBzOi8vd3d3LnRvbXNndWlkZS5jb20vcHJvZHVjdHMvY2Fyb3VzZWwvY29tcHV0aW5nLmpwZyxodHRwczovL3d3dy50b21zZ3VpZGUuY29tL3Byb2R1Y3RzL2Nhcm91c2VsL3Bob25lcy5wbmcsaHR0cHM6Ly93d3cudG9tc2d1aWRlLmNvbS9wcm9kdWN0cy9jYXJvdXNlbC9nYW1pbmcucG5nLGh0dHBzOi8vaW1hZ2VzLmZpZS5mdXR1cmVjZG4ubmV0L3Byb2R1Y3RzLzRmNmM2MjFjYWMwYmMxYTg1ZDU5M2UzNTk0YmE1YjM0OWVmZmQyOTIuanBnLndlYnANClNlYXJjaCBRdWVyeSxFdmVyeXRoaW5nLFRlbGV2aXNpb25zLCJTbmVha2VycywgcnVubmluZyBzaG9lcywgc2FuZGFscyIsQ2xvdGhpbmcsTWF0dHJlc3NlcyxIb21lIEFwcGxpYW5jZXMsV2VhcmFibGVzICYgRml0bmVzcyBUZWNoLEhlYWRwaG9uZXMsSG9tZSBUZWNoLFNwZWFrZXJzLExhcHRvcHMsVGFibGV0cyxDb21wdXRpbmcsUGhvbmVzLEdhbWluZyxDb25zdHJ1Y3Rpb24gVG95cw0KRGlzY291bnQgQW1vdW50LG1pbiA1JSxtaW4gMTAlLG1pbiA1JSxtaW4gNSUsbWluIDUlLG1pbiA1JSxtaW4gNSUsbWluIDUlLG1pbiA1JSxtaW4gNSUsbWluIDUlLG1pbiA1JSxtaW4gNSUsbWluIDUlLG1pbiA1JSxtaW4gNSUNClByaWNlIFJhbmdlLCwsLCxtaW4gJDQwMCwsLCxtaW4gJDI1LCxtaW4gJDMwMCwsLG1pbiAkMTAwLCwNCkJyYW5kIFNlbGVjdGlvbiwsLCwsLCwsLCwsLCwsLCwNCkZpbHRlciBidXR0b25zLCwsLCwsLCwsLCwsLCwsLA0KMSxMaWdodG5pbmcgZGVhbHMsTGlnaHRuaW5nIGRlYWxzLExpZ2h0bmluZyBkZWFscyxMaWdodG5pbmcgZGVhbHMsTGlnaHRuaW5nIGRlYWxzLExpZ2h0bmluZyBkZWFscyxMaWdodG5pbmcgZGVhbHMsTGlnaHRuaW5nIGRlYWxzLExpZ2h0bmluZyBkZWFscyxMaWdodG5pbmcgZGVhbHMsTGlnaHRuaW5nIGRlYWxzLExpZ2h0bmluZyBkZWFscyxMaWdodG5pbmcgZGVhbHMsTGlnaHRuaW5nIGRlYWxzLExpZ2h0bmluZyBkZWFscyxMaWdodG5pbmcgZGVhbHMNCjIsQW1hem9uIGRlYWxzLFVuZGVyICQxMDAwLDUwJSBvZmYsQWRpZGFzLEFtYXpvbiBkZWFscyxBbWF6b24gZGVhbHMsNTAlIG9mZixBbWF6b24gZGVhbHMsQW1hem9uIGRlYWxzLEFtYXpvbiBkZWFscyxBbWF6b24gZGVhbHMsQW1hem9uIGRlYWxzLEFtYXpvbiBkZWFscyxBbWF6b24gZGVhbHMsQW1hem9uIGRlYWxzLEFtYXpvbiBkZWFscw0KMyxPdmVyICQ0MDAsVW5kZXIgJDUwMCxIb2thLE5pa2UsU2FhdHZhLE5pbmphLDQwJSBvZmYsSkxhYiwsSkJMLERlbGwsLEFzdXMsQXBwbGUsQ29uc29sZXMsU3RhciBXYXJzDQo0LFVuZGVyICQxMDAwLDUwJSBvZmYsU2tlY2hlcnMsVW5kZXIgQXJtb3VyLEhlbGl4LFNoYXJrLEdhcm1pbixBbmtlciBTb3VuZGNvcmUsUmluZyxTb25vcyxBcHBsZSxBcHBsZSxUUC1saW5rLFNhbXN1bmcsQWNjZXNzb3JpZXMsVW5kZXIgJDI1DQo1LFVuZGVyICQ1MDAsTEcsQXNpY3MsQ29sdW1iaWEsRHJlYW1DbG91ZCxLZXVyaWcsQXBwbGUsU29ueSxHb3ZlZSxUcmliaXQsTGVub3ZvLFNhbXN1bmcsRWVybyxHb29nbGUsR2FtZXMsVW5kZXIgJDUwDQo2LDUwJSBvZmYsU2Ftc3VuZyxOaWtlLFBhdGFnb25pYSxOZWN0YXIsRGUnTG9uZ2hpLEFtYXpmaXQsQXBwbGUsS2FzYSBzbWFydCxTb255LEFsaWVud2FyZSxUQ0wsTmV0Z2VhcixNb3Rvcm9sYSxOaW50ZW5kbyxCb3RhbmljYWxzDQo3LEFtYXpvbixIaXNlbnNlLE5ldyBCYWxhbmNlLEFyYyd0ZXJ5eCxUZW1wdXItcGVkaWMsRHlzb24sRml0Yml0LEJlYXRzLFBoaWxpcHMgSHVlLEFua2VyLEFjZXIsT25lUGx1cyxEZWxsLE9uZVBsdXMsU29ueSxEaXNuZXkNCjgsQXBwbGUsVENMLEFkaWRhcyxDYXJoYXJ0dCxCZWFyLEJpc3NlbGwsU2Ftc3VuZyxFYXJmdW4sQmxpbmssQmVhdHMsTVNJLE1pY3Jvc29mdCxBY2VyLE5vdGhpbmcsWGJveCxNYXJ2ZWwNCjksLFNvbnksU2F1Y29ueSxUaGUgTm9ydGggRmFjZSxTaWVuYSxOdXRyaWJ1bGxldCxPdXJhLFNhbXN1bmcsR29vZ2xlIE5lc3QgLE1hcnNoYWxsLFNhbXN1bmcsTGVub3ZvLExlbm92bywsLFBva2Vtb24NCjEwLCxSb2t1LEJpcmtlbnN0b2NrLENSWiBZb2dhLFdpbmtCZWRzLEJsYWNrIGFuZCBEZWNrZXIsUmluZ2Nvbm4sQ01GLEV1ZnksU2Ftc3VuZyxNaWNyb3NvZnQsUmVNYXJrYWJsZSxBbGllbndhcmUsLCwNCjExLCwsQnJvb2tzLFRoZSBHeW0gUGVvcGxlLEJyb29rbHluIGJlZGRpbmcsTmVzcHJlc3NvLCwxTW9yZSxBcmxvLCxSYXplciwsQ29yc2FpciwsLA0KMTIsLCxDcm9jcywsRWlnaHQgU2xlZXAsQ3Vpc2luYXJ0LCxKQkwsLCwsLEhQLCwsDQpOb3RlcywsLCwsLCwsLCwsLCwsLCwNCiwsIlByaW9yaXRpc2UgYmlnZ2VzdCAlLyQgZGlzY291bnQsIFR2cyB3aXRoIH41MCUgb2ZmIGhhdmUgYmVlbiB0aGUgbW9zdCBwb3B1bGFyIGV2ZW4gaWYgdGhleSBhcmUgc3RpbGwgZXhwZW5zaXZlIiwiTm8gcGF0dGVybiB0byBwcmljaW5nL2Rpc2NvdW50LCByZWFkZXJzIG1haW5seSBzaG9wIGJ5IGJyYW5kL3JlY29nbmlzYWJsZSBzaG9lcyIsIk5vIHBhdHRlcm4gdG8gcHJpY2luZy9kaXNjb3VudCwgcmVhZGVycyBtYWlubHkgc2hvcCBieSBicmFuZCIsIkEgbGFiZWwgd2lsbCBkZWZpbml0ZWx5IGhlbHAgaGVyZSBlLmcuIGJlc3QgZm9yIHNpZGUgc2xlZXBlciwgYmVzdCBtZW1vcnkgZm9hbSIsIkFwcGxpYW5jZXMgaXMgYSBiaWcgY2F0ZWdvcnksIGlzIGl0IHBvc3NpYmxlIHRvIHNwbGl0IGludG8ga2l0Y2hlbiBhcHBsaWFuY2VzLCBmbG9vcmNhcmUsIGFpciBoZWFsdGgvY29vbGluZz8gT3Igc2ltaWxhciIsIkZvY3VzIG9uIHZhbHVlIGZvciBtb25leSwgR2FybWlucyB3aXRoIH41MCUgb2ZmIGhhdmUgYmVlbiBwb3B1bGFyIGV2ZW4gdGhvdWdoIHRoZXkgYXJlIHN0aWxsICQ1MDAiLCwsLCxJbmNsdWRlIEtpbmRsZXMsSSB3b3VsZCBpbmNsdWRlIHdpZmkgcm91dGVycyBoZXJlIGluc3RlYWQgb2Ygc21hcnQgaG9tZSxDYW4gd2Ugc3VyZmFjZSBwaG9uZSBwcm92aWRlciBkZWFscz8gVC1tb2JpbGUgYW5kIHZlcml6b24gd291bGQgbWFrZSBhIGxvdCBtb3JlIG1vbmV5IHRoYW4gQW1hem9uLCwNCiwsaGF2aW5nIGEgJ2Jlc3QgZm9yJyBsYWJlbCB3b3VsZCBiZSBoZWxwZnVsIGUuZy4gYmVzdCBmb3IgYnJpZ2h0IHJvb20sQ2FuIHdlIHN0b3Aga2lkcyBzaG9lcyBmcm9tIHB1bGxpbmcgdGhyb3VnaD8sIldpbGwgdGhpcyBpbmNsdWRlIGFjY2Vzc29yaWVzIGUuZy4gY2FwcywgYmFncywgaWYgc28gbWFrZSBzdXJlIHRoZXNlIGFyZSBtaXhlZCB0aHJvdWdob3V0IGNsb3RoaW5nIGRlYWxzIixXaWxsIHRoaXMgaW5jbHVkZSB0b3BwZXJzIGFuZCBwaWxsb3dzPyBTZWVpbmcgbW9yZSBtb21lbnR1bSB3aXRoIHRoaXMgY2F0ZWdvcnkgcmVjZW50bHkgc28gYSBiZWRkaW5nIHRhYiBtaWdodCB3b3JrLCwiTmVlZCB0byBtYWtlIHN1cmUgYmFuZHMsIHNjcmVlbiBwcm90ZWN0b3JzIGV0Yy4gZG9uJ3QgcHVsbCBpbnRvIGhlcmUiLCwsLCwsLCwsDQosLCJQcmlvcml0aXNlIDY1JycgYW5kIDU1JyBpbmNoIFRWcywgdGhlbiBiaWdnZXIgc2NyZWVucyBiZWZvcmUgdGhlIHNtYWxsZXIgc2l6ZXMiLCwsUXVlZW4gaXMgdGhlIG1vc3QgcG9wdWxhciBzaXplIGluIHRoZSBVUyAtIHByaW9yaXRpc2UgZGVhbHMgZm9yIHRoaXMgc2l6ZSwsLCwsLCwsLCwsDQosLCwsLCwsLCwsLCwsLCwsDQpDYXRlZ29yaWVzIHRvIGNvbnNpZGVyLCxQcm9kdWN0cyBpbmNsdWRlZCwsLCwsLCwsLCwsLCwsDQpVbmRlciAkNTA/LCxBaXIgdGFncywsLCwsLCwsLCwsLCwsDQosLFBvcnRhYmxlIGNoYXJnZXJzL3dpcmVsZXNzIGNoYXJnZXJzLCwsLCwsLCwsLCwsLCwNCiwsIldhdGVyIGJvdHRsZXMgKHN0YW5sZXlzLCBPd2FsYSwgSHlkcm8gZmxhc2ssIFlldGkpIiwsLCwsLCwsLCwsLCwsDQosLEhhbmQgaGVsZCBmYW5zLCwsLCwsLCwsLCwsLCwNCiwsLCwsLCwsLCwsLCwsLCwNCmhvbWUgb2ZmaWNlLCxvZmZpY2UgY2hhaXJzLCwsLCwsLCwsLCwsLCwNCiwsc3RhbmRpbmcgZGVza3MsLCwsLCwsLCwsLCwsLA0KLCxtb25pdG9ycywsLCwsLCwsLCwsLCwsDQosLEtleWJvYXJkcywsLCwsLCwsLCwsLCwsDQosLGRvY2tpbmcgc3RhdGlvbiwsLCwsLCwsLCwsLCwsDQosLCwsLCwsLCwsLCwsLCwsDQpHYW1pbmcsLENvbnNvbGVzLCwsLCwsLCwsLCwsLCwNCiwsQWNjZXNzb3JpZXMsLCwsLCwsLCwsLCwsLA0KLCxHYW1lcywsLCwsLCwsLCwsLCwsDQosLENvdWxkIGluY2x1ZGUgTGVnbz8sLCwsLCwsLCwsLCwsLA==")));              const text = preloadedCSV;              const parsed = parseCSV(text);                            const rowsByName = {};              let filterStart = -1;              parsed.forEach((rc, i) => {                 if (rc && rc.length > 0 && rc[0]) rowsByName[rc[0]] = rc;                 if (rc && rc.length > 0 && rc[0] === 'Filter buttons') filterStart = i;              });                            const cols = [];              if(rowsByName['Roundel text']) {                const headerRow = rowsByName['Roundel text'];                for(let col = 1; col < headerRow.length; col++) {                   let label = headerRow[col];                   if (!label) continue;                                      let q = rowsByName['Search Query'] && rowsByName['Search Query'][col] ? rowsByName['Search Query'][col] : '';                   let img = rowsByName['Roundel image'] && rowsByName['Roundel image'][col] ? rowsByName['Roundel image'][col] : '';                   let ds = rowsByName['Discount Amount'] && rowsByName['Discount Amount'][col] ? rowsByName['Discount Amount'][col] : '';                   let pr = rowsByName['Price Range'] && rowsByName['Price Range'][col] ? rowsByName['Price Range'][col] : '';                   let rt = rowsByName['Retailer'] && rowsByName['Retailer'][col] ? rowsByName['Retailer'][col] : '';                   let ot = rowsByName['Offer Type'] && rowsByName['Offer Type'][col] ? rowsByName['Offer Type'][col] : '';                                      let filters = [];                   if(filterStart > 0) {                     for(let r = filterStart + 1; r < parsed.length; r++) {                         if(!parsed[r] || parsed[r][0] === 'Notes' || parsed[r][0] === 'Categories to consider') break;                         let f = parsed[r][col];                         if(f) filters.push(f);                     }                   }                   cols.push({ label, img, q, ds, pr, rt, ot, filters });                }              }              this.carouselData = cols;              if (this.carouselData && this.carouselData.length > 0) {                 const isMatched = this.carouselData.some(c => c.q === this.currentQuery || c.label === this.currentQuery);                 if (!isMatched) {                    const first = this.carouselData[0];                    this.currentQuery = first.q || first.label;                    if (this.priceFilter) this.priceFilter.value = 'all';                    if (this.customPriceMin) this.customPriceMin.value = '';                    if (this.customPriceMax) this.customPriceMax.value = '';                    let dPr = first.pr || 'all';                    if (typeof dPr === 'string' && dPr !== 'all') {                       let prLower = dPr.toLowerCase();                       if (prLower.includes('min') || prLower.includes('over')) {                          let m = dPr.match(/(\d+)/);                          if (m && this.customPriceMin) this.customPriceMin.value = m[1];                       } else if (prLower.includes('max') || prLower.includes('under')) {                          let m = dPr.match(/(\d+)/);                          if (m && this.customPriceMax) this.customPriceMax.value = m[1];                       }                    }                    let dAm = '0';                    if(first.ds && typeof first.ds === 'string') {                       let m = first.ds.match(/(\d+)/);                       if(m) dAm = m[1];                    }                    if (this.discountFilter) this.discountFilter.value = dAm;                    if (this.offerTypeSelect) this.offerTypeSelect.value = first.ot || '';                    if (this.retailerSelect) this.retailerSelect.value = first.rt || '';                    this.selectedBrands = [];                    if (this.brandDropdown) {                        const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                        chks.forEach(chk => chk.checked = false);                    }                    if (this.searchInput) this.searchInput.value = this.currentQuery;                 }              }              this.renderCarouselUI();          } catch(e){ console.warn(e); }        }                renderCarouselUI() {           const roundelWrapper = this.root.querySelector('.tg-df-carousel-roundels');           if(!roundelWrapper || !this.carouselData) return;                      let html = '';           this.carouselData.forEach(r => {              const q = r.q || r.label;              const isActive = (this.currentQuery === q || this.currentQuery === r.label) ? 'active' : '';              const imgHtml = r.img ? `\x3Cimg src="${r.img}" alt="${r.label}" />` : `\x3Csvg width="32" height="32" fill="#1F69FF" viewBox="0 0 24 24">\x3Cpath d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z"/>\x3C/svg>`;              html += `                \x3Cdiv class="tg-df-roundel tg-df-carousel-cat ${isActive}" data-label="${this.escapeHTML(r.label)}">                  \x3Cdiv class="tg-df-roundel-img-box">${imgHtml}\x3C/div>                  \x3Cspan class="tg-df-roundel-label">${this.escapeHTML(r.label)}\x3C/span>                \x3C/div>              `;           });           roundelWrapper.innerHTML = html;                      // Rebind clicks           const roundels = this.root.querySelectorAll('.tg-df-carousel-cat');           roundels.forEach(rNode => {             rNode.addEventListener('click', () => {                const r = this.carouselData.find(c => c.label === rNode.getAttribute('data-label'));                 if(!r) return;                                  if (typeof trackHawkEvent !== 'undefined') {                     trackHawkEvent({                         clickType: "CC",                         widgetId: this.widgetId,                         productCategoryName: "deals",                         zeroBasedProductIndexOrNull: null,                         totalDealsOrProducts: null,                         areaClicked: "Category Roundel",                         revenueId: this.revenueId,                         isoCurrencyCode: typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD',                         queryName: r.label,                         widgetTypeName: this.widgetTypeName                     });                 }                this.currentQuery = r.q || r.label;                const labelTitle = this.root.querySelector('#tg-df-carousel-title-label');                if (labelTitle) labelTitle.textContent = 'Best ' + this.currentQuery;                if (this.priceFilter) this.priceFilter.value = 'all';                if (this.customPriceMin) this.customPriceMin.value = '';                if (this.customPriceMax) this.customPriceMax.value = '';                let dPr = r.pr || 'all';                if (typeof dPr === 'string' && dPr !== 'all') {                   let prLower = dPr.toLowerCase();                   if (prLower.includes('min') || prLower.includes('over')) {                      let m = dPr.match(/(\d+)/);                      if (m && this.customPriceMin) this.customPriceMin.value = m[1];                   } else if (prLower.includes('max') || prLower.includes('under')) {                      let m = dPr.match(/(\d+)/);                      if (m && this.customPriceMax) this.customPriceMax.value = m[1];                   }                }                                let discountAmount = '0';                if(r.ds && typeof r.ds === 'string') {                   let m = r.ds.match(/(\d+)/);                   if(m) discountAmount = m[1];                }                if (this.discountFilter) this.discountFilter.value = discountAmount;                if (this.offerTypeSelect) this.offerTypeSelect.value = r.ot || '';                if (this.retailerSelect) this.retailerSelect.value = r.rt || '';                                // Clear brands                    this.selectedBrands = [];                    if (this.brandDropdown) {                    const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                    chks.forEach(chk => chk.checked = false);                }                                if (this.searchInput) this.searchInput.value = this.currentQuery;                                roundels.forEach(ro => ro.classList.remove('active'));                if (rNode) rNode.classList.add('active');                                this.renderCarouselFilters(r);                this.fetchDeals(this.currentQuery);             });           });                      // Auto-highlight active           const activeR = this.carouselData.find(c => c.q === this.currentQuery || c.label === this.currentQuery);           if(activeR) this.renderCarouselFilters(activeR);        }                renderCarouselFilters(r) {           const filtersWrap = this.root.querySelector('.tg-df-carousel-filters-wrap');           if(!filtersWrap) return;                      let html = `\x3Cbutton class="tg-df-carousel-filter-btn" data-type="all">All\x3C/button>`;                      r.filters.forEach(f => {              let fL = f.toLowerCase();              let icon = '';              let logic = `data-type="custom" data-v="${this.escapeHTML(f)}"`;              if (fL === 'amazon deals' || fL === 'prime deals') {                 html += `\x3Cbutton class="tg-df-carousel-filter-btn" ${logic}>\x3Cimg src="https://cdn.mos.cms.futurecdn.net/fwoVXvL79turN3Ph535m38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/u75QjVpt3w2EsMimJiRo38-600-100.png" class="active-img" alt="" /> Prime deals\x3C/button>`;              } else if (fL === 'lightning deals') {                 html += `\x3Cbutton class="tg-df-carousel-filter-btn" ${logic}>\x3Cimg src="https://cdn.mos.cms.futurecdn.net/HqAui7w97ft2NPqBtQ5r38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/yWPQ5yyQRhUwVKzGwYbh38-600-100.png" class="active-img" alt="" /> Lightning deals\x3C/button>`;              } else {                 if (fL.includes('lightning')) {                    icon = `\x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-zap">\x3Cpolygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2">\x3C/polygon>\x3C/svg>`;                 } else if (fL.includes('% off')) {                    icon = `\x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>`;                 } else if (fL.includes('under') || fL.includes('min ')) {                    icon = `\x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-badge-dollar-sign">\x3Cpath d="M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z">\x3C/path>\x3Cpath d="M16 8h-6a2 2 0 1 0 0 4h4a2 2 0 1 1 0 4H8">\x3C/path>\x3Cpath d="M12 18V6">\x3C/path>\x3C/svg>`;                 }                 html += `\x3Cbutton class="tg-df-carousel-filter-btn" ${logic}>${icon} ${this.escapeHTML(f)}\x3C/button>`;              }           });                      filtersWrap.innerHTML = html;                      const btns = filtersWrap.querySelectorAll('button');           btns.forEach(b => {             b.addEventListener('click', () => {                const type = b.getAttribute('data-type');                if (type === 'custom') {                   const v = b.getAttribute('data-v');                   if (typeof trackElementInteraction === 'function') trackElementInteraction({ id: `filter-custom-${(v||'').toLowerCase().replace(/[^a-z0-9]+/g, '-')}`, name: 'Custom Filter', label: v });                }                if (type === 'all') {                   if (typeof trackElementInteraction === 'function') trackElementInteraction({ id: 'filter-clear-all', name: 'Clear all', label: 'Clear all filters' });                   // reset everything                   btns.forEach(btn => btn.classList.remove('active'));                   b.classList.add('active');                                      // Reset prices                   if (this.priceFilter) this.priceFilter.value = 'all';                   if (this.customPriceMin) this.customPriceMin.value = '';                   if (this.customPriceMax) this.customPriceMax.value = '';                   let dPr = r.pr || 'all';                   if (typeof dPr === 'string' && dPr !== 'all') {                      let prLower = dPr.toLowerCase();                      if (prLower.includes('min') || prLower.includes('over')) {                         let m = dPr.match(/(\d+)/);                         if (m && this.customPriceMin) this.customPriceMin.value = m[1];                      } else if (prLower.includes('max') || prLower.includes('under')) {                         let m = dPr.match(/(\d+)/);                         if (m && this.customPriceMax) this.customPriceMax.value = m[1];                      }                   }                                      let discountAmount = '0';                   if(r.ds && typeof r.ds === 'string') {                      let m = r.ds.match(/(\d+)/);                      if(m) discountAmount = m[1];                   }                   if (this.discountFilter) this.discountFilter.value = discountAmount;                   if (this.offerTypeSelect) this.offerTypeSelect.value = r.ot || '';                   if (this.retailerSelect) this.retailerSelect.value = r.rt || '';                   this.selectedBrands = [];                   if (this.brandDropdown) {                     const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                     chks.forEach(chk => chk.checked = false);                   }                } else {                   const v = b.getAttribute('data-v');                   const fL = v.toLowerCase();                                      let mapRet = ['amazon', 'walmart', 'best buy', 'target', 'john lewis', 'currys', 'argos'];                   const getCategory = (s) => {                      if (s === 'lightning deals' || s === 'amazon deals' || s === 'prime deals') return 'offer';                      if (s.includes('% off')) return 'discount';                      if (s.includes('under') || s.includes('over') || s.includes('min') || s.includes('max')) return 'price';                      if (mapRet.includes(s)) return 'retailer';                      return 'brand';                   };                   const cat = getCategory(fL);                   const wasActive = b.classList.contains('active');                   if (cat !== 'brand') {                      btns.forEach(btn => {                          if (btn === b) return;                          if (btn.getAttribute('data-type') === 'all') return;                          const bV = btn.getAttribute('data-v');                          if (!bV) return;                          if (getCategory(bV.toLowerCase()) === cat) btn.classList.remove('active');                      });                   }                   if (wasActive) b.classList.remove('active');                   else b.classList.add('active');                   let anyActive = Array.from(btns).some(btn => btn !== btns[0] && btn.classList.contains('active'));                   if (!anyActive) {                       btns[0].click();                       return;                   } else {                       btns[0].classList.remove('active');                   }                                      if (this.priceFilter) this.priceFilter.value = 'all';                   if (this.customPriceMin) this.customPriceMin.value = '';                   if (this.customPriceMax) this.customPriceMax.value = '';                   let dPr = r.pr || 'all';                   if (typeof dPr === 'string' && dPr !== 'all') {                      let prLower = dPr.toLowerCase();                      if (prLower.includes('min') || prLower.includes('over')) {                         let m = dPr.match(/(\d+)/);                         if (m && this.customPriceMin) this.customPriceMin.value = m[1];                      } else if (prLower.includes('max') || prLower.includes('under')) {                         let m = dPr.match(/(\d+)/);                         if (m && this.customPriceMax) this.customPriceMax.value = m[1];                      }                   }                                      let discountAmount = '0';                   if(r.ds && typeof r.ds === 'string') {                      let m = r.ds.match(/(\d+)/);                      if(m) discountAmount = m[1];                   }                   if (this.discountFilter) this.discountFilter.value = discountAmount;                   if (this.offerTypeSelect) this.offerTypeSelect.value = r.ot || '';                   if (this.retailerSelect) this.retailerSelect.value = r.rt || '';                   this.selectedBrands = [];                   btns.forEach(btn => {                       if (!btn.classList.contains('active') || btn.getAttribute('data-type') === 'all') return;                       const vv = btn.getAttribute('data-v');                       const vl = vv.toLowerCase();                                              if (vl === 'lightning deals') {                          if (this.offerTypeSelect) this.offerTypeSelect.value = 'amazon_lightning';                       } else if (vl === 'amazon deals' || vl === 'prime deals') {                          if (this.offerTypeSelect) this.offerTypeSelect.value = 'amazon_prime';                       } else if (vl.includes('% off')) {                          let m = vl.match(/(\d+)%/);                          if (m && this.discountFilter) this.discountFilter.value = m[1];                       } else if (vl.includes('under') || vl.includes('max')) {                          let m = vl.match(/(\d+)/);                          if (m && this.customPriceMax) this.customPriceMax.value = m[1];                       } else if (vl.includes('min') || vl.includes('over')) {                          let m = vl.match(/(\d+)/);                          if (m && this.customPriceMin) this.customPriceMin.value = m[1];                       } else {                          let foundR = mapRet.find(x => x === vl);                          if (foundR) {                             let realR = ['Amazon', 'Walmart', 'Best Buy', 'Target', 'John Lewis', 'Currys', 'Argos'].find(x => x.toLowerCase() === vl);                             if (this.retailerSelect) this.retailerSelect.value = realR;                          } else {                             this.selectedBrands.push(vv);                          }                       }                   });                                      if (this.brandDropdown) {                       const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                       chks.forEach(c => c.checked = this.selectedBrands.includes(c.value));                   }                                      if (r.pr && typeof r.pr === 'string') {                       let prL = r.pr.toLowerCase();                       if (prL.includes('under $')) {                           let m = prL.match(/under \$(\d+)/i);                           if (m && this.customPriceMax && !this.customPriceMax.value) this.customPriceMax.value = m[1];                       }                   }                }                                this.fetchDeals(this.currentQuery);             });           });                      // default to highlighting first           btns[0].classList.add('active');        }async fetchDeals(query, append = false) {          if (!append) {             this.showLoading();             this.deals = [];             this.displayLimit = this.getRowsLimit();          } else {             this.displayLimit += this.getRowsLimit();          }                    try {            if (this.getViewMode() === 'savings_squad') {               await this.fetchSavingsSquad(append);            } else {               if (this.isBroadQuery(query)) {                 await this.fetchAdviserDeals(query, append);               } else {                 await this.fetchHawkDeals(query, append);                 if (this.deals.length === 0) {                   await this.fetchAdviserDeals(query, append);                 }               }            }          } catch (error) {            console.warn("[Tom's Guide Widget] Fetch error:", error);            this.showError();          }        }        async fetchSavingsSquad() {          let topArticles = this.airedaleArticles;          if (!topArticles) {            const airedaleUrl = `https://airedale.futurecdn.net/feeds/feed_1776420579726.json?site=tomsguide&articleType=deals&limit=50`;            let res;            try {               res = await fetch(airedaleUrl);            } catch(e) {               try { res = await fetch(`https://airedale.futurecdn.net/feeds/feed_1776420579726.json?site=tomsguide&articleType=deals&limit=50`); } catch (err) { console.warn("Fallback fetch failed", err); return; }            }            if (!res.ok) throw new Error('Airedale API Error');            const articles = await res.json();            topArticles = Array.isArray(articles) ? articles.slice(0, 50) : ((articles.data && Array.isArray(articles.data)) ? articles.data.slice(0, 50) : []);            this.airedaleArticles = topArticles;                        let tagCounts = {};            topArticles.forEach((a) => {              let articleTags = new Set();              if (a.articlecategory && Array.isArray(a.articlecategory)) {                 a.articlecategory.forEach((t) => articleTags.add(t));              }              articleTags.forEach(t => {                 tagCounts[t] = (tagCounts[t] || 0) + 1;              });            });                        this.airedaleTags = Object.keys(tagCounts).sort((a, b) => tagCounts[b] - tagCounts[a]);            this.airedaleTagCounts = tagCounts;          }                    let targetArticles = topArticles;          if (this.activeDealTag) {             const cleanTag = this.activeDealTag.toLowerCase().replace(/&/g, '').replace(/[^a-z0-9]+/g, '-').replace(/-+/g, '-').replace(/^-|-$/g, '');             const encodedTag = encodeURIComponent(cleanTag);             const url = `https://airedale.futurecdn.net/feeds/feed_1776420579726.json?site=tomsguide&articleType=deals&limit=50&articleCategoryHandle=${encodedTag}`;             try {                const res = await fetch(url);                if (res.ok) {                   const articles = await res.json();                   targetArticles = Array.isArray(articles) ? articles.slice(0, 50) : ((articles.data && Array.isArray(articles.data)) ? articles.data.slice(0, 50) : []);                }             } catch(e) {                console.warn("Failed to fetch by activeDealTag", e);             }          }          let extractedDeals = [];          let dynamicBrandsCounts = {};                    targetArticles.forEach((article) => {             if (!article.articlepage) return;                          let pageData = [];             try {                pageData = JSON.parse(article.articlepage[0]);             } catch(e){ console.warn(e); }                          const savingsSquad = pageData.filter((p) => p.type === 'deal' || p.type === 'featured-product');                          savingsSquad.forEach((block, idx) => {                const data = block.data || {};                const isFeatured = block.type === 'featured-product';                                const link = data.link || {};                const priceObj = data.price || {};                const image = data.image || {};                                if (data.brand) {                   data.brand = data.brand.replace(/^\d+\.\s*/, '').trim();                   dynamicBrandsCounts[data.brand] = (dynamicBrandsCounts[data.brand] || 0) + 1;                }                const externalUrl = isFeatured ? data.url : (link.href || null);                let summaryTitle = isFeatured ? (data.name || data.brand) : (data.productName || link.label || article.articlename);                let description = isFeatured ? (data.strapline || '') : (data.text || '');                                if (!isFeatured && !data.productName && data.text) {                   const brSplit = data.text.split(new RegExp('\x3Cbr\\s*\\/?\\x3E', 'i'));                   if (brSplit.length > 1) {                     summaryTitle = brSplit[0].replace(/<[^>]+>/g, '').trim();                     description = brSplit.slice(1).join(' ').replace(/<br\s*\/?>/gi, ' ').replace(/<\/?(p|div)[^>]*>/gi, ' ').replace(/<[^>]+>/g, '').replace(/\s+/g, ' ').trim();                   } else {                     const match = data.text.match(/\x3Cstrong>(.*?)<\/strong>/);                     if (match) {                       summaryTitle = match[1].replace(/<[^>]+>/g, '').trim();                       if (summaryTitle.endsWith(':')) summaryTitle = summaryTitle.slice(0, -1);                     }                   }                }                                let imageUrl = isFeatured ? image.mos : (image.src || null);                if (imageUrl && imageUrl.startsWith('//')) imageUrl = 'https:' + imageUrl;                                description = description.replace(/<br\s*\/?>/gi, ' ').replace(/<\/?(p|div)[^>]*>/gi, ' ').replace(/<[^>]+>/g, '').replace(/\s+/g, ' ').replace(/View Deal$/i, '').trim();                                let merchantName = data.retailer || '';                if (!merchantName && externalUrl) {                   try {                     merchantName = new URL(externalUrl).hostname.replace('www.', '').split('.')[0];                     merchantName = merchantName.charAt(0).toUpperCase() + merchantName.slice(1);                   }catch(e){ console.warn(e); }                }                if (!merchantName) merchantName = 'Retailer';                const q = (this.currentQuery || '').toLowerCase();                const activeTagLogic = (this.activeDealTag || '').toLowerCase();                if (q.length > 2 && q !== activeTagLogic) {                   const searchTarget = `${summaryTitle || ''} ${description || ''}`.toLowerCase();                   if (!searchTarget.includes(q)) return;                }                let rawPrice = 0;                let rawMsrp = 0;                let currencyStr = '$';                if (isFeatured) {                   rawPrice = typeof data.salePrice === 'number' && data.salePrice > 0 ? data.salePrice : (typeof data.price === 'number' ? data.price : 0);                   rawMsrp = typeof data.salePrice === 'number' && typeof data.price === 'number' && data.price > data.salePrice ? data.price : 0;                   currencyStr = data.currency === 'GBP' ? '£' : '$';                } else {                   rawPrice = priceObj.amount ? parseFloat(priceObj.amount) : 0;                   rawMsrp = priceObj.amountWas ? parseFloat(priceObj.amountWas) : 0;                   currencyStr = priceObj.currency === 'GBP' ? '£' : '$';                }                                let savingAmt = 0;                let savingLabel = '';                if (rawPrice > 0 && rawMsrp > rawPrice) {                   savingAmt = parseFloat((rawMsrp - rawPrice).toFixed(2));                   savingLabel = `Save ${currencyStr}${savingAmt}`;                }                                // Apply Brand filter                if (this.selectedBrands && this.selectedBrands.length > 0) {                   const itemBrand = (data.brand || '').toLowerCase();                   const hasMatch = this.selectedBrands.some(sb => sb.toLowerCase() === itemBrand);                   if (!hasMatch) return;                }                // Apply Price filter                let priceFilterVal = null;                const min = this.customPriceMin ? this.customPriceMin.value : '';                const max = this.customPriceMax ? this.customPriceMax.value : '';                if (min || max) {                   priceFilterVal = `${min}_${max}`;                } else if (this.priceFilter && this.priceFilter.value !== 'all') {                   priceFilterVal = this.priceFilter.value;                }                if (priceFilterVal && rawPrice > 0) {                   if (priceFilterVal === 'under50' && rawPrice >= 50) return;                   if (priceFilterVal === 'over50' && rawPrice <= 50) return;                   if (priceFilterVal === 'over30' && rawPrice <= 30) return;                   if (priceFilterVal === 'over500' && rawPrice <= 500) return;                   if (priceFilterVal.includes('_')) {                      const parts = priceFilterVal.split('_');                      const min = parseFloat(parts[0]);                      const max = parseFloat(parts[1]);                      if (!isNaN(min) && rawPrice < min) return;                      if (!isNaN(max) && rawPrice > max) return;                   }                }                // Apply Discount filter                if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {                   const requiredDiscount = parseInt(this.discountFilter.value);                   if (!isNaN(requiredDiscount) && requiredDiscount > 0) {                      if (!rawMsrp || rawMsrp <= rawPrice) return;                      const ratio = Math.round((1 - (rawPrice / rawMsrp)) * 100);                      if (ratio < requiredDiscount) return;                   }                }                                extractedDeals.push({                   id: `airedale-${article.id || Math.random()}-${idx}`,                   url: externalUrl,                   image: imageUrl,                   fallbackImage: imageUrl,                   title: summaryTitle,                   brand: data.brand || '',                   productName: data.productName || '',                   merchant: merchantName,                   rawPrice: rawPrice,                   rawMsrp: rawMsrp,                   price: rawPrice > 0 ? rawPrice.toString() : '',                   msrp: rawMsrp > 0 ? rawMsrp.toString() : '',                   currency: currencyStr,                   isCheckPrice: !rawPrice,                   savingLabel: savingLabel,                   savingType: rawMsrp > rawPrice ? 'amount' : 'none',                   isPrime: false,                   starRating: null,                   description: description,                   text: data.text || ''                });             });          });                    const airedaleBrandsList = Object.keys(dynamicBrandsCounts).map(b => ({              formatted_value: b,              count: dynamicBrandsCounts[b]          })).sort((a,b) => b.count - a.count);                    if (this.getViewMode() === 'savings_squad') {             this.populateBrandDropdown(airedaleBrandsList.slice(0, 15));             if (this.brandFilterWrapper) {                if (airedaleBrandsList.length === 0) {                    this.brandFilterWrapper.style.display = 'none';                } else {                    this.brandFilterWrapper.style.display = 'flex';                }             }          }                    this.deals = extractedDeals;          this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        isBroadQuery(query) {          const q = query.toLowerCase();          const intentModifiers = ['deals', 'best', 'sale', 'under', 'cheap', 'offers', 'discount'];          return intentModifiers.some(term => q.includes(term));        }        async fetchHawkDeals(query, append = false) {          const url = new URL(this.apiUrl);          url.searchParams.append('model_name', query);          const areaCode = this.getAreaCode();          if (areaCode) {            url.searchParams.append('area', areaCode);          }                    if (append && this.deals.length > 0) {            url.searchParams.append('offset', this.deals.length.toString());          }                    if (this.retailerSelect && this.retailerSelect.value) {            url.searchParams.append('filter_merchant_name', this.retailerSelect.value);          }                    if (this.selectedBrands && this.selectedBrands.length > 0) {            url.searchParams.append('filter_label[text_brand]', this.selectedBrands.join(','));          }                    let priceVal = null;          const min = this.customPriceMin ? this.customPriceMin.value : '';          const max = this.customPriceMax ? this.customPriceMax.value : '';          if (min || max) {             priceVal = `${min}_${max}`;          } else if (this.priceFilter && this.priceFilter.value !== 'all') {             priceVal = this.priceFilter.value;          }          if (priceVal) {            if (priceVal === 'under50') {              url.searchParams.append('filter_max_price', '50');            } else if (priceVal === 'over50') {              url.searchParams.append('filter_min_price', '50');            } else if (priceVal === 'over30') {              url.searchParams.append('filter_min_price', '30');            } else if (priceVal === 'over500') {              url.searchParams.append('filter_min_price', '500');            } else if (priceVal.includes('_')) {              const parts = priceVal.split('_');              if (parts[0]) url.searchParams.append('filter_min_price', parts[0]);              if (parts[1]) url.searchParams.append('filter_max_price', parts[1]);            }          }                    if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {            const v = parseInt(this.discountFilter.value);            if (!isNaN(v) && v > 0) {              const ratio = (100 - v) / 100;              url.searchParams.append('min_discount_ratio', ratio.toString());            }          }                    if (this.offerTypeSelect && this.offerTypeSelect.value) {            url.searchParams.append('offer', this.offerTypeSelect.value);          }                    url.searchParams.append('filter_product_types', 'deals');                    url.searchParams.append('rows', this.getRowsLimit().toString());          let response;          try {             response = await fetch(url.toString());          } catch(e) {             if (window.location.protocol === 'file:') {                console.warn("[Tom's Guide Widget] fetch from file:// blocked by local CORS policy, falling back to Adviser mock.");                await this.fetchAdviserDeals(query);                return;             }             console.warn("Hawk fetch failed", e);             this.deals = [];             this.render();             return;          }          if (!response.ok) {            throw new Error('Hawk API Response Error');          }          const rawData = await response.json();          // Safely locate data array from potentially wrapped response          let offers = [];          let modelInfoArray = [];                    let brandFilterData = null;          if (rawData && rawData.widget && rawData.widget.data && Array.isArray(rawData.widget.data.filters)) {             brandFilterData = rawData.widget.data.filters.find(f => f.type === 'label_text_brand');          } else if (rawData && rawData.data && Array.isArray(rawData.data.filters)) {             brandFilterData = rawData.data.filters.find(f => f.type === 'label_text_brand');          }          if (brandFilterData && Array.isArray(brandFilterData.values) && brandFilterData.values.length > 0) {             this.populateBrandDropdown(brandFilterData.values);          } else {             if (this.brandFilterWrapper && this.selectedBrands.length === 0) {                this.brandFilterWrapper.style.display = 'none';             }          }                    if (rawData && rawData.widget && rawData.widget.data) {            if (Array.isArray(rawData.widget.data.offers)) offers = rawData.widget.data.offers;            if (rawData.widget.data.model_info && typeof rawData.widget.data.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.widget.data.model_info) ? rawData.widget.data.model_info : Object.values(rawData.widget.data.model_info);            }          } else if (rawData && rawData.data) {            if (Array.isArray(rawData.data.offers)) offers = rawData.data.offers;            if (rawData.data.model_info && typeof rawData.data.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.data.model_info) ? rawData.data.model_info : Object.values(rawData.data.model_info);            }          } else {            if (Array.isArray(rawData)) offers = rawData;            else if (rawData && Array.isArray(rawData.offers)) offers = rawData.offers;            else if (rawData && rawData.offers && Array.isArray(rawData.offers.offer)) offers = rawData.offers.offer;            else if (rawData && rawData.offers) offers = [].concat(rawData.offers);                        if (rawData && rawData.model_info && typeof rawData.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.model_info) ? rawData.model_info : Object.values(rawData.model_info);            }          }          let modelDetails = {};          modelInfoArray.forEach(m => {            const mId = m.model_id || m.id;            if (mId) {              modelDetails[mId] = {                score: m.score != null ? parseFloat(m.score) : null,                brand: m.brand || null,                parent: (m.parents && Array.isArray(m.parents) && m.parents.length > 0) ? m.parents[0].name : null              };            }          });          offers.forEach(item => {            let data = { ...item };            const mId = data.model_id;            if (mId && modelDetails[mId]) {              data.review_score = modelDetails[mId].score;              data.model_brand = modelDetails[mId].brand;              data.model_parent = modelDetails[mId].parent;            } else {              data.review_score = null;            }                        let itemOffers = [];            if (Array.isArray(item.offers)) itemOffers = item.offers;            else if (Array.isArray(item.offer)) itemOffers = item.offer;            else if (item.offers && typeof item.offers === 'object') itemOffers = [item.offers];            else if (item.offer && typeof item.offer === 'object') itemOffers = [item.offer];            if (itemOffers.length > 0) {              itemOffers.forEach(subItem => {                let subData = { ...item, ...subItem };                const subId = subData.model_id;                if (subId && modelDetails[subId]) {                  subData.review_score = modelDetails[subId].score;                  subData.model_brand = modelDetails[subId].brand;                  subData.model_parent = modelDetails[subId].parent;                } else if (data.review_score != null) {                  subData.review_score = data.review_score;                }                if (subData.merchant && typeof subData.merchant === 'object') {                  subData.merchant_name = subData.merchant.name;                }                this.deals.push(this.extractDealData(subData));              });              return;            }                        if (item.merchant && typeof item.merchant === 'object') {              data.merchant_name = item.merchant.name;            }                        this.deals.push(this.extractDealData(data));          });                    this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        async fetchAdviserDeals(query) {          // ======================================================================          // TODO: ADVISER API REPLACEMENT          // The code below simulates the Adviser API response using mock data.          // Once the real endpoint is ready, remove getAdviserMockData() and           // perform an actual fetch() request similar to fetchHawkDeals().          // Example:          // const area = this.getAreaCode();          // let apiUrl = `https://your-adviser-api.com/search?q=${query}&area=${area}`;          // if (this.priceFilter && this.priceFilter.value !== 'all') {          //   const val = this.priceFilter.value;          //   if (val === 'under50') apiUrl += '&filter_max_price=50';          //   else if (val === '50_100') apiUrl += '&filter_max_price=100';          //   else if (val === '100_200') apiUrl += '&filter_max_price=200';          //   else if (val === '200_500') apiUrl += '&filter_max_price=500';          // }          // const res = await fetch(apiUrl);          // const rawData = await res.json();          // ======================================================================          // Simulating network latency          await new Promise(resolve => setTimeout(resolve, 400));                    const rawData = this.getAdviserMockData();          let offers = [];                    if (rawData && rawData.data && rawData.data.Get && Array.isArray(rawData.data.Get.Deal)) {            offers = rawData.data.Get.Deal;          }                    // Basic client-side filtering for the mock if we want it to react to the query          const q = query.toLowerCase();          const selectedRetailer = (this.retailerSelect && this.retailerSelect.value) ? this.retailerSelect.value.toLowerCase() : null;                    offers.forEach(item => {            const dataObj = item;                        // Apply retailer filter            const itemRetailer = (dataObj.dataRetailer || '').toLowerCase();            if (selectedRetailer && itemRetailer !== selectedRetailer && !itemRetailer.includes(selectedRetailer)) {              return;            }                        // Apply mock price filter            let price = dataObj.dataDiscountedPrice || 0;            if (typeof price === 'string') {              price = parseFloat(price.replace(/[^0-9.]/g, ''));            }            let priceVal = null;            const min = this.customPriceMin ? this.customPriceMin.value : '';            const max = this.customPriceMax ? this.customPriceMax.value : '';            if (min || max) {               priceVal = `${min}_${max}`;            } else if (this.priceFilter && this.priceFilter.value !== 'all') {               priceVal = this.priceFilter.value;            }            if (priceVal) {              if (priceVal === 'under50' && price >= 50) return;              if (priceVal === 'over50' && price <= 50) return;              if (priceVal === 'over30' && price <= 30) return;              if (priceVal === 'over500' && price <= 500) return;              if (priceVal.includes('_')) {                 const parts = priceVal.split('_');                 if (parts[0] && price < parseFloat(parts[0])) return;                 if (parts[1] && price > parseFloat(parts[1])) return;              }            }                        // Map Adviser schema to our widget's expected schema            const mappedData = {              url: dataObj.linkHREF || dataObj.dataLink || '#',              image: dataObj.imageURL || (dataObj.image && dataObj.image.src) || '',              title: dataObj.dataProduct || (dataObj.product && dataObj.product.name) || 'Product Deal',              merchant: dataObj.dataRetailer || 'Retailer',              price: dataObj.dataDiscountedPrice || 0,              currency: dataObj.dataCurrency === 'USD' ? '$' : (dataObj.dataCurrency || '$'),              msrp: dataObj.dataOriginalPrice || null            };                        const titleLow = mappedData.title.toLowerCase();            const merchLow = mappedData.merchant.toLowerCase();                        // Smarter mock filtering            let isMatch = false;            if (q === '' || this.isBroadQuery(q)) {              isMatch = true;            } else if (titleLow.includes(q) || merchLow.includes(q)) {              isMatch = true;            } else if ((q.includes('laptop') || q.includes('mac') || q.includes('pc')) && (titleLow.includes('macbook') || titleLow.includes('laptop'))) {              isMatch = true;            } else if ((q.includes('tv') || q.includes('television')) && (titleLow.includes('tv') || titleLow.includes('oled') || titleLow.includes('qled'))) {              isMatch = true;            } else if ((q.includes('phone') || q.includes('smartphone')) && (titleLow.includes('galaxy') || titleLow.includes('phone'))) {              isMatch = true;            } else if ((q.match(/watch|fitness|run|shoe/)) && (titleLow.includes('forerunner') || titleLow.includes('saucony') || titleLow.includes('watch'))) {              isMatch = true;            }                        if (isMatch) {               this.deals.push(this.extractDealData(mappedData));            }          });                    let rowLimit = this.getRowsLimit();          // Intentionally omitting the slice here to allow "Load More" to work if the API returns more                    this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        getAdviserMockData() {          return {            "data": {              "Get": {                "Deal": [                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 300,                    "dataOriginalPrice": 399,                    "dataProduct": "Samsung Galaxy A36",                    "dataRetailer": "Samsung",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/MqDYsukV3JBG54te6dEs7j.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 14,                    "dataOriginalPrice": 24,                    "dataProduct": "Blink Mini",                    "dataRetailer": "Amazon",                    "imageURL": "http://cdn.mos.cms.futurecdn.net/3JurmAjHsDa5tPdaHAwEV8.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 59,                    "dataOriginalPrice": 99,                    "dataProduct": "Ring Video Doorbell",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/rAh4uR7AsAsALCCLTXnLNJ.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 10,                    "dataOriginalPrice": 599,                    "dataProduct": "MacBook Neo",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/Lg4Dvg68j9SbB5CPNrTEpH.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 749,                    "dataOriginalPrice": 849,                    "dataProduct": "65\\\" Fire TV Omni 4K QLED TV",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/SG34ZWodUkLTxJvMTbjPYR.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 71,                    "dataOriginalPrice": 160,                    "dataProduct": "Saucony Hurricane 24",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/vxf7UD5T2Am7guVzFoFcZ4.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 649,                    "dataOriginalPrice": 749,                    "dataProduct": "Garmin Forerunner 970",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/3GKnEu7CdhtxPMfnPCMCiA.png"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 1049,                    "dataOriginalPrice": 1499,                    "dataProduct": "LG 48\\\" C4 4K OLED TV",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/imvwZV9zoMD6fn9Afuge35.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 1499,                    "dataOriginalPrice": 2199,                    "dataProduct": "Samsung 49\\\" Odyssey Neo G9 4K Gaming Monitor",                    "dataRetailer": "Amazon",                    "imageURL": "http://cdn.mos.cms.futurecdn.net/XWDEJ5dUAE2nhK8k3Jk7k7.png"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 299,                    "dataOriginalPrice": 699,                    "dataProduct": "EGOHOME Black Memory Foam Mattress (queen)",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/hMUemtAejNETLVYxNrktzm.jpg"                  }                ]              }            }          };        }        decodeHTML(html) {          if (!html) return '';          const txt = document.createElement("textarea");          txt.innerHTML = String(html);          return txt.value;        }        extractDealData(item) {          const priceRawStr = String(item.price || item.current_price || '0');          const msrpRawStr = String(item.was_price || item.msrp || item.original_price || '0');          const rawPrice = parseFloat(priceRawStr.replace(/[^\d.]/g, '')) || 0;          const rawMsrp = parseFloat(msrpRawStr.replace(/[^\d.]/g, '')) || 0;          const isCheckPrice = rawPrice === 0 || priceRawStr === '0.00' || priceRawStr === '0';                    let originalImageUrl = item.image || item.image_url || item.product_image || '';          let imageUrl = originalImageUrl;          if ((!imageUrl || isCheckPrice) && item.model_image_url) {             imageUrl = item.model_image_url;             originalImageUrl = imageUrl;          } else if ((!imageUrl || isCheckPrice) && item.model_image) {             imageUrl = item.model_image;             originalImageUrl = imageUrl;          }                    if (imageUrl) {            imageUrl = imageUrl.replace(/-(\d+)-(\d+)(\.[a-z.]+)$/i, '$3');          }                    let fallbackImage = '';          if (originalImageUrl && originalImageUrl !== imageUrl) {             fallbackImage = originalImageUrl;          } else if (item.model_image && item.model_image !== imageUrl) {             fallbackImage = item.model_image;          } else if (item.model_image_url && item.model_image_url !== imageUrl) {             fallbackImage = item.model_image_url;          }                    const rawCurrency = item.currency || item.currency_symbol || '$';                    let savingLabel = item.percentage_saving_label || '';          if (!savingLabel && rawMsrp > rawPrice && rawPrice > 0) {            const pct = Math.round(((rawMsrp - rawPrice) / rawMsrp) * 100);            if (pct > 0) {              savingLabel = `${pct}% OFF`;            }          }                    const isPrime = item.shipping && item.shipping.prime === true;                    let scoreRaw = (item.review_score !== undefined && item.review_score !== null && item.review_score > 0) ? parseFloat(item.review_score) : null;          let starRating = 0;          if (scoreRaw !== null) {            starRating = Math.round((scoreRaw > 10 ? scoreRaw / 20 : scoreRaw / 2) * 2) / 2;          }                    return {            id: item.offer_id || item.link || item.url || item.offer_link || Math.random().toString(),            url: item.link || item.url || item.offer_link || '#',            image: imageUrl,            fallbackImage: fallbackImage,            title: item.name || item.title || item.model_name || item.product_name || 'Unknown Product',            brand: item.brand || '',            productName: item.model_name || item.product_name || item.name || '',            merchant: item.merchant_name || item.merchant || item.retailer || 'Retailer',            price: item.price !== undefined ? String(item.price) : '0.00',            currency: this.decodeHTML(rawCurrency),            msrp: item.was_price || item.msrp || item.original_price || null,            rawPrice: rawPrice,            rawMsrp: rawMsrp,            hasWasPrice: (item.was_price !== undefined && item.was_price !== null),            isCheckPrice: isCheckPrice,            savingLabel: savingLabel,            isPrime: isPrime,            starRating: starRating > 0 ? starRating : null,            modelId: item.model_id || '',            productKey: item.product_key || '',            merchantId: (item.merchant && typeof item.merchant === 'object') ? item.merchant.id || '' : '',            matchId: item.match_id || '',            merchantNetwork: (item.merchant && typeof item.merchant === 'object') ? item.merchant.an || '' : '',            merchantUrl: (item.merchant && typeof item.merchant === 'object') ? item.merchant.url || '' : '',            modelBrand: item.model_brand || item.brand || '',            modelParent: item.model_parent || ''          };        }        sortData() {          const sortVal = this.sortSelect ? this.sortSelect.value : (this.getViewMode() === 'savings_squad' ? 'date_desc' : 'discount_desc');          if (sortVal === 'price_asc') {            this.deals.sort((a, b) => a.rawPrice - b.rawPrice);          } else if (sortVal === 'price_desc') {            this.deals.sort((a, b) => b.rawPrice - a.rawPrice);          } else if (sortVal === 'discount_desc') {            this.deals.sort((a, b) => {              const aDiscount = a.rawMsrp > a.rawPrice ? (a.rawMsrp - a.rawPrice) : 0;              const bDiscount = b.rawMsrp > b.rawPrice ? (b.rawMsrp - b.rawPrice) : 0;              return bDiscount - aDiscount;            });          } else if (sortVal === 'date_desc') {             this.deals.sort((a, b) => {                let dateA = 0;                let dateB = 0;                if (a && a.modifiedDate) {                   const valA = Array.isArray(a.modifiedDate) ? a.modifiedDate[0] : a.modifiedDate;                   dateA = new Date(valA).getTime();                   if (isNaN(dateA)) dateA = 0;                }                if (b && b.modifiedDate) {                   const valB = Array.isArray(b.modifiedDate) ? b.modifiedDate[0] : b.modifiedDate;                   dateB = new Date(valB).getTime();                   if (isNaN(dateB)) dateB = 0;                }                return dateB - dateA;             });          }        }        getFilteredDeals() {          let filteredDeals = [...this.deals];                    if (this.dealModeToggle && this.dealModeToggle.checked) {            filteredDeals = filteredDeals.filter(d => d.hasWasPrice || (d.msrp && d.rawMsrp > d.rawPrice));          }                    return filteredDeals;        }        showLoading() {          const _div = '<' + '/div>';          const skeletonCardHtml = `            \x3Cdiv class="tg-df-card">              \x3Cdiv class="tg-df-card-image-box">                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-img">${_div}              ${_div}              \x3Cdiv class="tg-df-card-body">                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short">${_div}                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text title">${_div}                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text title">${_div}                \x3Cdiv class="tg-df-card-footer mt-auto">                  \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="height:24px;">${_div}                  \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text" style="height:44px; margin-top:8px;">${_div}                ${_div}              ${_div}            ${_div}`;          this.grid.innerHTML = Array(4).fill(skeletonCardHtml).join('');        }        showError() {          const _div = '<' + '/div>';          this.grid.innerHTML = `\x3Cdiv class="tg-df-message">            An error occurred while finding deals. Please check your connection and try again.          ${_div}`;        }        escapeHTML(str) {          if (!str) return '';          return String(str).replace(/[&<>'"]/g, tag => ({              '&': '&', '<': '<', '>': '>', "'": ''', '"': '"'          }[tag] || tag));        }                bindCouponButtons() {          const btns = this.root.querySelectorAll('.tg-df-tag-coupons');          btns.forEach(btn => {            btn.addEventListener('click', (e) => {              e.preventDefault();              e.stopPropagation();              const merchant = btn.getAttribute('data-merchant');              this.openVouchersModal(merchant);            });          });                    const closeBtn = this.root.querySelector('#tg-df-vouchers-close');          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          if (closeBtn) {            closeBtn.onclick = () => this.closeVouchersModal();          }          if (backdrop) {            backdrop.onclick = (e) => {              if (e.target === backdrop) this.closeVouchersModal();            };          }        }                closeVouchersModal() {          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          if (backdrop) backdrop.classList.remove('active');        }                async checkMerchantsCouponsBulk(merchants) {          if (!merchants || merchants.length === 0) return {};          const controller = new AbortController();          const timeoutId = setTimeout(() => controller.abort(), 4000);          try {            const area = this.getAreaCode();            const url = new URL('https://search-api.fie.future.net.uk/widget.php');            url.searchParams.append('model_name', 'Everything');            url.searchParams.append('language', 'en-GB');            if (area) url.searchParams.append('area', area);            url.searchParams.append('combine_product_types', '1');            url.searchParams.append('filter_merchant_name', merchants.join(','));            url.searchParams.append('all_filters', 'false');            url.searchParams.append('exclude_unlabelled', 'false');            url.searchParams.append('include_specs', 'false');            url.searchParams.append('sort', 'voucher');            url.searchParams.append('distinct_merchants', 'natural');            url.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');            url.searchParams.append('rows', '120');            url.searchParams.append('origin', 'widgets-clientside');                        let res; try { res = await fetch(url.toString(), { signal: controller.signal }); } catch (e) { return {}; }            clearTimeout(timeoutId);            if (!res.ok) return {};            const data = await res.json();                        let offers = [];            if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {              offers = data.widget.data.offers;            } else if (data && data.data && Array.isArray(data.data.offers)) {              offers = data.data.offers;            } else if (Array.isArray(data)) {              offers = data;            } else if (data && Array.isArray(data.offers)) {              offers = data.offers;            } else if (data && data.offers && Array.isArray(data.offers.offer)) {              offers = data.offers.offer;            } else if (data && Array.isArray(data.data)) {              offers = data.data;            }                        const foundMerchants = new Set();            offers.forEach(o => {              let mName = o.merchant_name || o.merchant || o.retailer;              if (mName && typeof mName === 'object') mName = mName.name;              if (mName) foundMerchants.add(String(mName).toLowerCase());            });            const resultMap = {};            merchants.forEach(m => {              if (m) resultMap[m] = foundMerchants.has(String(m).toLowerCase());            });            return resultMap;          } catch (e) {            return {};          }        }                async openVouchersModal(merchantName) {          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          const title = this.root.querySelector('#tg-df-vouchers-title');          const content = this.root.querySelector('#tg-df-vouchers-content');                    if (!backdrop || !content) return;                    // HACK: Hide closing tags          const _div = '<' + '/div>';          const _span = '<' + '/span>';          const _a = '<' + '/a>';          const _h4 = '<' + '/h4>';          const _svg = '<' + '/svg>';          const _circle = '<' + '/circle>';          const _polyline = '<' + '/polyline>';          const _rect = '<' + '/rect>';          const _path = '<' + '/path>';                    title.innerText = `${merchantName} Coupons & Deals`;          content.innerHTML = `\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text">${_div}                               \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text">${_div}`;          backdrop.classList.add('active');                    try {            const area = this.getAreaCode();            const url = new URL('https://search-api.fie.future.net.uk/widget.php');            url.searchParams.append('model_name', 'Everything');            url.searchParams.append('language', 'en-GB');            if (area) url.searchParams.append('area', area);            url.searchParams.append('combine_product_types', '1');            url.searchParams.append('filter_merchant_name', merchantName);            url.searchParams.append('all_filters', 'false');            url.searchParams.append('exclude_unlabelled', 'false');            url.searchParams.append('include_specs', 'false');            url.searchParams.append('sort', 'voucher');            url.searchParams.append('distinct_merchants', 'natural');            url.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');            url.searchParams.append('rows', '50');            url.searchParams.append('origin', 'widgets-clientside');                        const res = await fetch(url.toString());            if (!res.ok) throw new Error('API Error');            const data = await res.json();                        let offers = [];            if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {              offers = data.widget.data.offers;            } else if (data && data.data && Array.isArray(data.data.offers)) {              offers = data.data.offers;            } else if (Array.isArray(data)) {              offers = data;            } else if (data && Array.isArray(data.offers)) {              offers = data.offers;            } else if (data && data.offers && Array.isArray(data.offers.offer)) {              offers = data.offers.offer;            } else if (data && Array.isArray(data.data)) {              offers = data.data;            }                        if (offers.length === 0) {              content.innerHTML = `\x3Cdiv class="tg-df-message">No vouchers currently available for ${this.escapeHTML(merchantName)}.${_div}`;              return;            }                        content.innerHTML = offers.map((v, idx) => {              let offerObj = v;              if (v.offers && v.offers.offer) {                offerObj = Array.isArray(v.offers.offer) ? v.offers.offer[0] : v.offers.offer;              } else if (v.offer) {                offerObj = Array.isArray(v.offer) ? v.offer[0] : v.offer;              }              let logoUrl = v.logo_url || offerObj.logo_url || '';              if (!logoUrl && v.merchant) {                if (Array.isArray(v.merchant) && v.merchant.length > 0) logoUrl = v.merchant[0].logo_url || '';                else logoUrl = v.merchant.logo_url || '';              }                            const offerName = offerObj.name || offerObj.title || v.name || v.title || 'Special Offer';              const endTime = offerObj.end_time || v.end_time || '';              const linkUrl = offerObj.link || offerObj.url || v.link || v.url || '#';                            let foundVoucherCode = '';              const findVoucherCode = (obj) => {                if (!obj || typeof obj !== 'object') return;                if (obj.type === 'voucher_code' && obj.display_value) {                  foundVoucherCode = obj.display_value;                  return;                }                if (Array.isArray(obj)) {                  for (const item of obj) {                    findVoucherCode(item);                    if (foundVoucherCode) return;                  }                } else {                  for (const k in obj) {                    if (Object.prototype.hasOwnProperty.call(obj, k)) {                      findVoucherCode(obj[k]);                      if (foundVoucherCode) return;                    }                  }                }              };              findVoucherCode(offerObj);              if (!foundVoucherCode) findVoucherCode(v);                            const voucherCode = foundVoucherCode || offerObj.voucher_code || v.voucher_code || '';              const codeHtml = voucherCode ? `\x3Cspan class="tg-df-voucher-code" data-action="copy-code" data-code="${this.escapeHTML(voucherCode)}" title="Copy to clipboard">                \x3Cspan class="tg-df-voucher-code-text">${this.escapeHTML(voucherCode)}${_span}                \x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-left:6px;flex-shrink:0;" class="tg-df-voucher-copy-icon">                  \x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2">${_rect}                  \x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1">${_path}                ${_svg}              ${_span}` : '';                            const logoHtml = logoUrl                 ? `\x3Cimg src="${this.escapeHTML(logoUrl)}" alt="${this.escapeHTML(offerName)}" class="tg-df-voucher-logo" />`                 : `\x3Cdiv class="tg-df-voucher-logo" style="background:#e2e8f0;">${_div}`;                            let expiryHtml = '';              if (endTime) {                let dStr = endTime;                if (!isNaN(dStr) && String(dStr).length === 10) dStr = Number(dStr) * 1000;                const d = new Date(dStr);                if (!isNaN(d.getTime())) {                  const options = { year: 'numeric', month: 'short', day: 'numeric' };                  expiryHtml = `                    \x3Cdiv class="tg-df-voucher-expiry">                      \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">                        \x3Ccircle cx="12" cy="12" r="10">${_circle}                        \x3Cpolyline points="12 6 12 12 16 14">${_polyline}                      ${_svg}                      Expires ${d.toLocaleDateString(undefined, options)}                    ${_div}`;                }              }              const revenueIdVal = generateRevenueId(linkUrl, offerName, merchantName, null);              const rewrittenLinkUrl = rewriteAffiliateLink(linkUrl, area, revenueIdVal);              return `                \x3Ca href="${this.escapeHTML(rewrittenLinkUrl)}" target="_blank" rel="noopener nofollow" class="tg-df-voucher-item"                  data-action="voucher-click"                  data-product-name="${this.escapeHTML(offerName)}"                  data-merchant-name="${this.escapeHTML(merchantName)}"                  data-analytics-id="${this.escapeHTML(offerObj.offer_id || offerObj.id || v.id || '')}"                  data-price=""                  data-previous-price=""                  data-original-link="${this.escapeHTML(linkUrl)}"                  data-revenue-id="${revenueIdVal}"                  data-index="${idx}"                  data-total="${offers.length}"                  data-in-stock="true"                  data-currency="USD"                  data-model-id="${this.escapeHTML(offerObj.model_id || v.model_id || offerObj.id || v.id || '')}"                  data-merchant-id="${this.escapeHTML(offerObj.merchant_id || offerObj.merchant?.id || '')}"                >                  ${logoHtml}                  \x3Cdiv class="tg-df-voucher-content">                    \x3Ch4 class="tg-df-voucher-title">${this.escapeHTML(offerName)}${_h4}                    ${codeHtml}                    ${expiryHtml}                  ${_div}                ${_a}              `;            }).join('');                        // Attach copy functionality            const copyBtns = content.querySelectorAll('[data-action="copy-code"]');            copyBtns.forEach(btn => {              btn.addEventListener('click', async (e) => {                e.preventDefault();                e.stopPropagation();                                const code = btn.getAttribute('data-code');                if (!code) return;                                try {                  const copyToClipboard = async (text) => {                     if (window.navigator.clipboard && window.isSecureContext) {                        try { await window.navigator.clipboard.writeText(text); return; } catch (e) {}                     }                     const textArea = document.createElement("textarea");                     textArea.value = text;                     textArea.style.position = "fixed";                     document.body.appendChild(textArea);                     textArea.focus();                     textArea.select();                     document.execCommand('copy');                     textArea.remove();                  };                  await copyToClipboard(code);                                    // Visual feedback                  btn.classList.add('copied');                  const textSpan = btn.querySelector('.tg-df-voucher-code-text');                  const iconSvg = btn.querySelector('.tg-df-voucher-copy-icon');                                    const origText = textSpan.innerText;                  const origIcon = iconSvg.innerHTML;                                    textSpan.innerText = 'Copied!';                  iconSvg.innerHTML = `\x3Cpolyline points="20 6 9 17 4 12">${_polyline}`;                                    setTimeout(() => {                    if (btn) {                      btn.classList.remove('copied');                      if (textSpan) textSpan.innerText = origText;                      if (iconSvg) iconSvg.innerHTML = origIcon;                    }                  }, 2000);                                    trackElementInteraction({                    id: 'voucher-code-copy',                    name: 'Copy Voucher Code',                    label: `Copied ${code} for ${merchantName}`                  });                } catch (err) {                  console.warn('Failed to copy text: ', err);                }              });            });            // Attach voucher click tracking            const voucherBtns = content.querySelectorAll('[data-action="voucher-click"]');            voucherBtns.forEach(btn => {              btn.addEventListener('click', (e) => {                if (e.target.closest('[data-action="copy-code"]')) return;                                const productName = btn.getAttribute('data-product-name');                const merchantNameAttr = btn.getAttribute('data-merchant-name');                const productId = btn.getAttribute('data-analytics-id');                const price = parseFloat(btn.getAttribute('data-price')) || null;                const prevPriceStr = btn.getAttribute('data-previous-price');                const previousPrice = prevPriceStr ? parseFloat(prevPriceStr) : null;                const originalLink = btn.getAttribute('data-original-link');                const rewrittenLink = btn.getAttribute('href');                const revenueId = btn.getAttribute('data-revenue-id');                const index = parseInt(btn.getAttribute('data-index'), 10) || 0;                const inStock = btn.getAttribute('data-in-stock') === 'true';                const totalText = btn.getAttribute('data-total');                const totalDeals = parseInt(totalText, 10) || 0;                const productCategoryName = 'deals';                const trackingParams = {                  widgetId: this.widgetId,                  productCategoryName: productCategoryName,                  product: {                    modelId: btn.getAttribute('data-model-id') || null,                    matchId: btn.getAttribute('data-match-id') || null,                    brand: btn.getAttribute('data-model-brand') || null,                    parent: btn.getAttribute('data-model-parent') || null,                    name: productName,                    price: price,                    previousPrice: previousPrice,                    link: rewrittenLink,                    originalLink: originalLink,                    inStock: inStock                  },                  zeroBasedProductIndexOrNull: index,                  totalDealsOrProducts: totalDeals,                   merchant: {                    id: btn.getAttribute('data-merchant-id') || null,                    network: btn.getAttribute('data-merchant-network') || null,                    url: btn.getAttribute('data-merchant-url') || null,                    name: merchantNameAttr                  },                  revenueId: revenueId,                  widgetTypeName: this.widgetTypeName,                  isoCurrencyCode: btn.getAttribute('data-currency') || 'USD'                };                if (typeof trackDealClick === 'function') {                  trackDealClick(trackingParams);                }              });            });                                  } catch (e) {            console.warn(e);            content.innerHTML = `\x3Cdiv class="tg-df-message">Failed to load vouchers.${_div}`;          }        }        render() {          try {            if (this.getViewMode() === 'savings_squad' && this.airedaleTags.length > 0) {              if (this.categoryFilterWrapper) {                 this.categoryFilterWrapper.style.display = 'flex';              }              if (this.categoryFilter) {                 const _option = '<' + '/option>';                 let optionsHtml = `\x3Coption value="all">All Categories${_option}`;                 this.airedaleTags.forEach(tag => {                    const isSelected = this.activeDealTag === tag ? 'selected' : '';                    optionsHtml += `\x3Coption value="${this.escapeHTML(tag)}" ${isSelected}>${this.escapeHTML(tag)} (${this.airedaleTagCounts[tag] || 0})${_option}`;                 });                 this.categoryFilter.innerHTML = optionsHtml;                 this.categoryFilter.value = this.activeDealTag || 'all';              }            } else {               if (this.categoryFilterWrapper) {                  this.categoryFilterWrapper.style.display = 'none';               }            }            const displayDeals = this.getFilteredDeals();          // HACK: Hide closing tags from the CMS HTML sanitizer so it doesn't strip them during in-page injection          const _div = '<' + '/div>';          const _span = '<' + '/span>';          const _a = '<' + '/a>';          const _h3 = '<' + '/h3>';          const _p = '<' + '/p>';          const _strong = '<' + '/strong>';          const _sup = '<' + '/sup>';          const _button = '<' + '/button>';          if (displayDeals.length === 0) {            if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {              if (this.deals.length > 0) {                 this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                  No deals match your selected filters.                ${_div}`;              } else if (this.getViewMode() === 'savings_squad' && this.currentQuery.length <= 2) {                 // Do not show "no exact matches" if query is empty for savings_squad                 this.grid.innerHTML = '';              } else {                 this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                  No exact matches found for "\x3Cstrong>${this.escapeHTML(this.currentQuery)}${_strong}". Try adjusting your search term.                ${_div}`;              }            } else {              this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                Search product or category names to discover the best deals from across the web.              ${_div}`;            }            return;          }          let dealsHtml = displayDeals.slice(0, this.displayLimit).map((deal, index) => {            try {               const currencySym = this.escapeHTML(deal.currency);               const isoCurrencyCode = normalizeCurrency(currencySym);               const escapedPrice = this.escapeHTML(deal.price);               const escapedMsrp = this.escapeHTML(deal.msrp);               const areaCode = this.getAreaCode();                              const revenueId = generateRevenueId(deal.url, deal.title, deal.merchant, null);               const originalLink = deal.url;               const rewrittenLink = rewriteAffiliateLink(deal.url, areaCode, revenueId);                        const productCategoryName = 'deals';            const dataAttr = `              data-action="${deal.isCheckPrice ? 'view-similar-click' : 'deal-click'}"              data-analytics-id="${this.escapeHTML(deal.externalProductId || deal.id || '')}"              data-product-name="${this.escapeHTML(deal.title)}"              data-merchant-name="${this.escapeHTML(deal.merchant)}"              data-price="${deal.rawPrice || ''}"              data-previous-price="${deal.rawMsrp || ''}"              data-original-link="${this.escapeHTML(originalLink)}"              data-revenue-id="${revenueId}"              data-index="${index}"              data-total="${displayDeals.length}"              data-in-stock="${deal.inStock !== false}"              data-currency="${this.escapeHTML(isoCurrencyCode)}"              data-model-id="${this.escapeHTML(deal.modelId || '')}"              data-product-key="${this.escapeHTML(deal.productKey || '')}"              data-merchant-id="${this.escapeHTML(deal.merchantId || '')}"            `;                        let priceGroupHtml = '';            let isSavingsSquadMode = this.getViewMode() === 'savings_squad';            let ctaText = 'View Deal';            let formattedPrice = '';            let msrpHtml = '';                        if (deal.isCheckPrice) {              ctaText = isSavingsSquadMode ? 'View Deal' : 'Check Price';              if (isSavingsSquadMode) {                priceGroupHtml = `                  \x3Cdiv class="tg-df-card-merchant-wrapper">                    \x3Cspan class="tg-df-card-merchant-pill" title="${this.escapeHTML(deal.merchant)}">${this.escapeHTML(deal.merchant)}${_span}                  ${_div}                  \x3Cdiv class="tg-df-card-price-group">                  ${_div}                `;              } else {                priceGroupHtml = `                  \x3Cdiv class="tg-df-card-merchant-wrapper">                    \x3Cspan class="tg-df-card-merchant-pill" title="${this.escapeHTML(deal.merchant)}">${this.escapeHTML(deal.merchant)}${_span}                  ${_div}                  \x3Cdiv class="tg-df-card-price-group">                    \x3Cspan class="tg-df-card-price" style="font-size: 15px; font-weight: 500; font-style: italic;">See price at retailer${_span}                  ${_div}                `;              }            } else {              // Format Price              formattedPrice = escapedPrice.includes(currencySym)                 ? escapedPrice                 : `${currencySym}${escapedPrice}`;                              // Format MSRP              msrpHtml = deal.msrp && deal.rawMsrp > deal.rawPrice                ? `\x3Cspan class="tg-df-card-msrp">${escapedMsrp.includes(currencySym) ? escapedMsrp : currencySym + escapedMsrp}${_span}`                : '';                              priceGroupHtml = `                \x3Cdiv class="tg-df-card-merchant-wrapper">                  \x3Cspan class="tg-df-card-merchant-pill" title="${this.escapeHTML(deal.merchant)}">${this.escapeHTML(deal.merchant)}${_span}                ${_div}                \x3Cdiv class="tg-df-card-price-group">                  ${isSavingsSquadMode ? '' : `                  \x3Cspan class="tg-df-card-price">${formattedPrice}${_span}                  ${msrpHtml}                  `}                ${_div}              `;            }                        const discountBadgeHtml = deal.savingLabel && !deal.isCheckPrice              ? `\x3Cspan class="tg-df-card-discount-badge">${this.escapeHTML(deal.savingLabel)}${_span}`              : '';                          // HACK for CMS            const _button = '<' + '/button>';            const _svg = '<' + '/svg>';            const _path = '<' + '/path>';            const _rect = '<' + '/rect>';            const _circle = '<' + '/circle>';            const _polyline = '<' + '/polyline>';            const _line = '<' + '/line>';                        let badgesHtml = '';            const primeBadge = deal.isPrime ? `              \x3Cspan class="tg-df-tag tg-df-tag-prime">                \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="currentColor">                  \x3Cpath d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z">${_path}                ${_svg} Prime              ${_span}            ` : '';                        const couponsBadge = deal.merchant && deal.merchant.toLowerCase().includes('amazon') ? '' : `              \x3Cdiv class="tg-df-coupon-wrapper" data-merchant="${this.escapeHTML(deal.merchant)}" style="display:inline-flex; align-items:center;">                \x3Cdiv class="tg-df-coupon-spinner">${_div}                \x3Cbutton type="button" class="tg-df-tag tg-df-tag-coupons" data-action="coupons-click" data-merchant="${this.escapeHTML(deal.merchant)}" style="display:none;">                  \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">                    \x3Cpath d="M20.59 13.41l-7.17 7.17a2 2 0 0 1-2.83 0L2 12V2h10l8.59 8.59a2 2 0 0 1 0 2.82z">${_path}                    \x3Cline x1="7" y1="7" x2="7.01" y2="7">${_line}                  ${_svg} Coupons                ${_button}              ${_div}            `;                        // Note: We always add coupons badge if there's a chance, but to allow 3-line titles we check wrapper display state            badgesHtml = `              \x3Cdiv class="tg-df-card-badges">                ${primeBadge}                ${couponsBadge}              ${_div}            `;            const _linearGradient = '<' + '/linearGradient>';            const _polygon = '<' + '/polygon>';            const _stop = '<' + '/stop>';            const _defs = '<' + '/defs>';                        let starHtml = '';            if (deal.starRating) {              let rating = deal.starRating;                            if (rating > 0) {                const fullStars = Math.floor(rating);                const halfStar = (rating - fullStars) >= 0.5 ? 1 : 0;                const emptyStars = Math.max(0, 5 - fullStars - halfStar);                const blue = '#1f69ff'; // Tom's guide brand color from VIEW DEAL button                const gray = '#cbd5e1';                                const starSvgFull = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="${blue}" stroke="${blue}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26">${_polygon}${_svg}`;                                const gradId = 'half_grad_' + Math.floor(Math.random()*1000000);                const starSvgHalf = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" stroke="${blue}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cdefs>\x3ClinearGradient id="${gradId}" x1="0" x2="1" y1="0" y2="0">\x3Cstop offset="50%" stop-color="${blue}">${_stop}\x3Cstop offset="50%" stop-color="transparent">${_stop}${_linearGradient}${_defs}                  \x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26" fill="url(#${gradId})">${_polygon}${_svg}`;                                  const starSvgEmpty = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="${gray}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26">${_polygon}${_svg}`;                                let stars = [];                for (let i=0; i<fullStars; i++) stars.push(starSvgFull);                if (halfStar) stars.push(starSvgHalf);                for (let i=0; i<emptyStars; i++) stars.push(starSvgEmpty);                                starHtml = `\x3Cdiv class="tg-df-card-stars" style="display:flex;align-items:center;margin-bottom:8px;font-size:13px;font-weight:600;color:var(--tg-df-text-muted);">                  \x3Cspan style="margin-right:6px;">Tom's Guide:${_span}                  \x3Cdiv style="display:flex;gap:2px;">                    ${stars.join('')}                  ${_div}                ${_div}`;              }            }            let htmlOutput = '';            if (isSavingsSquadMode) {              htmlOutput += `              \x3Cdiv class="hawk-deal-widget-container tg-df-mobile-only" data-collapsible="true">                ${this.editorMode ? `\x3Cinput type="checkbox" class="tg-df-deal-checkbox" data-id="${this.escapeHTML(deal.id)}" ${this.selectedDeals.has(deal.id) ? 'checked' : ''} style="margin-bottom: 10px;">` : ''}                \x3Cdiv class="hawk-deal-widget-wrap">                  \x3Cdiv class="hawk-deal-widget-image-container">                    \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" rel="sponsored noopener" target="_blank" class="hawk-affiliate-link-deal-widget" ${dataAttr}>                      \x3Cimg ${deal.image ? `src="${this.escapeHTML(deal.image)}"` : ''} alt="${this.escapeHTML(deal.title)}" class="hawk-lazy-image-deal-widget" loading="lazy" width="140" height="160" onerror="${deal.fallbackImage ? `if(!this.dataset.fb) { this.dataset.fb='1'; this.src='${this.escapeHTML(deal.fallbackImage)}'; } else { this.style.opacity='0'; }` : `this.style.opacity='0';`}">                    ${_a}                  ${_div}                  \x3Cdiv class="hawk-deal-widget-text-cta-container">                    \x3Cdiv class="hawk-deal-widget-text-body-container">                      \x3Cdiv class="hawk-deal-widget-text-body-main">                        \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                          ${deal.isCheckPrice ? `                            \x3Cspan class="hawk-deal-widget-title-product-title">${this.escapeHTML(deal.title)}${_span}                          ` : `                            \x3Cspan class="hawk-deal-widget-title-product-title">${deal.brand ? this.escapeHTML(deal.brand) + ' ' : ''}${this.escapeHTML(deal.productName || deal.title || '')}:${_span}                          `}                        ${_a}                        ${!deal.isCheckPrice && deal.rawMsrp && deal.rawMsrp > deal.rawPrice ? `                          \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                            \x3Cspan class="hawk-deal-widget-title-was-price">was ${currencySym}${escapedMsrp}${_span}                          ${_a}                        ` : ''}                        \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                          \x3Cspan class="hawk-deal-widget-title-retailer-price">                            ${!deal.isCheckPrice ? `                              \x3Cspan class="hawk-deal-widget-title-price">now ${formattedPrice}${_span}                              \x3Cspan class="hawk-deal-widget-title-retailer"> at ${this.escapeHTML(deal.merchant)}${_span}                            ` : `                              \x3Cspan class="hawk-deal-widget-title-price">See price at ${this.escapeHTML(deal.merchant)}${_span}                            `}                          ${_span}                        ${_a}                        ${deal.description ? `\x3Cdiv class="hawk-deal-widget-text-body-description">\x3Cp>${this.escapeHTML(deal.description)}${_p}${_div}` : ''}                      ${_div}                    ${_div}                    \x3Cdiv class="hawk-deal-widget-footer">                      \x3Cdiv class="hawk-deal-widget-button-wrapper">                        \x3Cdiv class="hawk-deal-widget-preferred-partner-wrapper">                          \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-deal-button" rel="sponsored noopener" target="_blank" ${dataAttr}>                            \x3Cspan>${deal.isCheckPrice ? 'Check Price' : 'View Deal'}${_span}                          ${_a}                        ${_div}                      ${_div}                    ${_div}                  ${_div}                ${_div}              ${_div}              `;            }            htmlOutput += `              \x3Cdiv class="tg-df-card ${isSavingsSquadMode ? 'tg-df-desktop-only' : ''}">                ${this.editorMode ? `\x3Cinput type="checkbox" class="tg-df-deal-checkbox" data-id="${this.escapeHTML(deal.id)}" ${this.selectedDeals.has(deal.id) ? 'checked' : ''}>` : ''}                \x3Cdiv class="tg-df-card-image-box">                  ${discountBadgeHtml}                  \x3Ca href="${this.escapeHTML(rewrittenLink)}" ${dataAttr} target="_blank" rel="noopener nofollow" style="display: flex; align-items: center; justify-content: center; width: 100%; height: 100%;">                    \x3Cimg ${deal.image ? `src="${this.escapeHTML(deal.image)}"` : ''} alt="${this.escapeHTML(deal.title)}" class="tg-df-card-image" loading="lazy" onerror="${deal.fallbackImage ? `if(!this.dataset.fb) { this.dataset.fb='1'; this.src='${this.escapeHTML(deal.fallbackImage)}'; } else { this.style.opacity='0'; }` : `this.style.opacity='0';`}">                  ${_a}                ${_div}                \x3Cdiv class="tg-df-card-body">                  ${starHtml}                  ${badgesHtml}                  \x3Ch3 class="tg-df-card-title tg-df-custom-savings-squad-title" title="${this.escapeHTML(deal.title)}">                    \x3Ca href="${this.escapeHTML(rewrittenLink)}" disable-tracking="true" target="_blank" rel="noopener nofollow" style="text-decoration: none; color: inherit;">                      ${isSavingsSquadMode                         ? (deal.isCheckPrice                             ? (deal.title && deal.title.includes(':')                                 ? `\x3Cstrong>${this.escapeHTML(deal.title.substring(0, deal.title.indexOf(':') + 1))}${_strong}\x3Cspan style="color: #1f69ff; font-weight: normal;">${this.escapeHTML(deal.title.substring(deal.title.indexOf(':') + 1))}${_span}`                                : this.escapeHTML(deal.title)                              )                             : `\x3Cstrong>${deal.brand ? this.escapeHTML(deal.brand) + ' ' : ''}${this.escapeHTML(deal.productName || deal.title || '')}:${_strong} ${deal.rawMsrp && deal.rawMsrp > deal.rawPrice ? `\x3Cspan style="color: #d0021b; text-decoration: line-through; font-weight: normal; margin-right: 4px;">was ${currencySym}${escapedMsrp}${_span} ` : ''}\x3Cspan style="color: #1f69ff; font-weight: normal;">now ${formattedPrice} at ${this.escapeHTML(deal.merchant)}${_span}`                          )                        : this.escapeHTML(deal.title)                      }                    ${_a}                  ${_h3}                  ${deal.description ? `\x3Cp style="font-size: 13px; color: var(--tg-df-text-muted); margin-bottom: 12px; line-height: 1.4;">${this.escapeHTML(deal.description)}${_p}` : ''}                  \x3Cdiv class="tg-df-card-footer">                    ${priceGroupHtml}                    \x3Ca href="${this.escapeHTML(rewrittenLink)}" ${dataAttr} target="_blank" rel="noopener nofollow" class="tg-df-card-cta ${isSavingsSquadMode ? 'tg-df-cta-savings-squad' : ''}" style="text-decoration: none;">${ctaText}${_a}                  ${_div}                ${_div}              ${_div}            `;                        return htmlOutput;            } catch (e) {               console.log("Error rendering deal in map for index", index, typeof deal === 'object' ? JSON.stringify(deal) : deal, "MSG:", e.message);               return '';            }          }).join('');                    if (displayDeals.length > this.displayLimit || ((this.getViewMode() === 'carousel' || this.getViewMode() === 'auto') && displayDeals.length > 0 && displayDeals.length % ((this.rowsSelect && this.rowsSelect.value) ? parseInt(this.rowsSelect.value, 10) : 12) === 0)) {            if (this.getViewMode() === 'carousel') {               dealsHtml += `                 \x3Cbutton type="button" class="tg-df-load-more-card tg-df-load-more">                   \x3Csvg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-bottom: 8px;">\x3Cpath d="M5 12h14">\x3C/path>\x3Cpath d="m12 5 7 7-7 7">\x3C/path>\x3C/svg>                   Load More                 ${_button}               `;            } else {               dealsHtml += `                 \x3Cdiv style="width: 100%; display: flex; justify-content: center; margin-top: 16px; grid-column: 1 / -1;">                   \x3Cbutton type="button" class="tg-df-tag-outline tg-df-load-more" style="padding: 8px 24px; border-radius: 100px; font-weight: 600; font-size: 14px; cursor: pointer; display: flex; align-items: center;">Load More${_button}                 ${_div}               `;            }          }                    this.grid.innerHTML = dealsHtml;          // Inject JSON-LD          try {            let targetNode = this.hostContainer || document.head;            let jsonLdScript = targetNode.querySelector('#tg-df-json-ld-' + this.widgetId);            if (!jsonLdScript) {                jsonLdScript = document.createElement('script');                jsonLdScript.type = 'application/ld+json';                jsonLdScript.id = 'tg-df-json-ld-' + this.widgetId;                targetNode.appendChild(jsonLdScript);            }            const jsonLdData = {              "@context": "https://schema.org",              "@type": "ItemList",              "itemListElement": displayDeals.slice(0, this.displayLimit).map((deal, index) => {                 let isoCurrency = "USD";                 if (deal.currency === '£') isoCurrency = "GBP";                 else if (deal.currency === '€') isoCurrency = "EUR";                 else if (deal.currency === 'A$') isoCurrency = "AUD";                 else if (deal.currency === 'CA$') isoCurrency = "CAD";                 const areaCode = typeof this.getAreaCode === 'function' ? this.getAreaCode() : 'US';                 const revenueId = typeof generateRevenueId === 'function' ? generateRevenueId(deal.url, deal.title, deal.merchant, null) : '';                 const rewrittenLink = typeof rewriteAffiliateLink === 'function' ? rewriteAffiliateLink(deal.url, areaCode, revenueId) : deal.url;                 return {                   "@type": "ListItem",                   "position": index + 1,                   "item": {                     "@type": "Product",                     "name": deal.title,                     "image": deal.image || "",                     "description": deal.description || "",                     "brand": {                       "@type": "Brand",                       "name": deal.brand || ""                     },                     "offers": {                       "@type": "Offer",                       "priceCurrency": isoCurrency,                       "price": deal.rawPrice || 0,                       "url": rewrittenLink,                       "seller": {                         "@type": "Organization",                         "name": deal.merchant || ""                       }                     }                   }                 };              }).filter(item => item.item.name)            };            jsonLdScript.textContent = JSON.stringify(jsonLdData);          } catch(e) { console.warn("JSON-LD generation failed", e); }                    let gridWrapper = this.grid.parentElement;          if (gridWrapper && gridWrapper.classList.contains('tg-df-grid-wrapper')) {             let rightChevron = gridWrapper.querySelector('.tg-df-carousel-scroll-right');             let leftChevron = gridWrapper.querySelector('.tg-df-carousel-scroll-left');             if (this.getViewMode() === 'carousel') {                 // The observer set up in setupScrollListeners handles visibility.                 if (rightChevron) rightChevron.style.display = 'flex';                 if (leftChevron) leftChevron.style.display = 'none'; // reset correctly             } else {                 if (rightChevron) rightChevron.style.display = 'none';                 if (leftChevron) leftChevron.style.display = 'none';             }          }                    const loadMoreBtn = this.grid.querySelector('.tg-df-load-more');          if (loadMoreBtn) {            loadMoreBtn.addEventListener('click', async () => {              if (typeof trackElementInteraction === 'function') {                trackElementInteraction({ id: 'load-more', name: 'Load more', label: 'Load More Results' });              }              if (displayDeals.length <= this.displayLimit) {                 loadMoreBtn.innerHTML = `                  <svg class="tg-df-spinner" style="width: 16px; height: 16px; display: inline-block; vertical-align: middle; margin-right: 8px;" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" d="M12 2v4m0 12v4M4.93 4.93l2.83 2.83m8.48 8.48l2.83 2.83M2 12h4m12 0h4M4.93 19.07l2.83-2.83m8.48-8.48l2.83-2.83"/></svg>                  Loading...                 `;                 loadMoreBtn.disabled = true;                 await this.fetchDeals(this.currentQuery, true);              } else {                 this.displayLimit += this.getRowsLimit();                 this.render();              }            });          }                      this.bindCouponButtons();            this.checkAndUpdateCoupons();                        // Allow hawklinks.js to discover and rewrite our widget links             // by appending the .article-body class and manually triggering processArticle.            let container = this.root.classList.contains('tg-df-container') ? this.root : this.root.querySelector('.tg-df-container');            if (container && !container.classList.contains('article-body')) {               container.classList.add('article-body');            }            setTimeout(() => {               if (this.grid && !this.grid.classList.contains('article-body')) this.grid.classList.add('article-body');               document.dispatchEvent(new CustomEvent('processArticle', { detail: { element: this.root } }));            }, 50);          } catch(e) {            console.warn("Widget render error", e);          }        }                async checkAndUpdateCoupons() {          const wrappers = Array.from(this.root.querySelectorAll('.tg-df-coupon-wrapper'));          if (wrappers.length === 0) return;                    const merchants = [...new Set(wrappers.map(w => w.getAttribute('data-merchant')).filter(Boolean))];          if (merchants.length === 0) return;          const couponResultsMap = await this.checkMerchantsCouponsBulk(merchants);                    for (const merchant of merchants) {            const hasCoupons = !!couponResultsMap[merchant];            const merchantWrappers = wrappers.filter(w => w.getAttribute('data-merchant') === merchant);            merchantWrappers.forEach(wrapper => {              const spinner = wrapper.querySelector('.tg-df-coupon-spinner');              const btn = wrapper.querySelector('.tg-df-tag-coupons');                            if (spinner) spinner.style.display = 'none';                            if (hasCoupons && btn) {                btn.style.display = 'inline-flex';              } else if (!hasCoupons) {                wrapper.style.display = 'none';              }            });          }        }        updateFloatingCopyBar() {          if (!this.editorBar || !this.editorSelectedCount) return;          if (this.editorMode && this.selectedDeals.size > 0) {            this.editorBar.style.display = 'flex';            this.editorSelectedCount.innerText = this.selectedDeals.size;          } else {            this.editorBar.style.display = 'none';          }        }        async copySelectedDealsToCMS() {           function htmlToSlate(htmlString) {              if (!htmlString) return [{ type: 'paragraph', children: [{ text: '' }] }];              let doc;              if (typeof window !== 'undefined' && window.DOMParser) {                 doc = new DOMParser().parseFromString(htmlString, 'text/html');              } else {                 doc = document.implementation.createHTMLDocument('');                 doc.body.innerHTML = htmlString;              }                            function parseNode(node, marks = {}) {                  if (node.nodeType === 3) {                      const text = node.textContent;                      if (!text) return null;                      return { text: text, ...marks };                  }                  if (node.nodeType === 1) {                      const tagName = node.tagName.toLowerCase();                      if (tagName === 'br') {                          return { type: 'line-break', children: [{ text: '' }] };                      }                      if (tagName === 'p') {                          let children = Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                          if (children.length === 0) children.push({ text: "" });                          return { type: 'paragraph', children };                      }                      if (tagName === 'strong' || tagName === 'b') {                          const newMarks = { ...marks, bold: true };                          return Array.from(node.childNodes).map(child => parseNode(child, newMarks)).flat().filter(Boolean);                      }                      if (tagName === 'em' || tagName === 'i') {                          const newMarks = { ...marks, italic: true };                          return Array.from(node.childNodes).map(child => parseNode(child, newMarks)).flat().filter(Boolean);                      }                      if (tagName === 'a') {                          const href = node.getAttribute('href') || '';                          let children = Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                          if (children.length === 0) children.push({ text: "" });                          return {                              type: 'link',                              url: href,                              isNoFollow: (node.getAttribute('rel') || '').includes('nofollow'),                              isSponsored: (node.getAttribute('rel') || '').includes('sponsored'),                              isOpenNewTab: node.getAttribute('target') === '_blank',                              isPreventDataRewrite: false,                              children: children                          };                      }                      return Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                  }                  return null;              }                            let blocksArray = [];              let currentParagraphChildren = [];              function flushParagraph() {                  if (currentParagraphChildren.length > 0) {                      blocksArray.push({ type: 'paragraph', children: currentParagraphChildren });                      currentParagraphChildren = [];                  }              }              Array.from(doc.body.childNodes).forEach(node => {                  const parsed = parseNode(node, {});                  const parsedItems = Array.isArray(parsed) ? parsed : (parsed ? [parsed] : []);                  parsedItems.forEach(item => {                      if (item.type === 'paragraph') {                          flushParagraph();                          blocksArray.push(item);                      } else {                          currentParagraphChildren.push(item);                      }                  });              });              flushParagraph();              if (blocksArray.length === 0) {                  blocksArray = [{ type: 'paragraph', children: [{ text: '' }] }];              }              return blocksArray;           }           const blocks = [];                      this.editorCopyBtn.innerHTML = '\x3Cspan class="tg-df-coupon-spinner" style="display:inline-block; margin-right:8px; border-top-color:#fff;">' + '<' + '/span> Copying...';           for (const deal of Array.from(this.selectedDeals.values())) {              const url = deal.url;              const merchant = deal.merchant;              const title = deal.title;              const image = deal.image;              const currentPrice = deal.currency + deal.rawPrice;              const wasPrice = deal.hasWasPrice && deal.rawMsrp > deal.rawPrice ? deal.currency + deal.rawMsrp : '';                            let couponsChildren = [];              try {                  const area = this.getAreaCode();                  const apiUrl = new URL('https://search-api.fie.future.net.uk/widget.php');                  apiUrl.searchParams.append('model_name', 'Everything');                  apiUrl.searchParams.append('language', 'en-GB');                  apiUrl.searchParams.append('area', area);                  apiUrl.searchParams.append('combine_product_types', '1');                  apiUrl.searchParams.append('filter_merchant_name', merchant);                  apiUrl.searchParams.append('all_filters', 'false');                  apiUrl.searchParams.append('exclude_unlabelled', 'false');                  apiUrl.searchParams.append('include_specs', 'false');                  apiUrl.searchParams.append('sort', 'voucher');                  apiUrl.searchParams.append('distinct_merchants', 'natural');                  apiUrl.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');                  apiUrl.searchParams.append('rows', '3');                  apiUrl.searchParams.append('origin', 'widgets-clientside');                                    let res; try { res = await fetch(apiUrl.toString()); } catch (e) { return; }                  if (res.ok) {                      const data = await res.json();                      let offers = [];                      if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {                        offers = data.widget.data.offers;                      } else if (data && data.data && Array.isArray(data.data.offers)) {                        offers = data.data.offers;                      }                                            if (offers.length > 0) {                          couponsChildren.push({ text: "Also check out these coupons: ", bold: true });                          offers.slice(0, 3).forEach((offer, idx) => {                              const actualOffer = offer.offer || offer;                              const offerName = actualOffer.name || actualOffer.title || offer.model_name || offer.title || offer.name || 'Coupon';                              const linkUrl = actualOffer.link || actualOffer.url || actualOffer.offer_link || '#';                              couponsChildren.push({ type: "line-break", children: [{ text: "" }] });                              couponsChildren.push({ text: "🎟️ " });                              couponsChildren.push({                                  type: "link",                                  url: linkUrl,                                  isNoFollow: true,                                  isSponsored: false,                                  isOpenNewTab: true,                                  isPreventDataRewrite: false,                                  children: [{ text: offerName, bold: true }]                              });                          });                      }                  }              } catch (err) {                  console.warn('Failed to fetch coupons for', merchant, err);              }              let descriptionValue = [];              if (deal.text) {                 descriptionValue = htmlToSlate(deal.text);              } else {                 const dealDescriptions = [                   `Don't miss out on this fantastic deal for the ${title}. It is currently available at ${merchant} for a highly competitive price.`,                   `We've spotted an excellent price drop on the ${title}. Grab it now at ${merchant} before it's gone.`,                   `The ${title} is currently seeing a generous discount over at ${merchant}. This is a perfect time to buy if you've been holding out.`,                   `If you're in the market for the ${title}, ${merchant} has just the deal for you.`,                   `Score the ${title} for less at ${merchant} right now. This is a rare chance to save big.`,                   `Upgrade your setup with the ${title}, now available at a stellar price via ${merchant}.`                 ];                 const randomDescription = dealDescriptions[Math.floor(Math.random() * dealDescriptions.length)];                 descriptionValue = [                    { type: "paragraph", children: [{ text: randomDescription }] }                 ];              }                            if (couponsChildren.length > 0) {                 let lastBlock = descriptionValue[descriptionValue.length - 1];                 if (lastBlock && lastBlock.type === 'paragraph') {                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children.push({ text: "Also check out these coupons: ", bold: true });                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children = lastBlock.children.concat(couponsChildren);                 } else {                     descriptionValue.push({                         type: "paragraph",                         children: [                             { type: "line-break", children: [{ text: "" }] },                             { type: "line-break", children: [{ text: "" }] },                             { text: "Also check out these coupons: ", bold: true },                             { type: "line-break", children: [{ text: "" }] },                             ...couponsChildren                         ]                     });                 }              }              function normalizeCurrencyToISO(symbol) {                const map = { '£': 'GBP', '$': 'USD', 'A$': 'AUD', 'CA$': 'CAD', '€': 'EUR' };                return map[symbol] || symbol;              }              const isoCurrency = normalizeCurrencyToISO(deal.currency);              blocks.push({                 id: (window.crypto && window.crypto.randomUUID) ? window.crypto.randomUUID() : 'cms-' + Date.now() + Math.random(),                 blockTypeName: "deal",                 excludeFrom: [],                 collapsible: false,                 props: {                    description: {                       value: descriptionValue,                       touched: false,                       validationMessage: ""                    },                    image: {                       value: {                          credit: [{ type: "paragraph", children: [{ text: merchant }] }],                          dateCreated: Date.now(),                          dateModified: Date.now(),                          distribution: [],                          fileSize: 0,                          height: 1000,                          id: deal.id,                          imageRights: "",                          src: image,                          name: title + ".jpg",                          tags: [],                          width: 1000                       },                       touched: false,                       validationMessage: ""                    },                    showDealButton: { value: true, touched: false, validationMessage: "" },                    isPreferredPartner: { value: false, touched: false, validationMessage: "" },                    linkHref: { value: url, touched: false, validationMessage: "" },                    linkLabel: { value: "", touched: false, validationMessage: "" },                    linkIsNoFollow: { value: true, touched: false, validationMessage: "" },                    linkIsSponsored: { value: false, touched: false, validationMessage: "" },                    linkIsOpenNewWindow: { value: true, touched: false, validationMessage: "" },                    customPromoFlags: { value: [], touched: false, validationMessage: "" },                    showStarDeal: { value: false, touched: false, validationMessage: "" },                    savingType: { value: "none", touched: false, validationMessage: "" },                    starDealPromoFlag: { value: "", touched: false, validationMessage: "" },                    showEditorsChoice: { value: false, touched: false, validationMessage: "" },                    editorsChoiceTitle: { value: "", touched: false, validationMessage: "" },                    hawkPriceCurrency: { value: { value: isoCurrency, label: isoCurrency }, touched: false, validationMessage: "" },                    hawkPrice: { value: deal.hasWasPrice ? String(deal.rawMsrp) : String(deal.rawPrice), touched: false, validationMessage: "" },                    hawkSalePrice: { value: String(deal.rawPrice), touched: false, validationMessage: "" },                    lastCheckedPriceDate: { value: "", touched: false, validationMessage: "" },                    hawkModel: { touched: false, validationMessage: "" },                    productId: { value: "", touched: false, validationMessage: "" },                    voucherId: { value: "", touched: false, validationMessage: "" },                    brand: { value: deal.brand || merchant, touched: false, validationMessage: "" },                    productName: { value: title, touched: false, validationMessage: "" },                    label: { value: "", touched: false, validationMessage: "" },                    retailer: { value: merchant, touched: false, validationMessage: "" },                    priceCheckError: false                 },                 failedFetchError: ""              });           }           const payload = {              type: "articleBuilderPages",              data: blocks           };           const jsonStr = JSON.stringify(payload);                      if (navigator.clipboard && navigator.clipboard.writeText) {              navigator.clipboard.writeText(jsonStr).then(() => {                 this.editorCopyBtn.innerHTML = 'Copied!';                 setTimeout(() => {                    this.editorCopyBtn.innerHTML = '\x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2"><' + '/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"><' + '/path><' + '/svg> Copy to CMS';                 }, 2000);              }).catch(err => {                 console.warn('Failed to copy text: ', err);                 alert('Failed to copy deals to clipboard. See console.');              });           } else {              // Fallback              const textArea = document.createElement("textarea");              textArea.value = jsonStr;              document.body.appendChild(textArea);              textArea.focus();              textArea.select();              try {                 document.execCommand('copy');                 this.editorCopyBtn.innerHTML = 'Copied!';                 setTimeout(() => {                    this.editorCopyBtn.innerHTML = '\x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2"><' + '/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"><' + '/path><' + '/svg> Copy to CMS';                 }, 2000);              } catch (err) {                 console.warn('Fallback: Oops, unable to copy', err);                 alert('Fallback: Failed to copy deals to clipboard.');              }              document.body.removeChild(textArea);           }        }      }      // Initialize the Widget      if (document.readyState === 'loading') {        document.addEventListener('DOMContentLoaded', () => new DealsFinderWidget({ rootId: 'signal-deals-finder-root', rootNode: shadowRoot, hostContainer: hostContainer }));      } else {        new DealsFinderWidget({ rootId: 'signal-deals-finder-root', rootNode: shadowRoot, hostContainer: hostContainer });      }    })();  </script></div> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/home/kitchen-dining/dont-let-summer-end-ninja-pizza-ovens-blenders-and-coolers-are-up-to-42-percent-off-at-amazon</link>
                                                                            <description>
                            <![CDATA[ A bunch of Ninja appliances are on sale at Amazon — check out the biggest upgrades for your home and kitchen. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">EfTBZoT6Fwj3CeUdpAZ3aV</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/CeAv82LBUHuqBFDCWGzZqb-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Thu, 13 Aug 2026 16:23:09 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Kitchen & Dining]]></category>
                                                    <category><![CDATA[Home]]></category>
                                                    <category><![CDATA[Home Appliances]]></category>
                                                                                                <author><![CDATA[ millie.daviswilliams@futurenet.com (Millie Davis-Williams) ]]></author>                    <dc:creator><![CDATA[ Millie Davis-Williams ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/WU6pa7hKuxs5ScCoqcXYWA.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Millie is a Deals Editor at Tom&#039;s Guide specializing in tech deals content. Based in London, Millie has spent a lifetime stubbornly refusing to pay full price on any possible purchase. She has years of searching for the best discounts on the latest and greatest phones, TVs and gadgets under her belt, and knows how to sort the best deals from the rest. Helping readers save on the products they want is her mission, whether it’s an Apple Watch or a new tablet.&lt;/p&gt;&lt;p&gt;Since working at Tom’s Guide, Millie has covered retail events like Prime Day, Black Friday and Cyber Monday extensively, meaning she knows the products readers are looking for and the best times of year to hit “purchase.”&lt;/p&gt;&lt;p&gt;When she’s not looking for discounts, Millie covers news and writes how-to articles about everything from phones, streaming devices, and headphones to apps and video games.&lt;/p&gt;&lt;p&gt;In her spare time, Millie enjoys reading, gaming on her Nintendo Switch and creating digital art. She’s also a fan of watching Disney movies and collecting plush (the latter having totally taken over her bedroom.)&lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/CeAv82LBUHuqBFDCWGzZqb-1280-80.jpg">
                                                            <media:credit><![CDATA[Tom&#039;s Guide]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Ninja Blast Max blender on counter]]></media:description>                                                            <media:text><![CDATA[Ninja Blast Max blender on counter]]></media:text>
                                <media:title type="plain"><![CDATA[Ninja Blast Max blender on counter]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/CeAv82LBUHuqBFDCWGzZqb-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Amazon is closing out the summer with a bunch of Ninja appliance deals. Whether you're hoping to extend grilling season into the fall, want to keep enjoying delicious smoothies, or even improve your knife skills while cooking — there are some discounts here that you definitely don't want to miss.</p><p>I've been searching the sale and have found <a href="https://www.amazon.com/stores/page/471F718E-0761-48DF-ABAF-0FC6590C695B" target="_blank" rel="nofollow">up to 30% off Ninja appliances</a>. I've listed all my favorites below, so keep scrolling to check them out.</p><h3 class="article-body__section" id="section-quick-links"><span>Quick Links</span></h3><ul><li><a href="https://www.amazon.com/stores/page/471F718E-0761-48DF-ABAF-0FC6590C695B" target="_blank" rel="nofollow"><strong>shop all Ninja deals at Amazon</strong></a></li><li><strong>Ninja Blast Max: </strong><a href="https://www.amazon.com/dp/B0GX2SD3K6?" target="_blank" rel="nofollow"><strong>was $99 now $69</strong></a><strong></strong></li><li><strong>Ninja Iced Coffee Maker: </strong><a href="https://www.amazon.com/Ninja-Specialty-Single-Serve-Compatible-PB055ABL/dp/B0C25Y15TL" target="_blank" rel="nofollow"><strong>was $129 now $99</strong></a></li><li><strong>Ninja Crispi 4-in-1 Portable Glass Air Fryer: </strong><a href="https://www.amazon.com/Ninja-Microwave-Dishwasher-Containers-FN101GY/dp/B0DDDD8WD6?" target="_blank" rel="nofollow"><strong>was $179 now $159</strong></a></li><li><strong>Ninja 10-Pc German Steel Knife Set: </strong><a href="https://www.amazon.com/dp/B0H2NLCZBQ" target="_blank" rel="nofollow"><strong>was $249 now $199</strong></a></li><li><strong>Ninja Woodfire Oven & Smoker: </strong><a href="https://www.amazon.com/Ninja-Woodfire-Technology-terracotta-OO101/dp/B0C6BQVDX3/" target="_blank" rel="nofollow"><strong>was $399 now $279</strong></a></li><li><strong>Ninja Luxe Café Premier: </strong><a href="https://www.amazon.com/dp/B0FGDTHY1Y" target="_blank" rel="nofollow"><strong>now $599</strong></a></li></ul><h3 class="article-body__section" id="section-ninja-deals"><span>Ninja Deals</span></h3><div class="product"><a data-dimension112="9ae6da84-96fe-11f1-a330-f9d854e50872" data-action="Deal Block" data-label="Blast Max" data-dimension48="Blast Max" data-dimension25="$69" href="https://www.amazon.com/dp/B0GX2SD3K6?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1216px;"><p class="vanilla-image-block" style="padding-top:123.36%;"><img id="9Q4QY399FaozAFUt4j8dTW" name="ninja-blast-max-portable-blender--twist--bb517479-54ce-4a77-974c-58e2f44dde33.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/9Q4QY399FaozAFUt4j8dTW.jpg" mos="" align="middle" fullscreen="" width="1216" height="1500" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>The Ninja Blast Max is capable of taking on any challenge you throw at it, including crushing ice and blitzing berries to make yummy smoothies. It comes with multiple blend settings to make sure your blender is using the right level of power for the task at hand, and the compact size means it’s a great option for anyone with a small kitchen. <a class="view-deal button" href="https://www.amazon.com/dp/B0GX2SD3K6?" target="_blank" rel="nofollow" data-dimension112="9ae6da84-96fe-11f1-a330-f9d854e50872" data-action="Deal Block" data-label="Blast Max" data-dimension48="Blast Max" data-dimension25="$69">View Deal</a></p></div><div class="product"><a data-dimension112="9ae6dae8-96fe-11f1-af0b-bffac6dd08f7" data-action="Deal Block" data-label="Belgian Waffle Maker" data-dimension48="Belgian Waffle Maker" data-dimension25="$79" href="https://www.amazon.com/Ninja-BW1001-NeverStick-Precision-Pour-Chef-curated/dp/B0B358VDZJ/ref=" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1614px;"><p class="vanilla-image-block" style="padding-top:86.00%;"><img id="XofzJVhShmZ3kcVxuocQvB" name="Ninja Belgian Waffle Maker" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/XofzJVhShmZ3kcVxuocQvB.png" mos="" align="middle" fullscreen="" width="1614" height="1388" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Ninja-BW1001-NeverStick-Precision-Pour-Chef-curated/dp/B0B358VDZJ/ref=" target="_blank" rel="nofollow" data-dimension112="9ae6dae8-96fe-11f1-af0b-bffac6dd08f7" data-action="Deal Block" data-label="Belgian Waffle Maker" data-dimension48="Belgian Waffle Maker" data-dimension25="$79">Belgian Waffle Maker: was $99 now $79</a></strong><br>Weekend brunch just got an upgrade. This vertical waffle maker has five shade settings so everyone gets their waffle exactly how they like it, plus a specialty setting for high-sugar batters like brownies (yes, really). The precision-pour cup takes the guesswork out of measuring, and audible alerts mean no more burnt disasters. Pair it with the Ninja CREAMi for the ultimate breakfast-dessert combo. <a class="view-deal button" href="https://www.amazon.com/Ninja-BW1001-NeverStick-Precision-Pour-Chef-curated/dp/B0B358VDZJ/ref=" target="_blank" rel="nofollow" data-dimension112="9ae6dae8-96fe-11f1-af0b-bffac6dd08f7" data-action="Deal Block" data-label="Belgian Waffle Maker" data-dimension48="Belgian Waffle Maker" data-dimension25="$79">View Deal</a></p></div><div class="product"><a data-dimension112="9ae6db42-96fe-11f1-bc49-877570370827" data-action="Deal Block" data-label="Pods & Grounds Specialty Single-Serve Iced Coffee Maker" data-dimension48="Pods & Grounds Specialty Single-Serve Iced Coffee Maker" data-dimension25="$99" href="https://www.amazon.com/Ninja-Specialty-Single-Serve-Compatible-PB055ABL/dp/B0C25Y15TL" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:679px;"><p class="vanilla-image-block" style="padding-top:99.56%;"><img id="4uiaRXRKY8Go6F4ZpM7UdA" name="Ninja coffee" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/4uiaRXRKY8Go6F4ZpM7UdA.jpg" mos="" align="middle" fullscreen="" width="679" height="676" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Ninja-Specialty-Single-Serve-Compatible-PB055ABL/dp/B0C25Y15TL" target="_blank" rel="nofollow" data-dimension112="9ae6db42-96fe-11f1-bc49-877570370827" data-action="Deal Block" data-label="Pods & Grounds Specialty Single-Serve Iced Coffee Maker" data-dimension48="Pods & Grounds Specialty Single-Serve Iced Coffee Maker" data-dimension25="$99">Pods & Grounds Specialty Single-Serve Iced Coffee Maker: was $129 now $99</a></strong><br>This stylish Ninja coffee maker comes in a gorgeous Sage colorway and is now on sale for $30 off. Whether you prefer pods or grounds, this device makes tasty brews in 7 sizes (6-oz. to 24-oz) and has a built-in, fold-away milk frother!<a class="view-deal button" href="https://www.amazon.com/Ninja-Specialty-Single-Serve-Compatible-PB055ABL/dp/B0C25Y15TL" target="_blank" rel="nofollow" data-dimension112="9ae6db42-96fe-11f1-bc49-877570370827" data-action="Deal Block" data-label="Pods & Grounds Specialty Single-Serve Iced Coffee Maker" data-dimension48="Pods & Grounds Specialty Single-Serve Iced Coffee Maker" data-dimension25="$99">View Deal</a></p></div><div class="product"><a data-dimension112="9ae6dba6-96fe-11f1-abb4-4baee8b836fa" data-action="Deal Block" data-label="NeverClog Cold Press Juicer" data-dimension48="NeverClog Cold Press Juicer" data-dimension25="$129" href="https://www.amazon.com/dp/B0DPXNR6YS" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:522px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="pKMqdL3azKMYSNwdTHk4m9" name="Ninja Never Clog" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/pKMqdL3azKMYSNwdTHk4m9.jpg" mos="" align="middle" fullscreen="" width="522" height="522" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0DPXNR6YS" target="_blank" rel="nofollow" data-dimension112="9ae6dba6-96fe-11f1-abb4-4baee8b836fa" data-action="Deal Block" data-label="NeverClog Cold Press Juicer" data-dimension48="NeverClog Cold Press Juicer" data-dimension25="$129">NeverClog Cold Press Juicer: was $149 now $129</a></strong><br>Create healthy juices from the comforts of your home with the Ninja Cold Press Juicer Pro. It features a powerful high torque motor and includes two one-touch programs that make it easy to operate. We also like that it has a pulp control that allows you to customize your juice with pulp or without.<a class="view-deal button" href="https://www.amazon.com/dp/B0DPXNR6YS" target="_blank" rel="nofollow" data-dimension112="9ae6dba6-96fe-11f1-abb4-4baee8b836fa" data-action="Deal Block" data-label="NeverClog Cold Press Juicer" data-dimension48="NeverClog Cold Press Juicer" data-dimension25="$129">View Deal</a></p></div><div class="product"><a data-dimension112="9ae6dc00-96fe-11f1-a154-9dead241a500" data-action="Deal Block" data-label="Mega Kitchen System" data-dimension48="Mega Kitchen System" data-dimension25="$179" href="https://www.amazon.com/dp/B00939I7EK" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1676px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="sWibiMn9jcqpLxyQRazy6f" name="Ninja Amazon 2.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/sWibiMn9jcqpLxyQRazy6f.jpg" mos="" align="middle" fullscreen="" width="1676" height="1676" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B00939I7EK" target="_blank" rel="nofollow" data-dimension112="9ae6dc00-96fe-11f1-a154-9dead241a500" data-action="Deal Block" data-label="Mega Kitchen System" data-dimension48="Mega Kitchen System" data-dimension25="$179">Mega Kitchen System: was $219 now $179</a></strong><br>Leave all the multi-tasking in the kitchen to one appliance with this Ninja blender. With four functions for smoothies, processing, dough, drinks and more it will quickly become your go-to kitchen appliance. With this ultimate appliance, you’ll be enjoying fresh, healthy drinks, homemade bread and sweet bakes.<a class="view-deal button" href="https://www.amazon.com/dp/B00939I7EK" target="_blank" rel="nofollow" data-dimension112="9ae6dc00-96fe-11f1-a154-9dead241a500" data-action="Deal Block" data-label="Mega Kitchen System" data-dimension48="Mega Kitchen System" data-dimension25="$179">View Deal</a></p></div><div class="product"><a data-dimension112="9ae6dc5a-96fe-11f1-9b25-51898ea4d818" data-action="Deal Block" data-label="Crispi 4-in-1 Portable Glass Air Fryer" data-dimension48="Crispi 4-in-1 Portable Glass Air Fryer" data-dimension25="$159" href="https://www.amazon.com/Ninja-Microwave-Dishwasher-Containers-FN101GY/dp/B0DDDD8WD6?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:679px;"><p class="vanilla-image-block" style="padding-top:85.86%;"><img id="zNkXNCVYCubXhCRwjaoGPj" name="Ninjs Crispi" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/zNkXNCVYCubXhCRwjaoGPj.jpg" mos="" align="middle" fullscreen="" width="679" height="583" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Ninja-Microwave-Dishwasher-Containers-FN101GY/dp/B0DDDD8WD6?" target="_blank" rel="nofollow" data-dimension112="9ae6dc5a-96fe-11f1-9b25-51898ea4d818" data-action="Deal Block" data-label="Crispi 4-in-1 Portable Glass Air Fryer" data-dimension48="Crispi 4-in-1 Portable Glass Air Fryer" data-dimension25="$159">Crispi 4-in-1 Portable Glass Air Fryer: was $179 now $159</a></strong><br>The Ninja Crispi is one of Ninja's most interesting recent releases. It features a removable cooking lid and interchangeable glass containers to cook meals of a range of sizes. In our <a href="https://www.tomsguide.com/home/air-fryers/ninja-crispi-air-fryer-review">Ninja Crispi review</a>, it earned a well-deserved 4.5 stars.  <a class="view-deal button" href="https://www.amazon.com/Ninja-Microwave-Dishwasher-Containers-FN101GY/dp/B0DDDD8WD6?" target="_blank" rel="nofollow" data-dimension112="9ae6dc5a-96fe-11f1-9b25-51898ea4d818" data-action="Deal Block" data-label="Crispi 4-in-1 Portable Glass Air Fryer" data-dimension48="Crispi 4-in-1 Portable Glass Air Fryer" data-dimension25="$159">View Deal</a></p></div><div class="product"><a data-dimension112="9ae6dcbe-96fe-11f1-8347-05248dfd47f6" data-action="Deal Block" data-label="FrostVault Go 24-Can Backpack Soft Cooler with Cold Dry Zone" data-dimension48="FrostVault Go 24-Can Backpack Soft Cooler with Cold Dry Zone" data-dimension25="$179" href="https://www.amazon.com/Ninja-FrostVaultTM-Backpack-Cooler-Storage/dp/B0GSHG5THD" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:540px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="bcxdGXf8PnyrQEezzPCfXb" name="Ninja FrostVault.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/bcxdGXf8PnyrQEezzPCfXb.jpg" mos="" align="middle" fullscreen="" width="540" height="540" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Ninja-FrostVaultTM-Backpack-Cooler-Storage/dp/B0GSHG5THD" target="_blank" rel="nofollow" data-dimension112="9ae6dcbe-96fe-11f1-8347-05248dfd47f6" data-action="Deal Block" data-label="FrostVault Go 24-Can Backpack Soft Cooler with Cold Dry Zone" data-dimension48="FrostVault Go 24-Can Backpack Soft Cooler with Cold Dry Zone" data-dimension25="$179">FrostVault Go 24-Can Backpack Soft Cooler with Cold Dry Zone: was $199 now $179</a></strong><br>The FrostVault Go is a super convenient backpack cooler from Ninja. It's available in two sizes — this deal is for the 24-can version. It has a Chillseal Lid for maximum ice retention and a Cold Dry Zone to keep food separate and at a food-safe temperature, to ensure its freshness.<a class="view-deal button" href="https://www.amazon.com/Ninja-FrostVaultTM-Backpack-Cooler-Storage/dp/B0GSHG5THD" target="_blank" rel="nofollow" data-dimension112="9ae6dcbe-96fe-11f1-8347-05248dfd47f6" data-action="Deal Block" data-label="FrostVault Go 24-Can Backpack Soft Cooler with Cold Dry Zone" data-dimension48="FrostVault Go 24-Can Backpack Soft Cooler with Cold Dry Zone" data-dimension25="$179">View Deal</a></p></div><div class="product"><a data-dimension112="9ae6dd18-96fe-11f1-97f5-8b56233f0907" data-action="Deal Block" data-label="10-Pc German Steel Knife Set" data-dimension48="10-Pc German Steel Knife Set" data-dimension25="$219" href="https://www.amazon.com/dp/B0H2NLCZBQ" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1368px;"><p class="vanilla-image-block" style="padding-top:109.65%;"><img id="juwy9ZiNjzvb7g4oTRTTT4" name="10-Pc German Steel Knife Set" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/juwy9ZiNjzvb7g4oTRTTT4.jpg" mos="" align="middle" fullscreen="" width="1368" height="1500" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0H2NLCZBQ" target="_blank" rel="nofollow" data-dimension112="9ae6dd18-96fe-11f1-97f5-8b56233f0907" data-action="Deal Block" data-label="10-Pc German Steel Knife Set" data-dimension48="10-Pc German Steel Knife Set" data-dimension25="$219">10-Pc German Steel Knife Set: was $249 now $219</a></strong><br>This 10-piece knife set from Ninja provides all the knives you need to cut, chop and dice your food. It also features a built-in knife sharpener, so you never have an excuse to use a blunt knife again — it'll keep them sharp for 10+ years.<a class="view-deal button" href="https://www.amazon.com/dp/B0H2NLCZBQ" target="_blank" rel="nofollow" data-dimension112="9ae6dd18-96fe-11f1-97f5-8b56233f0907" data-action="Deal Block" data-label="10-Pc German Steel Knife Set" data-dimension48="10-Pc German Steel Knife Set" data-dimension25="$219">View Deal</a></p></div><div class="product"><a data-dimension112="c39b8028-96ff-11f1-98e3-63e3970b16f9" data-action="Deal Block" data-label="Double Oven, 12-in-1 DCT401" data-dimension48="Double Oven, 12-in-1 DCT401" data-dimension25="$219" href="https://www.amazon.com/Ninja-DCT401-FlavorSeal-Convection-Stainless/dp/B0BRQS5BH6" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:875px;"><p class="vanilla-image-block" style="padding-top:85.60%;"><img id="LQBDeKyzWKbLWRQgh54YmA" name="Double Oven, 12-in-1 DCT401" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/LQBDeKyzWKbLWRQgh54YmA.jpg" mos="" align="middle" fullscreen="" width="875" height="749" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Ninja-DCT401-FlavorSeal-Convection-Stainless/dp/B0BRQS5BH6" target="_blank" rel="nofollow" data-dimension112="c39b8028-96ff-11f1-98e3-63e3970b16f9" data-action="Deal Block" data-label="Double Oven, 12-in-1 DCT401" data-dimension48="Double Oven, 12-in-1 DCT401" data-dimension25="$219">Double Oven, 12-in-1 DCT401: was $379 now $219</a></strong><br>We couldn’t recommend this toaster oven more. Although it has since been replaced by a newer model, the DCT401 is a previous winner on our list of the <a href="https://www.tomsguide.com/best-picks/best-toaster-ovens">best toaster ovens</a>. We love that it divides into two ovens you can access separately via the FlexDoor, so you can cook two things at once. There are 12 functions overall, including toast, bake, whole roast, air fry, convection and pizza — meaning you can cook pretty much anything in there however you like.<a class="view-deal button" href="https://www.amazon.com/Ninja-DCT401-FlavorSeal-Convection-Stainless/dp/B0BRQS5BH6" target="_blank" rel="nofollow" data-dimension112="c39b8028-96ff-11f1-98e3-63e3970b16f9" data-action="Deal Block" data-label="Double Oven, 12-in-1 DCT401" data-dimension48="Double Oven, 12-in-1 DCT401" data-dimension25="$219">View Deal</a></p></div><div class="product"><a data-dimension112="9ae6dd72-96fe-11f1-88b3-e97212624547" data-action="Deal Block" data-label="Foodi XL Pro Air Fry Oven, 10-in-1" data-dimension48="Foodi XL Pro Air Fry Oven, 10-in-1" data-dimension25="$229" href="https://www.amazon.com/Ninja-DT201-Countertop-Convection-Dehydrate/dp/B08BXX69K4" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1500px;"><p class="vanilla-image-block" style="padding-top:75.80%;"><img id="sFc44K8P9eTgsrZ4Kc25oB" name="Foodi XL Pro Air Fry Oven, 10-in-1" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/sFc44K8P9eTgsrZ4Kc25oB.jpg" mos="" align="middle" fullscreen="" width="1500" height="1137" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Ninja-DT201-Countertop-Convection-Dehydrate/dp/B08BXX69K4" target="_blank" rel="nofollow" data-dimension112="9ae6dd72-96fe-11f1-88b3-e97212624547" data-action="Deal Block" data-label="Foodi XL Pro Air Fry Oven, 10-in-1" data-dimension48="Foodi XL Pro Air Fry Oven, 10-in-1" data-dimension25="$229">Foodi XL Pro Air Fry Oven, 10-in-1: was $379 now $229</a></strong><br>39% off is one of the biggest Ninja discounts you'll find right now. While this XL air fryer/oven takes up a lot of space, it offers plenty of cooking functions and perfect cooking results every time. <a class="view-deal button" href="https://www.amazon.com/Ninja-DT201-Countertop-Convection-Dehydrate/dp/B08BXX69K4" target="_blank" rel="nofollow" data-dimension112="9ae6dd72-96fe-11f1-88b3-e97212624547" data-action="Deal Block" data-label="Foodi XL Pro Air Fry Oven, 10-in-1" data-dimension48="Foodi XL Pro Air Fry Oven, 10-in-1" data-dimension25="$229">View Deal</a></p></div><div class="product"><a data-dimension112="9ae6ddd6-96fe-11f1-a3e0-737367858cbe" data-action="Deal Block" data-label="Woodfire Oven & Smoker" data-dimension48="Woodfire Oven & Smoker" data-dimension25="$279" href="https://www.amazon.com/Ninja-Woodfire-Technology-terracotta-OO101/dp/B0C6BQVDX3/" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1500px;"><p class="vanilla-image-block" style="padding-top:90.20%;"><img id="C5KWDYUzjspNSP6tT8AAQP" name="81IeXOFExqL._AC_SL1500_.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/C5KWDYUzjspNSP6tT8AAQP.jpg" mos="" align="middle" fullscreen="" width="1500" height="1353" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>The Ninja Woodfire Oven & Smoker is a favorite with the Tom's Guide team. It makes amazing pizzas, smoked wings and many things in between. It's perfect to keep the summer vibes going all year long with delicious dishes.<a class="view-deal button" href="https://www.amazon.com/Ninja-Woodfire-Technology-terracotta-OO101/dp/B0C6BQVDX3/" target="_blank" rel="nofollow" data-dimension112="9ae6ddd6-96fe-11f1-a3e0-737367858cbe" data-action="Deal Block" data-label="Woodfire Oven & Smoker" data-dimension48="Woodfire Oven & Smoker" data-dimension25="$279">View Deal</a></p></div><div class="product"><a data-dimension112="9ae6de30-96fe-11f1-93b8-cf7bb06625b2" data-action="Deal Block" data-label="Luxe Café Premier" data-dimension48="Luxe Café Premier" data-dimension25="$599" href="https://www.amazon.com/dp/B0FGDTHY1Y" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:541px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="HcnQ36qmUJg5VJidxsJ76X" name="Ninja Luxe Cafe.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/HcnQ36qmUJg5VJidxsJ76X.jpg" mos="" align="middle" fullscreen="" width="541" height="541" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>It's not on sale, but the Ninja Luxe Café Premier is just that good. This 3-in-1 coffee machine brews quality espresso, drip coffee, and fast cold brew using its Barista Assist technology, an integrated grinder, and weight-based dosing. Plus, it makes creating pro-level microfoam easy, thanks to its Dual Froth system. Our reviewer called it "the best beginner-friendly espresso machine I’ve ever tested" in our <a href="https://www.tomsguide.com/home/ninja-luxe-cafe-premier-series-espresso-machine-review" data-dimension112="9ae6de30-96fe-11f1-93b8-cf7bb06625b2" data-action="Deal Block" data-label="Luxe Café Premier" data-dimension48="Luxe Café Premier" data-dimension25="$599">Ninja Luxe Café coffee maker review</a>.<a class="view-deal button" href="https://www.amazon.com/dp/B0FGDTHY1Y" target="_blank" rel="nofollow" data-dimension112="9ae6de30-96fe-11f1-93b8-cf7bb06625b2" data-action="Deal Block" data-label="Luxe Café Premier" data-dimension48="Luxe Café Premier" data-dimension25="$599">View Deal</a></p></div><div class="vizualizer-embed"><div class="tg-df-widget-host" data-widget-config="?search=Home+Appliances&brands=Ninja%2CShark&min_discount_ratio=0.95&offer_type=all&view_mode=carousel&widget_title=Top+Deals+Handpicked+by+Our+Editors&widget_subtitle=Discover+the+best+discounts+currently+available%2C+curated+daily+by+the+Tom%27s+Guide+Savings+Squad.&bg_color=light_blue" data-vizualizer-embed="true"></div>    <script>    /**     * Tom's Guide Deals Finder - Vanilla JS Encapsulated Engine     */    (function() {      // --- Freyr Analytics Adapter ---      function initAnalytics() {        window.dataLayer = window.dataLayer || [];        window.googletag = window.googletag || {};        window.googletag.cmd = window.googletag.cmd || [];        window.hawk = window.hawk || { analytics: { freyr: [] } };        window.hawk.analytics = window.hawk.analytics || { freyr: [] };        window.hawk.analytics.freyr = window.hawk.analytics.freyr || [];        window.freyr = window.freyr || { cmd: [] };        const scriptSrc = 'https://freyr.futurecdn.net/freyr.js';        const hostname = typeof window !== 'undefined' ? window.location.hostname : '';        const isTestEnv = typeof window.navigator !== 'undefined' && (window.navigator.webdriver || window.navigator.userAgent.includes('Headless'));        const shouldSendRealAnalytics = !isTestEnv && hostname && hostname !== 'localhost' && hostname !== '127.0.0.1' && !hostname.includes('run.app');        if (shouldSendRealAnalytics && !document.querySelector(`script[src="${scriptSrc}"]`)) {          const script = document.createElement('script');          script.src = scriptSrc;          script.async = true;          document.head.appendChild(script);        }      }      function storeEventForDebug(name, data) {        if (!window.hawk || !window.hawk.analytics || !window.hawk.analytics.freyr) return;        window.hawk.analytics.freyr.push({ name, data });        try {          if (typeof window !== 'undefined' && window.localStorage) {            window.localStorage.setItem("hawk", JSON.stringify(window.hawk));          }        } catch (e) {          // Ignore storage issues        }        try {          window.dispatchEvent(new CustomEvent("hawk-analytics-update"));        } catch (e) {}      }      function sendToFreyr(eventName, data) {        if (typeof window === 'undefined') return;        window.freyr = window.freyr || { cmd: [] };        window.freyr.cmd.push(() => {          if (window.freyr && window.freyr.pushAndUpdate) {            window.freyr.pushAndUpdate(eventName, data);          }        });      }      function sendEvent(event, skip = false) {        try {          storeEventForDebug(event.name, event.data);          if (!skip) {            sendToFreyr(event.name, event.data);          }        } catch (e) {          // Ensure tracking errors don't surface to the user        }      }      function getCookie(name) {        try {          const match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));          return match ? match[2] : null;        } catch (e) {          return null;        }      }      function normalizeCurrency(symbol) {        const map = {          '£': 'GBP',          '$': 'USD',          'A$': 'AUD',          'CA$': 'CAD',          '€': 'EUR'        };        return map[symbol] || symbol;      }      function trackElementInteraction(props) {        sendEvent({          name: 'elementInteraction',          data: {            element: {              action: props.action || "click",              id: props.id || undefined,              class: props.class || undefined,              name: props.name || undefined,              text: props.text || undefined,              label: props.label || undefined,              container: props.container || undefined,              url: props.url || undefined,              articleId: props.articleId || undefined            }          }        });      }      function generateRevenueId(url, productName, merchantName, modelId) {        const str = `${window.location.href}|${productName}|${merchantName}|${modelId || ''}|${new Date().toDateString()}|tomsguide`;        let hash = 0;        for (let i = 0; i < str.length; i++) {          const char = str.charCodeAt(i);          hash = ((hash << 5) - hash) + char;          hash = hash & hash;        }        let numericStr = Math.abs(hash).toString();        while (numericStr.length < 19) {          numericStr += Math.floor(Math.random() * 10).toString();        }        return numericStr.substring(0, 19);      }      function rewriteAffiliateLink(url, territory, revenueId) {        if (!url) return url;        const t = (territory || 'gb').toLowerCase();        return url.replace(/hawk-custom-tracking/g, `tomsguide-${t}-${revenueId}`);      }      function trackHawkEvent(params) {        const { clickType, widgetId, productCategoryName, product, productsArray, zeroBasedProductIndexOrNull, totalDealsOrProducts, areaClicked, merchant, revenueId, isoCurrencyCode, queryName, widgetTypeName } = params;        const data = {          event: "hawkEvent",          category: "Affiliates",          affiliate: {            action: {              type: clickType,              id: widgetId,              event: clickType === "appeared" ? "viewed" : "Click from",              timestamp: Date.now()            },            component: {              flag: "Editor",              product: productCategoryName || "deals",              category: `Signal Deal Finder ${widgetTypeName || "Carousel"} widget`,              type: clickType === "appeared" ? "review" : "signal product",              label: queryName || (product ? (product.name || "") : ""),              index: zeroBasedProductIndexOrNull === null || zeroBasedProductIndexOrNull === undefined ? -1 : zeroBasedProductIndexOrNull,              linkCount: totalDealsOrProducts || 0,              blockLayout: "",              areaClicked: areaClicked || ""            }          },          products: productsArray || (product && merchant ? [            {              product: {                primary: {                  id: product.id || product.matchId || null,                  name: product.name,                  type: "deal",                  price: product.price,                  previousPrice: product.previousPrice || null,                  currency: isoCurrencyCode || "USD",                  preorder: false,                  labels: [],                  link: product.link,                  originalLink: product.originalLink || null,                  revenueId: revenueId || null,                  startTime: null,                  endTime: null,                  voucherCode: null,                  voucherAudience: null,                  voucherPercentageSaving: null,                  voucherMoneySaving: null,                  voucherType: null,                  offerExclusive: false,                  offerScope: null,                  globalId: product.globalId || null,                  inStock: product.inStock !== false,                  contractProvider: null,                  contractMinutes: null,                  contractTexts: null,                  contractData: null,                  contractLength: null,                  contractMonthlyPrice: null,                  contractCurrency: isoCurrencyCode || "USD"                }              },              merchant: {                id: merchant.id || null,                name: merchant.name,                url: merchant.url || null,                network: merchant.network || null              },              model: {                id: product.modelId || null,                brand: product.brand || null,                name: product.name,                parent: product.parent || null              }            }          ] : []),          reviews: [],          _clear: true,          "gtm.uniqueEventId": Date.now() % 10000        };        sendEvent({ name: 'hawkEvent', data });      }      function trackDealClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Product Card" });      }      function trackViewSimilarClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Product Card View Similar" });      }      function trackPriceComparisonClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Price Comparison" });      }      function trackReviewClick(params) {        trackHawkEvent({ ...params, clickType: "review", areaClicked: "Signal Product Card Review Link" });      }      function trackShare(params) {        trackHawkEvent({ ...params, clickType: "share", areaClicked: "Signal Product Card Share" });      }      function trackDealsAppeared(widgetId, deals, revenueId, currency, queryName, widgetTypeName) {         if (!deals || deals.length === 0) return;                  const productsArray = deals.slice(0, 50).map((deal) => {            let voucherPct = null;            let rawPrice = parseFloat(deal.rawPrice) || parseFloat(deal.price) || null;            let rawMsrp = parseFloat(deal.rawMsrp) || parseFloat(deal.msrp) || null;            if (rawMsrp > rawPrice && rawPrice > 0) {              voucherPct = Math.round((1 - (rawPrice / rawMsrp)) * 100);            }            let numId = null;            if (deal.externalProductId && !isNaN(parseInt(deal.externalProductId))) {              numId = parseInt(deal.externalProductId);            } else if (deal.id && !isNaN(parseInt(deal.id))) {              numId = parseInt(deal.id);            } else {              numId = deal.matchId || null;            }            return {              product: {                primary: {                  id: numId,                  name: deal.productName || deal.title || "",                  type: "deal",                  price: rawPrice,                  previousPrice: rawMsrp,                  currency: currency || 'USD',                  preorder: false,                  labels: deal.modelBrand || deal.brand ? [                     { type: "brand", value: deal.modelBrand || deal.brand }                  ] : [],                  link: deal.url,                  originalLink: deal.url,                  revenueId: revenueId || null,                  startTime: null,                  endTime: null,                  voucherCode: null,                  voucherAudience: null,                  voucherPercentageSaving: voucherPct,                  voucherMoneySaving: null,                  voucherType: null,                  offerExclusive: false,                  offerScope: null,                  globalId: deal.productKey || null,                  inStock: deal.inStock !== false,                  contractProvider: null,                  contractMinutes: null,                  contractTexts: null,                  contractData: null,                  contractLength: null,                  contractMonthlyPrice: null,                  contractCurrency: currency || 'USD'                }              },              merchant: {                id: deal.merchantId ? parseInt(deal.merchantId) : null,                name: deal.merchant || "Retailer",                url: deal.merchantUrl || null,                network: deal.merchantNetwork || null              },              model: {                id: deal.modelId ? parseInt(deal.modelId) : null,                brand: deal.modelBrand || deal.brand || null,                name: deal.productName || deal.title || "",                parent: deal.modelParent || null              }            };         });                  trackHawkEvent({             clickType: "appeared",             widgetId: widgetId,             productCategoryName: "deals",             zeroBasedProductIndexOrNull: null,             totalDealsOrProducts: deals.length,             productsArray: productsArray,             queryName: queryName,             widgetTypeName: widgetTypeName         });      }      // 1. Setup Shadow DOM Sandbox      const currentScript = document.currentScript;      let hostContainer = null;      let template = null;            if (currentScript) {        let prev = currentScript.previousElementSibling;        while (prev) {          if (prev.tagName === 'TEMPLATE' && prev.classList.contains('tg-df-widget-template')) {            template = prev;          } else if (prev.tagName === 'DIV' && prev.classList.contains('tg-df-widget-host') && !prev.hasAttribute('data-initialized')) {            hostContainer = prev;            break;          }          prev = prev.previousElementSibling;        }      }            // Fallbacks in case script is deferred      if (!hostContainer) {        const hosts = document.querySelectorAll('.tg-df-widget-host:not([data-initialized])');        if (hosts.length > 0) hostContainer = hosts[0];      }            // Safely embedded template for CMS environments      const rawTemplate = `  \x3Cstyle>    /* --- Shadow DOM Base Reset --- */    *, *::before, *::after {      box-sizing: border-box;    }    img, picture, svg, video {      max-width: 100%;      height: auto;      display: block;    }    /*       1. Scoped CSS for Tom's Guide Deals Widget       All classes are prefixed with \`tg-df-\` to prevent CMS style leakage.    */    .tg-df-container {      container-type: inline-size;      container-name: tg-df;      --tg-df-blue: #1F69FF;      --tg-df-blue-hover: #004d8c;      --tg-df-text: #222222;      --tg-df-text-muted: #555555;      --tg-df-bg: #ffffff;      --tg-df-bg-secondary: #f4f4f4;      --tg-df-border: #e2e8f0;      font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;      color: var(--tg-df-text);      background-color: transparent;       width: 100%;      max-width: 1200px;      margin: 0 auto;      padding-bottom: 24px;    }    .tg-df-container *, .tg-df-container *::before, .tg-df-container *::after {      margin: 0;      padding: 0;      box-sizing: border-box;    }    .tg-df-container img {      border: none;      margin: 0;      padding: 0;    }    .tg-df-container a {      text-decoration: none;      color: inherit;    }    /*       2. Search & Filter Bar    */    .tg-df-controls {      display: flex;      flex-direction: column;      align-items: center;      gap: 20px;      margin-bottom: 32px;      width: 100%;    }    .tg-df-top-bar {      display: flex;      width: 100%;      max-width: 760px;      gap: 12px;      align-items: center;    }    .tg-df-search-wrapper {      position: relative;      flex: 1;      width: 100%;      box-shadow: 0 8px 24px rgba(0,0,0,0.06);      border-radius: 40px;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      z-index: 100;    }    .tg-df-autocomplete-dropdown {      position: absolute;      top: calc(100% + 4px);      left: 0;      right: 0;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 12px;      box-shadow: 0 8px 32px rgba(0,0,0,0.12);      max-height: 300px;      overflow-y: auto;      z-index: 200;      display: none;    }    .tg-df-autocomplete-dropdown.active {      display: block;    }    .tg-df-autocomplete-item {      padding: 12px 24px;      cursor: pointer;      font-size: 14px;      color: var(--tg-df-text);      transition: background 0.1s ease;    }    .tg-df-autocomplete-item:hover {      background: var(--tg-df-bg-secondary);    }    .tg-df-search-input {      width: 100%;      padding: 16px 64px 16px 24px;      font-size: 16px;      border: 2px solid transparent;      border-radius: 40px;      outline: none;      transition: border-color 0.2s ease, box-shadow 0.2s ease;      color: var(--tg-df-text);      background: transparent;    }    .tg-df-search-input:focus {      border-color: transparent;      box-shadow: 0 0 0 3px rgba(0, 108, 196, 0.15);    }    .tg-df-search-input::placeholder {      color: #999999;    }        .tg-df-search-btn {      position: absolute;      right: 8px;      top: 50%;      transform: translateY(-50%);      width: 40px;      height: 40px;      border-radius: 50%;      background: #222;      border: none;      display: flex;      align-items: center;      justify-content: center;      cursor: pointer;      transition: background 0.2s ease;    }        .tg-df-search-btn:hover {      background: #000;    }    .tg-df-search-icon {      width: 16px;      height: 16px;      fill: #fff;    }    .tg-df-settings-wrapper {      position: relative;    }        .tg-df-settings-btn {      width: 48px;      height: 48px;      border-radius: 50%;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      box-shadow: 0 4px 12px rgba(0,0,0,0.04);      display: flex;      align-items: center;      justify-content: center;      cursor: pointer;      transition: all 0.2s ease;      color: var(--tg-df-text-muted);      flex-shrink: 0;    }    .tg-df-settings-btn:hover {      background: var(--tg-df-bg-secondary);      border-color: #0000ff;      color: var(--tg-df-text);    }    .tg-df-settings-btn svg {      width: 24px;      height: 24px;      fill: currentColor;    }    .tg-df-settings-dropdown {      position: absolute;      top: calc(100% + 8px);      right: 0;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 12px;      box-shadow: 0 8px 32px rgba(0,0,0,0.12);      width: 280px;      padding: 20px;      display: none;      z-index: 100;      flex-direction: column;      gap: 20px;    }    .tg-df-settings-dropdown.active {      display: flex;    }        .tg-df-settings-dropdown-backdrop {      display: none;      position: fixed;      inset: 0;      z-index: 99;    }        .tg-df-settings-dropdown-backdrop.active {      display: block;    }    .tg-df-setting-item {      display: flex;      flex-direction: column;      gap: 10px;    }    .tg-df-setting-label {      font-size: 11px;      font-weight: 700;      color: var(--tg-df-text-muted);      text-transform: uppercase;      letter-spacing: 0.5px;    }        .tg-df-region-select {        padding: 10px 12px;        border-radius: 8px;        border: 1px solid var(--tg-df-border);        font-size: 15px;        outline: none;        background: var(--tg-df-bg-secondary);        color: var(--tg-df-text);        cursor: pointer;        width: 100%;    }    .tg-df-toggle {        position: relative;        display: inline-block;        width: 44px;        height: 24px;        flex-shrink: 0;    }    .tg-df-toggle input {        opacity: 0;        width: 0;        height: 0;    }    .tg-df-slider {        position: absolute;        cursor: pointer;        top: 0; left: 0; right: 0; bottom: 0;        background-color: #ccc;        transition: .2s;        border-radius: 24px;    }    .tg-df-slider:before {        position: absolute;        content: "";        height: 18px;        width: 18px;        left: 3px;        bottom: 3px;        background-color: white;        transition: .2s;        border-radius: 50%;    }    .tg-df-toggle input:checked + .tg-df-slider {        background-color: #1F69FF;    }    .tg-df-toggle input:checked + .tg-df-slider:before {        transform: translateX(20px);    }    .tg-df-dl-row {        flex-direction: row;        align-items: center;        justify-content: space-between;    }    .tg-df-dl-row-text {        font-size: 14px;        font-weight: 600;        color: var(--tg-df-text);    }    .tg-df-dl-row-subtext {        font-size: 12px;        font-weight: 400;        line-height: 1.3;        color: var(--tg-df-text-muted);        margin-top: 4px;        display: block;    }    .tg-df-filters {      display: flex;      gap: 12px;      justify-content: center;      flex-wrap: wrap;    }    .tg-df-sort-wrapper {      position: relative;      display: flex;      align-items: center;    }        .tg-df-sort-icon {      position: absolute;      left: 14px;      width: 14px;      height: 14px;      fill: var(--tg-df-text-muted);      pointer-events: none;    }    .tg-df-sort-select, .tg-df-filter-select {      padding: 10px 36px 10px 38px;      font-size: 14px;      border: 1px solid var(--tg-df-border);      border-radius: 100px;      outline: none;      appearance: none;      background-color: var(--tg-df-bg-secondary);      background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 12 12'%3E%3Cpath fill='%23555555' d='M6 8L1 3h10z'/%3E%3C/svg%3E");      background-repeat: no-repeat;      background-position: right 14px center;      color: var(--tg-df-text);      cursor: pointer;      font-weight: 500;      transition: all 0.2s ease;    }        .tg-df-price-input::-webkit-outer-spin-button,    .tg-df-price-input::-webkit-inner-spin-button {      -webkit-appearance: none;      margin: 0;    }    .tg-df-price-input {      -moz-appearance: textfield;    }    .tg-df-sort-select:hover, .tg-df-filter-select:hover {      background-color: #e2e8f0;    }    .tg-df-multiselect-container {      position: relative;    }        .tg-df-multiselect-trigger {      display: block;      background: #fff;      user-select: none;      width: 100%;      overflow: hidden;      white-space: nowrap;      text-overflow: ellipsis;    }        .tg-df-multiselect-dropdown {      display: none;      position: absolute;      top: calc(100% + 4px);      left: 0;      width: 100%;      min-width: 220px;      max-height: 300px;      overflow-y: auto;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 8px;      box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);      z-index: 100;      padding: 8px 0;    }    .tg-df-multiselect-dropdown.active {      display: block;    }    .tg-df-ms-option {      padding: 8px 16px;      display: flex;      align-items: center;      gap: 8px;      cursor: pointer;      font-size: 14px;    }    .tg-df-ms-option:hover {      background-color: var(--tg-df-bg-secondary);    }        .tg-df-ms-option input {      cursor: pointer;      accent-color: #1f69ff;    }    .tg-df-sort-select:focus, .tg-df-filter-select:focus {      border-color: #0000ff;      box-shadow: 0 0 0 3px rgba(0, 0, 255, 0.2);      background-color: var(--tg-df-bg);    }    /*       3. Deal Grid Layout    */    .tg-df-grid.tg-df-grid-auto {      padding-top: 24px;    }    .tg-df-grid, .tg-df-grid.layout-grid {      display: grid;      grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));      gap: 10px;    }    .tg-df-grid.layout-row {      grid-template-columns: 1fr;      gap: 16px;    }        .tg-df-grid.layout-row .tg-df-card {      flex-direction: row;      align-items: stretch;      height: auto;      box-shadow: none;      border-bottom: 1px solid var(--tg-df-border);    }    .tg-df-grid.layout-row .tg-df-card:hover {      box-shadow: none;    }    .tg-df-grid.layout-row .tg-df-card-image-box {      width: 140px;      min-width: 140px;      aspect-ratio: 3/4;      border-right: none;      padding: 16px 16px 16px 32px;    }    .tg-df-grid.layout-row .tg-df-card-body {      padding: 16px;      justify-content: space-between;    }    .tg-df-grid.layout-row .tg-df-card-title {      font-size: 15px;      margin-bottom: 16px;    }    .tg-df-grid.layout-row .tg-df-card-stars { margin-bottom: 8px; }    .tg-df-grid.layout-row .tg-df-card-footer {      flex-direction: column;      align-items: flex-start;      gap: 0;    }    .tg-df-grid.layout-row .tg-df-card-merchant-pill {      margin-bottom: 4px;    }    .tg-df-grid.layout-row .tg-df-card-price-group {      margin-bottom: 8px;    }    .tg-df-grid.layout-row .tg-df-price-group {      width: auto;    }    .tg-df-grid.layout-row .tg-df-card-cta {      width: 100%;      max-width: 200px;      padding: 10px 24px;      font-size: 13px;      flex-shrink: 0;      text-align: center;      justify-content: center;    }    /*       4. Deal Card Design    */    .tg-df-card {      position: relative;      display: flex;      flex-direction: column;      background-color: #ffffff;      border-radius: 0;      overflow: hidden;      transition: transform 0.2s ease, box-shadow 0.2s ease;      text-decoration: none;      color: inherit;      height: 100%;      box-shadow: 0 0 16px rgba(0, 0, 0, 0.08);      border: 1px solid var(--tg-df-border);    }    .tg-df-card:hover {      box-shadow: 0 0 24px rgba(0, 0, 0, 0.12);    }    .tg-df-card-image-box {      width: 100%;      aspect-ratio: 3/4;      background-color: #f8f8f8;      display: flex;      align-items: center;      justify-content: center;      position: relative;      overflow: hidden;      padding: 32px;      flex: 0 0 auto;    }    .tg-df-card-image {      max-width: 100%;      max-height: 100%;      width: auto;      height: auto;      object-fit: contain;      mix-blend-mode: multiply; /* Helps white background images blend into secondary bg */      transition: transform 0.3s ease;    }    .tg-df-card:hover .tg-df-card-image {      transform: scale(1.05); /* Zoom in on hover */    }    .tg-df-card-discount-badge {      position: absolute;      top: 12px;      left: 12px;      background: #dc2626; /* Red */      color: #ffffff;      padding: 6px 8px;      font-size: 11px;      font-weight: 500;      text-transform: uppercase;      letter-spacing: 0.5px;      border-radius: 0;      z-index: 10;    }        .tg-df-card-merchant-pill {      display: block;      padding: 0;      font-size: 11px;      font-weight: 600;      text-transform: uppercase;      letter-spacing: 0.5px;      border-radius: 0;      color: var(--tg-df-text-muted);      margin-bottom: 8px;      white-space: nowrap;      overflow: hidden;      text-overflow: ellipsis;    }    .tg-df-card-body {      padding: 16px;      display: flex;      flex-direction: column;      flex-grow: 1;      min-width: 0;    }    .tg-df-card-badges {      display: flex;      flex-wrap: wrap;      gap: 6px;      margin-bottom: 8px;    }    .tg-df-tag {      display: inline-flex;      align-items: center;      padding: 4px 6px;      font-size: 11px;      font-weight: 700;      text-transform: uppercase;      border-radius: 4px;      gap: 4px;    }    .tg-df-tag-prime {      background-color: #00A8E1;      color: #fff;    }    .tg-df-tag-coupons {      background-color: #f1f5f9;      color: #334155;      border: 1px solid #cbd5e1;      cursor: pointer;      transition: background-color 0.2s;    }    .tg-df-tag-coupons:hover {      background-color: #e2e8f0;    }        .tg-df-tag-outline {      background-color: #f1f5f9;      color: #334155;      border: 1px solid #cbd5e1;      cursor: pointer;      transition: background-color 0.2s;    }    .tg-df-tag-outline:hover {      background-color: #e2e8f0;    }        @keyframes tg-df-spin {      0% { transform: rotate(0deg); }      100% { transform: rotate(360deg); }    }    .tg-df-coupon-spinner {      border: 2px solid #e2e8f0;      border-top: 2px solid #3b82f6;      border-radius: 50%;      width: 14px;      height: 14px;      animation: tg-df-spin 1s linear infinite;      margin: 4px 8px;      display: inline-block;    }        /* Vouchers Modal */    .tg-df-modal-backdrop {      position: fixed;      top: 0; left: 0; right: 0; bottom: 0;      background: rgba(0,0,0,0.5);      z-index: 10000;      display: flex;      align-items: center;      justify-content: center;      opacity: 0;      pointer-events: none;      transition: opacity 0.3s;    }    .tg-df-modal-backdrop.active {      opacity: 1;      pointer-events: auto;    }    .tg-df-modal {      background: #fff;      border-radius: 12px;      width: 90%;      max-width: 400px;      max-height: 80vh;      display: flex;      flex-direction: column;      box-shadow: 0 10px 40px rgba(0,0,0,0.2);      transform: translateY(20px);      transition: transform 0.3s;    }    .tg-df-modal-backdrop.active .tg-df-modal {      transform: translateY(0);    }    .tg-df-modal-header {      padding: 16px;      border-bottom: 1px solid #e2e8f0;      display: flex;      align-items: center;      justify-content: space-between;    }    .tg-df-modal-title {      font-size: 16px;      font-weight: 600;      margin: 0;    }    .tg-df-modal-close {      background: none;      border: none;      cursor: pointer;      padding: 4px;      color: #64748b;    }    .tg-df-modal-body {      padding: 16px;      overflow-y: auto;    }    .tg-df-voucher-item {      padding: 12px;      border: 1px dashed #cbd5e1;      border-radius: 8px;      margin-bottom: 10px;      background: #f8fafc;      display: flex;      align-items: center;      gap: 12px;      text-decoration: none;      color: inherit;      transition: background-color 0.2s, border-color 0.2s;    }    .tg-df-voucher-item:hover {      background: #f1f5f9;      border-color: #94a3b8;    }    .tg-df-voucher-item:last-child {      margin-bottom: 0;    }    .tg-df-voucher-logo {      width: 48px;      height: 48px;      object-fit: contain;      border-radius: 4px;      background: #fff;      border: 1px solid #e2e8f0;      flex-shrink: 0;    }    .tg-df-voucher-content {      flex: 1;      min-width: 0;    }    .tg-df-voucher-title {      font-size: 14px;      font-weight: 600;      margin: 0 0 4px 0;      line-height: 1.3;      color: #0f172a;    }    .tg-df-voucher-expiry {      font-size: 12px;      color: #64748b;      display: flex;      align-items: center;      gap: 4px;      margin-top: 6px;    }    .tg-df-voucher-code {      display: inline-flex;      align-items: center;      background: #f1f5f9;      border: 1px dashed #cbd5e1;      padding: 6px 10px;      font-family: monospace;      font-weight: 700;      font-size: 14px;      color: #0f172a;      border-radius: 4px;      margin-top: 8px;      cursor: pointer;      transition: all 0.2s ease;    }    .tg-df-voucher-code:hover {      background: #e2e8f0;      border-color: #94a3b8;    }    .tg-df-voucher-code.copied {      background: #ecfdf5;      border-color: #10b981;      color: #10b981;    }    .tg-df-voucher-cta {      display: inline-block;      margin-top: 8px;      font-size: 13px;      font-weight: 600;      color: #2563eb;      text-decoration: none;    }    .tg-df-card-title {      font-size: 15px;      font-weight: 400;      line-height: 1.4;      margin: 0 0 12px 0;      color: var(--tg-df-text);      display: -webkit-box;      -webkit-line-clamp: 2;      -webkit-box-orient: vertical;      overflow: hidden;    }    .tg-df-card-footer {      margin-top: auto;      display: flex;      flex-direction: column;      width: 100%;    }    .tg-df-card-price-group {      display: flex;      flex-direction: row;      align-items: center;      gap: 8px;      margin-bottom: 12px;    }    .tg-df-card-price {      font-size: 16px;      font-weight: 700;      color: #dc2626; /* Red price */      line-height: 1;    }        .tg-df-card-msrp {      font-size: 13px;      color: var(--tg-df-text-muted);      text-decoration: line-through;    }    .tg-df-container .tg-df-card-cta {      display: flex;      align-items: center;      justify-content: center;      width: 100%;      box-sizing: border-box;      background-color: #1f69ff;      color: #ffffff;      font-size: 12px;      font-weight: 700;      text-transform: uppercase;      letter-spacing: 0.5px;      padding: 12px 16px;      border-radius: 0;      border: none;      cursor: pointer;      transition: background-color 0.2s ease;    }    .tg-df-card:hover .tg-df-card-cta,    .tg-df-card-cta:hover {      background-color: #1555cc;    }    .tg-df-container .tg-df-card-cta.tg-df-cta-savings-squad {      background-color: #3c8d0d;    }    .tg-df-card:hover .tg-df-card-cta.tg-df-cta-savings-squad,    .tg-df-card-cta.tg-df-cta-savings-squad:hover {      background-color: #2b6509;    }    /*       5. State & Skeleton Styles    */    .tg-df-message {      grid-column: 1 / -1;      text-align: center;      padding: 48px 24px;      color: var(--tg-df-text-muted);      font-size: 16px;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 8px;    }    @keyframes tg-df-shimmer {      0% { background-position: -200% 0; }      100% { background-position: 200% 0; }    }    .tg-df-skeleton {      background: linear-gradient(90deg, var(--tg-df-bg-secondary) 25%, #e2e8f0 50%, var(--tg-df-bg-secondary) 75%);      background-size: 200% 100%;      animation: tg-df-shimmer 1.5s infinite;      border-radius: 4px;    }    .tg-df-skeleton-img {      width: 100%;      height: 100%;      position: absolute;      top: 0; left: 0;    }        .tg-df-skeleton-text {      height: 16px;      margin-bottom: 8px;      width: 100%;    }    .tg-df-skeleton-text.short { width: 40%; }    .tg-df-skeleton-text.title { height: 20px; margin-bottom: 16px; }    /* Editor Floating Bar & Elements */    .tg-df-editor-bar {      position: sticky;      top: 0;      z-index: 1000;      background: #111827;      color: #fff;      padding: 12px 16px;      border-radius: 8px;      margin-bottom: 16px;      display: flex;      align-items: center;      justify-content: space-between;      box-shadow: 0 4px 12px rgba(0,0,0,0.15);    }    .tg-df-editor-bar-text {      font-weight: 600;      font-size: 14px;    }    .tg-df-editor-copy-btn {      background: #10b981;      color: #fff;      padding: 6px 16px;      border: none;      border-radius: 4px;      font-weight: 600;      cursor: pointer;      display: flex;      align-items: center;      font-size: 13px;    }    .tg-df-editor-copy-btn:hover { background: #059669; }        .tg-df-deal-checkbox {      position: absolute;      top: 12px;      right: 12px;      z-index: 10;      width: 20px;      height: 20px;      cursor: pointer;      pointer-events: auto;    }    /*       6. Mobile List View (Stacks into a cleaner horizontal row/list)    */    @container tg-df (max-width: 599px) {      .tg-df-controls {        padding: 0 16px;      }            .tg-df-top-bar {        width: 100%;      }            .tg-df-settings-dropdown {        position: fixed;        top: auto;        bottom: 0;        left: 0;        right: 0;        width: 100%;        border-radius: 20px 20px 0 0;        padding: 24px;        box-shadow: 0 -8px 32px rgba(0,0,0,0.15);        z-index: 1000;        border: none;        border-top: 1px solid var(--tg-df-border);      }            .tg-df-settings-dropdown-backdrop.active {        background: rgba(0,0,0,0.4);      }            .tg-df-search-wrapper {        box-shadow: 0 0 16px rgba(0,0,0,0.08);      }            .tg-df-filters {        width: calc(100% + 32px);        margin: 0 -16px;        padding: 0 16px 4px 16px;        display: flex;        justify-content: flex-start;        gap: 8px;        flex-wrap: nowrap;        overflow-x: auto;        -webkit-overflow-scrolling: touch;        scrollbar-width: none;      }      .tg-df-filters::after {        content: "";        display: block;        flex: 0 0 8px;      }      .tg-df-filters::-webkit-scrollbar {        display: none;      }            .tg-df-sort-wrapper {        flex: 0 0 max(42%, 130px);        min-width: 0;      }      .tg-df-sort-wrapper.tg-df-price-range-wrapper {        flex: 0 0 auto;        min-width: max-content;      }            .tg-df-sort-select, .tg-df-filter-select {        width: 100%;        text-align: left;        padding: 10px 24px 10px 32px;        background-position: right 8px center;        text-overflow: ellipsis;        white-space: nowrap;        overflow: hidden;      }      .tg-df-sort-icon {        left: 10px;      }      .tg-df-grid:not(.layout-grid):not(.layout-row),      .tg-df-grid.layout-row {        grid-template-columns: 1fr;        gap: 16px;      }            .tg-df-grid.tg-df-grid-auto {        padding-top: 24px;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card,      .tg-df-grid.layout-row .tg-df-card {        flex-direction: row;        align-items: stretch;        height: auto;        box-shadow: none; /* simple line on mobile if preferred, or keep */        border-bottom: 1px solid var(--tg-df-border);      }      .tg-df-grid.tg-df-grid-auto .tg-df-card:hover,      .tg-df-grid.layout-row .tg-df-card:hover {        box-shadow: none;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-image-box,      .tg-df-grid.layout-row .tg-df-card-image-box {        width: 120px;        min-width: 120px;        aspect-ratio: 3/4;        border-right: none;        padding: 12px;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-body,      .tg-df-grid.layout-row .tg-df-card-body {        padding: 12px;        justify-content: space-between;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-title,      .tg-df-grid.layout-row .tg-df-card-title {        font-size: 14px;        margin-bottom: 12px;        -webkit-line-clamp: 3;      }      /* Single column mobile grid override */      .tg-df-grid.layout-grid {        grid-template-columns: 1fr;        gap: 16px;      }      .tg-df-grid.layout-grid .tg-df-card-image-box {        padding: 12px;      }      .tg-df-grid.layout-grid .tg-df-card-body {        padding: 10px;      }      .tg-df-grid.layout-grid .tg-df-card-title {        font-size: 13px;        -webkit-line-clamp: 3;        margin-bottom: 8px;      }      .tg-df-grid.layout-grid .tg-df-card-price {        font-size: 14px;      }            .tg-df-card-footer {        flex-direction: column;        align-items: stretch;        gap: 0;        width: 100%;        min-width: 0;      }      .tg-df-card-merchant-pill {        margin-bottom: 4px;      }      .tg-df-card-price-group {        flex: 1 1 auto;        margin-bottom: 8px;      }      .tg-df-card-price {        font-size: 16px;      }      .tg-df-card-msrp {        display: block;       }      .tg-df-grid.layout-row .tg-df-card-cta,      .tg-df-container .tg-df-card-cta {        width: 100%;        max-width: none;        min-width: 0;        box-sizing: border-box;        padding: 8px 16px;        font-size: 12px;        flex: 0 0 auto;        text-align: center;        white-space: normal;        line-height: 1.2;      }    }    .tg-df-container.is-carousel {      min-height: 760px;      background-color: #E7F0FF;      padding: 0 0 24px 0;      border-radius: 24px;    }    .tg-df-container.is-carousel.hide-header-details {      min-height: 480px;    }    /*       7. Carousel View Mode    */    .tg-df-container .tg-df-carousel-host {      /* Layout is now handled by container wrapper */    }    .tg-df-container .tg-df-carousel-eyebrow {      color: #1F69FF;      font-weight: 700;      font-size: 14px;      text-transform: uppercase;      letter-spacing: 1px;      padding: 24px 16px 0 16px;      display: none;    }    .tg-df-container .tg-df-carousel-query-title {      color: #011535;      font-size: 28px;      font-weight: 600;      padding: 0 16px 24px 16px;      line-height: 1.2;      display: none;    }    .tg-df-container .tg-df-carousel-blue-box {      background-color: transparent;      border-radius: 0;      padding: 24px 24px 0 24px;      margin: 0;      color: #1F69FF;          position: relative;      overflow: hidden;    }    .tg-df-container .tg-df-carousel-bg-circle-1 {      display: none;    }    .tg-df-container .tg-df-carousel-bg-circle-2 {      display: none;    }    .tg-df-container .tg-df-carousel-bg-circle-3 {      display: none;    }    .tg-df-container .tg-df-carousel-box-content {      position: relative;      z-index: 10;    }    .tg-df-container .tg-df-carousel-box-eyebrow {      background-color: transparent;      color: #1F69FF;      font-weight: 700;      font-size: 14px;      text-transform: uppercase;      letter-spacing: 1px;      display: inline-block;      padding: 0;      border-radius: 0;    }    .tg-df-container .tg-df-carousel-box-title {      font-size: 28px;      font-weight: 600;      line-height: 1.2;      margin-top: 8px;      color: #1e293b;    }    .tg-df-container .tg-df-countdown-wrapper {      position: absolute;      top: 0;      right: 0;      display: flex;      flex-direction: column;      align-items: flex-end;      gap: 12px;      transform: scale(0.67);      transform-origin: top right;    }    .tg-df-container .tg-df-countdown-title {      font-size: 16px;      text-align: center;      width: 100%;      font-weight: 600;      color: #011535;      margin: 0;    }    .tg-df-container .tg-df-countdown-blocks {      display: flex;      gap: 16px;    }    .tg-df-container .tg-df-countdown-item {      display: flex;      flex-direction: column;      align-items: center;      gap: 4px;    }    .tg-df-container .tg-df-countdown-box {      width: 59px;      height: 59px;      background: #03FE9E;      border-radius: 15px;      display: flex;      align-items: center;      justify-content: center;    }    .tg-df-container .tg-df-countdown-num {      font-family: 'Inter', sans-serif;      font-weight: 700;      font-size: 20px;      line-height: normal;      color: #011535;    }    .tg-df-container .tg-df-countdown-label {      font-family: 'Inter', sans-serif;      font-weight: 500;      font-size: 16px;      line-height: normal;      color: #1e293b;      text-transform: uppercase;    }    .tg-df-container .tg-df-carousel-box-subtitle {      font-size: 16px;      margin-top: 8px;      font-weight: 300;      color: #1e293b;      line-height: 24px;    }    .tg-df-container .tg-df-carousel-roundels-wrapper {      position: relative;      margin-top: 24px;      margin-left: -24px;      margin-right: -24px;    }    .tg-df-container .tg-df-carousel-roundels {      display: flex;      gap: 16px;      overflow-x: auto;            scrollbar-width: none;      padding-top: 12px;      padding-bottom: 24px;      padding-left: 24px;      padding-right: 24px;      margin-left: 0;      margin-right: 0;    }        .tg-df-container .tg-df-carousel-scroll-left,    .tg-df-container .tg-df-carousel-scroll-right {      position: absolute;      top: 50%;      transform: translateY(-50%);      height: 36px;      width: 36px;      display: flex;      align-items: center;      justify-content: center;      border-radius: 50%;      background-color: #ffffff;      border: 1px solid #e2e8f0;      box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);      color: #1F69FF;      cursor: pointer;      transition: all 0.2s;      margin-top: -4px;      z-index: 20;    }    .tg-df-container .tg-df-carousel-scroll-left { left: 8px; }    .tg-df-container .tg-df-carousel-scroll-right { right: 8px; }    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-left { left: 0px; }    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-right { right: 0px; }    .tg-df-carousel-filters-outer { margin-left: -24px; margin-right: -24px; padding-left: 24px; padding-right: 24px; }    @container tg-df (max-width: 599px) { .tg-df-carousel-filters-outer { margin-left: -16px; margin-right: -16px; padding-left: 16px; padding-right: 16px; } }        .tg-df-container .tg-df-carousel-scroll-left:hover,    .tg-df-container .tg-df-carousel-scroll-right:hover {      background-color: #f8fafc;      border-color: #cbd5e1;    }        .tg-df-carousel-roundels-wrapper .tg-df-carousel-scroll-left,    .tg-df-carousel-roundels-wrapper .tg-df-carousel-scroll-right,    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-left,    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-right {      background-color: rgba(255, 255, 255, 0.4);      border: none;      box-shadow: none;      backdrop-filter: blur(4px);      -webkit-backdrop-filter: blur(4px);    }    .tg-df-carousel-roundels-wrapper .tg-df-carousel-scroll-left { left: 0; }    .tg-df-carousel-roundels-wrapper .tg-df-carousel-scroll-right { right: 0; }    .tg-df-grid-wrapper .tg-df-carousel-scroll-left { left: 0; }    .tg-df-grid-wrapper .tg-df-carousel-scroll-right { right: 0; }        .tg-df-carousel-roundels-wrapper .tg-df-carousel-scroll-left:hover,    .tg-df-carousel-roundels-wrapper .tg-df-carousel-scroll-right:hover {      background-color: rgba(255, 255, 255, 0.6);      border: none;    }    .tg-df-container .tg-df-carousel-roundels::-webkit-scrollbar {      display: none;    }    .tg-df-container .tg-df-carousel-roundels::after {      content: "";      flex: 0 0 32px;    }    .tg-df-container .tg-df-roundel {      display: flex;      flex-direction: column;      align-items: center;      gap: 8px;      cursor: pointer;      min-width: 120px;      flex-shrink: 0;    }    .tg-df-container .tg-df-roundel-img-box {      width: 120px;      height: 120px;      border-radius: 50%;      background: white;      display: flex;      align-items: center;      justify-content: center;      overflow: hidden;      box-shadow: 0px 3px 14px 0px rgba(30, 41, 59, 0.08);      transition: box-shadow 0.2s;    }    .tg-df-container .tg-df-roundel:hover .tg-df-roundel-img-box {      box-shadow: 0 0 0 2px #E7F0FF, 0 0 0 4px #1F69FF;    }    .tg-df-container .tg-df-roundel.active .tg-df-roundel-img-box {      box-shadow: 0 0 0 2px #E7F0FF, 0 0 0 4px #1F69FF;    }    .tg-df-container .tg-df-roundel:hover .tg-df-roundel-img-box img {      transform: scale(1.08);    }    .tg-df-container .tg-df-roundel-img-box img {      width: 100%;      height: 100%;      object-fit: contain;      padding: 10px;      box-sizing: border-box;      transition: transform 0.3s ease;    }    .tg-df-container .tg-df-roundel-label {      font-size: 13px;      font-weight: 400;      color: #1e293b;      text-align: center;      transition: font-weight 0.2s;    }    .tg-df-container .tg-df-roundel.active .tg-df-roundel-label {      font-weight: 700;    }    .tg-df-container .tg-df-carousel-filters-label {      font-size: 16px;      font-weight: 400;      color: #1e293b;      white-space: nowrap;      margin-right: 4px;    }    .tg-df-container .tg-df-carousel-filters-wrap {      display: flex;      align-items: center;      flex-wrap: nowrap;      gap: 8px;      margin-top: 8px;      overflow-x: auto;      scrollbar-width: none;      -webkit-overflow-scrolling: touch;      padding-bottom: 8px;      margin-left: -24px;      margin-right: -24px;      padding-left: 24px;      padding-right: 24px;    }    .tg-df-container .tg-df-carousel-filters-wrap::-webkit-scrollbar {      display: none;    }        .tg-df-container .tg-df-carousel-filter-btn img,    .tg-df-container .tg-df-carousel-filter-btn picture {      height: 20px;      width: 20px;      object-fit: contain;      object-position: center;      display: inline-flex;      align-items: center;      justify-content: center;      margin-right: 6px;    }    .tg-df-container .tg-df-carousel-filter-btn picture img {      margin-right: 0;      height: 100%;      width: 100%;    }    .tg-df-container .tg-df-carousel-filter-btn img.active-img,    .tg-df-container .tg-df-carousel-filter-btn picture:has(.active-img) {      display: none;    }    .tg-df-container .tg-df-carousel-filter-btn:hover img.inactive-img,    .tg-df-container .tg-df-carousel-filter-btn.active img.inactive-img,    .tg-df-container .tg-df-carousel-filter-btn:hover picture:has(.inactive-img),    .tg-df-container .tg-df-carousel-filter-btn.active picture:has(.inactive-img) {      display: none;    }    .tg-df-container .tg-df-carousel-filter-btn:hover img.active-img,    .tg-df-container .tg-df-carousel-filter-btn.active img.active-img,    .tg-df-container .tg-df-carousel-filter-btn:hover picture:has(.active-img),    .tg-df-container .tg-df-carousel-filter-btn.active picture:has(.active-img) {      display: inline-flex;    }    .tg-df-container .tg-df-carousel-filter-btn {      background: #ffffff;      border: 2px solid #1e293b;      color: #1e293b;      border-radius: 24px;      padding: 6px 16px;      font-size: 14px;      font-weight: 600;      cursor: pointer;      transition: all 0.2s;      flex-shrink: 0;      white-space: nowrap;      display: inline-flex;      align-items: center;      justify-content: center;      min-height: 36px;      box-sizing: border-box;    }    .tg-df-container .tg-df-carousel-filter-btn svg {      margin-right: 6px;    }    .tg-df-container .tg-df-carousel-filter-btn:hover {      background: #1e293b;      color: white;      border-color: #1e293b;    }    .tg-df-container .tg-df-carousel-filter-btn.active {      background: #1e293b;      color: white;      border-color: #1e293b;    }        .tg-df-grid.carousel-compact {      display: flex;      flex-wrap: nowrap;      overflow-x: auto;      gap: 16px;      padding: 16px 24px;      align-items: stretch;      scrollbar-width: none;    }    .tg-df-grid.carousel-compact::after {      content: "";      flex: 0 0 32px;    }    .tg-df-grid-wrapper {      position: relative;    }    .tg-df-grid.carousel-compact::-webkit-scrollbar {      display: none;    }    .tg-df-grid.carousel-compact .tg-df-load-more-card {      flex: 0 0 auto;      width: 100px;      border-radius: 15px;      box-shadow: 0 0 16px rgba(0,0,0,0.08);      border: 2px solid #1e293b;      background: white;      color: #1e293b;      display: flex;      flex-direction: column;      justify-content: center;      align-items: center;      font-weight: 600;      font-size: 14px;      cursor: pointer;      padding: 16px;      text-align: center;      transition: all 0.2s;    }    .tg-df-grid.carousel-compact .tg-df-load-more-card:hover {      background: #1e293b;      color: white;    }    .tg-df-grid.carousel-compact .tg-df-card {      flex: 0 0 auto;      width: 200px;      min-height: auto;      height: auto;      display: flex;      flex-direction: column;      border-radius: 15px;      border: none;      box-shadow: 0 0 16px rgba(0,0,0,0.08);      overflow: visible;    }    .tg-df-grid.carousel-compact .tg-df-card-image-box {      padding: 12px;      background-color: transparent;      border-radius: 15px 15px 0 0;      height: 130px;    }    .tg-df-grid.carousel-compact .tg-df-card-image {      mix-blend-mode: normal;    }    .tg-df-grid.carousel-compact .tg-df-card-discount-badge {      border-radius: 0;      top: 0px;      left: 0px;      padding: 4px 8px;      font-size: 11px;    }    .tg-df-grid.carousel-compact .tg-df-card-body {      padding: 8px 12px 12px 12px;    }    .tg-df-grid.carousel-compact .tg-df-card-title {      font-size: 14px;      font-weight: 400;      -webkit-line-clamp: 2;      margin-bottom: 8px;      color: #011535;    }    .tg-df-grid.carousel-compact .tg-df-card-body:not(:has(.tg-df-card-stars)):not(:has(.tg-df-tag-prime)):not(:has(.tg-df-coupon-wrapper:not([style*="none"]))) > .tg-df-card-title,    .tg-df-grid.carousel-compact .tg-df-card-body:not(:has(.tg-df-card-stars)):has(> .tg-df-card-title:first-child) > .tg-df-card-title {      -webkit-line-clamp: 3;    }    .tg-df-grid.carousel-compact .tg-df-card-cta {      border-radius: 5px;      padding: 8px 10px;      margin-top: 4px;      background-color: #1F69FF;    }    .tg-df-grid.carousel-compact .tg-df-card-price-group {      margin-bottom: 2px;    }    .tg-df-grid.carousel-compact .tg-df-card-merchant-pill {      margin-bottom: 2px;    }    @container tg-df (max-width: 599px) {      .tg-df-container .tg-df-carousel-blue-box-title {        font-size: 24px;      }      .tg-df-container .tg-df-countdown-title {        display: none;      }      .tg-df-container .tg-df-countdown-wrapper {        position: absolute;        top: 0;        right: 0;        align-items: flex-end;        transform: scale(0.45);        transform-origin: top right;      }      .tg-df-container .tg-df-roundel {        min-width: 88px;      }      .tg-df-container .tg-df-roundel-img-box {        width: 88px;        height: 88px;      }    }    /* REPLICA BLOCK STYLES */    .tg-df-grid.layout-replica-2 { grid-template-columns: repeat(2, 1fr) !important; gap: 20px; }    .tg-df-grid.layout-replica-1 { grid-template-columns: 1fr !important; gap: 20px; }        .tg-df-container .hawk-deal-widget-container { border-bottom: 1px solid #e5e7eb; display: flex; flex-direction: column; margin: 0; padding: 20px 0; box-sizing: border-box; font-family: inherit; }    .tg-df-container .hawk-deal-widget-wrap { display: flex; flex-direction: row; align-items: flex-start; width: 100%; gap: 24px; }    .tg-df-container .hawk-deal-widget-image-container { display: flex; flex-shrink: 0; justify-content: center; width: 160px; height: 160px; align-items: center; background: white; margin-bottom: 0px; }    .tg-df-container .hawk-deal-widget-title-product-title { color: #111827; font-size: 18px; font-weight: 700; line-height: 1.4; display: inline; }    .tg-df-container .hawk-deal-widget-title-price { font-size: 18px; font-weight: 700; line-height: 1.4; white-space: nowrap; color: #2563eb; }    .tg-df-container .hawk-deal-widget-title-price-now { font-weight: 700; }    .tg-df-container .hawk-deal-widget-title-retailer-price:hover { text-decoration: underline; }    .tg-df-container .hawk-deal-widget-title-retailer { font-size: 18px; font-weight: 700; line-height: 1.4; color: #2563eb; }    .tg-df-container .hawk-deal-widget-title-was-price { color: #dc2626; font-size: 16px; font-weight: 500; line-height: 1.4; text-decoration: line-through; white-space: nowrap; margin-left: 8px; margin-right: 8px; }    .tg-df-container .hawk-deal-widget-text-body-container { position: relative; width: 100%; box-sizing: border-box; }    .tg-df-container .hawk-deal-widget-text-body-main { font-size: 16px; width: 100%; margin-bottom: 12px; }    .tg-df-container .hawk-deal-widget-text-body-description { display: block; font-size: 15px; margin-top: 12px; color: #4b5563; line-height: 1.6; }    .tg-df-container .hawk-deal-widget-text-body-description p { margin: 0; line-height: 1.6; }    .tg-df-container .hawk-deal-widget-text-cta-container { display: flex; flex-direction: column; gap: 12px; width: 100%; flex: 1; min-width: 0; box-sizing: border-box; }    .tg-df-container .hawk-deal-widget-footer { display: flex; justify-content: flex-end; width: 100%; margin-top: auto; }    .tg-df-container .hawk-deal-widget-button-wrapper { display: flex; flex-direction: column; align-items: flex-end; justify-content: flex-end; width: 100%; }    .tg-df-container .hawk-deal-widget-preferred-partner-wrapper { display: flex; flex-direction: row; }        @container tg-df (min-width: 600px) {      .tg-df-mobile-only { display: none !important; }    }    @container tg-df (max-width: 599px) {      .tg-df-desktop-only { display: none !important; }      .tg-df-grid.layout-replica-2 { grid-template-columns: 1fr !important; }      .tg-df-grid.savings-squad-cards { grid-template-columns: 1fr !important; display: flex; flex-direction: column; }    }    .tg-df-grid.savings-squad-cards .tg-df-card-title {      -webkit-line-clamp: unset !important;      display: block !important;      overflow: visible !important;    }    @container tg-df (max-width: 500px) {      .tg-df-container .hawk-deal-widget-wrap { display: block; }      .tg-df-container .hawk-deal-widget-image-container { display: block; float: left; margin: 0 16px 8px 0; width: 120px; max-width: 120px; height: auto; align-items: normal; justify-content: normal; }      .tg-df-container .hawk-deal-widget-text-cta-container { display: block; text-align: left; }      .tg-df-container .hawk-deal-widget-footer { display: block; margin-top: 16px; clear: both; width: 100%; }      .tg-df-container .hawk-deal-widget-button-wrapper { display: block; width: 100%; }      .tg-df-container .hawk-deal-widget-button-wrapper .hawk-deal-widget-preferred-partner-wrapper { display: block; width: 100%; }      .tg-df-container .hawk-affiliate-link-deal-button { box-sizing: border-box !important; display: flex !important; max-width: none !important; width: 100% !important; margin: 0 !important; }    }        .tg-df-container .hawk-affiliate-link-deal-button {       align-items: center; background-color: #5aaf0b; box-sizing: border-box; color: #ffffff !important; display: flex; font-size: 14px; font-weight: 700; justify-content: center; letter-spacing: 0.5px; line-height: 1; min-width: 160px; padding: 14px 24px; text-align: center; text-decoration: none; text-transform: uppercase; width: 100%; word-break: normal; border-radius: 4px; border: 0; transition: background-color 0.2s;     }    .tg-df-container .hawk-affiliate-link-deal-button:hover { background-color: #4a9109; text-decoration: none; }    .tg-df-container .hawk-lazy-image-deal-widget { display: block; height: auto; margin: auto; max-height: 160px; max-width: 100%; mix-blend-mode: multiply; object-fit: contain; }    .tg-df-container .hawk-deal-widget-text-cta-container a { color: #2563eb; text-decoration: none; display: inline; }    .tg-df-container .hawk-deal-widget-text-cta-container a:hover { text-decoration: underline; }    .tg-df-container .hawk-deal-widget-text-cta-container a:has(.hawk-deal-widget-title-product-title) { color: #111827; }    .tg-df-container .hawk-deal-widget-text-cta-container a:hover .hawk-deal-widget-title-product-title,    .tg-df-container .hawk-deal-widget-text-cta-container a:hover .hawk-deal-widget-title-retailer-price { text-decoration: underline; }  \x3C/style>  \x3C!-- Widget Container --\x3E  \x3Cdiv class="tg-df-container" id="signal-deals-finder-root">    \x3C!-- Editor Floating Bar --\x3E    \x3Cdiv class="tg-df-editor-bar" id="tg-df-editor-bar" style="display:none;">      \x3Cdiv class="tg-df-editor-bar-text" style="display: flex; align-items: center;">        \x3Cspan id="tg-df-selected-count">0\x3C/span>\x26nbsp;Deals Selected        \x3Cbutton class="tg-df-editor-clear-btn" id="tg-df-editor-clear" type="button" style="margin-left: 12px; font-size: 13px; color: #9ca3af; background: none; border: none; cursor: pointer; text-decoration: underline;">Clear All\x3C/button>      \x3C/div>      \x3Cbutton class="tg-df-editor-copy-btn" id="tg-df-editor-copy" type="button">        \x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2">\x3C/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1">\x3C/path>\x3C/svg>        Copy to CMS      \x3C/button>    \x3C/div>    \x3Cdiv class="tg-df-carousel-host" id="tg-df-carousel-host" style="display: none;">      \x3Cdiv class="tg-df-carousel-eyebrow">DEAL FINDER\x3C/div>      \x3Cdiv class="tg-df-carousel-query-title" id="tg-df-carousel-title-label">Best Deals\x3C/div>            \x3Cdiv class="tg-df-carousel-blue-box">        \x3Cdiv class="tg-df-carousel-bg-circle-1" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-bg-circle-2" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-bg-circle-3" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-box-content">          \x3Cdiv class="tg-df-countdown-wrapper" id="tg-df-countdown-wrapper" style="display:none;">            \x3Cdiv class="tg-df-countdown-title" id="tg-df-countdown-title">Prime Day starts in\x3C/div>            \x3Cdiv class="tg-df-countdown-blocks">              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-days">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">DAYS\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-hrs">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">HRS\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-min">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">MIN\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-sec">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">SEC\x3C/div>\x3C/div>            \x3C/div>          \x3C/div>          \x3Cdiv class="tg-df-carousel-box-eyebrow">DEAL FINDER\x3C/div>          \x3Cdiv class="tg-df-carousel-box-title">Find Deals Fast\x3C/div>          \x3Cdiv class="tg-df-carousel-box-subtitle">The latest deals from the biggest retailers, all in one place\x3C/div>                    \x3Cdiv class="tg-df-carousel-roundels-wrapper">          \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-roundels').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>          \x3Cdiv class="tg-df-carousel-roundels">            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>          \x3C/div>          \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" onclick="this.parentElement.querySelector('.tg-df-carousel-roundels').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>        \x3C/div>        \x3Cdiv class="tg-df-carousel-filters-outer" style="position: relative;">          \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-filters-wrap').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>          \x3Cdiv class="tg-df-carousel-filters-wrap">                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="0">All\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-ot="amazon_lightning">              \x3Cimg src="https://cdn.mos.cms.futurecdn.net/HqAui7w97ft2NPqBtQ5r38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/yWPQ5yyQRhUwVKzGwYbh38-600-100.png" class="active-img" alt="" /> Lightning deals\x3C/button>            \x3Cbutton class="tg-df-carousel-filter-btn" data-ot="amazon_prime">              \x3Cimg src="https://cdn.mos.cms.futurecdn.net/fwoVXvL79turN3Ph535m38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/u75QjVpt3w2EsMimJiRo38-600-100.png" class="active-img" alt="" /> Prime deals\x3C/button>            \x3Cbutton class="tg-df-carousel-filter-btn" data-d="10">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 10% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="15">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 15% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="25">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 25% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-pr="under50">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-badge-dollar-sign">\x3Cpath d="M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z">\x3C/path>\x3Cpath d="M16 8h-6a2 2 0 1 0 0 4h4a2 2 0 1 1 0 4H8">\x3C/path>\x3Cpath d="M12 18V6">\x3C/path>\x3C/svg>            Under $50\x3C/button>        \x3C/div>        \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-filters-wrap').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>      \x3C/div>    \x3C/div>    \x3C/div>      \x3C!-- Search & Filter Controls --\x3E    \x3Cdiv class="tg-df-controls" id="tg-df-controls" style="display:flex;">      \x3Cdiv class="tg-df-top-bar">        \x3Cdiv class="tg-df-search-wrapper">          \x3Cinput type="text" class="tg-df-search-input" placeholder="Search for deals, products, or brands...">          \x3Cbutton type="button" class="tg-df-search-btn" aria-label="Search">              \x3Csvg class="tg-df-search-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">                \x3Cpath d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/>              \x3C/svg>          \x3C/button>          \x3Cdiv class="tg-df-autocomplete-dropdown" id="tg-df-autocomplete">\x3C/div>        \x3C/div>                \x3Cdiv class="tg-df-settings-wrapper">          \x3Cbutton type="button" class="tg-df-settings-btn" aria-label="Settings" id="tg-df-settings-toggle">            \x3Csvg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="20" height="20">                \x3Cpath d="M19.14 12.94c.04-.3.06-.61.06-.94 0-.32-.02-.64-.06-.94l2.03-1.58c.18-.14.23-.41.12-.61l-1.92-3.32c-.12-.22-.37-.29-.59-.22l-2.39.96c-.5-.38-1.03-.7-1.62-.94l-.36-2.54c-.04-.24-.24-.41-.48-.41h-3.84c-.24 0-.43.17-.47.41l-.36 2.54c-.59.24-1.13.57-1.62.94l-2.39-.96c-.22-.08-.47 0-.59.22L2.73 8.87c-.12.21-.08.47.12.61l2.03 1.58c-.05.3-.09.63-.09.94s.02.64.06.94l-2.03 1.58c-.18.14-.23.41-.12.61l1.92 3.32c.12.22.37.29.59.22l2.39-.96c.5.38 1.03.7 1.62.94l.36 2.54c.05.24.24.41.48.41h3.84c.24 0 .43-.17.47-.41l.36-2.54c.59-.24 1.13-.56 1.62-.94l2.39.96c.22.08.47 0 .59-.22l1.92-3.32c.12-.22.07-.49-.12-.61l-2.01-1.58zM12 15.6c-1.98 0-3.6-1.62-3.6-3.6s1.62-3.6 3.6-3.6 3.6 1.62 3.6 3.6-1.62 3.6-3.6 3.6z"/>            \x3C/svg>          \x3C/button>          \x3Cdiv class="tg-df-settings-dropdown-backdrop" id="tg-df-settings-backdrop">\x3C/div>          \x3Cdiv class="tg-df-settings-dropdown" id="tg-df-settings-panel">            \x3Cdiv class="tg-df-setting-item">              \x3Clabel class="tg-df-setting-label">Search Region\x3C/label>              \x3Cselect class="tg-df-region-select" id="tg-df-region-select">                \x3Coption value="auto">🌍 Auto-detect\x3C/option>                \x3Coption value="US">🇺🇸 United States (US)\x3C/option>                \x3Coption value="GB">🇬🇧 United Kingdom (UK)\x3C/option>                \x3Coption value="CA">🇨🇦 Canada (CA)\x3C/option>                \x3Coption value="AU">🇦🇺 Australia (AU)\x3C/option>                \x3Coption value="DE">🇩🇪 Germany (DE)\x3C/option>                \x3Coption value="FR">🇫🇷 France (FR)\x3C/option>                \x3Coption value="IT">🇮🇹 Italy (IT)\x3C/option>              \x3C/select>            \x3C/div>            \x3Cdiv class="tg-df-setting-item">              \x3Clabel class="tg-df-setting-label">Retailer\x3C/label>              \x3Cselect class="tg-df-region-select" id="tg-df-retailer-select">                \x3Coption value="">All Retailers\x3C/option>                \x3Coption value="Amazon">Amazon\x3C/option>                \x3Coption value="Walmart">Walmart\x3C/option>                \x3Coption value="Best Buy">Best Buy\x3C/option>                \x3Coption value="Target">Target\x3C/option>                \x3Coption value="John Lewis">John Lewis\x3C/option>                \x3Coption value="Currys">Currys\x3C/option>                \x3Coption value="Argos">Argos\x3C/option>              \x3C/select>            \x3C/div>            \x3Cdiv class="tg-df-setting-item">              \x3Clabel class="tg-df-setting-label">Offer Type\x3C/label>              \x3Cselect class="tg-df-region-select" id="tg-df-offer-type-select">                \x3Coption value="">All Offers\x3C/option>                \x3Coption value="amazon_prime">Amazon Prime\x3C/option>                \x3Coption value="recommended_promo">Recommended Promo\x3C/option>                \x3Coption value="amazon_lightning">Amazon Lightning Deal\x3C/option>              \x3C/select>            \x3C/div>            \x3Cdiv class="tg-df-setting-item">              \x3Clabel class="tg-df-setting-label">Result Count\x3C/label>              \x3Cselect class="tg-df-region-select" id="tg-df-rows-select">                \x3Coption value="3">3 Items\x3C/option>                \x3Coption value="4">4 Items\x3C/option>                \x3Coption value="6">6 Items\x3C/option>                \x3Coption value="12" selected>12 Items\x3C/option>                \x3Coption value="24">24 Items\x3C/option>                \x3Coption value="48">48 Items\x3C/option>              \x3C/select>            \x3C/div>            \x3Cdiv class="tg-df-setting-item tg-df-dl-row">              \x3Cdiv>                \x3Cspan class="tg-df-dl-row-text">Deal Mode\x3C/span>                \x3Cspan class="tg-df-dl-row-subtext">Only show products with active offers or previous prices (was_price)\x3C/span>              \x3C/div>              \x3Clabel class="tg-df-toggle">                \x3Cinput type="checkbox" id="tg-df-deal-mode">                \x3Cspan class="tg-df-slider">\x3C/span>              \x3C/label>            \x3C/div>            \x3Cdiv class="tg-df-setting-item tg-df-dl-row">              \x3Cdiv>                \x3Cspan class="tg-df-dl-row-text">Editor Mode\x3C/span>                \x3Cspan class="tg-df-dl-row-subtext">Enable multi-select to copy deals to CMS\x3C/span>              \x3C/div>              \x3Clabel class="tg-df-toggle">                \x3Cinput type="checkbox" id="tg-df-editor-mode">                \x3Cspan class="tg-df-slider">\x3C/span>              \x3C/label>            \x3C/div>            \x3Cdiv class="tg-df-setting-item">              \x3Clabel class="tg-df-setting-label">View Mode\x3C/label>              \x3Cselect class="tg-df-region-select" id="tg-df-view-mode-select">                \x3Coption value="auto">Auto Collection\x3C/option>                \x3Coption value="carousel">Carousel\x3C/option>                \x3Coption value="savings_squad">Savings Squad\x3C/option>                \x3Coption value="grid">Grid (Columns)\x3C/option>                \x3Coption value="row">Row (List)\x3C/option>              \x3C/select>            \x3C/div>          \x3C/div>        \x3C/div>      \x3C/div>      \x3Cdiv class="tg-df-filters">        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-category-filter-wrapper" style="display: none;">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-category-filter" aria-label="Category">            \x3Coption value="all">All Categories\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper tg-df-multiselect-container" id="tg-df-brand-filter-wrapper" style="display:none;">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M4.25 5.61C6.27 8.2 10 13 10 13v6c0 .55.45 1 1 1h2c.55 0 1-.45 1-1v-6s3.72-4.8 5.74-7.39A.998.998 0 0 0 18.95 4H5.04c-.83 0-1.3.95-.79 1.61z"/>          \x3C/svg>          \x3Cdiv class="tg-df-filter-select tg-df-multiselect-trigger" id="tg-df-brand-trigger" tabindex="0">            Any Brand          \x3C/div>          \x3Cdiv class="tg-df-multiselect-dropdown" id="tg-df-brand-dropdown">            \x3C!-- Populated via script --\x3E          \x3C/div>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M9 3L5 6.99h3V14h2V6.99h3L9 3zm7 14.01V10h-2v7.01h-3L15 21l4-3.99h-3z"/>          \x3C/svg>          \x3Cselect class="tg-df-sort-select" aria-label="Sort Deals">            \x3Coption value="date_desc">Newest First\x3C/option>            \x3Coption value="best_match">Sort by: Match\x3C/option>            \x3Coption value="price_asc">Price Low to High\x3C/option>            \x3Coption value="price_desc">Price High to Low\x3C/option>            \x3Coption value="discount_desc">Biggest Discount\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper tg-df-price-range-wrapper" id="tg-df-custom-price-wrapper" style="display: flex; align-items:center; justify-content:center; padding: 10px 20px; gap: 8px; border: 1px solid var(--tg-df-border); border-radius: 100px; background-color: var(--tg-df-bg);">          \x3Cspan style="font-size:14px; font-weight:500; color:var(--tg-df-text-primary);">Price\x3C/span>          \x3Cinput type="number" class="tg-df-price-input" id="tg-df-custom-price-min" placeholder="Min" style="width: 48px; background: transparent; border: none; color: var(--tg-df-text-primary); outline: none; font-size: 14px; text-align: center; padding: 0;">          \x3Cspan style="color:var(--tg-df-text-muted)">-\x3C/span>          \x3Cinput type="number" class="tg-df-price-input" id="tg-df-custom-price-max" placeholder="Max" style="width: 48px; background: transparent; border: none; color: var(--tg-df-text-primary); outline: none; font-size: 14px; text-align: center; padding: 0;">        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-legacy-price-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58.55 0 1.05-.22 1.41-.59l7-7c.37-.36.59-.86.59-1.41 0-.55-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-price-filter" aria-label="Filter Prices">            \x3Coption value="all">All Prices\x3C/option>            \x3Coption value="under50">Under $50\x3C/option>            \x3Coption value="50_100">$50 - $100\x3C/option>            \x3Coption value="100_200">$100 - $200\x3C/option>            \x3Coption value="200_500">$200 - $500\x3C/option>            \x3Coption value="over500">Over $500\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-discount-filter-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">            \x3Cpath d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58.55 0 1.05-.22 1.41-.59l7-7c.37-.36.59-.86.59-1.41 0-.55-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-discount-filter" aria-label="Discount Amount">            \x3Coption value="all">Any discount\x3C/option>            \x3Coption value="5">Min 5%\x3C/option>            \x3Coption value="10">Min 10%\x3C/option>            \x3Coption value="15">Min 15%\x3C/option>            \x3Coption value="20">Min 20%\x3C/option>            \x3Coption value="25">Min 25%\x3C/option>            \x3Coption value="30">Min 30%\x3C/option>            \x3Coption value="40">Min 40%\x3C/option>            \x3Coption value="50">Min 50%\x3C/option>            \x3Coption value="60">Min 60%\x3C/option>            \x3Coption value="70">Min 70%\x3C/option>          \x3C/select>        \x3C/div>      \x3C/div>    \x3C/div>    \x3C!-- Deals Grid Wrapper --\x3E    \x3Cdiv class="tg-df-grid-wrapper tg-df-carousel-cards-wrapper" id="tg-df-grid-wrapper">      \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('#tg-df-grid').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>      \x3Cdiv class="tg-df-grid" id="tg-df-grid">        \x3C!-- Content populated by JavaScript --\x3E      \x3C/div>      \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" style="display:none;" onclick="this.parentElement.querySelector('#tg-df-grid').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>    \x3C/div>        \x3C!-- Vouchers Modal --\x3E    \x3Cdiv class="tg-df-modal-backdrop" id="tg-df-vouchers-modal">      \x3Cdiv class="tg-df-modal">        \x3Cdiv class="tg-df-modal-header">          \x3Ch3 class="tg-df-modal-title" id="tg-df-vouchers-title">Available Coupons & Deals\x3C/h3>          \x3Cbutton class="tg-df-modal-close" id="tg-df-vouchers-close">            \x3Csvg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">              \x3Cline x1="18" y1="6" x2="6" y2="18">\x3C/line>              \x3Cline x1="6" y1="6" x2="18" y2="18">\x3C/line>            \x3C/svg>          \x3C/button>        \x3C/div>        \x3Cdiv class="tg-df-modal-body" id="tg-df-vouchers-content">          \x3C!-- Vouchers injected here --\x3E        \x3C/div>      \x3C/div>    \x3C/div>  \x3C/div>`;      if (!template) {        template = document.createElement('template');        template.innerHTML = rawTemplate;      }      let shadowRoot = null;      if (hostContainer && template) {        hostContainer.setAttribute('data-initialized', 'true');        shadowRoot = hostContainer.attachShadow({ mode: 'open' });        shadowRoot.appendChild(template.content.cloneNode(true));      }      class DealsFinderWidget {        constructor(config) {          this.rootNode = config.rootNode || document;          this.hostContainer = config.hostContainer || null;          this.rootId = config.rootId || 'signal-deals-finder-root';          this.root = this.rootNode.querySelector('#' + this.rootId);          if (!this.root) return;          this.widgetId = (window.crypto && window.crypto.randomUUID) ? window.crypto.randomUUID() : 'widget-' + Date.now() + '-' + Math.random().toString(36).slice(2);          this.grid = this.root.querySelector('#tg-df-grid');          this.tagsContainer = this.root.querySelector('#tg-df-tags-container');          this.categoryFilter = this.root.querySelector('#tg-df-category-filter');          this.categoryFilterWrapper = this.root.querySelector('#tg-df-category-filter-wrapper');          this.searchInput = this.root.querySelector('.tg-df-search-input');          this.autocompleteDropdown = this.root.querySelector('#tg-df-autocomplete');          this.sortSelect = this.root.querySelector('.tg-df-sort-select');          this.searchBtn = this.root.querySelector('.tg-df-search-btn');                    this.settingsToggle = this.root.querySelector('#tg-df-settings-toggle');          this.settingsPanel = this.root.querySelector('#tg-df-settings-panel');          this.settingsBackdrop = this.root.querySelector('#tg-df-settings-backdrop');          this.regionSelect = this.root.querySelector('#tg-df-region-select');          this.retailerSelect = this.root.querySelector('#tg-df-retailer-select');          this.offerTypeSelect = this.root.querySelector('#tg-df-offer-type-select');          this.viewModeSelect = this.root.querySelector('#tg-df-view-mode-select');          this.rowsSelect = this.root.querySelector('#tg-df-rows-select');          this.dealModeToggle = this.root.querySelector('#tg-df-deal-mode');          this.editorModeToggle = this.root.querySelector('#tg-df-editor-mode');          this.priceFilter = this.root.querySelector('#tg-df-price-filter');          this.discountFilter = this.root.querySelector('#tg-df-discount-filter');                    this.editorBar = this.root.querySelector('#tg-df-editor-bar');          this.editorSelectedCount = this.root.querySelector('#tg-df-selected-count');          this.editorCopyBtn = this.root.querySelector('#tg-df-editor-copy');          this.editorClearBtn = this.root.querySelector('#tg-df-editor-clear');                    this.apiUrl = 'https://search-api.fie.future.net.uk/widget.php';          this.deals = [];          this.displayLimit = 12;          this.airedaleArticles = null;          this.airedaleTags = [];          this.airedaleTagCounts = {};          this.activeDealTag = null;          this.selectedBrands = [];          this.currentQuery = '';          this.editorMode = this.hostContainer ? this.hostContainer.hasAttribute('data-editor-mode') : false;          this.viewModeOverride = this.hostContainer ? this.hostContainer.getAttribute('data-view-mode') : null;          this.selectedDeals = new Map();                    this.brandFilterWrapper = this.root.querySelector('#tg-df-brand-filter-wrapper');          this.brandTrigger = this.root.querySelector('#tg-df-brand-trigger');          this.brandDropdown = this.root.querySelector('#tg-df-brand-dropdown');                    this.customPriceWrapper = this.root.querySelector('#tg-df-custom-price-wrapper');          this.customPriceMin = this.root.querySelector('#tg-df-custom-price-min');          this.customPriceMax = this.root.querySelector('#tg-df-custom-price-max');          this.legacyPriceWrapper = this.root.querySelector('#tg-df-legacy-price-wrapper');          this.discountFilterWrapper = this.root.querySelector('#tg-df-discount-filter-wrapper');          this.initResizeObserver();          this.init();            if (['carousel', 'carousel-compact', 'auto', 'grid', 'row'].includes(this.getViewMode())) { this.loadCarouselSpreadsheet(); }        }        getViewMode() {          if (this.viewModeOverride && (!this.editorMode || !this.viewModeSelect)) {            return this.viewModeOverride;          }          return (this.viewModeSelect && this.viewModeSelect.value) ? this.viewModeSelect.value : (this.viewModeOverride || 'auto');        }        applyLayoutMode() {          if (!this.grid) return;          const mode = this.getViewMode();          this.grid.classList.remove('layout-row', 'layout-grid', 'tg-df-grid-auto', 'carousel-compact', 'layout-replica-1', 'layout-replica-2');                    const carouselHost = this.root.querySelector('#tg-df-carousel-host');          const controlsDiv = this.root.querySelector('#tg-df-controls');          if (mode === 'carousel' || mode === 'auto' || mode === 'grid' || mode === 'row') {             if (mode === 'carousel') this.grid.classList.add('carousel-compact');             if (carouselHost) carouselHost.style.display = 'block';             if (controlsDiv) controlsDiv.style.display = 'none';             if (this.root.classList.contains('tg-df-container') && mode === 'carousel') {               this.root.classList.add('is-carousel');             } else if (this.root.classList.contains('tg-df-container')) {               this.root.classList.remove('is-carousel');             }          } else {             if (carouselHost) carouselHost.style.display = 'none';             if (controlsDiv) controlsDiv.style.display = 'flex';             if (this.root.classList.contains('tg-df-container')) {               this.root.classList.remove('is-carousel');             }          }          if (mode === 'grid') {            this.grid.classList.add('layout-grid');          } else if (mode === 'row') {            this.grid.classList.add('layout-row');          } else if (mode === 'savings_squad') {            this.grid.classList.add('tg-df-grid-auto', 'savings-squad-cards');          } else if (mode !== 'carousel') {            this.grid.classList.add('tg-df-grid-auto');          }                    const settingsWrapper = this.root.querySelector('.tg-df-settings-wrapper');          if (settingsWrapper) {            settingsWrapper.style.display = mode === 'auto' ? 'none' : 'block';          }          if (this.customPriceWrapper) {             this.customPriceWrapper.style.display = mode === 'auto' ? 'flex' : 'none';          }          if (this.legacyPriceWrapper) {             this.legacyPriceWrapper.style.display = mode === 'auto' ? 'none' : 'flex';          }          if (this.discountFilterWrapper) {             this.discountFilterWrapper.style.display = mode === 'auto' ? 'none' : 'flex';          }        }        initResizeObserver() {          try {            if (window.parent === window) return;          } catch (e) {            // cross origin frame check threw          }          const emitHeight = () => {            try {              const height = document.documentElement.scrollHeight || document.body.scrollHeight;              const msg = { type: 'embed-size', height: height };              if (window.parent && window.parent !== window) {                window.parent.postMessage(msg, '*');                window.parent.postMessage(JSON.stringify({ ...msg, sentinel: 'amp' }), '*');              }            } catch (e) {}          };                    if (window.ResizeObserver) {            try {              const ro = new ResizeObserver(() => emitHeight());              ro.observe(document.body);              if (this.root) ro.observe(this.root);            } catch(e){ console.warn(e); }          }          window.addEventListener('resize', emitHeight);          setTimeout(emitHeight, 300);        }        initCountdown() {          this.cdWrapper = this.root.querySelector('#tg-df-countdown-wrapper');                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          this.showCountdown = params.get('show_countdown') === 'true';          const showHeaderDetails = params.get('show_header_details') !== 'false';          const eyebrow = this.root.querySelector('.tg-df-carousel-box-eyebrow');          const title = this.root.querySelector('.tg-df-carousel-box-title');          const subtitle = this.root.querySelector('.tg-df-carousel-box-subtitle');          if (!showHeaderDetails) {            let containerElement = this.root.classList.contains('tg-df-container') ? this.root : this.root.querySelector('.tg-df-container');            if (containerElement) containerElement.classList.add('hide-header-details');            if (eyebrow) eyebrow.style.display = 'none';            if (title) title.style.display = 'none';            if (subtitle) subtitle.style.display = 'none';          }          if (!this.cdWrapper) return;          this.cdTitle = this.root.querySelector('#tg-df-countdown-title');          this.cdDays = this.root.querySelector('#tg-df-cd-days');          this.cdHrs = this.root.querySelector('#tg-df-cd-hrs');          this.cdMin = this.root.querySelector('#tg-df-cd-min');          this.cdSec = this.root.querySelector('#tg-df-cd-sec');          this.updateCountdown();          this.cdInterval = setInterval(() => this.updateCountdown(), 1000);        }        updateCountdown() {          if (!this.cdWrapper) return;          if (!this.showCountdown) {            this.cdWrapper.style.display = 'none';            return;          }          const area = this.getAreaCode();          let offset = '-04:00';          if (['DE', 'FR', 'IT', 'ES', 'NL'].includes(area)) {             offset = '+02:00';          } else if (['GB', 'IE', 'UK'].includes(area)) {             offset = '+01:00';          }          const startTime = new Date('2026-06-23T00:00:00' + offset).getTime();          const endTime = new Date('2026-06-26T00:00:00' + offset).getTime();          const now = Date.now();          let targetTime = 0;          if (now < startTime) {             targetTime = startTime;             if (this.cdTitle) this.cdTitle.textContent = 'Prime Day starts in';             this.cdWrapper.style.display = 'flex';          } else if (now < endTime) {             targetTime = endTime;             if (this.cdTitle) this.cdTitle.textContent = 'Prime Day ends in';             this.cdWrapper.style.display = 'flex';          } else {             this.cdWrapper.style.display = 'none';             if (this.cdInterval) clearInterval(this.cdInterval);             return;          }          const diff = Math.max(0, targetTime - now);          const d = Math.floor(diff / (1000 * 60 * 60 * 24));          const h = Math.floor((diff / (1000 * 60 * 60)) % 24);          const m = Math.floor((diff / 1000 / 60) % 60);          const s = Math.floor((diff / 1000) % 60);          if (this.cdDays) this.cdDays.textContent = d;          if (this.cdHrs) this.cdHrs.textContent = h;          if (this.cdMin) this.cdMin.textContent = m;          if (this.cdSec) this.cdSec.textContent = s;        }        init() {          this.initCountdown();          try {            initAnalytics();          } catch (e) {            console.warn('Deals Widget Analytics Error:', e);          }                    this.bindEvents();                    let initialQuery = '';                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          let initialViewMode = params.get('view_mode');          if (!params.has('search') && !params.has('q') && !params.has('query') && initialViewMode !== 'savings_squad') {             initialQuery = 'Everything';             if (this.discountFilter && !params.has('min_discount_ratio')) {               this.discountFilter.value = '5';             }          }          const website = params.get('website') || 'tomsguide';          this.website = website;          if (website === 'techradar') {            const squadHeader = this.root.querySelector('.tg-df-savings-squad-header');            if (squadHeader) {               const pic = squadHeader.querySelector('picture');               if (pic) pic.style.display = 'none';            }            const style = document.createElement('style');            style.innerHTML = `              .tg-df-container .hawk-affiliate-link-deal-button, .tg-df-container .tg-df-card-cta { background-color: #5DAF08 !important; }              .tg-df-container .hawk-affiliate-link-deal-button:hover, .tg-df-container .tg-df-card-cta:hover { background-color: #4a8c06 !important; }            `;            this.root.appendChild(style);          }                    if (this.regionSelect) {            this.regionSelect.value = params.get('region') || 'auto';            this.updatePriceDropdownCurrency();          }                    if (this.retailerSelect && params.has('retailer')) {            this.retailerSelect.value = params.get('retailer');          }                    if (params.has('brands')) {            const b = params.get('brands');            if (b) {              this.selectedBrands = b.split(',');            }          }                    if (this.offerTypeSelect && params.has('offer_type')) {            this.offerTypeSelect.value = params.get('offer_type');          }          if (params.has('bg_color')) {            const bg = params.get('bg_color');            if (bg === 'white') {              this.root.style.setProperty('background-color', '#ffffff', 'important');            } else if (bg === 'transparent') {              this.root.style.setProperty('background-color', 'transparent', 'important');            } else if (bg === 'light_blue') {              this.root.style.setProperty('background-color', '#E7F0FF', 'important');            }          } else {             this.root.style.removeProperty('background-color');          }                    if (params.has('view_mode')) {            if (this.viewModeSelect) {              this.viewModeSelect.value = params.get('view_mode');            } else {              this.viewModeOverride = params.get('view_mode');            }          }          if (this.rowsSelect && params.has('rows')) {            this.rowsSelect.value = params.get('rows');          }          if (params.has('price')) {            const priceVal = params.get('price');            if (this.priceFilter) {               // Try assigning it directly to select. If it's not present implicitly ignores               this.priceFilter.value = priceVal;            }            if (priceVal.includes('_')) {               const parts = priceVal.split('_');               if (this.customPriceMin && parts[0]) this.customPriceMin.value = parts[0];               if (this.customPriceMax && parts[1]) this.customPriceMax.value = parts[1];            }          }          if (this.discountFilter && params.has('min_discount_ratio')) {            // Need to convert back from ratio (e.g. 0.8) to select value (e.g. "20")            const ratioStr = params.get('min_discount_ratio');            const ratioFloat = parseFloat(ratioStr);            if (!isNaN(ratioFloat)) {               const percentage = Math.round((1 - ratioFloat) * 100);               this.discountFilter.value = percentage.toString();            }          }          if (this.sortSelect) {            this.sortSelect.value = params.get('sort') || 'discount_desc';          }          if (this.dealModeToggle && params.has('deal_mode')) {            this.dealModeToggle.checked = params.get('deal_mode') === 'true' || params.get('deal_mode') === '1';          }                    // Re-apply layout after params have updated control values          this.applyLayoutMode();                    if (params.get('search')) {            initialQuery = params.get('search');          } else if (params.get('q')) {            initialQuery = params.get('q');          } else if (params.get('query')) {            initialQuery = params.get('query');          }                    this.currentQuery = initialQuery;          if (this.searchInput) {            this.searchInput.value = this.currentQuery;          }                    if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {            this.fetchDeals(this.currentQuery);          } else {            this.render();          }        }        updatePriceDropdownCurrency() {          if (!this.priceFilter || !this.regionSelect) return;          const currencySymbols = {            'US': '$',            'GB': '£',            'CA': '$CA',            'AU': '$AU',            'DE': '€',            'FR': '€',            'IT': '€',          };          const area = this.getAreaCode();          const cur = currencySymbols[area || 'US'] || '$';                    const options = this.priceFilter.options;          for (let i = 0; i < options.length; i++) {            const opt = options[i];            if (opt.value === 'all') {              opt.innerText = 'All Prices';            } else if (opt.value === 'under50') {              opt.innerText = `Under ${cur}50`;            } else if (opt.value === '50_100') {              opt.innerText = `${cur}50 - ${cur}100`;            } else if (opt.value === '100_200') {              opt.innerText = `${cur}100 - ${cur}200`;            } else if (opt.value === '200_500') {              opt.innerText = `${cur}200 - ${cur}500`;            } else if (opt.value === 'over500') {              opt.innerText = `Over ${cur}500`;            }          }        }        populateBrandDropdown(values) {          if (!this.brandDropdown || !this.brandFilterWrapper) return;          this.brandFilterWrapper.style.display = 'flex'; // show the wrapper                    let html = '';          const allChecked = this.selectedBrands.length === 0 ? 'checked' : '';          const _div = '<' + '/div>';          const _span = '<' + '/span>';          html += `\x3Cdiv class="tg-df-ms-option">\x3Cinput type="checkbox" value="" ${allChecked} class="tg-df-brand-chk"> Any Brand${_div}`;                    values.forEach(v => {             if (!v.formatted_value || v.formatted_value === 'Any Brand') return;             const isChecked = this.selectedBrands.includes(v.formatted_value) ? 'checked' : '';             html += `\x3Cdiv class="tg-df-ms-option">\x3Cinput type="checkbox" value="${this.escapeHTML(v.formatted_value)}" ${isChecked} class="tg-df-brand-chk"> ${this.escapeHTML(v.formatted_value)} \x3Cspan style="color:var(--tg-df-text-muted);font-size:12px">(${v.count || 0})${_span}${_div}`;          });                    this.brandDropdown.innerHTML = html;                    // Re-bind listeners          const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');          chks.forEach(chk => {            chk.addEventListener('change', (e) => {              const val = e.target.value;              if (val === '') {                this.selectedBrands = [];              } else {                if (e.target.checked) {                   if (!this.selectedBrands.includes(val)) this.selectedBrands.push(val);                } else {                   this.selectedBrands = this.selectedBrands.filter(b => b !== val);                }              }                            if (this.selectedBrands.length === 0) {                 this.brandTrigger.innerText = 'Any Brand';              } else if (this.selectedBrands.length === 1) {                 this.brandTrigger.innerText = this.selectedBrands[0];              } else {                 this.brandTrigger.innerText = `${this.selectedBrands.length} Brands selected`;              }                            // Only call API if changed from UI interactions              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                 this.updateURLParams();                 this.fetchDeals(this.currentQuery);              }            });          });                    // Update button text on load          if (this.selectedBrands.length === 0) {             this.brandTrigger.innerText = 'Any Brand';          } else if (this.selectedBrands.length === 1) {             this.brandTrigger.innerText = this.selectedBrands[0];          } else {             this.brandTrigger.innerText = `${this.selectedBrands.length} Brands selected`;          }        }        updateURLParams() {          const url = new URL(window.location);          if (this.currentQuery && this.currentQuery !== 'Gaming laptops') {            url.searchParams.set('q', this.currentQuery);          } else {            url.searchParams.delete('q');            url.searchParams.delete('search');            url.searchParams.delete('query');          }                    if (this.regionSelect && this.regionSelect.value !== 'auto') {            url.searchParams.set('region', this.regionSelect.value);          } else {            url.searchParams.delete('region');          }                    if (this.retailerSelect && this.retailerSelect.value) {            url.searchParams.set('retailer', this.retailerSelect.value);          } else {            url.searchParams.delete('retailer');          }                    if (this.selectedBrands && this.selectedBrands.length > 0) {            url.searchParams.set('brands', this.selectedBrands.join(','));          } else {            url.searchParams.delete('brands');          }                    if (this.offerTypeSelect && this.offerTypeSelect.value) {            url.searchParams.set('offer_type', this.offerTypeSelect.value);          } else {            url.searchParams.delete('offer_type');          }                    if (this.viewModeSelect && this.viewModeSelect.value !== 'auto') {            url.searchParams.set('view_mode', this.viewModeSelect.value);          } else {            url.searchParams.delete('view_mode');          }                    if (this.rowsSelect && this.rowsSelect.value !== '12') {            url.searchParams.set('rows', this.rowsSelect.value);          } else {            url.searchParams.delete('rows');          }                    const min = this.customPriceMin ? this.customPriceMin.value : '';          const max = this.customPriceMax ? this.customPriceMax.value : '';          if (min || max) {             url.searchParams.set('price', `${min}_${max}`);          } else if (this.priceFilter && this.priceFilter.value !== 'all') {            url.searchParams.set('price', this.priceFilter.value);          } else {            url.searchParams.delete('price');          }                    if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {            const v = parseInt(this.discountFilter.value);            if (!isNaN(v) && v > 0) {               const ratio = (100 - v) / 100;               url.searchParams.set('min_discount_ratio', ratio.toString());            }          } else {            url.searchParams.delete('min_discount_ratio');          }                    if (this.sortSelect && this.sortSelect.value !== 'discount_desc') {            url.searchParams.set('sort', this.sortSelect.value);          } else {            url.searchParams.delete('sort');          }                    if (this.dealModeToggle && this.dealModeToggle.checked) {            url.searchParams.set('deal_mode', 'true');          } else {            url.searchParams.delete('deal_mode');          }                    window.history.replaceState({}, '', url);        }        bindEvents() {          const roundels = this.root.querySelectorAll('.tg-df-carousel-cat.original-hardcoded');          roundels.forEach(r => {             r.addEventListener('click', () => {                const q = r.getAttribute('data-query');                const pr = r.getAttribute('data-pr');                if (typeof trackHawkEvent !== 'undefined') {                     trackHawkEvent({                         clickType: "CC",                         widgetId: this.widgetId,                         productCategoryName: "deals",                         zeroBasedProductIndexOrNull: null,                         totalDealsOrProducts: null,                         areaClicked: "Category Roundel",                         revenueId: this.revenueId,                         isoCurrencyCode: typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD',                         queryName: q,                         widgetTypeName: this.widgetTypeName                     });                 }                this.currentQuery = q;                const label = this.root.querySelector('#tg-df-carousel-title-label');                if (label) label.textContent = 'Best ' + q;                if (this.priceFilter) this.priceFilter.value = pr || 'all';                if (this.discountFilter) this.discountFilter.value = '5';                if (this.searchInput) this.searchInput.value = q;                                roundels.forEach(ro => ro.classList.remove('active'));                r.classList.add('active');                this.fetchDeals(this.currentQuery);             });          });          const discBtns = this.root.querySelectorAll('.tg-df-carousel-filter-btn');          discBtns.forEach(b => {             b.addEventListener('click', () => {                const d = b.getAttribute('data-d');                const pr = b.getAttribute('data-pr');                const ot = b.getAttribute('data-ot');                let label = b.innerText ? b.innerText.trim() : '';                let filterType = 'unknown';                let filterVal = 'unknown';                if (d !== null) { filterType = 'discount'; filterVal = d; }                else if (pr !== null) { filterType = 'price'; filterVal = pr; }                else if (ot !== null) { filterType = 'offertype'; filterVal = ot; }                if (typeof trackElementInteraction === 'function') trackElementInteraction({ id: `filter-${filterType}-${filterVal}`, name: 'Filter Button', label: label });                                if (d !== null) {                   if (this.discountFilter) this.discountFilter.value = this.discountFilter.value === d ? '0' : d;                } else if (pr !== null) {                   if (this.priceFilter) this.priceFilter.value = this.priceFilter.value === pr ? 'all' : pr;                } else if (ot !== null) {                   if (this.offerTypeSelect) this.offerTypeSelect.value = this.offerTypeSelect.value === ot ? 'all' : ot;                } else {                   if (this.discountFilter) this.discountFilter.value = '0';                   if (this.priceFilter) this.priceFilter.value = 'all';                   if (this.offerTypeSelect) this.offerTypeSelect.value = 'all';                }                if (d === null && pr === null && ot === null && b.getAttribute("data-type") !== "custom") {                   discBtns.forEach(ro => ro.classList.remove('active'));                   b.classList.add('active');                } else if (b.getAttribute("data-type") !== "custom") {                   // Only operate on hardcoded buttons (those without data-type)                   discBtns.forEach(ro => {                      if (!ro.getAttribute('data-d') && !ro.getAttribute('data-pr') && !ro.getAttribute('data-ot') && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active');                   });                                      let makeActive = true;                   if (d !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-d') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   } else if (pr !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-pr') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   } else if (ot !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-ot') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   }                                      if (makeActive) b.classList.add('active');                                      // Check if anything is active, if not activate "All"                   let anyActive = false;                   discBtns.forEach(ro => { if (ro.classList.contains('active') && ro.getAttribute('data-type') !== 'custom') anyActive = true; });                   if (!anyActive) {                       discBtns.forEach(ro => { if (!ro.getAttribute('data-d') && !ro.getAttribute('data-pr') && !ro.getAttribute('data-ot') && ro.getAttribute('data-type') !== 'custom') ro.classList.add('active'); });                   }                }                                this.fetchDeals(this.currentQuery);             });          });          if (this.brandTrigger && this.brandDropdown) {            this.brandTrigger.addEventListener('click', () => {              this.brandDropdown.classList.toggle('active');            });            document.addEventListener('click', (e) => {              if (this.brandFilterWrapper && !e.composedPath().includes(this.brandFilterWrapper)) {                this.brandDropdown.classList.remove('active');              }            });          }          let debounceTimer;          if(this.searchInput) {            this.searchInput.addEventListener('input', (e) => {              clearTimeout(debounceTimer);              const query = e.target.value.trim();              this.currentQuery = query;              if (this.getViewMode() === 'savings_squad' && this.autocompleteDropdown && this.airedaleTags && query.length > 0) {                 const matches = this.airedaleTags.filter(t => t.toLowerCase().includes(query.toLowerCase()) && t.toLowerCase() !== query.toLowerCase()).slice(0, 5);                 if (matches.length > 0) {                    this.autocompleteDropdown.innerHTML = matches.map(m => `\x3Cdiv class="tg-df-autocomplete-item" data-tag="${this.escapeHTML(m)}">${this.escapeHTML(m)}<` + `/div>`).join('');                    this.autocompleteDropdown.classList.add('active');                 } else {                    this.autocompleteDropdown.classList.remove('active');                 }              } else if (this.autocompleteDropdown) {                 this.autocompleteDropdown.classList.remove('active');              }              debounceTimer = setTimeout(() => {                this.updateURLParams();                if (query.length > 2) {                  this.fetchDeals(query);                } else if (query.length === 0) {                  this.deals = [];                  this.render();                }              }, 400);            });            this.searchInput.addEventListener('keypress', (e) => {              if (e.key === 'Enter') {                if (this.autocompleteDropdown) this.autocompleteDropdown.classList.remove('active');                clearTimeout(debounceTimer);                const query = e.target.value.trim();                this.currentQuery = query;                this.activeDealTag = null;                trackElementInteraction({ id: 'search-submit', name: 'Ask', label: 'Ask (main search)', text: query });                this.updateURLParams();                if (query.length > 2 || (this.getViewMode() === 'savings_squad')) {                   this.fetchDeals(query);                }              }            });          }          if (this.autocompleteDropdown) {             this.autocompleteDropdown.addEventListener('click', (e) => {                const item = e.target.closest('.tg-df-autocomplete-item');                if (item) {                   const tag = item.getAttribute('data-tag');                   this.currentQuery = tag;                   if (this.searchInput) this.searchInput.value = tag;                   this.activeDealTag = tag;                   this.autocompleteDropdown.classList.remove('active');                   this.updateURLParams();                   this.fetchDeals(tag);                }             });             document.addEventListener('click', (e) => {               if (this.autocompleteDropdown && this.searchInput && !e.composedPath().includes(this.searchInput) && !e.composedPath().includes(this.autocompleteDropdown)) {                 this.autocompleteDropdown.classList.remove('active');               }             });          }          if (this.searchBtn) {            this.searchBtn.addEventListener('click', () => {              if (this.autocompleteDropdown) this.autocompleteDropdown.classList.remove('active');              clearTimeout(debounceTimer);              const query = this.searchInput.value.trim();              trackElementInteraction({ id: 'search-submit', name: 'Ask', label: 'Ask (main search)', text: query });              this.activeDealTag = null;              this.currentQuery = query;              this.updateURLParams();              if (query.length > 2 || (this.getViewMode() === 'savings_squad')) {                 this.fetchDeals(query);              }            });          }          if(this.sortSelect) this.sortSelect.addEventListener('change', () => {            trackElementInteraction({ id: `sort-option-${this.sortSelect.value}`, name: 'Sort', label: `Sort: ${this.sortSelect.options[this.sortSelect.selectedIndex].text}` });            this.updateURLParams();            if (this.deals.length > 0) {              this.sortData();              this.render();            }          });                    const priceFilter = this.root.querySelector('#tg-df-price-filter');          if (priceFilter) {            this.priceFilter = priceFilter;            this.priceFilter.addEventListener('change', () => {              trackElementInteraction({ id: `filter-price-${this.priceFilter.value}`, name: 'Price', label: this.priceFilter.options[this.priceFilter.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }            });          }          const updateCustomPrice = () => {             this.updateURLParams();             if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);             } else {                this.render();             }          };          if (this.customPriceMin) {             this.customPriceMin.addEventListener('change', updateCustomPrice);             this.customPriceMin.addEventListener('keypress', (e) => {                if (e.key === 'Enter') updateCustomPrice();             });          }          if (this.customPriceMax) {             this.customPriceMax.addEventListener('change', updateCustomPrice);             this.customPriceMax.addEventListener('keypress', (e) => {                if (e.key === 'Enter') updateCustomPrice();             });          }          const discountFilter = this.root.querySelector('#tg-df-discount-filter');          if (discountFilter) {            this.discountFilter = discountFilter;            this.discountFilter.addEventListener('change', () => {              trackElementInteraction({ id: `filter-discount-${this.discountFilter.value}`, name: 'Discount', label: this.discountFilter.options[this.discountFilter.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }            });          }          if (this.categoryFilter) {            this.categoryFilter.addEventListener('change', (e) => {               const val = e.target.value === 'all' ? null : e.target.value;               this.activeDealTag = val;               this.fetchSavingsSquad();            });          }                    if (this.settingsToggle) {            this.settingsToggle.addEventListener('click', () => {              const o = this.settingsPanel.classList.toggle('active');              this.settingsBackdrop.classList.toggle('active');              if (o) trackElementInteraction({ id: 'filter-open', name: 'Filters', label: 'Open filters' });            });          }                    if (this.settingsBackdrop) {            this.settingsBackdrop.addEventListener('click', () => {              this.settingsPanel.classList.remove('active');              this.settingsBackdrop.classList.remove('active');            });          }                    if (this.regionSelect) {            this.regionSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-region-${this.regionSelect.value}`, name: 'Region', label: this.regionSelect.options[this.regionSelect.selectedIndex].text });              this.updateURLParams();              this.updatePriceDropdownCurrency();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.retailerSelect) {            this.retailerSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-merchant-${this.retailerSelect.value}`, name: 'Retailer', label: this.retailerSelect.options[this.retailerSelect.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.offerTypeSelect) {            this.offerTypeSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-offertype-${this.offerTypeSelect.value}`, name: 'Offer Type', label: this.offerTypeSelect.options[this.offerTypeSelect.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.viewModeSelect) {            this._prevViewMode = this.viewModeSelect.value;            this.viewModeSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-viewmode-${this.viewModeSelect.value}`, name: 'View Mode', label: this.viewModeSelect.options[this.viewModeSelect.selectedIndex].text });                            // Reset all active toggles and filters to prevent config carry-over              this.selectedBrands = [];              if (this.brandTrigger) this.brandTrigger.innerText = 'Select Brands';              if (this.brandDropdown) {                const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                chks.forEach(chk => { chk.checked = false; });              }              if (this.priceFilter) this.priceFilter.value = 'all';              if (this.customPriceMin) this.customPriceMin.value = '';              if (this.customPriceMax) this.customPriceMax.value = '';              if (this.sortSelect) this.sortSelect.value = this.viewModeSelect.value === 'savings_squad' ? 'date_desc' : 'discount_desc';              if (this.discountFilter) this.discountFilter.value = '0';              if (this.retailerSelect) this.retailerSelect.value = '';              if (this.offerTypeSelect) this.offerTypeSelect.value = '';              if (this.rowsSelect) this.rowsSelect.value = '12';              if (this.categoryFilter) this.categoryFilter.value = 'all';              this.activeDealTag = null;              this.updateURLParams();              this.applyLayoutMode();                            if (this.getViewMode() === 'savings_squad' || this._prevViewMode === 'savings_squad') {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }              this._prevViewMode = this.viewModeSelect.value;            });          }                    if (this.rowsSelect) {            this.rowsSelect.addEventListener('change', () => {              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.dealModeToggle) {            this.dealModeToggle.addEventListener('change', () => {              this.updateURLParams();              this.render();            });          }          if (this.editorModeToggle) {             this.editorModeToggle.addEventListener('change', (e) => {                this.editorMode = e.target.checked;                this.render();                this.updateFloatingCopyBar();             });          }          if (this.editorCopyBtn) {             this.editorCopyBtn.addEventListener('click', () => {                this.copySelectedDealsToCMS();             });          }          if (this.editorClearBtn) {             this.editorClearBtn.addEventListener('click', () => {                this.selectedDeals.clear();                this.render();                this.updateFloatingCopyBar();             });          }          if (this.grid) {            this.grid.addEventListener('change', (e) => {               if (e.target.classList.contains('tg-df-deal-checkbox')) {                  const dealId = e.target.getAttribute('data-id');                  if (e.target.checked) {                     const dealObj = this.deals.find(d => d.id === dealId);                     if (dealObj) this.selectedDeals.set(dealId, dealObj);                  } else {                     this.selectedDeals.delete(dealId);                  }                  this.updateFloatingCopyBar();               }            });            this.grid.addEventListener('click', (e) => {              const dealCard = e.target.closest('[data-action="deal-click"]');              const similarCard = e.target.closest('[data-action="view-similar-click"]');              const cardLink = dealCard || similarCard;              if (cardLink) {                const productName = cardLink.getAttribute('data-product-name');                const merchantName = cardLink.getAttribute('data-merchant-name');                const productId = cardLink.getAttribute('data-analytics-id');                const price = parseFloat(cardLink.getAttribute('data-price')) || null;                const prevPriceStr = cardLink.getAttribute('data-previous-price');                const previousPrice = prevPriceStr ? parseFloat(prevPriceStr) : null;                const originalLink = cardLink.getAttribute('data-original-link');                const rewrittenLink = cardLink.getAttribute('href');                const revenueId = cardLink.getAttribute('data-revenue-id');                const index = parseInt(cardLink.getAttribute('data-index'), 10) || 0;                const inStock = cardLink.getAttribute('data-in-stock') === 'true';                const totalText = cardLink.getAttribute('data-total');                const totalDeals = parseInt(totalText, 10) || 0;                const productCategoryName = 'deals';                const trackingParams = {                  widgetId: this.widgetId,                  productCategoryName: productCategoryName,                  product: {                    modelId: cardLink.getAttribute('data-model-id') || null,                    matchId: cardLink.getAttribute('data-match-id') || null,                    brand: cardLink.getAttribute('data-model-brand') || null,                    parent: cardLink.getAttribute('data-model-parent') || null,                    name: productName,                    price: price,                    previousPrice: previousPrice,                    link: rewrittenLink,                    originalLink: originalLink,                    inStock: inStock                  },                  zeroBasedProductIndexOrNull: index,                  totalDealsOrProducts: totalDeals,                   merchant: {                    id: cardLink.getAttribute('data-merchant-id') || null,                    network: cardLink.getAttribute('data-merchant-network') || null,                    url: cardLink.getAttribute('data-merchant-url') || null,                    name: merchantName                  },                  revenueId: revenueId,                  widgetTypeName: this.widgetTypeName,                  isoCurrencyCode: normalizeCurrency(this.escapeHTML(cardLink.getAttribute('data-currency') || '$'))                };                if (dealCard) {                  trackDealClick(trackingParams);                } else {                  trackViewSimilarClick(trackingParams);                }              }              const couponsBtn = e.target.closest('[data-action="coupons-click"]');              if (couponsBtn) {                trackElementInteraction({                  id: 'product-card-show-coupons',                  name: 'Coupons',                  label: `Product card coupons: ${couponsBtn.getAttribute('data-merchant')}`                });              }            });          }          this.setupScrollListeners();        }        setupScrollListeners() {          const containers = [             this.root.querySelector('.tg-df-carousel-roundels'),             this.root.querySelector('.tg-df-carousel-filters-wrap'),             this.root.querySelector('#tg-df-grid')          ];                    containers.forEach(container => {             if (!container) return;                          const checkScroll = () => {                if (!container.parentElement) return;                const leftBtn = container.parentElement.querySelector('.tg-df-carousel-scroll-left');                const rightBtn = container.parentElement.querySelector('.tg-df-carousel-scroll-right');                                if (leftBtn) {                   if (container.scrollLeft <= 5) leftBtn.style.display = 'none';                   else leftBtn.style.display = 'flex';                }                                if (rightBtn) {                   if (container.scrollWidth <= container.clientWidth) {                       rightBtn.style.display = 'none';                   } else if (container.scrollLeft >= container.scrollWidth - container.clientWidth - 5) {                       rightBtn.style.display = 'none';                   } else {                       rightBtn.style.display = 'flex';                   }                }             };                          container.addEventListener('scroll', checkScroll);             checkScroll();                          window.addEventListener('resize', checkScroll);                          const observer = new MutationObserver(checkScroll);             observer.observe(container, { childList: true, subtree: true, characterData: false });          });        }        get widgetTypeName() {          const mode = this.viewModeSelect ? this.viewModeSelect.value : (this.viewModeOverride || 'auto');          switch(mode) {              case 'carousel': return 'Carousel';              case 'savings_squad': return 'Savings Squad';              case 'grid': return 'Grid';              case 'row': return 'Row';              default: return 'Auto Collection';          }        }        getRowsLimit() {          if (this.rowsSelect && this.rowsSelect.value) return parseInt(this.rowsSelect.value, 10);          let configSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {             configSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {             configSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(configSource);          if (params.has('rows')) return parseInt(params.get('rows'), 10) || 12;          return 12;        }        getAreaCode() {          if (this.regionSelect && this.regionSelect.value) {            if (this.regionSelect.value === 'auto') return null;            return this.regionSelect.value;          }          let area = null;          try {            const locale = window.navigator.language || window.navigator.userLanguage;            if (locale && locale.includes('-')) {              area = locale.split('-')[1].toUpperCase();            } else if (locale && locale.length === 2) {              if (locale.toUpperCase() === 'EN') { area = 'US'; }              else { area = locale.toUpperCase(); }            }          } catch (e) { /* Ignore */ }                    // Map to known valid options or fallback to US          const valid = ['US', 'GB', 'CA', 'AU', 'DE', 'FR', 'IT'];          if (area === 'UK') area = 'GB';          if (valid.includes(area)) {             return area;          }          return 'US';        }                async loadCarouselSpreadsheet() {          try {              const parseCSVRow = (str) => {                  let result = [], cur = '', inQuotes = false;                  for (let i = 0; i < str.length; i++) {                      let char = str[i];                      if (inQuotes) {                          if (char === '"') {                              if (str[i + 1] === '"') { cur += '"'; i++; }                              else { inQuotes = false; }                          } else { cur += char; }                      } else {                          if (char === '"') { inQuotes = true; }                          else if (char === ',') { result.push(cur); cur = ''; }                          else { cur += char; }                      }                  }                  result.push(cur); return result;              };              const parseCSV = (str) => {                  const rows = []; let curRow = '', inQuotes = false;                  for (let i = 0; i < str.length; i++) {                      let char = str[i];                      if (char === '"') inQuotes = !inQuotes;                      if ((char === '\n' || char === '\r') && !inQuotes) {                          if (char === '\r' && str[i+1] === '\n') i++;                          if (curRow) rows.push(parseCSVRow(curRow));                          curRow = '';                      } else { curRow += char; }                  }                  if (curRow) rows.push(parseCSVRow(curRow));                  return rows;              };              const preloadedCSV = decodeURIComponent(escape(atob("LCwxLDIsMyw0LDUsNiw3LDgsOSwxMCwxMSwxMiwxMywxNCwxNQ0KUm91bmRlbCB0ZXh0LEFsbCxUVnMsRm9vdHdlYXIsQXBwYXJlbCxNYXR0cmVzZXMsQXBwbGlhbmNlcyxXZWFyYWJsZSB0ZWNoLEhlYWRwaG9uZXMsU21hcnQgSG9tZSxTcGVha2VycyxMYXB0b3BzLFRhYmxldHMsQ29tcHV0aW5nLFBob25lcyxHYW1pbmcsTGVnbw0KUm91bmRlbCBpbWFnZSxodHRwczovL3d3dy50b21zZ3VpZGUuY29tL3Byb2R1Y3RzL2Nhcm91c2VsL2FpLnBuZyxodHRwczovL3d3dy50b21zZ3VpZGUuY29tL3Byb2R1Y3RzL2Nhcm91c2VsL3R2cy5wbmcsaHR0cHM6Ly9pbWFnZXMuZmllLmZ1dHVyZWNkbi5uZXQvcHJvZHVjdHMvN2IzYTIyNGIwNzk2M2M2MjdiNmI5MDliZDc4MzM4MzZlMDJmZjgxOS5qcGcud2VicCxodHRwczovL2ltYWdlcy5maWUuZnV0dXJlY2RuLm5ldC9wcm9kdWN0cy84NGRhYzVkNDhlZDJkNDQ4NTU5ZWJhNjdhY2U4MzE0Y2M2N2NjZDk0LmpwZy53ZWJwLGh0dHBzOi8vd3d3LnRvbXNndWlkZS5jb20vcHJvZHVjdHMvY2Fyb3VzZWwvbWF0dHJlc3Nlcy5wbmcsaHR0cHM6Ly9pbWFnZXMuZmllLmZ1dHVyZWNkbi5uZXQvcHJvZHVjdHMvNzY4ZTk3Y2ViMDcxODAxZmFlMjA5MTBkMDgyMGIxNmY3NDdhZjkzOS5qcGcud2VicCxodHRwczovL3d3dy50b21zZ3VpZGUuY29tL3Byb2R1Y3RzL2Nhcm91c2VsL3dlbGxuZXNzLnBuZyxodHRwczovL3d3dy50b21zZ3VpZGUuY29tL3Byb2R1Y3RzL2Nhcm91c2VsL2hlYWRwaG9uZXMuanBnLGh0dHBzOi8vaW1hZ2VzLmZpZS5mdXR1cmVjZG4ubmV0L3Byb2R1Y3RzLzg5NTM1YmVlYmUyMGRiYmQ0YTM0NmQ2ZDZiZGZlOTFkOGE4ODRhMjEuanBnLndlYnAsaHR0cHM6Ly93d3cudG9tc2d1aWRlLmNvbS9wcm9kdWN0cy9jYXJvdXNlbC9hdWRpby5qcGcsaHR0cHM6Ly93d3cudG9tc2d1aWRlLmNvbS9wcm9kdWN0cy9jYXJvdXNlbC9sYXB0b3BzLmpwZyxodHRwczovL2ltYWdlcy5maWUuZnV0dXJlY2RuLm5ldC9wcm9kdWN0cy8yMzk3NTY0ZWQ3YTVmZjk0N2U5YjZiMzBlNTRmNDc0OTRiODQxZjg5LmpwZy53ZWJwLGh0dHBzOi8vd3d3LnRvbXNndWlkZS5jb20vcHJvZHVjdHMvY2Fyb3VzZWwvY29tcHV0aW5nLmpwZyxodHRwczovL3d3dy50b21zZ3VpZGUuY29tL3Byb2R1Y3RzL2Nhcm91c2VsL3Bob25lcy5wbmcsaHR0cHM6Ly93d3cudG9tc2d1aWRlLmNvbS9wcm9kdWN0cy9jYXJvdXNlbC9nYW1pbmcucG5nLGh0dHBzOi8vaW1hZ2VzLmZpZS5mdXR1cmVjZG4ubmV0L3Byb2R1Y3RzLzRmNmM2MjFjYWMwYmMxYTg1ZDU5M2UzNTk0YmE1YjM0OWVmZmQyOTIuanBnLndlYnANClNlYXJjaCBRdWVyeSxFdmVyeXRoaW5nLFRlbGV2aXNpb25zLCJTbmVha2VycywgcnVubmluZyBzaG9lcywgc2FuZGFscyIsQ2xvdGhpbmcsTWF0dHJlc3NlcyxIb21lIEFwcGxpYW5jZXMsV2VhcmFibGVzICYgRml0bmVzcyBUZWNoLEhlYWRwaG9uZXMsSG9tZSBUZWNoLFNwZWFrZXJzLExhcHRvcHMsVGFibGV0cyxDb21wdXRpbmcsUGhvbmVzLEdhbWluZyxDb25zdHJ1Y3Rpb24gVG95cw0KRGlzY291bnQgQW1vdW50LG1pbiA1JSxtaW4gMTAlLG1pbiA1JSxtaW4gNSUsbWluIDUlLG1pbiA1JSxtaW4gNSUsbWluIDUlLG1pbiA1JSxtaW4gNSUsbWluIDUlLG1pbiA1JSxtaW4gNSUsbWluIDUlLG1pbiA1JSxtaW4gNSUNClByaWNlIFJhbmdlLCwsLCxtaW4gJDQwMCwsLCxtaW4gJDI1LCxtaW4gJDMwMCwsLG1pbiAkMTAwLCwNCkJyYW5kIFNlbGVjdGlvbiwsLCwsLCwsLCwsLCwsLCwNCkZpbHRlciBidXR0b25zLCwsLCwsLCwsLCwsLCwsLA0KMSxMaWdodG5pbmcgZGVhbHMsTGlnaHRuaW5nIGRlYWxzLExpZ2h0bmluZyBkZWFscyxMaWdodG5pbmcgZGVhbHMsTGlnaHRuaW5nIGRlYWxzLExpZ2h0bmluZyBkZWFscyxMaWdodG5pbmcgZGVhbHMsTGlnaHRuaW5nIGRlYWxzLExpZ2h0bmluZyBkZWFscyxMaWdodG5pbmcgZGVhbHMsTGlnaHRuaW5nIGRlYWxzLExpZ2h0bmluZyBkZWFscyxMaWdodG5pbmcgZGVhbHMsTGlnaHRuaW5nIGRlYWxzLExpZ2h0bmluZyBkZWFscyxMaWdodG5pbmcgZGVhbHMNCjIsQW1hem9uIGRlYWxzLFVuZGVyICQxMDAwLDUwJSBvZmYsQWRpZGFzLEFtYXpvbiBkZWFscyxBbWF6b24gZGVhbHMsNTAlIG9mZixBbWF6b24gZGVhbHMsQW1hem9uIGRlYWxzLEFtYXpvbiBkZWFscyxBbWF6b24gZGVhbHMsQW1hem9uIGRlYWxzLEFtYXpvbiBkZWFscyxBbWF6b24gZGVhbHMsQW1hem9uIGRlYWxzLEFtYXpvbiBkZWFscw0KMyxPdmVyICQ0MDAsVW5kZXIgJDUwMCxIb2thLE5pa2UsU2FhdHZhLE5pbmphLDQwJSBvZmYsSkxhYiwsSkJMLERlbGwsLEFzdXMsQXBwbGUsQ29uc29sZXMsU3RhciBXYXJzDQo0LFVuZGVyICQxMDAwLDUwJSBvZmYsU2tlY2hlcnMsVW5kZXIgQXJtb3VyLEhlbGl4LFNoYXJrLEdhcm1pbixBbmtlciBTb3VuZGNvcmUsUmluZyxTb25vcyxBcHBsZSxBcHBsZSxUUC1saW5rLFNhbXN1bmcsQWNjZXNzb3JpZXMsVW5kZXIgJDI1DQo1LFVuZGVyICQ1MDAsTEcsQXNpY3MsQ29sdW1iaWEsRHJlYW1DbG91ZCxLZXVyaWcsQXBwbGUsU29ueSxHb3ZlZSxUcmliaXQsTGVub3ZvLFNhbXN1bmcsRWVybyxHb29nbGUsR2FtZXMsVW5kZXIgJDUwDQo2LDUwJSBvZmYsU2Ftc3VuZyxOaWtlLFBhdGFnb25pYSxOZWN0YXIsRGUnTG9uZ2hpLEFtYXpmaXQsQXBwbGUsS2FzYSBzbWFydCxTb255LEFsaWVud2FyZSxUQ0wsTmV0Z2VhcixNb3Rvcm9sYSxOaW50ZW5kbyxCb3RhbmljYWxzDQo3LEFtYXpvbixIaXNlbnNlLE5ldyBCYWxhbmNlLEFyYyd0ZXJ5eCxUZW1wdXItcGVkaWMsRHlzb24sRml0Yml0LEJlYXRzLFBoaWxpcHMgSHVlLEFua2VyLEFjZXIsT25lUGx1cyxEZWxsLE9uZVBsdXMsU29ueSxEaXNuZXkNCjgsQXBwbGUsVENMLEFkaWRhcyxDYXJoYXJ0dCxCZWFyLEJpc3NlbGwsU2Ftc3VuZyxFYXJmdW4sQmxpbmssQmVhdHMsTVNJLE1pY3Jvc29mdCxBY2VyLE5vdGhpbmcsWGJveCxNYXJ2ZWwNCjksLFNvbnksU2F1Y29ueSxUaGUgTm9ydGggRmFjZSxTaWVuYSxOdXRyaWJ1bGxldCxPdXJhLFNhbXN1bmcsR29vZ2xlIE5lc3QgLE1hcnNoYWxsLFNhbXN1bmcsTGVub3ZvLExlbm92bywsLFBva2Vtb24NCjEwLCxSb2t1LEJpcmtlbnN0b2NrLENSWiBZb2dhLFdpbmtCZWRzLEJsYWNrIGFuZCBEZWNrZXIsUmluZ2Nvbm4sQ01GLEV1ZnksU2Ftc3VuZyxNaWNyb3NvZnQsUmVNYXJrYWJsZSxBbGllbndhcmUsLCwNCjExLCwsQnJvb2tzLFRoZSBHeW0gUGVvcGxlLEJyb29rbHluIGJlZGRpbmcsTmVzcHJlc3NvLCwxTW9yZSxBcmxvLCxSYXplciwsQ29yc2FpciwsLA0KMTIsLCxDcm9jcywsRWlnaHQgU2xlZXAsQ3Vpc2luYXJ0LCxKQkwsLCwsLEhQLCwsDQpOb3RlcywsLCwsLCwsLCwsLCwsLCwNCiwsIlByaW9yaXRpc2UgYmlnZ2VzdCAlLyQgZGlzY291bnQsIFR2cyB3aXRoIH41MCUgb2ZmIGhhdmUgYmVlbiB0aGUgbW9zdCBwb3B1bGFyIGV2ZW4gaWYgdGhleSBhcmUgc3RpbGwgZXhwZW5zaXZlIiwiTm8gcGF0dGVybiB0byBwcmljaW5nL2Rpc2NvdW50LCByZWFkZXJzIG1haW5seSBzaG9wIGJ5IGJyYW5kL3JlY29nbmlzYWJsZSBzaG9lcyIsIk5vIHBhdHRlcm4gdG8gcHJpY2luZy9kaXNjb3VudCwgcmVhZGVycyBtYWlubHkgc2hvcCBieSBicmFuZCIsIkEgbGFiZWwgd2lsbCBkZWZpbml0ZWx5IGhlbHAgaGVyZSBlLmcuIGJlc3QgZm9yIHNpZGUgc2xlZXBlciwgYmVzdCBtZW1vcnkgZm9hbSIsIkFwcGxpYW5jZXMgaXMgYSBiaWcgY2F0ZWdvcnksIGlzIGl0IHBvc3NpYmxlIHRvIHNwbGl0IGludG8ga2l0Y2hlbiBhcHBsaWFuY2VzLCBmbG9vcmNhcmUsIGFpciBoZWFsdGgvY29vbGluZz8gT3Igc2ltaWxhciIsIkZvY3VzIG9uIHZhbHVlIGZvciBtb25leSwgR2FybWlucyB3aXRoIH41MCUgb2ZmIGhhdmUgYmVlbiBwb3B1bGFyIGV2ZW4gdGhvdWdoIHRoZXkgYXJlIHN0aWxsICQ1MDAiLCwsLCxJbmNsdWRlIEtpbmRsZXMsSSB3b3VsZCBpbmNsdWRlIHdpZmkgcm91dGVycyBoZXJlIGluc3RlYWQgb2Ygc21hcnQgaG9tZSxDYW4gd2Ugc3VyZmFjZSBwaG9uZSBwcm92aWRlciBkZWFscz8gVC1tb2JpbGUgYW5kIHZlcml6b24gd291bGQgbWFrZSBhIGxvdCBtb3JlIG1vbmV5IHRoYW4gQW1hem9uLCwNCiwsaGF2aW5nIGEgJ2Jlc3QgZm9yJyBsYWJlbCB3b3VsZCBiZSBoZWxwZnVsIGUuZy4gYmVzdCBmb3IgYnJpZ2h0IHJvb20sQ2FuIHdlIHN0b3Aga2lkcyBzaG9lcyBmcm9tIHB1bGxpbmcgdGhyb3VnaD8sIldpbGwgdGhpcyBpbmNsdWRlIGFjY2Vzc29yaWVzIGUuZy4gY2FwcywgYmFncywgaWYgc28gbWFrZSBzdXJlIHRoZXNlIGFyZSBtaXhlZCB0aHJvdWdob3V0IGNsb3RoaW5nIGRlYWxzIixXaWxsIHRoaXMgaW5jbHVkZSB0b3BwZXJzIGFuZCBwaWxsb3dzPyBTZWVpbmcgbW9yZSBtb21lbnR1bSB3aXRoIHRoaXMgY2F0ZWdvcnkgcmVjZW50bHkgc28gYSBiZWRkaW5nIHRhYiBtaWdodCB3b3JrLCwiTmVlZCB0byBtYWtlIHN1cmUgYmFuZHMsIHNjcmVlbiBwcm90ZWN0b3JzIGV0Yy4gZG9uJ3QgcHVsbCBpbnRvIGhlcmUiLCwsLCwsLCwsDQosLCJQcmlvcml0aXNlIDY1JycgYW5kIDU1JyBpbmNoIFRWcywgdGhlbiBiaWdnZXIgc2NyZWVucyBiZWZvcmUgdGhlIHNtYWxsZXIgc2l6ZXMiLCwsUXVlZW4gaXMgdGhlIG1vc3QgcG9wdWxhciBzaXplIGluIHRoZSBVUyAtIHByaW9yaXRpc2UgZGVhbHMgZm9yIHRoaXMgc2l6ZSwsLCwsLCwsLCwsDQosLCwsLCwsLCwsLCwsLCwsDQpDYXRlZ29yaWVzIHRvIGNvbnNpZGVyLCxQcm9kdWN0cyBpbmNsdWRlZCwsLCwsLCwsLCwsLCwsDQpVbmRlciAkNTA/LCxBaXIgdGFncywsLCwsLCwsLCwsLCwsDQosLFBvcnRhYmxlIGNoYXJnZXJzL3dpcmVsZXNzIGNoYXJnZXJzLCwsLCwsLCwsLCwsLCwNCiwsIldhdGVyIGJvdHRsZXMgKHN0YW5sZXlzLCBPd2FsYSwgSHlkcm8gZmxhc2ssIFlldGkpIiwsLCwsLCwsLCwsLCwsDQosLEhhbmQgaGVsZCBmYW5zLCwsLCwsLCwsLCwsLCwNCiwsLCwsLCwsLCwsLCwsLCwNCmhvbWUgb2ZmaWNlLCxvZmZpY2UgY2hhaXJzLCwsLCwsLCwsLCwsLCwNCiwsc3RhbmRpbmcgZGVza3MsLCwsLCwsLCwsLCwsLA0KLCxtb25pdG9ycywsLCwsLCwsLCwsLCwsDQosLEtleWJvYXJkcywsLCwsLCwsLCwsLCwsDQosLGRvY2tpbmcgc3RhdGlvbiwsLCwsLCwsLCwsLCwsDQosLCwsLCwsLCwsLCwsLCwsDQpHYW1pbmcsLENvbnNvbGVzLCwsLCwsLCwsLCwsLCwNCiwsQWNjZXNzb3JpZXMsLCwsLCwsLCwsLCwsLA0KLCxHYW1lcywsLCwsLCwsLCwsLCwsDQosLENvdWxkIGluY2x1ZGUgTGVnbz8sLCwsLCwsLCwsLCwsLA==")));              const text = preloadedCSV;              const parsed = parseCSV(text);                            const rowsByName = {};              let filterStart = -1;              parsed.forEach((rc, i) => {                 if (rc && rc.length > 0 && rc[0]) rowsByName[rc[0]] = rc;                 if (rc && rc.length > 0 && rc[0] === 'Filter buttons') filterStart = i;              });                            const cols = [];              if(rowsByName['Roundel text']) {                const headerRow = rowsByName['Roundel text'];                for(let col = 1; col < headerRow.length; col++) {                   let label = headerRow[col];                   if (!label) continue;                                      let q = rowsByName['Search Query'] && rowsByName['Search Query'][col] ? rowsByName['Search Query'][col] : '';                   let img = rowsByName['Roundel image'] && rowsByName['Roundel image'][col] ? rowsByName['Roundel image'][col] : '';                   let ds = rowsByName['Discount Amount'] && rowsByName['Discount Amount'][col] ? rowsByName['Discount Amount'][col] : '';                   let pr = rowsByName['Price Range'] && rowsByName['Price Range'][col] ? rowsByName['Price Range'][col] : '';                   let rt = rowsByName['Retailer'] && rowsByName['Retailer'][col] ? rowsByName['Retailer'][col] : '';                   let ot = rowsByName['Offer Type'] && rowsByName['Offer Type'][col] ? rowsByName['Offer Type'][col] : '';                                      let filters = [];                   if(filterStart > 0) {                     for(let r = filterStart + 1; r < parsed.length; r++) {                         if(!parsed[r] || parsed[r][0] === 'Notes' || parsed[r][0] === 'Categories to consider') break;                         let f = parsed[r][col];                         if(f) filters.push(f);                     }                   }                   cols.push({ label, img, q, ds, pr, rt, ot, filters });                }              }              this.carouselData = cols;              if (this.carouselData && this.carouselData.length > 0) {                 const isMatched = this.carouselData.some(c => c.q === this.currentQuery || c.label === this.currentQuery);                 if (!isMatched) {                    const first = this.carouselData[0];                    this.currentQuery = first.q || first.label;                    if (this.priceFilter) this.priceFilter.value = 'all';                    if (this.customPriceMin) this.customPriceMin.value = '';                    if (this.customPriceMax) this.customPriceMax.value = '';                    let dPr = first.pr || 'all';                    if (typeof dPr === 'string' && dPr !== 'all') {                       let prLower = dPr.toLowerCase();                       if (prLower.includes('min') || prLower.includes('over')) {                          let m = dPr.match(/(\d+)/);                          if (m && this.customPriceMin) this.customPriceMin.value = m[1];                       } else if (prLower.includes('max') || prLower.includes('under')) {                          let m = dPr.match(/(\d+)/);                          if (m && this.customPriceMax) this.customPriceMax.value = m[1];                       }                    }                    let dAm = '0';                    if(first.ds && typeof first.ds === 'string') {                       let m = first.ds.match(/(\d+)/);                       if(m) dAm = m[1];                    }                    if (this.discountFilter) this.discountFilter.value = dAm;                    if (this.offerTypeSelect) this.offerTypeSelect.value = first.ot || '';                    if (this.retailerSelect) this.retailerSelect.value = first.rt || '';                    this.selectedBrands = [];                    if (this.brandDropdown) {                        const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                        chks.forEach(chk => chk.checked = false);                    }                    if (this.searchInput) this.searchInput.value = this.currentQuery;                 }              }              this.renderCarouselUI();          } catch(e){ console.warn(e); }        }                renderCarouselUI() {           const roundelWrapper = this.root.querySelector('.tg-df-carousel-roundels');           if(!roundelWrapper || !this.carouselData) return;                      let html = '';           this.carouselData.forEach(r => {              const q = r.q || r.label;              const isActive = (this.currentQuery === q || this.currentQuery === r.label) ? 'active' : '';              const imgHtml = r.img ? `\x3Cimg src="${r.img}" alt="${r.label}" />` : `\x3Csvg width="32" height="32" fill="#1F69FF" viewBox="0 0 24 24">\x3Cpath d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z"/>\x3C/svg>`;              html += `                \x3Cdiv class="tg-df-roundel tg-df-carousel-cat ${isActive}" data-label="${this.escapeHTML(r.label)}">                  \x3Cdiv class="tg-df-roundel-img-box">${imgHtml}\x3C/div>                  \x3Cspan class="tg-df-roundel-label">${this.escapeHTML(r.label)}\x3C/span>                \x3C/div>              `;           });           roundelWrapper.innerHTML = html;                      // Rebind clicks           const roundels = this.root.querySelectorAll('.tg-df-carousel-cat');           roundels.forEach(rNode => {             rNode.addEventListener('click', () => {                const r = this.carouselData.find(c => c.label === rNode.getAttribute('data-label'));                 if(!r) return;                                  if (typeof trackHawkEvent !== 'undefined') {                     trackHawkEvent({                         clickType: "CC",                         widgetId: this.widgetId,                         productCategoryName: "deals",                         zeroBasedProductIndexOrNull: null,                         totalDealsOrProducts: null,                         areaClicked: "Category Roundel",                         revenueId: this.revenueId,                         isoCurrencyCode: typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD',                         queryName: r.label,                         widgetTypeName: this.widgetTypeName                     });                 }                this.currentQuery = r.q || r.label;                const labelTitle = this.root.querySelector('#tg-df-carousel-title-label');                if (labelTitle) labelTitle.textContent = 'Best ' + this.currentQuery;                if (this.priceFilter) this.priceFilter.value = 'all';                if (this.customPriceMin) this.customPriceMin.value = '';                if (this.customPriceMax) this.customPriceMax.value = '';                let dPr = r.pr || 'all';                if (typeof dPr === 'string' && dPr !== 'all') {                   let prLower = dPr.toLowerCase();                   if (prLower.includes('min') || prLower.includes('over')) {                      let m = dPr.match(/(\d+)/);                      if (m && this.customPriceMin) this.customPriceMin.value = m[1];                   } else if (prLower.includes('max') || prLower.includes('under')) {                      let m = dPr.match(/(\d+)/);                      if (m && this.customPriceMax) this.customPriceMax.value = m[1];                   }                }                                let discountAmount = '0';                if(r.ds && typeof r.ds === 'string') {                   let m = r.ds.match(/(\d+)/);                   if(m) discountAmount = m[1];                }                if (this.discountFilter) this.discountFilter.value = discountAmount;                if (this.offerTypeSelect) this.offerTypeSelect.value = r.ot || '';                if (this.retailerSelect) this.retailerSelect.value = r.rt || '';                                // Clear brands                    this.selectedBrands = [];                    if (this.brandDropdown) {                    const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                    chks.forEach(chk => chk.checked = false);                }                                if (this.searchInput) this.searchInput.value = this.currentQuery;                                roundels.forEach(ro => ro.classList.remove('active'));                if (rNode) rNode.classList.add('active');                                this.renderCarouselFilters(r);                this.fetchDeals(this.currentQuery);             });           });                      // Auto-highlight active           const activeR = this.carouselData.find(c => c.q === this.currentQuery || c.label === this.currentQuery);           if(activeR) this.renderCarouselFilters(activeR);        }                renderCarouselFilters(r) {           const filtersWrap = this.root.querySelector('.tg-df-carousel-filters-wrap');           if(!filtersWrap) return;                      let html = `\x3Cbutton class="tg-df-carousel-filter-btn" data-type="all">All\x3C/button>`;                      r.filters.forEach(f => {              let fL = f.toLowerCase();              let icon = '';              let logic = `data-type="custom" data-v="${this.escapeHTML(f)}"`;              if (fL === 'amazon deals' || fL === 'prime deals') {                 html += `\x3Cbutton class="tg-df-carousel-filter-btn" ${logic}>\x3Cimg src="https://cdn.mos.cms.futurecdn.net/fwoVXvL79turN3Ph535m38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/u75QjVpt3w2EsMimJiRo38-600-100.png" class="active-img" alt="" /> Prime deals\x3C/button>`;              } else if (fL === 'lightning deals') {                 html += `\x3Cbutton class="tg-df-carousel-filter-btn" ${logic}>\x3Cimg src="https://cdn.mos.cms.futurecdn.net/HqAui7w97ft2NPqBtQ5r38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/yWPQ5yyQRhUwVKzGwYbh38-600-100.png" class="active-img" alt="" /> Lightning deals\x3C/button>`;              } else {                 if (fL.includes('lightning')) {                    icon = `\x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-zap">\x3Cpolygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2">\x3C/polygon>\x3C/svg>`;                 } else if (fL.includes('% off')) {                    icon = `\x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>`;                 } else if (fL.includes('under') || fL.includes('min ')) {                    icon = `\x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-badge-dollar-sign">\x3Cpath d="M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z">\x3C/path>\x3Cpath d="M16 8h-6a2 2 0 1 0 0 4h4a2 2 0 1 1 0 4H8">\x3C/path>\x3Cpath d="M12 18V6">\x3C/path>\x3C/svg>`;                 }                 html += `\x3Cbutton class="tg-df-carousel-filter-btn" ${logic}>${icon} ${this.escapeHTML(f)}\x3C/button>`;              }           });                      filtersWrap.innerHTML = html;                      const btns = filtersWrap.querySelectorAll('button');           btns.forEach(b => {             b.addEventListener('click', () => {                const type = b.getAttribute('data-type');                if (type === 'custom') {                   const v = b.getAttribute('data-v');                   if (typeof trackElementInteraction === 'function') trackElementInteraction({ id: `filter-custom-${(v||'').toLowerCase().replace(/[^a-z0-9]+/g, '-')}`, name: 'Custom Filter', label: v });                }                if (type === 'all') {                   if (typeof trackElementInteraction === 'function') trackElementInteraction({ id: 'filter-clear-all', name: 'Clear all', label: 'Clear all filters' });                   // reset everything                   btns.forEach(btn => btn.classList.remove('active'));                   b.classList.add('active');                                      // Reset prices                   if (this.priceFilter) this.priceFilter.value = 'all';                   if (this.customPriceMin) this.customPriceMin.value = '';                   if (this.customPriceMax) this.customPriceMax.value = '';                   let dPr = r.pr || 'all';                   if (typeof dPr === 'string' && dPr !== 'all') {                      let prLower = dPr.toLowerCase();                      if (prLower.includes('min') || prLower.includes('over')) {                         let m = dPr.match(/(\d+)/);                         if (m && this.customPriceMin) this.customPriceMin.value = m[1];                      } else if (prLower.includes('max') || prLower.includes('under')) {                         let m = dPr.match(/(\d+)/);                         if (m && this.customPriceMax) this.customPriceMax.value = m[1];                      }                   }                                      let discountAmount = '0';                   if(r.ds && typeof r.ds === 'string') {                      let m = r.ds.match(/(\d+)/);                      if(m) discountAmount = m[1];                   }                   if (this.discountFilter) this.discountFilter.value = discountAmount;                   if (this.offerTypeSelect) this.offerTypeSelect.value = r.ot || '';                   if (this.retailerSelect) this.retailerSelect.value = r.rt || '';                   this.selectedBrands = [];                   if (this.brandDropdown) {                     const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                     chks.forEach(chk => chk.checked = false);                   }                } else {                   const v = b.getAttribute('data-v');                   const fL = v.toLowerCase();                                      let mapRet = ['amazon', 'walmart', 'best buy', 'target', 'john lewis', 'currys', 'argos'];                   const getCategory = (s) => {                      if (s === 'lightning deals' || s === 'amazon deals' || s === 'prime deals') return 'offer';                      if (s.includes('% off')) return 'discount';                      if (s.includes('under') || s.includes('over') || s.includes('min') || s.includes('max')) return 'price';                      if (mapRet.includes(s)) return 'retailer';                      return 'brand';                   };                   const cat = getCategory(fL);                   const wasActive = b.classList.contains('active');                   if (cat !== 'brand') {                      btns.forEach(btn => {                          if (btn === b) return;                          if (btn.getAttribute('data-type') === 'all') return;                          const bV = btn.getAttribute('data-v');                          if (!bV) return;                          if (getCategory(bV.toLowerCase()) === cat) btn.classList.remove('active');                      });                   }                   if (wasActive) b.classList.remove('active');                   else b.classList.add('active');                   let anyActive = Array.from(btns).some(btn => btn !== btns[0] && btn.classList.contains('active'));                   if (!anyActive) {                       btns[0].click();                       return;                   } else {                       btns[0].classList.remove('active');                   }                                      if (this.priceFilter) this.priceFilter.value = 'all';                   if (this.customPriceMin) this.customPriceMin.value = '';                   if (this.customPriceMax) this.customPriceMax.value = '';                   let dPr = r.pr || 'all';                   if (typeof dPr === 'string' && dPr !== 'all') {                      let prLower = dPr.toLowerCase();                      if (prLower.includes('min') || prLower.includes('over')) {                         let m = dPr.match(/(\d+)/);                         if (m && this.customPriceMin) this.customPriceMin.value = m[1];                      } else if (prLower.includes('max') || prLower.includes('under')) {                         let m = dPr.match(/(\d+)/);                         if (m && this.customPriceMax) this.customPriceMax.value = m[1];                      }                   }                                      let discountAmount = '0';                   if(r.ds && typeof r.ds === 'string') {                      let m = r.ds.match(/(\d+)/);                      if(m) discountAmount = m[1];                   }                   if (this.discountFilter) this.discountFilter.value = discountAmount;                   if (this.offerTypeSelect) this.offerTypeSelect.value = r.ot || '';                   if (this.retailerSelect) this.retailerSelect.value = r.rt || '';                   this.selectedBrands = [];                   btns.forEach(btn => {                       if (!btn.classList.contains('active') || btn.getAttribute('data-type') === 'all') return;                       const vv = btn.getAttribute('data-v');                       const vl = vv.toLowerCase();                                              if (vl === 'lightning deals') {                          if (this.offerTypeSelect) this.offerTypeSelect.value = 'amazon_lightning';                       } else if (vl === 'amazon deals' || vl === 'prime deals') {                          if (this.offerTypeSelect) this.offerTypeSelect.value = 'amazon_prime';                       } else if (vl.includes('% off')) {                          let m = vl.match(/(\d+)%/);                          if (m && this.discountFilter) this.discountFilter.value = m[1];                       } else if (vl.includes('under') || vl.includes('max')) {                          let m = vl.match(/(\d+)/);                          if (m && this.customPriceMax) this.customPriceMax.value = m[1];                       } else if (vl.includes('min') || vl.includes('over')) {                          let m = vl.match(/(\d+)/);                          if (m && this.customPriceMin) this.customPriceMin.value = m[1];                       } else {                          let foundR = mapRet.find(x => x === vl);                          if (foundR) {                             let realR = ['Amazon', 'Walmart', 'Best Buy', 'Target', 'John Lewis', 'Currys', 'Argos'].find(x => x.toLowerCase() === vl);                             if (this.retailerSelect) this.retailerSelect.value = realR;                          } else {                             this.selectedBrands.push(vv);                          }                       }                   });                                      if (this.brandDropdown) {                       const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                       chks.forEach(c => c.checked = this.selectedBrands.includes(c.value));                   }                                      if (r.pr && typeof r.pr === 'string') {                       let prL = r.pr.toLowerCase();                       if (prL.includes('under $')) {                           let m = prL.match(/under \$(\d+)/i);                           if (m && this.customPriceMax && !this.customPriceMax.value) this.customPriceMax.value = m[1];                       }                   }                }                                this.fetchDeals(this.currentQuery);             });           });                      // default to highlighting first           btns[0].classList.add('active');        }async fetchDeals(query, append = false) {          if (!append) {             this.showLoading();             this.deals = [];             this.displayLimit = this.getRowsLimit();          } else {             this.displayLimit += this.getRowsLimit();          }                    try {            if (this.getViewMode() === 'savings_squad') {               await this.fetchSavingsSquad(append);            } else {               if (this.isBroadQuery(query)) {                 await this.fetchAdviserDeals(query, append);               } else {                 await this.fetchHawkDeals(query, append);                 if (this.deals.length === 0) {                   await this.fetchAdviserDeals(query, append);                 }               }            }          } catch (error) {            console.warn("[Tom's Guide Widget] Fetch error:", error);            this.showError();          }        }        async fetchSavingsSquad() {          let topArticles = this.airedaleArticles;          if (!topArticles) {            const airedaleUrl = `https://airedale.futurecdn.net/feeds/feed_1776420579726.json?site=tomsguide&articleType=deals&limit=50`;            let res;            try {               res = await fetch(airedaleUrl);            } catch(e) {               try { res = await fetch(`https://airedale.futurecdn.net/feeds/feed_1776420579726.json?site=tomsguide&articleType=deals&limit=50`); } catch (err) { console.warn("Fallback fetch failed", err); return; }            }            if (!res.ok) throw new Error('Airedale API Error');            const articles = await res.json();            topArticles = Array.isArray(articles) ? articles.slice(0, 50) : ((articles.data && Array.isArray(articles.data)) ? articles.data.slice(0, 50) : []);            this.airedaleArticles = topArticles;                        let tagCounts = {};            topArticles.forEach((a) => {              let articleTags = new Set();              if (a.articlecategory && Array.isArray(a.articlecategory)) {                 a.articlecategory.forEach((t) => articleTags.add(t));              }              articleTags.forEach(t => {                 tagCounts[t] = (tagCounts[t] || 0) + 1;              });            });                        this.airedaleTags = Object.keys(tagCounts).sort((a, b) => tagCounts[b] - tagCounts[a]);            this.airedaleTagCounts = tagCounts;          }                    let targetArticles = topArticles;          if (this.activeDealTag) {             const cleanTag = this.activeDealTag.toLowerCase().replace(/&/g, '').replace(/[^a-z0-9]+/g, '-').replace(/-+/g, '-').replace(/^-|-$/g, '');             const encodedTag = encodeURIComponent(cleanTag);             const url = `https://airedale.futurecdn.net/feeds/feed_1776420579726.json?site=tomsguide&articleType=deals&limit=50&articleCategoryHandle=${encodedTag}`;             try {                const res = await fetch(url);                if (res.ok) {                   const articles = await res.json();                   targetArticles = Array.isArray(articles) ? articles.slice(0, 50) : ((articles.data && Array.isArray(articles.data)) ? articles.data.slice(0, 50) : []);                }             } catch(e) {                console.warn("Failed to fetch by activeDealTag", e);             }          }          let extractedDeals = [];          let dynamicBrandsCounts = {};                    targetArticles.forEach((article) => {             if (!article.articlepage) return;                          let pageData = [];             try {                pageData = JSON.parse(article.articlepage[0]);             } catch(e){ console.warn(e); }                          const savingsSquad = pageData.filter((p) => p.type === 'deal' || p.type === 'featured-product');                          savingsSquad.forEach((block, idx) => {                const data = block.data || {};                const isFeatured = block.type === 'featured-product';                                const link = data.link || {};                const priceObj = data.price || {};                const image = data.image || {};                                if (data.brand) {                   data.brand = data.brand.replace(/^\d+\.\s*/, '').trim();                   dynamicBrandsCounts[data.brand] = (dynamicBrandsCounts[data.brand] || 0) + 1;                }                const externalUrl = isFeatured ? data.url : (link.href || null);                let summaryTitle = isFeatured ? (data.name || data.brand) : (data.productName || link.label || article.articlename);                let description = isFeatured ? (data.strapline || '') : (data.text || '');                                if (!isFeatured && !data.productName && data.text) {                   const brSplit = data.text.split(new RegExp('\x3Cbr\\s*\\/?\\x3E', 'i'));                   if (brSplit.length > 1) {                     summaryTitle = brSplit[0].replace(/<[^>]+>/g, '').trim();                     description = brSplit.slice(1).join(' ').replace(/<br\s*\/?>/gi, ' ').replace(/<\/?(p|div)[^>]*>/gi, ' ').replace(/<[^>]+>/g, '').replace(/\s+/g, ' ').trim();                   } else {                     const match = data.text.match(/\x3Cstrong>(.*?)<\/strong>/);                     if (match) {                       summaryTitle = match[1].replace(/<[^>]+>/g, '').trim();                       if (summaryTitle.endsWith(':')) summaryTitle = summaryTitle.slice(0, -1);                     }                   }                }                                let imageUrl = isFeatured ? image.mos : (image.src || null);                if (imageUrl && imageUrl.startsWith('//')) imageUrl = 'https:' + imageUrl;                                description = description.replace(/<br\s*\/?>/gi, ' ').replace(/<\/?(p|div)[^>]*>/gi, ' ').replace(/<[^>]+>/g, '').replace(/\s+/g, ' ').replace(/View Deal$/i, '').trim();                                let merchantName = data.retailer || '';                if (!merchantName && externalUrl) {                   try {                     merchantName = new URL(externalUrl).hostname.replace('www.', '').split('.')[0];                     merchantName = merchantName.charAt(0).toUpperCase() + merchantName.slice(1);                   }catch(e){ console.warn(e); }                }                if (!merchantName) merchantName = 'Retailer';                const q = (this.currentQuery || '').toLowerCase();                const activeTagLogic = (this.activeDealTag || '').toLowerCase();                if (q.length > 2 && q !== activeTagLogic) {                   const searchTarget = `${summaryTitle || ''} ${description || ''}`.toLowerCase();                   if (!searchTarget.includes(q)) return;                }                let rawPrice = 0;                let rawMsrp = 0;                let currencyStr = '$';                if (isFeatured) {                   rawPrice = typeof data.salePrice === 'number' && data.salePrice > 0 ? data.salePrice : (typeof data.price === 'number' ? data.price : 0);                   rawMsrp = typeof data.salePrice === 'number' && typeof data.price === 'number' && data.price > data.salePrice ? data.price : 0;                   currencyStr = data.currency === 'GBP' ? '£' : '$';                } else {                   rawPrice = priceObj.amount ? parseFloat(priceObj.amount) : 0;                   rawMsrp = priceObj.amountWas ? parseFloat(priceObj.amountWas) : 0;                   currencyStr = priceObj.currency === 'GBP' ? '£' : '$';                }                                let savingAmt = 0;                let savingLabel = '';                if (rawPrice > 0 && rawMsrp > rawPrice) {                   savingAmt = parseFloat((rawMsrp - rawPrice).toFixed(2));                   savingLabel = `Save ${currencyStr}${savingAmt}`;                }                                // Apply Brand filter                if (this.selectedBrands && this.selectedBrands.length > 0) {                   const itemBrand = (data.brand || '').toLowerCase();                   const hasMatch = this.selectedBrands.some(sb => sb.toLowerCase() === itemBrand);                   if (!hasMatch) return;                }                // Apply Price filter                let priceFilterVal = null;                const min = this.customPriceMin ? this.customPriceMin.value : '';                const max = this.customPriceMax ? this.customPriceMax.value : '';                if (min || max) {                   priceFilterVal = `${min}_${max}`;                } else if (this.priceFilter && this.priceFilter.value !== 'all') {                   priceFilterVal = this.priceFilter.value;                }                if (priceFilterVal && rawPrice > 0) {                   if (priceFilterVal === 'under50' && rawPrice >= 50) return;                   if (priceFilterVal === 'over50' && rawPrice <= 50) return;                   if (priceFilterVal === 'over30' && rawPrice <= 30) return;                   if (priceFilterVal === 'over500' && rawPrice <= 500) return;                   if (priceFilterVal.includes('_')) {                      const parts = priceFilterVal.split('_');                      const min = parseFloat(parts[0]);                      const max = parseFloat(parts[1]);                      if (!isNaN(min) && rawPrice < min) return;                      if (!isNaN(max) && rawPrice > max) return;                   }                }                // Apply Discount filter                if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {                   const requiredDiscount = parseInt(this.discountFilter.value);                   if (!isNaN(requiredDiscount) && requiredDiscount > 0) {                      if (!rawMsrp || rawMsrp <= rawPrice) return;                      const ratio = Math.round((1 - (rawPrice / rawMsrp)) * 100);                      if (ratio < requiredDiscount) return;                   }                }                                extractedDeals.push({                   id: `airedale-${article.id || Math.random()}-${idx}`,                   url: externalUrl,                   image: imageUrl,                   fallbackImage: imageUrl,                   title: summaryTitle,                   brand: data.brand || '',                   productName: data.productName || '',                   merchant: merchantName,                   rawPrice: rawPrice,                   rawMsrp: rawMsrp,                   price: rawPrice > 0 ? rawPrice.toString() : '',                   msrp: rawMsrp > 0 ? rawMsrp.toString() : '',                   currency: currencyStr,                   isCheckPrice: !rawPrice,                   savingLabel: savingLabel,                   savingType: rawMsrp > rawPrice ? 'amount' : 'none',                   isPrime: false,                   starRating: null,                   description: description,                   text: data.text || ''                });             });          });                    const airedaleBrandsList = Object.keys(dynamicBrandsCounts).map(b => ({              formatted_value: b,              count: dynamicBrandsCounts[b]          })).sort((a,b) => b.count - a.count);                    if (this.getViewMode() === 'savings_squad') {             this.populateBrandDropdown(airedaleBrandsList.slice(0, 15));             if (this.brandFilterWrapper) {                if (airedaleBrandsList.length === 0) {                    this.brandFilterWrapper.style.display = 'none';                } else {                    this.brandFilterWrapper.style.display = 'flex';                }             }          }                    this.deals = extractedDeals;          this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        isBroadQuery(query) {          const q = query.toLowerCase();          const intentModifiers = ['deals', 'best', 'sale', 'under', 'cheap', 'offers', 'discount'];          return intentModifiers.some(term => q.includes(term));        }        async fetchHawkDeals(query, append = false) {          const url = new URL(this.apiUrl);          url.searchParams.append('model_name', query);          const areaCode = this.getAreaCode();          if (areaCode) {            url.searchParams.append('area', areaCode);          }                    if (append && this.deals.length > 0) {            url.searchParams.append('offset', this.deals.length.toString());          }                    if (this.retailerSelect && this.retailerSelect.value) {            url.searchParams.append('filter_merchant_name', this.retailerSelect.value);          }                    if (this.selectedBrands && this.selectedBrands.length > 0) {            url.searchParams.append('filter_label[text_brand]', this.selectedBrands.join(','));          }                    let priceVal = null;          const min = this.customPriceMin ? this.customPriceMin.value : '';          const max = this.customPriceMax ? this.customPriceMax.value : '';          if (min || max) {             priceVal = `${min}_${max}`;          } else if (this.priceFilter && this.priceFilter.value !== 'all') {             priceVal = this.priceFilter.value;          }          if (priceVal) {            if (priceVal === 'under50') {              url.searchParams.append('filter_max_price', '50');            } else if (priceVal === 'over50') {              url.searchParams.append('filter_min_price', '50');            } else if (priceVal === 'over30') {              url.searchParams.append('filter_min_price', '30');            } else if (priceVal === 'over500') {              url.searchParams.append('filter_min_price', '500');            } else if (priceVal.includes('_')) {              const parts = priceVal.split('_');              if (parts[0]) url.searchParams.append('filter_min_price', parts[0]);              if (parts[1]) url.searchParams.append('filter_max_price', parts[1]);            }          }                    if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {            const v = parseInt(this.discountFilter.value);            if (!isNaN(v) && v > 0) {              const ratio = (100 - v) / 100;              url.searchParams.append('min_discount_ratio', ratio.toString());            }          }                    if (this.offerTypeSelect && this.offerTypeSelect.value) {            url.searchParams.append('offer', this.offerTypeSelect.value);          }                    url.searchParams.append('filter_product_types', 'deals');                    url.searchParams.append('rows', this.getRowsLimit().toString());          let response;          try {             response = await fetch(url.toString());          } catch(e) {             if (window.location.protocol === 'file:') {                console.warn("[Tom's Guide Widget] fetch from file:// blocked by local CORS policy, falling back to Adviser mock.");                await this.fetchAdviserDeals(query);                return;             }             console.warn("Hawk fetch failed", e);             this.deals = [];             this.render();             return;          }          if (!response.ok) {            throw new Error('Hawk API Response Error');          }          const rawData = await response.json();          // Safely locate data array from potentially wrapped response          let offers = [];          let modelInfoArray = [];                    let brandFilterData = null;          if (rawData && rawData.widget && rawData.widget.data && Array.isArray(rawData.widget.data.filters)) {             brandFilterData = rawData.widget.data.filters.find(f => f.type === 'label_text_brand');          } else if (rawData && rawData.data && Array.isArray(rawData.data.filters)) {             brandFilterData = rawData.data.filters.find(f => f.type === 'label_text_brand');          }          if (brandFilterData && Array.isArray(brandFilterData.values) && brandFilterData.values.length > 0) {             this.populateBrandDropdown(brandFilterData.values);          } else {             if (this.brandFilterWrapper && this.selectedBrands.length === 0) {                this.brandFilterWrapper.style.display = 'none';             }          }                    if (rawData && rawData.widget && rawData.widget.data) {            if (Array.isArray(rawData.widget.data.offers)) offers = rawData.widget.data.offers;            if (rawData.widget.data.model_info && typeof rawData.widget.data.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.widget.data.model_info) ? rawData.widget.data.model_info : Object.values(rawData.widget.data.model_info);            }          } else if (rawData && rawData.data) {            if (Array.isArray(rawData.data.offers)) offers = rawData.data.offers;            if (rawData.data.model_info && typeof rawData.data.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.data.model_info) ? rawData.data.model_info : Object.values(rawData.data.model_info);            }          } else {            if (Array.isArray(rawData)) offers = rawData;            else if (rawData && Array.isArray(rawData.offers)) offers = rawData.offers;            else if (rawData && rawData.offers && Array.isArray(rawData.offers.offer)) offers = rawData.offers.offer;            else if (rawData && rawData.offers) offers = [].concat(rawData.offers);                        if (rawData && rawData.model_info && typeof rawData.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.model_info) ? rawData.model_info : Object.values(rawData.model_info);            }          }          let modelDetails = {};          modelInfoArray.forEach(m => {            const mId = m.model_id || m.id;            if (mId) {              modelDetails[mId] = {                score: m.score != null ? parseFloat(m.score) : null,                brand: m.brand || null,                parent: (m.parents && Array.isArray(m.parents) && m.parents.length > 0) ? m.parents[0].name : null              };            }          });          offers.forEach(item => {            let data = { ...item };            const mId = data.model_id;            if (mId && modelDetails[mId]) {              data.review_score = modelDetails[mId].score;              data.model_brand = modelDetails[mId].brand;              data.model_parent = modelDetails[mId].parent;            } else {              data.review_score = null;            }                        let itemOffers = [];            if (Array.isArray(item.offers)) itemOffers = item.offers;            else if (Array.isArray(item.offer)) itemOffers = item.offer;            else if (item.offers && typeof item.offers === 'object') itemOffers = [item.offers];            else if (item.offer && typeof item.offer === 'object') itemOffers = [item.offer];            if (itemOffers.length > 0) {              itemOffers.forEach(subItem => {                let subData = { ...item, ...subItem };                const subId = subData.model_id;                if (subId && modelDetails[subId]) {                  subData.review_score = modelDetails[subId].score;                  subData.model_brand = modelDetails[subId].brand;                  subData.model_parent = modelDetails[subId].parent;                } else if (data.review_score != null) {                  subData.review_score = data.review_score;                }                if (subData.merchant && typeof subData.merchant === 'object') {                  subData.merchant_name = subData.merchant.name;                }                this.deals.push(this.extractDealData(subData));              });              return;            }                        if (item.merchant && typeof item.merchant === 'object') {              data.merchant_name = item.merchant.name;            }                        this.deals.push(this.extractDealData(data));          });                    this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        async fetchAdviserDeals(query) {          // ======================================================================          // TODO: ADVISER API REPLACEMENT          // The code below simulates the Adviser API response using mock data.          // Once the real endpoint is ready, remove getAdviserMockData() and           // perform an actual fetch() request similar to fetchHawkDeals().          // Example:          // const area = this.getAreaCode();          // let apiUrl = `https://your-adviser-api.com/search?q=${query}&area=${area}`;          // if (this.priceFilter && this.priceFilter.value !== 'all') {          //   const val = this.priceFilter.value;          //   if (val === 'under50') apiUrl += '&filter_max_price=50';          //   else if (val === '50_100') apiUrl += '&filter_max_price=100';          //   else if (val === '100_200') apiUrl += '&filter_max_price=200';          //   else if (val === '200_500') apiUrl += '&filter_max_price=500';          // }          // const res = await fetch(apiUrl);          // const rawData = await res.json();          // ======================================================================          // Simulating network latency          await new Promise(resolve => setTimeout(resolve, 400));                    const rawData = this.getAdviserMockData();          let offers = [];                    if (rawData && rawData.data && rawData.data.Get && Array.isArray(rawData.data.Get.Deal)) {            offers = rawData.data.Get.Deal;          }                    // Basic client-side filtering for the mock if we want it to react to the query          const q = query.toLowerCase();          const selectedRetailer = (this.retailerSelect && this.retailerSelect.value) ? this.retailerSelect.value.toLowerCase() : null;                    offers.forEach(item => {            const dataObj = item;                        // Apply retailer filter            const itemRetailer = (dataObj.dataRetailer || '').toLowerCase();            if (selectedRetailer && itemRetailer !== selectedRetailer && !itemRetailer.includes(selectedRetailer)) {              return;            }                        // Apply mock price filter            let price = dataObj.dataDiscountedPrice || 0;            if (typeof price === 'string') {              price = parseFloat(price.replace(/[^0-9.]/g, ''));            }            let priceVal = null;            const min = this.customPriceMin ? this.customPriceMin.value : '';            const max = this.customPriceMax ? this.customPriceMax.value : '';            if (min || max) {               priceVal = `${min}_${max}`;            } else if (this.priceFilter && this.priceFilter.value !== 'all') {               priceVal = this.priceFilter.value;            }            if (priceVal) {              if (priceVal === 'under50' && price >= 50) return;              if (priceVal === 'over50' && price <= 50) return;              if (priceVal === 'over30' && price <= 30) return;              if (priceVal === 'over500' && price <= 500) return;              if (priceVal.includes('_')) {                 const parts = priceVal.split('_');                 if (parts[0] && price < parseFloat(parts[0])) return;                 if (parts[1] && price > parseFloat(parts[1])) return;              }            }                        // Map Adviser schema to our widget's expected schema            const mappedData = {              url: dataObj.linkHREF || dataObj.dataLink || '#',              image: dataObj.imageURL || (dataObj.image && dataObj.image.src) || '',              title: dataObj.dataProduct || (dataObj.product && dataObj.product.name) || 'Product Deal',              merchant: dataObj.dataRetailer || 'Retailer',              price: dataObj.dataDiscountedPrice || 0,              currency: dataObj.dataCurrency === 'USD' ? '$' : (dataObj.dataCurrency || '$'),              msrp: dataObj.dataOriginalPrice || null            };                        const titleLow = mappedData.title.toLowerCase();            const merchLow = mappedData.merchant.toLowerCase();                        // Smarter mock filtering            let isMatch = false;            if (q === '' || this.isBroadQuery(q)) {              isMatch = true;            } else if (titleLow.includes(q) || merchLow.includes(q)) {              isMatch = true;            } else if ((q.includes('laptop') || q.includes('mac') || q.includes('pc')) && (titleLow.includes('macbook') || titleLow.includes('laptop'))) {              isMatch = true;            } else if ((q.includes('tv') || q.includes('television')) && (titleLow.includes('tv') || titleLow.includes('oled') || titleLow.includes('qled'))) {              isMatch = true;            } else if ((q.includes('phone') || q.includes('smartphone')) && (titleLow.includes('galaxy') || titleLow.includes('phone'))) {              isMatch = true;            } else if ((q.match(/watch|fitness|run|shoe/)) && (titleLow.includes('forerunner') || titleLow.includes('saucony') || titleLow.includes('watch'))) {              isMatch = true;            }                        if (isMatch) {               this.deals.push(this.extractDealData(mappedData));            }          });                    let rowLimit = this.getRowsLimit();          // Intentionally omitting the slice here to allow "Load More" to work if the API returns more                    this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        getAdviserMockData() {          return {            "data": {              "Get": {                "Deal": [                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 300,                    "dataOriginalPrice": 399,                    "dataProduct": "Samsung Galaxy A36",                    "dataRetailer": "Samsung",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/MqDYsukV3JBG54te6dEs7j.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 14,                    "dataOriginalPrice": 24,                    "dataProduct": "Blink Mini",                    "dataRetailer": "Amazon",                    "imageURL": "http://cdn.mos.cms.futurecdn.net/3JurmAjHsDa5tPdaHAwEV8.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 59,                    "dataOriginalPrice": 99,                    "dataProduct": "Ring Video Doorbell",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/rAh4uR7AsAsALCCLTXnLNJ.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 10,                    "dataOriginalPrice": 599,                    "dataProduct": "MacBook Neo",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/Lg4Dvg68j9SbB5CPNrTEpH.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 749,                    "dataOriginalPrice": 849,                    "dataProduct": "65\\\" Fire TV Omni 4K QLED TV",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/SG34ZWodUkLTxJvMTbjPYR.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 71,                    "dataOriginalPrice": 160,                    "dataProduct": "Saucony Hurricane 24",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/vxf7UD5T2Am7guVzFoFcZ4.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 649,                    "dataOriginalPrice": 749,                    "dataProduct": "Garmin Forerunner 970",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/3GKnEu7CdhtxPMfnPCMCiA.png"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 1049,                    "dataOriginalPrice": 1499,                    "dataProduct": "LG 48\\\" C4 4K OLED TV",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/imvwZV9zoMD6fn9Afuge35.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 1499,                    "dataOriginalPrice": 2199,                    "dataProduct": "Samsung 49\\\" Odyssey Neo G9 4K Gaming Monitor",                    "dataRetailer": "Amazon",                    "imageURL": "http://cdn.mos.cms.futurecdn.net/XWDEJ5dUAE2nhK8k3Jk7k7.png"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 299,                    "dataOriginalPrice": 699,                    "dataProduct": "EGOHOME Black Memory Foam Mattress (queen)",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/hMUemtAejNETLVYxNrktzm.jpg"                  }                ]              }            }          };        }        decodeHTML(html) {          if (!html) return '';          const txt = document.createElement("textarea");          txt.innerHTML = String(html);          return txt.value;        }        extractDealData(item) {          const priceRawStr = String(item.price || item.current_price || '0');          const msrpRawStr = String(item.was_price || item.msrp || item.original_price || '0');          const rawPrice = parseFloat(priceRawStr.replace(/[^\d.]/g, '')) || 0;          const rawMsrp = parseFloat(msrpRawStr.replace(/[^\d.]/g, '')) || 0;          const isCheckPrice = rawPrice === 0 || priceRawStr === '0.00' || priceRawStr === '0';                    let originalImageUrl = item.image || item.image_url || item.product_image || '';          let imageUrl = originalImageUrl;          if ((!imageUrl || isCheckPrice) && item.model_image_url) {             imageUrl = item.model_image_url;             originalImageUrl = imageUrl;          } else if ((!imageUrl || isCheckPrice) && item.model_image) {             imageUrl = item.model_image;             originalImageUrl = imageUrl;          }                    if (imageUrl) {            imageUrl = imageUrl.replace(/-(\d+)-(\d+)(\.[a-z.]+)$/i, '$3');          }                    let fallbackImage = '';          if (originalImageUrl && originalImageUrl !== imageUrl) {             fallbackImage = originalImageUrl;          } else if (item.model_image && item.model_image !== imageUrl) {             fallbackImage = item.model_image;          } else if (item.model_image_url && item.model_image_url !== imageUrl) {             fallbackImage = item.model_image_url;          }                    const rawCurrency = item.currency || item.currency_symbol || '$';                    let savingLabel = item.percentage_saving_label || '';          if (!savingLabel && rawMsrp > rawPrice && rawPrice > 0) {            const pct = Math.round(((rawMsrp - rawPrice) / rawMsrp) * 100);            if (pct > 0) {              savingLabel = `${pct}% OFF`;            }          }                    const isPrime = item.shipping && item.shipping.prime === true;                    let scoreRaw = (item.review_score !== undefined && item.review_score !== null && item.review_score > 0) ? parseFloat(item.review_score) : null;          let starRating = 0;          if (scoreRaw !== null) {            starRating = Math.round((scoreRaw > 10 ? scoreRaw / 20 : scoreRaw / 2) * 2) / 2;          }                    return {            id: item.offer_id || item.link || item.url || item.offer_link || Math.random().toString(),            url: item.link || item.url || item.offer_link || '#',            image: imageUrl,            fallbackImage: fallbackImage,            title: item.name || item.title || item.model_name || item.product_name || 'Unknown Product',            brand: item.brand || '',            productName: item.model_name || item.product_name || item.name || '',            merchant: item.merchant_name || item.merchant || item.retailer || 'Retailer',            price: item.price !== undefined ? String(item.price) : '0.00',            currency: this.decodeHTML(rawCurrency),            msrp: item.was_price || item.msrp || item.original_price || null,            rawPrice: rawPrice,            rawMsrp: rawMsrp,            hasWasPrice: (item.was_price !== undefined && item.was_price !== null),            isCheckPrice: isCheckPrice,            savingLabel: savingLabel,            isPrime: isPrime,            starRating: starRating > 0 ? starRating : null,            modelId: item.model_id || '',            productKey: item.product_key || '',            merchantId: (item.merchant && typeof item.merchant === 'object') ? item.merchant.id || '' : '',            matchId: item.match_id || '',            merchantNetwork: (item.merchant && typeof item.merchant === 'object') ? item.merchant.an || '' : '',            merchantUrl: (item.merchant && typeof item.merchant === 'object') ? item.merchant.url || '' : '',            modelBrand: item.model_brand || item.brand || '',            modelParent: item.model_parent || ''          };        }        sortData() {          const sortVal = this.sortSelect ? this.sortSelect.value : (this.getViewMode() === 'savings_squad' ? 'date_desc' : 'discount_desc');          if (sortVal === 'price_asc') {            this.deals.sort((a, b) => a.rawPrice - b.rawPrice);          } else if (sortVal === 'price_desc') {            this.deals.sort((a, b) => b.rawPrice - a.rawPrice);          } else if (sortVal === 'discount_desc') {            this.deals.sort((a, b) => {              const aDiscount = a.rawMsrp > a.rawPrice ? (a.rawMsrp - a.rawPrice) : 0;              const bDiscount = b.rawMsrp > b.rawPrice ? (b.rawMsrp - b.rawPrice) : 0;              return bDiscount - aDiscount;            });          } else if (sortVal === 'date_desc') {             this.deals.sort((a, b) => {                let dateA = 0;                let dateB = 0;                if (a && a.modifiedDate) {                   const valA = Array.isArray(a.modifiedDate) ? a.modifiedDate[0] : a.modifiedDate;                   dateA = new Date(valA).getTime();                   if (isNaN(dateA)) dateA = 0;                }                if (b && b.modifiedDate) {                   const valB = Array.isArray(b.modifiedDate) ? b.modifiedDate[0] : b.modifiedDate;                   dateB = new Date(valB).getTime();                   if (isNaN(dateB)) dateB = 0;                }                return dateB - dateA;             });          }        }        getFilteredDeals() {          let filteredDeals = [...this.deals];                    if (this.dealModeToggle && this.dealModeToggle.checked) {            filteredDeals = filteredDeals.filter(d => d.hasWasPrice || (d.msrp && d.rawMsrp > d.rawPrice));          }                    return filteredDeals;        }        showLoading() {          const _div = '<' + '/div>';          const skeletonCardHtml = `            \x3Cdiv class="tg-df-card">              \x3Cdiv class="tg-df-card-image-box">                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-img">${_div}              ${_div}              \x3Cdiv class="tg-df-card-body">                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short">${_div}                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text title">${_div}                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text title">${_div}                \x3Cdiv class="tg-df-card-footer mt-auto">                  \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="height:24px;">${_div}                  \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text" style="height:44px; margin-top:8px;">${_div}                ${_div}              ${_div}            ${_div}`;          this.grid.innerHTML = Array(4).fill(skeletonCardHtml).join('');        }        showError() {          const _div = '<' + '/div>';          this.grid.innerHTML = `\x3Cdiv class="tg-df-message">            An error occurred while finding deals. Please check your connection and try again.          ${_div}`;        }        escapeHTML(str) {          if (!str) return '';          return String(str).replace(/[&<>'"]/g, tag => ({              '&': '&', '<': '<', '>': '>', "'": ''', '"': '"'          }[tag] || tag));        }                bindCouponButtons() {          const btns = this.root.querySelectorAll('.tg-df-tag-coupons');          btns.forEach(btn => {            btn.addEventListener('click', (e) => {              e.preventDefault();              e.stopPropagation();              const merchant = btn.getAttribute('data-merchant');              this.openVouchersModal(merchant);            });          });                    const closeBtn = this.root.querySelector('#tg-df-vouchers-close');          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          if (closeBtn) {            closeBtn.onclick = () => this.closeVouchersModal();          }          if (backdrop) {            backdrop.onclick = (e) => {              if (e.target === backdrop) this.closeVouchersModal();            };          }        }                closeVouchersModal() {          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          if (backdrop) backdrop.classList.remove('active');        }                async checkMerchantsCouponsBulk(merchants) {          if (!merchants || merchants.length === 0) return {};          const controller = new AbortController();          const timeoutId = setTimeout(() => controller.abort(), 4000);          try {            const area = this.getAreaCode();            const url = new URL('https://search-api.fie.future.net.uk/widget.php');            url.searchParams.append('model_name', 'Everything');            url.searchParams.append('language', 'en-GB');            if (area) url.searchParams.append('area', area);            url.searchParams.append('combine_product_types', '1');            url.searchParams.append('filter_merchant_name', merchants.join(','));            url.searchParams.append('all_filters', 'false');            url.searchParams.append('exclude_unlabelled', 'false');            url.searchParams.append('include_specs', 'false');            url.searchParams.append('sort', 'voucher');            url.searchParams.append('distinct_merchants', 'natural');            url.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');            url.searchParams.append('rows', '120');            url.searchParams.append('origin', 'widgets-clientside');                        let res; try { res = await fetch(url.toString(), { signal: controller.signal }); } catch (e) { return {}; }            clearTimeout(timeoutId);            if (!res.ok) return {};            const data = await res.json();                        let offers = [];            if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {              offers = data.widget.data.offers;            } else if (data && data.data && Array.isArray(data.data.offers)) {              offers = data.data.offers;            } else if (Array.isArray(data)) {              offers = data;            } else if (data && Array.isArray(data.offers)) {              offers = data.offers;            } else if (data && data.offers && Array.isArray(data.offers.offer)) {              offers = data.offers.offer;            } else if (data && Array.isArray(data.data)) {              offers = data.data;            }                        const foundMerchants = new Set();            offers.forEach(o => {              let mName = o.merchant_name || o.merchant || o.retailer;              if (mName && typeof mName === 'object') mName = mName.name;              if (mName) foundMerchants.add(String(mName).toLowerCase());            });            const resultMap = {};            merchants.forEach(m => {              if (m) resultMap[m] = foundMerchants.has(String(m).toLowerCase());            });            return resultMap;          } catch (e) {            return {};          }        }                async openVouchersModal(merchantName) {          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          const title = this.root.querySelector('#tg-df-vouchers-title');          const content = this.root.querySelector('#tg-df-vouchers-content');                    if (!backdrop || !content) return;                    // HACK: Hide closing tags          const _div = '<' + '/div>';          const _span = '<' + '/span>';          const _a = '<' + '/a>';          const _h4 = '<' + '/h4>';          const _svg = '<' + '/svg>';          const _circle = '<' + '/circle>';          const _polyline = '<' + '/polyline>';          const _rect = '<' + '/rect>';          const _path = '<' + '/path>';                    title.innerText = `${merchantName} Coupons & Deals`;          content.innerHTML = `\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text">${_div}                               \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text">${_div}`;          backdrop.classList.add('active');                    try {            const area = this.getAreaCode();            const url = new URL('https://search-api.fie.future.net.uk/widget.php');            url.searchParams.append('model_name', 'Everything');            url.searchParams.append('language', 'en-GB');            if (area) url.searchParams.append('area', area);            url.searchParams.append('combine_product_types', '1');            url.searchParams.append('filter_merchant_name', merchantName);            url.searchParams.append('all_filters', 'false');            url.searchParams.append('exclude_unlabelled', 'false');            url.searchParams.append('include_specs', 'false');            url.searchParams.append('sort', 'voucher');            url.searchParams.append('distinct_merchants', 'natural');            url.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');            url.searchParams.append('rows', '50');            url.searchParams.append('origin', 'widgets-clientside');                        const res = await fetch(url.toString());            if (!res.ok) throw new Error('API Error');            const data = await res.json();                        let offers = [];            if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {              offers = data.widget.data.offers;            } else if (data && data.data && Array.isArray(data.data.offers)) {              offers = data.data.offers;            } else if (Array.isArray(data)) {              offers = data;            } else if (data && Array.isArray(data.offers)) {              offers = data.offers;            } else if (data && data.offers && Array.isArray(data.offers.offer)) {              offers = data.offers.offer;            } else if (data && Array.isArray(data.data)) {              offers = data.data;            }                        if (offers.length === 0) {              content.innerHTML = `\x3Cdiv class="tg-df-message">No vouchers currently available for ${this.escapeHTML(merchantName)}.${_div}`;              return;            }                        content.innerHTML = offers.map((v, idx) => {              let offerObj = v;              if (v.offers && v.offers.offer) {                offerObj = Array.isArray(v.offers.offer) ? v.offers.offer[0] : v.offers.offer;              } else if (v.offer) {                offerObj = Array.isArray(v.offer) ? v.offer[0] : v.offer;              }              let logoUrl = v.logo_url || offerObj.logo_url || '';              if (!logoUrl && v.merchant) {                if (Array.isArray(v.merchant) && v.merchant.length > 0) logoUrl = v.merchant[0].logo_url || '';                else logoUrl = v.merchant.logo_url || '';              }                            const offerName = offerObj.name || offerObj.title || v.name || v.title || 'Special Offer';              const endTime = offerObj.end_time || v.end_time || '';              const linkUrl = offerObj.link || offerObj.url || v.link || v.url || '#';                            let foundVoucherCode = '';              const findVoucherCode = (obj) => {                if (!obj || typeof obj !== 'object') return;                if (obj.type === 'voucher_code' && obj.display_value) {                  foundVoucherCode = obj.display_value;                  return;                }                if (Array.isArray(obj)) {                  for (const item of obj) {                    findVoucherCode(item);                    if (foundVoucherCode) return;                  }                } else {                  for (const k in obj) {                    if (Object.prototype.hasOwnProperty.call(obj, k)) {                      findVoucherCode(obj[k]);                      if (foundVoucherCode) return;                    }                  }                }              };              findVoucherCode(offerObj);              if (!foundVoucherCode) findVoucherCode(v);                            const voucherCode = foundVoucherCode || offerObj.voucher_code || v.voucher_code || '';              const codeHtml = voucherCode ? `\x3Cspan class="tg-df-voucher-code" data-action="copy-code" data-code="${this.escapeHTML(voucherCode)}" title="Copy to clipboard">                \x3Cspan class="tg-df-voucher-code-text">${this.escapeHTML(voucherCode)}${_span}                \x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-left:6px;flex-shrink:0;" class="tg-df-voucher-copy-icon">                  \x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2">${_rect}                  \x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1">${_path}                ${_svg}              ${_span}` : '';                            const logoHtml = logoUrl                 ? `\x3Cimg src="${this.escapeHTML(logoUrl)}" alt="${this.escapeHTML(offerName)}" class="tg-df-voucher-logo" />`                 : `\x3Cdiv class="tg-df-voucher-logo" style="background:#e2e8f0;">${_div}`;                            let expiryHtml = '';              if (endTime) {                let dStr = endTime;                if (!isNaN(dStr) && String(dStr).length === 10) dStr = Number(dStr) * 1000;                const d = new Date(dStr);                if (!isNaN(d.getTime())) {                  const options = { year: 'numeric', month: 'short', day: 'numeric' };                  expiryHtml = `                    \x3Cdiv class="tg-df-voucher-expiry">                      \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">                        \x3Ccircle cx="12" cy="12" r="10">${_circle}                        \x3Cpolyline points="12 6 12 12 16 14">${_polyline}                      ${_svg}                      Expires ${d.toLocaleDateString(undefined, options)}                    ${_div}`;                }              }              const revenueIdVal = generateRevenueId(linkUrl, offerName, merchantName, null);              const rewrittenLinkUrl = rewriteAffiliateLink(linkUrl, area, revenueIdVal);              return `                \x3Ca href="${this.escapeHTML(rewrittenLinkUrl)}" target="_blank" rel="noopener nofollow" class="tg-df-voucher-item"                  data-action="voucher-click"                  data-product-name="${this.escapeHTML(offerName)}"                  data-merchant-name="${this.escapeHTML(merchantName)}"                  data-analytics-id="${this.escapeHTML(offerObj.offer_id || offerObj.id || v.id || '')}"                  data-price=""                  data-previous-price=""                  data-original-link="${this.escapeHTML(linkUrl)}"                  data-revenue-id="${revenueIdVal}"                  data-index="${idx}"                  data-total="${offers.length}"                  data-in-stock="true"                  data-currency="USD"                  data-model-id="${this.escapeHTML(offerObj.model_id || v.model_id || offerObj.id || v.id || '')}"                  data-merchant-id="${this.escapeHTML(offerObj.merchant_id || offerObj.merchant?.id || '')}"                >                  ${logoHtml}                  \x3Cdiv class="tg-df-voucher-content">                    \x3Ch4 class="tg-df-voucher-title">${this.escapeHTML(offerName)}${_h4}                    ${codeHtml}                    ${expiryHtml}                  ${_div}                ${_a}              `;            }).join('');                        // Attach copy functionality            const copyBtns = content.querySelectorAll('[data-action="copy-code"]');            copyBtns.forEach(btn => {              btn.addEventListener('click', async (e) => {                e.preventDefault();                e.stopPropagation();                                const code = btn.getAttribute('data-code');                if (!code) return;                                try {                  const copyToClipboard = async (text) => {                     if (window.navigator.clipboard && window.isSecureContext) {                        try { await window.navigator.clipboard.writeText(text); return; } catch (e) {}                     }                     const textArea = document.createElement("textarea");                     textArea.value = text;                     textArea.style.position = "fixed";                     document.body.appendChild(textArea);                     textArea.focus();                     textArea.select();                     document.execCommand('copy');                     textArea.remove();                  };                  await copyToClipboard(code);                                    // Visual feedback                  btn.classList.add('copied');                  const textSpan = btn.querySelector('.tg-df-voucher-code-text');                  const iconSvg = btn.querySelector('.tg-df-voucher-copy-icon');                                    const origText = textSpan.innerText;                  const origIcon = iconSvg.innerHTML;                                    textSpan.innerText = 'Copied!';                  iconSvg.innerHTML = `\x3Cpolyline points="20 6 9 17 4 12">${_polyline}`;                                    setTimeout(() => {                    if (btn) {                      btn.classList.remove('copied');                      if (textSpan) textSpan.innerText = origText;                      if (iconSvg) iconSvg.innerHTML = origIcon;                    }                  }, 2000);                                    trackElementInteraction({                    id: 'voucher-code-copy',                    name: 'Copy Voucher Code',                    label: `Copied ${code} for ${merchantName}`                  });                } catch (err) {                  console.warn('Failed to copy text: ', err);                }              });            });            // Attach voucher click tracking            const voucherBtns = content.querySelectorAll('[data-action="voucher-click"]');            voucherBtns.forEach(btn => {              btn.addEventListener('click', (e) => {                if (e.target.closest('[data-action="copy-code"]')) return;                                const productName = btn.getAttribute('data-product-name');                const merchantNameAttr = btn.getAttribute('data-merchant-name');                const productId = btn.getAttribute('data-analytics-id');                const price = parseFloat(btn.getAttribute('data-price')) || null;                const prevPriceStr = btn.getAttribute('data-previous-price');                const previousPrice = prevPriceStr ? parseFloat(prevPriceStr) : null;                const originalLink = btn.getAttribute('data-original-link');                const rewrittenLink = btn.getAttribute('href');                const revenueId = btn.getAttribute('data-revenue-id');                const index = parseInt(btn.getAttribute('data-index'), 10) || 0;                const inStock = btn.getAttribute('data-in-stock') === 'true';                const totalText = btn.getAttribute('data-total');                const totalDeals = parseInt(totalText, 10) || 0;                const productCategoryName = 'deals';                const trackingParams = {                  widgetId: this.widgetId,                  productCategoryName: productCategoryName,                  product: {                    modelId: btn.getAttribute('data-model-id') || null,                    matchId: btn.getAttribute('data-match-id') || null,                    brand: btn.getAttribute('data-model-brand') || null,                    parent: btn.getAttribute('data-model-parent') || null,                    name: productName,                    price: price,                    previousPrice: previousPrice,                    link: rewrittenLink,                    originalLink: originalLink,                    inStock: inStock                  },                  zeroBasedProductIndexOrNull: index,                  totalDealsOrProducts: totalDeals,                   merchant: {                    id: btn.getAttribute('data-merchant-id') || null,                    network: btn.getAttribute('data-merchant-network') || null,                    url: btn.getAttribute('data-merchant-url') || null,                    name: merchantNameAttr                  },                  revenueId: revenueId,                  widgetTypeName: this.widgetTypeName,                  isoCurrencyCode: btn.getAttribute('data-currency') || 'USD'                };                if (typeof trackDealClick === 'function') {                  trackDealClick(trackingParams);                }              });            });                                  } catch (e) {            console.warn(e);            content.innerHTML = `\x3Cdiv class="tg-df-message">Failed to load vouchers.${_div}`;          }        }        render() {          try {            if (this.getViewMode() === 'savings_squad' && this.airedaleTags.length > 0) {              if (this.categoryFilterWrapper) {                 this.categoryFilterWrapper.style.display = 'flex';              }              if (this.categoryFilter) {                 const _option = '<' + '/option>';                 let optionsHtml = `\x3Coption value="all">All Categories${_option}`;                 this.airedaleTags.forEach(tag => {                    const isSelected = this.activeDealTag === tag ? 'selected' : '';                    optionsHtml += `\x3Coption value="${this.escapeHTML(tag)}" ${isSelected}>${this.escapeHTML(tag)} (${this.airedaleTagCounts[tag] || 0})${_option}`;                 });                 this.categoryFilter.innerHTML = optionsHtml;                 this.categoryFilter.value = this.activeDealTag || 'all';              }            } else {               if (this.categoryFilterWrapper) {                  this.categoryFilterWrapper.style.display = 'none';               }            }            const displayDeals = this.getFilteredDeals();          // HACK: Hide closing tags from the CMS HTML sanitizer so it doesn't strip them during in-page injection          const _div = '<' + '/div>';          const _span = '<' + '/span>';          const _a = '<' + '/a>';          const _h3 = '<' + '/h3>';          const _p = '<' + '/p>';          const _strong = '<' + '/strong>';          const _sup = '<' + '/sup>';          const _button = '<' + '/button>';          if (displayDeals.length === 0) {            if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {              if (this.deals.length > 0) {                 this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                  No deals match your selected filters.                ${_div}`;              } else if (this.getViewMode() === 'savings_squad' && this.currentQuery.length <= 2) {                 // Do not show "no exact matches" if query is empty for savings_squad                 this.grid.innerHTML = '';              } else {                 this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                  No exact matches found for "\x3Cstrong>${this.escapeHTML(this.currentQuery)}${_strong}". Try adjusting your search term.                ${_div}`;              }            } else {              this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                Search product or category names to discover the best deals from across the web.              ${_div}`;            }            return;          }          let dealsHtml = displayDeals.slice(0, this.displayLimit).map((deal, index) => {            try {               const currencySym = this.escapeHTML(deal.currency);               const isoCurrencyCode = normalizeCurrency(currencySym);               const escapedPrice = this.escapeHTML(deal.price);               const escapedMsrp = this.escapeHTML(deal.msrp);               const areaCode = this.getAreaCode();                              const revenueId = generateRevenueId(deal.url, deal.title, deal.merchant, null);               const originalLink = deal.url;               const rewrittenLink = rewriteAffiliateLink(deal.url, areaCode, revenueId);                        const productCategoryName = 'deals';            const dataAttr = `              data-action="${deal.isCheckPrice ? 'view-similar-click' : 'deal-click'}"              data-analytics-id="${this.escapeHTML(deal.externalProductId || deal.id || '')}"              data-product-name="${this.escapeHTML(deal.title)}"              data-merchant-name="${this.escapeHTML(deal.merchant)}"              data-price="${deal.rawPrice || ''}"              data-previous-price="${deal.rawMsrp || ''}"              data-original-link="${this.escapeHTML(originalLink)}"              data-revenue-id="${revenueId}"              data-index="${index}"              data-total="${displayDeals.length}"              data-in-stock="${deal.inStock !== false}"              data-currency="${this.escapeHTML(isoCurrencyCode)}"              data-model-id="${this.escapeHTML(deal.modelId || '')}"              data-product-key="${this.escapeHTML(deal.productKey || '')}"              data-merchant-id="${this.escapeHTML(deal.merchantId || '')}"            `;                        let priceGroupHtml = '';            let isSavingsSquadMode = this.getViewMode() === 'savings_squad';            let ctaText = 'View Deal';            let formattedPrice = '';            let msrpHtml = '';                        if (deal.isCheckPrice) {              ctaText = isSavingsSquadMode ? 'View Deal' : 'Check Price';              if (isSavingsSquadMode) {                priceGroupHtml = `                  \x3Cdiv class="tg-df-card-merchant-wrapper">                    \x3Cspan class="tg-df-card-merchant-pill" title="${this.escapeHTML(deal.merchant)}">${this.escapeHTML(deal.merchant)}${_span}                  ${_div}                  \x3Cdiv class="tg-df-card-price-group">                  ${_div}                `;              } else {                priceGroupHtml = `                  \x3Cdiv class="tg-df-card-merchant-wrapper">                    \x3Cspan class="tg-df-card-merchant-pill" title="${this.escapeHTML(deal.merchant)}">${this.escapeHTML(deal.merchant)}${_span}                  ${_div}                  \x3Cdiv class="tg-df-card-price-group">                    \x3Cspan class="tg-df-card-price" style="font-size: 15px; font-weight: 500; font-style: italic;">See price at retailer${_span}                  ${_div}                `;              }            } else {              // Format Price              formattedPrice = escapedPrice.includes(currencySym)                 ? escapedPrice                 : `${currencySym}${escapedPrice}`;                              // Format MSRP              msrpHtml = deal.msrp && deal.rawMsrp > deal.rawPrice                ? `\x3Cspan class="tg-df-card-msrp">${escapedMsrp.includes(currencySym) ? escapedMsrp : currencySym + escapedMsrp}${_span}`                : '';                              priceGroupHtml = `                \x3Cdiv class="tg-df-card-merchant-wrapper">                  \x3Cspan class="tg-df-card-merchant-pill" title="${this.escapeHTML(deal.merchant)}">${this.escapeHTML(deal.merchant)}${_span}                ${_div}                \x3Cdiv class="tg-df-card-price-group">                  ${isSavingsSquadMode ? '' : `                  \x3Cspan class="tg-df-card-price">${formattedPrice}${_span}                  ${msrpHtml}                  `}                ${_div}              `;            }                        const discountBadgeHtml = deal.savingLabel && !deal.isCheckPrice              ? `\x3Cspan class="tg-df-card-discount-badge">${this.escapeHTML(deal.savingLabel)}${_span}`              : '';                          // HACK for CMS            const _button = '<' + '/button>';            const _svg = '<' + '/svg>';            const _path = '<' + '/path>';            const _rect = '<' + '/rect>';            const _circle = '<' + '/circle>';            const _polyline = '<' + '/polyline>';            const _line = '<' + '/line>';                        let badgesHtml = '';            const primeBadge = deal.isPrime ? `              \x3Cspan class="tg-df-tag tg-df-tag-prime">                \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="currentColor">                  \x3Cpath d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z">${_path}                ${_svg} Prime              ${_span}            ` : '';                        const couponsBadge = deal.merchant && deal.merchant.toLowerCase().includes('amazon') ? '' : `              \x3Cdiv class="tg-df-coupon-wrapper" data-merchant="${this.escapeHTML(deal.merchant)}" style="display:inline-flex; align-items:center;">                \x3Cdiv class="tg-df-coupon-spinner">${_div}                \x3Cbutton type="button" class="tg-df-tag tg-df-tag-coupons" data-action="coupons-click" data-merchant="${this.escapeHTML(deal.merchant)}" style="display:none;">                  \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">                    \x3Cpath d="M20.59 13.41l-7.17 7.17a2 2 0 0 1-2.83 0L2 12V2h10l8.59 8.59a2 2 0 0 1 0 2.82z">${_path}                    \x3Cline x1="7" y1="7" x2="7.01" y2="7">${_line}                  ${_svg} Coupons                ${_button}              ${_div}            `;                        // Note: We always add coupons badge if there's a chance, but to allow 3-line titles we check wrapper display state            badgesHtml = `              \x3Cdiv class="tg-df-card-badges">                ${primeBadge}                ${couponsBadge}              ${_div}            `;            const _linearGradient = '<' + '/linearGradient>';            const _polygon = '<' + '/polygon>';            const _stop = '<' + '/stop>';            const _defs = '<' + '/defs>';                        let starHtml = '';            if (deal.starRating) {              let rating = deal.starRating;                            if (rating > 0) {                const fullStars = Math.floor(rating);                const halfStar = (rating - fullStars) >= 0.5 ? 1 : 0;                const emptyStars = Math.max(0, 5 - fullStars - halfStar);                const blue = '#1f69ff'; // Tom's guide brand color from VIEW DEAL button                const gray = '#cbd5e1';                                const starSvgFull = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="${blue}" stroke="${blue}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26">${_polygon}${_svg}`;                                const gradId = 'half_grad_' + Math.floor(Math.random()*1000000);                const starSvgHalf = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" stroke="${blue}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cdefs>\x3ClinearGradient id="${gradId}" x1="0" x2="1" y1="0" y2="0">\x3Cstop offset="50%" stop-color="${blue}">${_stop}\x3Cstop offset="50%" stop-color="transparent">${_stop}${_linearGradient}${_defs}                  \x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26" fill="url(#${gradId})">${_polygon}${_svg}`;                                  const starSvgEmpty = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="${gray}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26">${_polygon}${_svg}`;                                let stars = [];                for (let i=0; i<fullStars; i++) stars.push(starSvgFull);                if (halfStar) stars.push(starSvgHalf);                for (let i=0; i<emptyStars; i++) stars.push(starSvgEmpty);                                starHtml = `\x3Cdiv class="tg-df-card-stars" style="display:flex;align-items:center;margin-bottom:8px;font-size:13px;font-weight:600;color:var(--tg-df-text-muted);">                  \x3Cspan style="margin-right:6px;">Tom's Guide:${_span}                  \x3Cdiv style="display:flex;gap:2px;">                    ${stars.join('')}                  ${_div}                ${_div}`;              }            }            let htmlOutput = '';            if (isSavingsSquadMode) {              htmlOutput += `              \x3Cdiv class="hawk-deal-widget-container tg-df-mobile-only" data-collapsible="true">                ${this.editorMode ? `\x3Cinput type="checkbox" class="tg-df-deal-checkbox" data-id="${this.escapeHTML(deal.id)}" ${this.selectedDeals.has(deal.id) ? 'checked' : ''} style="margin-bottom: 10px;">` : ''}                \x3Cdiv class="hawk-deal-widget-wrap">                  \x3Cdiv class="hawk-deal-widget-image-container">                    \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" rel="sponsored noopener" target="_blank" class="hawk-affiliate-link-deal-widget" ${dataAttr}>                      \x3Cimg ${deal.image ? `src="${this.escapeHTML(deal.image)}"` : ''} alt="${this.escapeHTML(deal.title)}" class="hawk-lazy-image-deal-widget" loading="lazy" width="140" height="160" onerror="${deal.fallbackImage ? `if(!this.dataset.fb) { this.dataset.fb='1'; this.src='${this.escapeHTML(deal.fallbackImage)}'; } else { this.style.opacity='0'; }` : `this.style.opacity='0';`}">                    ${_a}                  ${_div}                  \x3Cdiv class="hawk-deal-widget-text-cta-container">                    \x3Cdiv class="hawk-deal-widget-text-body-container">                      \x3Cdiv class="hawk-deal-widget-text-body-main">                        \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                          ${deal.isCheckPrice ? `                            \x3Cspan class="hawk-deal-widget-title-product-title">${this.escapeHTML(deal.title)}${_span}                          ` : `                            \x3Cspan class="hawk-deal-widget-title-product-title">${deal.brand ? this.escapeHTML(deal.brand) + ' ' : ''}${this.escapeHTML(deal.productName || deal.title || '')}:${_span}                          `}                        ${_a}                        ${!deal.isCheckPrice && deal.rawMsrp && deal.rawMsrp > deal.rawPrice ? `                          \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                            \x3Cspan class="hawk-deal-widget-title-was-price">was ${currencySym}${escapedMsrp}${_span}                          ${_a}                        ` : ''}                        \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                          \x3Cspan class="hawk-deal-widget-title-retailer-price">                            ${!deal.isCheckPrice ? `                              \x3Cspan class="hawk-deal-widget-title-price">now ${formattedPrice}${_span}                              \x3Cspan class="hawk-deal-widget-title-retailer"> at ${this.escapeHTML(deal.merchant)}${_span}                            ` : `                              \x3Cspan class="hawk-deal-widget-title-price">See price at ${this.escapeHTML(deal.merchant)}${_span}                            `}                          ${_span}                        ${_a}                        ${deal.description ? `\x3Cdiv class="hawk-deal-widget-text-body-description">\x3Cp>${this.escapeHTML(deal.description)}${_p}${_div}` : ''}                      ${_div}                    ${_div}                    \x3Cdiv class="hawk-deal-widget-footer">                      \x3Cdiv class="hawk-deal-widget-button-wrapper">                        \x3Cdiv class="hawk-deal-widget-preferred-partner-wrapper">                          \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-deal-button" rel="sponsored noopener" target="_blank" ${dataAttr}>                            \x3Cspan>${deal.isCheckPrice ? 'Check Price' : 'View Deal'}${_span}                          ${_a}                        ${_div}                      ${_div}                    ${_div}                  ${_div}                ${_div}              ${_div}              `;            }            htmlOutput += `              \x3Cdiv class="tg-df-card ${isSavingsSquadMode ? 'tg-df-desktop-only' : ''}">                ${this.editorMode ? `\x3Cinput type="checkbox" class="tg-df-deal-checkbox" data-id="${this.escapeHTML(deal.id)}" ${this.selectedDeals.has(deal.id) ? 'checked' : ''}>` : ''}                \x3Cdiv class="tg-df-card-image-box">                  ${discountBadgeHtml}                  \x3Ca href="${this.escapeHTML(rewrittenLink)}" ${dataAttr} target="_blank" rel="noopener nofollow" style="display: flex; align-items: center; justify-content: center; width: 100%; height: 100%;">                    \x3Cimg ${deal.image ? `src="${this.escapeHTML(deal.image)}"` : ''} alt="${this.escapeHTML(deal.title)}" class="tg-df-card-image" loading="lazy" onerror="${deal.fallbackImage ? `if(!this.dataset.fb) { this.dataset.fb='1'; this.src='${this.escapeHTML(deal.fallbackImage)}'; } else { this.style.opacity='0'; }` : `this.style.opacity='0';`}">                  ${_a}                ${_div}                \x3Cdiv class="tg-df-card-body">                  ${starHtml}                  ${badgesHtml}                  \x3Ch3 class="tg-df-card-title tg-df-custom-savings-squad-title" title="${this.escapeHTML(deal.title)}">                    \x3Ca href="${this.escapeHTML(rewrittenLink)}" disable-tracking="true" target="_blank" rel="noopener nofollow" style="text-decoration: none; color: inherit;">                      ${isSavingsSquadMode                         ? (deal.isCheckPrice                             ? (deal.title && deal.title.includes(':')                                 ? `\x3Cstrong>${this.escapeHTML(deal.title.substring(0, deal.title.indexOf(':') + 1))}${_strong}\x3Cspan style="color: #1f69ff; font-weight: normal;">${this.escapeHTML(deal.title.substring(deal.title.indexOf(':') + 1))}${_span}`                                : this.escapeHTML(deal.title)                              )                             : `\x3Cstrong>${deal.brand ? this.escapeHTML(deal.brand) + ' ' : ''}${this.escapeHTML(deal.productName || deal.title || '')}:${_strong} ${deal.rawMsrp && deal.rawMsrp > deal.rawPrice ? `\x3Cspan style="color: #d0021b; text-decoration: line-through; font-weight: normal; margin-right: 4px;">was ${currencySym}${escapedMsrp}${_span} ` : ''}\x3Cspan style="color: #1f69ff; font-weight: normal;">now ${formattedPrice} at ${this.escapeHTML(deal.merchant)}${_span}`                          )                        : this.escapeHTML(deal.title)                      }                    ${_a}                  ${_h3}                  ${deal.description ? `\x3Cp style="font-size: 13px; color: var(--tg-df-text-muted); margin-bottom: 12px; line-height: 1.4;">${this.escapeHTML(deal.description)}${_p}` : ''}                  \x3Cdiv class="tg-df-card-footer">                    ${priceGroupHtml}                    \x3Ca href="${this.escapeHTML(rewrittenLink)}" ${dataAttr} target="_blank" rel="noopener nofollow" class="tg-df-card-cta ${isSavingsSquadMode ? 'tg-df-cta-savings-squad' : ''}" style="text-decoration: none;">${ctaText}${_a}                  ${_div}                ${_div}              ${_div}            `;                        return htmlOutput;            } catch (e) {               console.log("Error rendering deal in map for index", index, typeof deal === 'object' ? JSON.stringify(deal) : deal, "MSG:", e.message);               return '';            }          }).join('');                    if (displayDeals.length > this.displayLimit || ((this.getViewMode() === 'carousel' || this.getViewMode() === 'auto') && displayDeals.length > 0 && displayDeals.length % ((this.rowsSelect && this.rowsSelect.value) ? parseInt(this.rowsSelect.value, 10) : 12) === 0)) {            if (this.getViewMode() === 'carousel') {               dealsHtml += `                 \x3Cbutton type="button" class="tg-df-load-more-card tg-df-load-more">                   \x3Csvg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-bottom: 8px;">\x3Cpath d="M5 12h14">\x3C/path>\x3Cpath d="m12 5 7 7-7 7">\x3C/path>\x3C/svg>                   Load More                 ${_button}               `;            } else {               dealsHtml += `                 \x3Cdiv style="width: 100%; display: flex; justify-content: center; margin-top: 16px; grid-column: 1 / -1;">                   \x3Cbutton type="button" class="tg-df-tag-outline tg-df-load-more" style="padding: 8px 24px; border-radius: 100px; font-weight: 600; font-size: 14px; cursor: pointer; display: flex; align-items: center;">Load More${_button}                 ${_div}               `;            }          }                    this.grid.innerHTML = dealsHtml;          // Inject JSON-LD          try {            let targetNode = this.hostContainer || document.head;            let jsonLdScript = targetNode.querySelector('#tg-df-json-ld-' + this.widgetId);            if (!jsonLdScript) {                jsonLdScript = document.createElement('script');                jsonLdScript.type = 'application/ld+json';                jsonLdScript.id = 'tg-df-json-ld-' + this.widgetId;                targetNode.appendChild(jsonLdScript);            }            const jsonLdData = {              "@context": "https://schema.org",              "@type": "ItemList",              "itemListElement": displayDeals.slice(0, this.displayLimit).map((deal, index) => {                 let isoCurrency = "USD";                 if (deal.currency === '£') isoCurrency = "GBP";                 else if (deal.currency === '€') isoCurrency = "EUR";                 else if (deal.currency === 'A$') isoCurrency = "AUD";                 else if (deal.currency === 'CA$') isoCurrency = "CAD";                 const areaCode = typeof this.getAreaCode === 'function' ? this.getAreaCode() : 'US';                 const revenueId = typeof generateRevenueId === 'function' ? generateRevenueId(deal.url, deal.title, deal.merchant, null) : '';                 const rewrittenLink = typeof rewriteAffiliateLink === 'function' ? rewriteAffiliateLink(deal.url, areaCode, revenueId) : deal.url;                 return {                   "@type": "ListItem",                   "position": index + 1,                   "item": {                     "@type": "Product",                     "name": deal.title,                     "image": deal.image || "",                     "description": deal.description || "",                     "brand": {                       "@type": "Brand",                       "name": deal.brand || ""                     },                     "offers": {                       "@type": "Offer",                       "priceCurrency": isoCurrency,                       "price": deal.rawPrice || 0,                       "url": rewrittenLink,                       "seller": {                         "@type": "Organization",                         "name": deal.merchant || ""                       }                     }                   }                 };              }).filter(item => item.item.name)            };            jsonLdScript.textContent = JSON.stringify(jsonLdData);          } catch(e) { console.warn("JSON-LD generation failed", e); }                    let gridWrapper = this.grid.parentElement;          if (gridWrapper && gridWrapper.classList.contains('tg-df-grid-wrapper')) {             let rightChevron = gridWrapper.querySelector('.tg-df-carousel-scroll-right');             let leftChevron = gridWrapper.querySelector('.tg-df-carousel-scroll-left');             if (this.getViewMode() === 'carousel') {                 // The observer set up in setupScrollListeners handles visibility.                 if (rightChevron) rightChevron.style.display = 'flex';                 if (leftChevron) leftChevron.style.display = 'none'; // reset correctly             } else {                 if (rightChevron) rightChevron.style.display = 'none';                 if (leftChevron) leftChevron.style.display = 'none';             }          }                    const loadMoreBtn = this.grid.querySelector('.tg-df-load-more');          if (loadMoreBtn) {            loadMoreBtn.addEventListener('click', async () => {              if (typeof trackElementInteraction === 'function') {                trackElementInteraction({ id: 'load-more', name: 'Load more', label: 'Load More Results' });              }              if (displayDeals.length <= this.displayLimit) {                 loadMoreBtn.innerHTML = `                  <svg class="tg-df-spinner" style="width: 16px; height: 16px; display: inline-block; vertical-align: middle; margin-right: 8px;" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" d="M12 2v4m0 12v4M4.93 4.93l2.83 2.83m8.48 8.48l2.83 2.83M2 12h4m12 0h4M4.93 19.07l2.83-2.83m8.48-8.48l2.83-2.83"/></svg>                  Loading...                 `;                 loadMoreBtn.disabled = true;                 await this.fetchDeals(this.currentQuery, true);              } else {                 this.displayLimit += this.getRowsLimit();                 this.render();              }            });          }                      this.bindCouponButtons();            this.checkAndUpdateCoupons();                        // Allow hawklinks.js to discover and rewrite our widget links             // by appending the .article-body class and manually triggering processArticle.            let container = this.root.classList.contains('tg-df-container') ? this.root : this.root.querySelector('.tg-df-container');            if (container && !container.classList.contains('article-body')) {               container.classList.add('article-body');            }            setTimeout(() => {               if (this.grid && !this.grid.classList.contains('article-body')) this.grid.classList.add('article-body');               document.dispatchEvent(new CustomEvent('processArticle', { detail: { element: this.root } }));            }, 50);          } catch(e) {            console.warn("Widget render error", e);          }        }                async checkAndUpdateCoupons() {          const wrappers = Array.from(this.root.querySelectorAll('.tg-df-coupon-wrapper'));          if (wrappers.length === 0) return;                    const merchants = [...new Set(wrappers.map(w => w.getAttribute('data-merchant')).filter(Boolean))];          if (merchants.length === 0) return;          const couponResultsMap = await this.checkMerchantsCouponsBulk(merchants);                    for (const merchant of merchants) {            const hasCoupons = !!couponResultsMap[merchant];            const merchantWrappers = wrappers.filter(w => w.getAttribute('data-merchant') === merchant);            merchantWrappers.forEach(wrapper => {              const spinner = wrapper.querySelector('.tg-df-coupon-spinner');              const btn = wrapper.querySelector('.tg-df-tag-coupons');                            if (spinner) spinner.style.display = 'none';                            if (hasCoupons && btn) {                btn.style.display = 'inline-flex';              } else if (!hasCoupons) {                wrapper.style.display = 'none';              }            });          }        }        updateFloatingCopyBar() {          if (!this.editorBar || !this.editorSelectedCount) return;          if (this.editorMode && this.selectedDeals.size > 0) {            this.editorBar.style.display = 'flex';            this.editorSelectedCount.innerText = this.selectedDeals.size;          } else {            this.editorBar.style.display = 'none';          }        }        async copySelectedDealsToCMS() {           function htmlToSlate(htmlString) {              if (!htmlString) return [{ type: 'paragraph', children: [{ text: '' }] }];              let doc;              if (typeof window !== 'undefined' && window.DOMParser) {                 doc = new DOMParser().parseFromString(htmlString, 'text/html');              } else {                 doc = document.implementation.createHTMLDocument('');                 doc.body.innerHTML = htmlString;              }                            function parseNode(node, marks = {}) {                  if (node.nodeType === 3) {                      const text = node.textContent;                      if (!text) return null;                      return { text: text, ...marks };                  }                  if (node.nodeType === 1) {                      const tagName = node.tagName.toLowerCase();                      if (tagName === 'br') {                          return { type: 'line-break', children: [{ text: '' }] };                      }                      if (tagName === 'p') {                          let children = Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                          if (children.length === 0) children.push({ text: "" });                          return { type: 'paragraph', children };                      }                      if (tagName === 'strong' || tagName === 'b') {                          const newMarks = { ...marks, bold: true };                          return Array.from(node.childNodes).map(child => parseNode(child, newMarks)).flat().filter(Boolean);                      }                      if (tagName === 'em' || tagName === 'i') {                          const newMarks = { ...marks, italic: true };                          return Array.from(node.childNodes).map(child => parseNode(child, newMarks)).flat().filter(Boolean);                      }                      if (tagName === 'a') {                          const href = node.getAttribute('href') || '';                          let children = Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                          if (children.length === 0) children.push({ text: "" });                          return {                              type: 'link',                              url: href,                              isNoFollow: (node.getAttribute('rel') || '').includes('nofollow'),                              isSponsored: (node.getAttribute('rel') || '').includes('sponsored'),                              isOpenNewTab: node.getAttribute('target') === '_blank',                              isPreventDataRewrite: false,                              children: children                          };                      }                      return Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                  }                  return null;              }                            let blocksArray = [];              let currentParagraphChildren = [];              function flushParagraph() {                  if (currentParagraphChildren.length > 0) {                      blocksArray.push({ type: 'paragraph', children: currentParagraphChildren });                      currentParagraphChildren = [];                  }              }              Array.from(doc.body.childNodes).forEach(node => {                  const parsed = parseNode(node, {});                  const parsedItems = Array.isArray(parsed) ? parsed : (parsed ? [parsed] : []);                  parsedItems.forEach(item => {                      if (item.type === 'paragraph') {                          flushParagraph();                          blocksArray.push(item);                      } else {                          currentParagraphChildren.push(item);                      }                  });              });              flushParagraph();              if (blocksArray.length === 0) {                  blocksArray = [{ type: 'paragraph', children: [{ text: '' }] }];              }              return blocksArray;           }           const blocks = [];                      this.editorCopyBtn.innerHTML = '\x3Cspan class="tg-df-coupon-spinner" style="display:inline-block; margin-right:8px; border-top-color:#fff;">' + '<' + '/span> Copying...';           for (const deal of Array.from(this.selectedDeals.values())) {              const url = deal.url;              const merchant = deal.merchant;              const title = deal.title;              const image = deal.image;              const currentPrice = deal.currency + deal.rawPrice;              const wasPrice = deal.hasWasPrice && deal.rawMsrp > deal.rawPrice ? deal.currency + deal.rawMsrp : '';                            let couponsChildren = [];              try {                  const area = this.getAreaCode();                  const apiUrl = new URL('https://search-api.fie.future.net.uk/widget.php');                  apiUrl.searchParams.append('model_name', 'Everything');                  apiUrl.searchParams.append('language', 'en-GB');                  apiUrl.searchParams.append('area', area);                  apiUrl.searchParams.append('combine_product_types', '1');                  apiUrl.searchParams.append('filter_merchant_name', merchant);                  apiUrl.searchParams.append('all_filters', 'false');                  apiUrl.searchParams.append('exclude_unlabelled', 'false');                  apiUrl.searchParams.append('include_specs', 'false');                  apiUrl.searchParams.append('sort', 'voucher');                  apiUrl.searchParams.append('distinct_merchants', 'natural');                  apiUrl.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');                  apiUrl.searchParams.append('rows', '3');                  apiUrl.searchParams.append('origin', 'widgets-clientside');                                    let res; try { res = await fetch(apiUrl.toString()); } catch (e) { return; }                  if (res.ok) {                      const data = await res.json();                      let offers = [];                      if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {                        offers = data.widget.data.offers;                      } else if (data && data.data && Array.isArray(data.data.offers)) {                        offers = data.data.offers;                      }                                            if (offers.length > 0) {                          couponsChildren.push({ text: "Also check out these coupons: ", bold: true });                          offers.slice(0, 3).forEach((offer, idx) => {                              const actualOffer = offer.offer || offer;                              const offerName = actualOffer.name || actualOffer.title || offer.model_name || offer.title || offer.name || 'Coupon';                              const linkUrl = actualOffer.link || actualOffer.url || actualOffer.offer_link || '#';                              couponsChildren.push({ type: "line-break", children: [{ text: "" }] });                              couponsChildren.push({ text: "🎟️ " });                              couponsChildren.push({                                  type: "link",                                  url: linkUrl,                                  isNoFollow: true,                                  isSponsored: false,                                  isOpenNewTab: true,                                  isPreventDataRewrite: false,                                  children: [{ text: offerName, bold: true }]                              });                          });                      }                  }              } catch (err) {                  console.warn('Failed to fetch coupons for', merchant, err);              }              let descriptionValue = [];              if (deal.text) {                 descriptionValue = htmlToSlate(deal.text);              } else {                 const dealDescriptions = [                   `Don't miss out on this fantastic deal for the ${title}. It is currently available at ${merchant} for a highly competitive price.`,                   `We've spotted an excellent price drop on the ${title}. Grab it now at ${merchant} before it's gone.`,                   `The ${title} is currently seeing a generous discount over at ${merchant}. This is a perfect time to buy if you've been holding out.`,                   `If you're in the market for the ${title}, ${merchant} has just the deal for you.`,                   `Score the ${title} for less at ${merchant} right now. This is a rare chance to save big.`,                   `Upgrade your setup with the ${title}, now available at a stellar price via ${merchant}.`                 ];                 const randomDescription = dealDescriptions[Math.floor(Math.random() * dealDescriptions.length)];                 descriptionValue = [                    { type: "paragraph", children: [{ text: randomDescription }] }                 ];              }                            if (couponsChildren.length > 0) {                 let lastBlock = descriptionValue[descriptionValue.length - 1];                 if (lastBlock && lastBlock.type === 'paragraph') {                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children.push({ text: "Also check out these coupons: ", bold: true });                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children = lastBlock.children.concat(couponsChildren);                 } else {                     descriptionValue.push({                         type: "paragraph",                         children: [                             { type: "line-break", children: [{ text: "" }] },                             { type: "line-break", children: [{ text: "" }] },                             { text: "Also check out these coupons: ", bold: true },                             { type: "line-break", children: [{ text: "" }] },                             ...couponsChildren                         ]                     });                 }              }              function normalizeCurrencyToISO(symbol) {                const map = { '£': 'GBP', '$': 'USD', 'A$': 'AUD', 'CA$': 'CAD', '€': 'EUR' };                return map[symbol] || symbol;              }              const isoCurrency = normalizeCurrencyToISO(deal.currency);              blocks.push({                 id: (window.crypto && window.crypto.randomUUID) ? window.crypto.randomUUID() : 'cms-' + Date.now() + Math.random(),                 blockTypeName: "deal",                 excludeFrom: [],                 collapsible: false,                 props: {                    description: {                       value: descriptionValue,                       touched: false,                       validationMessage: ""                    },                    image: {                       value: {                          credit: [{ type: "paragraph", children: [{ text: merchant }] }],                          dateCreated: Date.now(),                          dateModified: Date.now(),                          distribution: [],                          fileSize: 0,                          height: 1000,                          id: deal.id,                          imageRights: "",                          src: image,                          name: title + ".jpg",                          tags: [],                          width: 1000                       },                       touched: false,                       validationMessage: ""                    },                    showDealButton: { value: true, touched: false, validationMessage: "" },                    isPreferredPartner: { value: false, touched: false, validationMessage: "" },                    linkHref: { value: url, touched: false, validationMessage: "" },                    linkLabel: { value: "", touched: false, validationMessage: "" },                    linkIsNoFollow: { value: true, touched: false, validationMessage: "" },                    linkIsSponsored: { value: false, touched: false, validationMessage: "" },                    linkIsOpenNewWindow: { value: true, touched: false, validationMessage: "" },                    customPromoFlags: { value: [], touched: false, validationMessage: "" },                    showStarDeal: { value: false, touched: false, validationMessage: "" },                    savingType: { value: "none", touched: false, validationMessage: "" },                    starDealPromoFlag: { value: "", touched: false, validationMessage: "" },                    showEditorsChoice: { value: false, touched: false, validationMessage: "" },                    editorsChoiceTitle: { value: "", touched: false, validationMessage: "" },                    hawkPriceCurrency: { value: { value: isoCurrency, label: isoCurrency }, touched: false, validationMessage: "" },                    hawkPrice: { value: deal.hasWasPrice ? String(deal.rawMsrp) : String(deal.rawPrice), touched: false, validationMessage: "" },                    hawkSalePrice: { value: String(deal.rawPrice), touched: false, validationMessage: "" },                    lastCheckedPriceDate: { value: "", touched: false, validationMessage: "" },                    hawkModel: { touched: false, validationMessage: "" },                    productId: { value: "", touched: false, validationMessage: "" },                    voucherId: { value: "", touched: false, validationMessage: "" },                    brand: { value: deal.brand || merchant, touched: false, validationMessage: "" },                    productName: { value: title, touched: false, validationMessage: "" },                    label: { value: "", touched: false, validationMessage: "" },                    retailer: { value: merchant, touched: false, validationMessage: "" },                    priceCheckError: false                 },                 failedFetchError: ""              });           }           const payload = {              type: "articleBuilderPages",              data: blocks           };           const jsonStr = JSON.stringify(payload);                      if (navigator.clipboard && navigator.clipboard.writeText) {              navigator.clipboard.writeText(jsonStr).then(() => {                 this.editorCopyBtn.innerHTML = 'Copied!';                 setTimeout(() => {                    this.editorCopyBtn.innerHTML = '\x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2"><' + '/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"><' + '/path><' + '/svg> Copy to CMS';                 }, 2000);              }).catch(err => {                 console.warn('Failed to copy text: ', err);                 alert('Failed to copy deals to clipboard. See console.');              });           } else {              // Fallback              const textArea = document.createElement("textarea");              textArea.value = jsonStr;              document.body.appendChild(textArea);              textArea.focus();              textArea.select();              try {                 document.execCommand('copy');                 this.editorCopyBtn.innerHTML = 'Copied!';                 setTimeout(() => {                    this.editorCopyBtn.innerHTML = '\x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2"><' + '/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"><' + '/path><' + '/svg> Copy to CMS';                 }, 2000);              } catch (err) {                 console.warn('Fallback: Oops, unable to copy', err);                 alert('Fallback: Failed to copy deals to clipboard.');              }              document.body.removeChild(textArea);           }        }      }      // Initialize the Widget      if (document.readyState === 'loading') {        document.addEventListener('DOMContentLoaded', () => new DealsFinderWidget({ rootId: 'signal-deals-finder-root', rootNode: shadowRoot, hostContainer: hostContainer }));      } else {        new DealsFinderWidget({ rootId: 'signal-deals-finder-root', rootNode: shadowRoot, hostContainer: hostContainer });      }    })();  </script></div>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ Casabrews Ultra Pro review: Why don’t all espresso machines have a built-in timer? ]]></title>
                                                                                                <dc:content><![CDATA[ <p>When I tested the original <a href="https://www.tomsguide.com/home/coffee-makers/casabrews-ultra-review">Casabrews Ultra</a> last year, I was perplexed. It has a PID controller and a built-in timer for under $349? And it doesn’t look overly plasticky or feel flimsy? How? Some major boiler issues, that’s how. Thankfully, these issues have been sorted out on its successor, the Casabrews Ultra Pro, released in July 2026. </p><p>So is this enough to make it one of the <a href="https://www.tomsguide.com/home/coffee-makers/best-espresso-machines">best espresso machines</a>? Hmm — not if you’re serious about your coffee. While it’s a good entry-level model with premium features like a customizable PID controller and has a built-in timer, its weak steam wand and habit of burning espresso holds me back from recommending it fully. </p><p>But might it be worth the $349 price tag? To get the full story, keep reading this Casabrews Ultra Pro review.</p><h2 class="article-body__section" id="section-casabrews-ultra-pro-review-specs"><span>Casabrews Ultra Pro review: Specs</span></h2><div ><table><tbody><tr><td class="firstcol " ><p><strong>Price</strong></p></td><td  ><p><a href="https://www.amazon.com/CASABREWS-Espresso-Machine-Heating-System/dp/B0H4FHZ2TZ" target="_blank" rel="nofollow">$349</a> </p></td></tr><tr><td class="firstcol " ><p><strong>Weight</strong></p></td><td  ><p>Not specified </p></td></tr><tr><td class="firstcol " ><p><strong>Dimensions</strong></p></td><td  ><p>12.2 x 10.3 x 13 inches</p></td></tr><tr><td class="firstcol " ><p><strong>Grinder</strong></p></td><td  ><p>No</p></td></tr><tr><td class="firstcol " ><p><strong>Heating system </strong></p></td><td  ><p>Casabrews proprietary</p></td></tr><tr><td class="firstcol " ><p><strong>Pressure </strong></p></td><td  ><p>20 bar</p></td></tr><tr><td class="firstcol " ><p><strong>Water tank capacity</strong></p></td><td  ><p>34 fluid ounces</p></td></tr><tr><td class="firstcol " ><p><strong>Accessories</strong></p></td><td  ><p>Tamper, single shot filter (dual-walled and single-walled), double shot filter (dual walled and single-walled)</p></td></tr></tbody></table></div><h2 class="article-body__section" id="section-casabrews-ultra-pro-review-price-availability"><span>Casabrews Ultra Pro review: Price & availability</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="bRzVpvC3MmAePAG2s3chTF" name="Casabrews Ultra Pro 3 copy.JPG" alt="the casabrews ultra pro photographed against the blue tom's guide background" src="https://cdn.mos.cms.futurecdn.net/bRzVpvC3MmAePAG2s3chTF.jpg" mos="" align="middle" fullscreen="" width="1920" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The Casabrews Ultra Pro is <a href="https://www.amazon.com/CASABREWS-Espresso-Machine-Heating-System/dp/B0H4FHZ2TZ" target="_blank" rel="nofollow">$349 from Amazon U.S.</a> At time of writing, it’s not available in the U.K. </p><p>For a Casabrews machine, this is a pretty premium price. I mean, you can probably tell from the name, right? They don’t call it the “Ultra Pro” for no reason. I tested the <a href="https://www.tomsguide.com/home/coffee-makers/casabrews-ultra-review">original Ultra</a> last year and liked it, but it had some flaws, like a weak steam wand and boiler issues. More on that later, but I didn’t experience the same boiler problems. </p><p>The $349 asking price is a little too steep for this machine. When you can get the $299 <a href="https://www.tomsguide.com/home/coffee-makers/sage-breville-bambino-review">Breville Bambino</a>, PID controller and customizable pre-infusion included, or the $499 <a href="https://www.tomsguide.com/home/home-appliances/breville-sage-bambino-plus-review">Breville Bambino Plus</a>, there’s not a lot of wiggle room. </p><h2 class="article-body__section" id="section-casabrews-ultra-pro-review-design"><span>Casabrews Ultra Pro review: Design </span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="Bf8G4ai2E3t2EmE5WQAddE" name="Casabrews Ultra Pro copy.JPG" alt="the casabrews ultra pro photographed against the blue tom's guide background" src="https://cdn.mos.cms.futurecdn.net/Bf8G4ai2E3t2EmE5WQAddE.jpg" mos="" align="middle" fullscreen="" width="1920" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The new Casabrews Ultra Pro looks pretty identical to the original Ultra. I liked the original version, so I like the new version. I didn’t notice any tarnishing issues this time around, so I’m glad to see Casabrews has improved on that; however, there’s still no water tank alert on the screen. </p><p>Speaking of the screen, I love it, and it’s by far the best feature on this machine. You don’t have to scrabble with a coffee scale timer anymore. Of course, you still need a coffee scale to ensure you’re getting the proper 36g espresso out, but forget that timer function. It’s redundant to you now. The Ultra Pro times your shot for you — and it’s reliable, every single time. </p><p>The screen has a few more capabilities: it shows you the double or single shot, hot water, and steam wand functions. That’s it, but I’m not mad about it. All I need is that sweet, sweet timer function, and I’m happy. </p><p>Like the previous model, the Ultra Pro utilizes a steam button rather than a dial, which is good if you need a low-effort machine. </p><p>Also like the previous machine, there’s a nice little groove on the top so you can store your tamper. I liked this feature as much as I like the 58mm portafilter basket. This is the coffee-snob standard, so is ideal for getting higher-quality aftermarket accessories… which you will need to purchase, as the Ultra Pro doesn’t come with a milk jug. Many Casabrews machines omit the milk jug, which I’m not a fan of. It’s so stingy. It’s literally a milk jug. All Breville machines come with a milk jug, but the $149 <a href="https://www.tomsguide.com/home/coffee-makers/delonghi-stilosa-review">De’Longhi Stilosa</a> doesn’t. </p><h2 class="article-body__section" id="section-casabrews-ultra-pro-review-espresso"><span>Casabrews Ultra Pro review: Espresso</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="LcKr4CeXrwicUJsD7K2ZxF" name="Casabrews Ultra Pro 3.JPG" alt="the casabrews ultra pro photographed against the blue tom's guide background" src="https://cdn.mos.cms.futurecdn.net/LcKr4CeXrwicUJsD7K2ZxF.jpg" mos="" align="middle" fullscreen="" width="1920" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>I didn’t experience any boiler issues while using the Ultra Pro. On the previous version, it took ages for the machine to switch between milk and espresso. The Ultra Pro makes strange clicking noises after brewing espresso, but I was always able to get the steam wand up and running in a few seconds. </p><p>Despite these successes, I have a few espresso-related qualms with the Casabrews Ultra Pro. Casabrews claim “this espresso machine ensures consistent 9-bar extraction”, which isn’t true. I <em>know</em> it isn’t true because the Ultra Pro has an LCD screen that literally displays the bar pressure during extraction. </p><p>Not once did the bar pressure number stay the same. It fluctuated from 3 to 7 to 9 to 15 at one point, and down and up again throughout extraction. I know pressure is supposed to increase from low to 9-bar during infusion, but it’s not supposed to go back down when only 5g has extracted. </p><p>This is not a consistent 9-bar extraction. Casabrews kind of shot itself in the foot here. Why include a digital “manometer” (quotation marks necessary there) only for it to tell on itself? </p><p>Despite what Casabrews says on its website, there also doesn’t seem to be a solenoid valve, as all my pucks came out wet. Now I’ve grown accustomed to my Bambino Plus’s solenoid valve, I’m not sure I can ever go back. Cleanup is so much easier with dry pucks. </p><p>Here’s a photo of an espresso I made on the Casabrews Ultra Pro. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:4061px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="PBTaydyjieQpKVR9MVRQZb" name="espresso casabrews" alt="a photo of coffee made on the casabrews ultra pro" src="https://cdn.mos.cms.futurecdn.net/PBTaydyjieQpKVR9MVRQZb.jpg" mos="" align="middle" fullscreen="" width="4061" height="2284" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Erin Bashford)</span></figcaption></figure><p>I wasn’t a huge fan of this espresso. It tasted burnt and overextracted, despite extracting in 25 seconds. This is the “ideal” extraction time. It didn’t pour too quickly or too slowly, meaning it wasn’t over- or under-extracted. </p><p>However, perhaps I’m simply too picky. I gave my colleagues many coffees made on the Casabrews Ultra Pro, and the feedback ranged from “really nice actually” to “a nice fruitiness”. </p><p>There’s also the (customizable) PID controller (temperature controller to prevent burnt or weak brews) to mention. This is better than Breville’s entry-level models, which have a non-programmable PID. You can easily adjust the brew temperature in intervals from 194°F to 204°F. This is great to see on a cheaper machine. </p><p>Finally, there’s a cold brew mode. Here’s a photo of said cold brew. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:4474px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="95GHLnny8EjNSNbYKVFoBd" name="cold brew casabrews" alt="a photo of coffee made on the casabrews ultra pro" src="https://cdn.mos.cms.futurecdn.net/95GHLnny8EjNSNbYKVFoBd.jpg" mos="" align="middle" fullscreen="" width="4474" height="2517" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Erin Bashford)</span></figcaption></figure><p>The cold brew was bright and juicy, but quite astringent. It took 101 seconds to brew 160ml. I wouldn’t use this again, but it’s good if you like juicy, sharp flavors and you’re on a time crunch. </p><p>If you’re what you’d consider a “coffee snob”, this machine might not be the one for you. In that case, I’d recommend the aforementioned Breville Bambino or Breville Bambino Plus. You may even want to go for the $499 <a href="https://www.tomsguide.com/home/coffee-makers/gaggia-classic-e24-evo-pro-review">Gaggia Classic E24 Evo Pro</a>, which has no PID controller but is a coffee nerd goldmine. </p><h2 class="article-body__section" id="section-casabrews-ultra-pro-review-milk"><span>Casabrews Ultra Pro review: Milk</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="oAtvXgdhdidszGkCAzeDgF" name="Casabrews Ultra Pro 1 copy.JPG" alt="the casabrews ultra pro photographed against the blue tom's guide background" src="https://cdn.mos.cms.futurecdn.net/oAtvXgdhdidszGkCAzeDgF.jpg" mos="" align="middle" fullscreen="" width="1920" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>My biggest issue with the Casabrews Ultra was the weak steam wand. Seeing as Casabrews fixed the boiler issues, I hoped the steam wand weakness would have been fixed, too. </p><p>Unfortunately, I was wrong. It still takes a whole minute to steam half a jug of milk, and said milk is unevenly aerated. I found my milk separated into layers immediately after finishing steaming. I also struggled to obtain the ideal “vortex” while steaming, which is the marker of a low-quality steam wand. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:3949px;"><p class="vanilla-image-block" style="padding-top:56.27%;"><img id="6oySnhNaMetGww9WwzK8mb" name="casabrews milk" alt="a photo of coffee made on the casabrews ultra pro" src="https://cdn.mos.cms.futurecdn.net/6oySnhNaMetGww9WwzK8mb.jpg" mos="" align="middle" fullscreen="" width="3949" height="2222" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Erin Bashford)</span></figcaption></figure><p>As you can see, the latte art is squashed. This is because the foam wasn’t integrated into the milk, so when I poured, it separated into layers. This is not what I’d want to see. </p><p>The De’Longhi Stilosa, Breville Bambino, and Breville Bambino Plus don’t suffer from this issue, so I’d recommend grabbing one of those instead if you value latte art. Even the <a href="https://www.tomsguide.com/home/coffee-makers/ninja-luxe-cafe-mini-plus-review">Ninja Luxe Cafe Mini Plus</a> ($499)’s auto steam wand is better, if you can afford the extra $150 (but you get a grinder). </p><h2 class="article-body__section" id="section-casabrews-ultra-pro-review-storage-maintenance"><span>Casabrews Ultra Pro review: Storage & maintenance</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="Z5dtEzXNRLPENkeE7Ldf8G" name="Casabrews Ultra Pro 6.JPG" alt="the casabrews ultra pro photographed against the blue tom's guide background" src="https://cdn.mos.cms.futurecdn.net/Z5dtEzXNRLPENkeE7Ldf8G.jpg" mos="" align="middle" fullscreen="" width="1920" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The Ultra Pro is just 13 inches deep and 12 inches tall, which makes it a mid-sized espresso machine. While considerably larger than the 7-inch-wide Breville Bambino and the 5-inch wide Casabrews 3700 Essential, it’s nowhere near as massive as the frankly Titanic <a href="https://www.tomsguide.com/home/coffee-makers/breville-oracle-dual-boiler-review">Breville Oracle Dual Boiler</a> ($3,000, 18 inches tall). </p><p>Obviously, still check it will fit in your kitchen, but it’s not a large model, as far as espresso machines go. </p><p>In terms of cleaning, well, Casabrews doesn’t provide you with any accessories, unlike Breville and De’Longhi. You’ll need to buy backflush tablets and descaler yourself, which is around <a href="https://www.amazon.com/Urnex-Espresso-Machine-Cleaning-Powder/dp/B001418KNS" target="_blank" rel="nofollow">$20 for a huge bottle on Amazon</a>.</p><p>In terms of warranty, it’s also pretty slim pickings here. Casabrews offers just one year, while Breville, De’Longhi, and Ninja offer two as standard.</p><h2 class="article-body__section" id="section-casabrews-ultra-pro-review-verdict"><span>Casabrews Ultra Pro review: Verdict</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="aMg2SqGPfmx4jci48W5x5G" name="Casabrews Ultra Pro 1.JPG" alt="the casabrews ultra pro photographed against the blue tom's guide background" src="https://cdn.mos.cms.futurecdn.net/aMg2SqGPfmx4jci48W5x5G.jpg" mos="" align="middle" fullscreen="" width="1920" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>I gave the Casabrews Ultra Pro 3 stars. Yeah, I know. “You gave the Ultra 3.5 stars, so how does that work?” The most egregious issue — the steam wand — has not been fixed. Even though Casabrews has had time to fix this, it didn’t, hence the lower rating this time around. Do I think the Ultra Pro is worth $349? No. No I do not. </p><p>When you can get the Casabrews CM5148 Pro for $199 — PID controller included — I really cannot see why the Ultra Pro is so much more expensive. The on-screen timer is a nice addition, but is it worth an extra $150? I think not. </p><p>So while I’m sure you won’t be majorly disappointed by the Ultra Pro, I simply can’t recommend it when there are similar machines for cheaper, or much better machines for a little extra. Treat yourself to the $499 Breville Bambino Plus or Gaggia Classic E24 Evo Pro, or save a little and get the Breville Bambino or Casabrews CM5418 Pro. It’s a no-brainer. </p> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/home/coffee-makers/casabrews-ultra-pro-review</link>
                                                                            <description>
                            <![CDATA[ The Casabrews Ultra Pro is a midrange espresso machine with a PID controller and a built-in timer, but the steam wand issues still haven’t been fixed. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">fYWvRUczdthpBiPWADxGL4</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/gd5oFXTPbjZpEGMLNUfB4F-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Thu, 13 Aug 2026 12:44:11 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Coffee Makers]]></category>
                                                    <category><![CDATA[Home]]></category>
                                                    <category><![CDATA[Home Appliances]]></category>
                                                    <category><![CDATA[Kitchen & Dining]]></category>
                                                                                                <author><![CDATA[ erin.bashford@futurenet.com (Erin Bashford) ]]></author>                    <dc:creator><![CDATA[ Erin Bashford ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/rLvJvJVZx43hEzSsJy3BpL.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Erin Bashford is a senior reviews writer at Tom’s Guide. She has a Master’s in Broadcast and Digital Journalism from the University of East Anglia and 7 years of experience reviewing music and events for various publications. She has edited publications such as Outline Magazine’s Guide to Norwich, and she has written for a number of music magazines and websites such as Clash Magazine, Outline Magazine and Dork Magazine. She has a strong interest in audio gear and the music world. &lt;/p&gt;&lt;p&gt;As an ex-barista, Erin is passionate about coffee tech. She also loves finding the best cooking hacks and kitchen appliances, including her beloved Instant Pot. &lt;/p&gt;&lt;p&gt;In her spare time, you can find her reading, practising yoga, hiking, writing fantasy novels, or stressing over NYT Games.&lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/gd5oFXTPbjZpEGMLNUfB4F-1280-80.jpg">
                                                            <media:credit><![CDATA[Tom&#039;s Guide]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[the casabrews ultra pro photographed against the blue tom&#039;s guide background]]></media:description>                                                            <media:text><![CDATA[the casabrews ultra pro photographed against the blue tom&#039;s guide background]]></media:text>
                                <media:title type="plain"><![CDATA[the casabrews ultra pro photographed against the blue tom&#039;s guide background]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/gd5oFXTPbjZpEGMLNUfB4F-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>When I tested the original <a href="https://www.tomsguide.com/home/coffee-makers/casabrews-ultra-review">Casabrews Ultra</a> last year, I was perplexed. It has a PID controller and a built-in timer for under $349? And it doesn’t look overly plasticky or feel flimsy? How? Some major boiler issues, that’s how. Thankfully, these issues have been sorted out on its successor, the Casabrews Ultra Pro, released in July 2026. </p><p>So is this enough to make it one of the <a href="https://www.tomsguide.com/home/coffee-makers/best-espresso-machines">best espresso machines</a>? Hmm — not if you’re serious about your coffee. While it’s a good entry-level model with premium features like a customizable PID controller and has a built-in timer, its weak steam wand and habit of burning espresso holds me back from recommending it fully. </p><p>But might it be worth the $349 price tag? To get the full story, keep reading this Casabrews Ultra Pro review.</p><h2 class="article-body__section" id="section-casabrews-ultra-pro-review-specs"><span>Casabrews Ultra Pro review: Specs</span></h2><div ><table><tbody><tr><td class="firstcol " ><p><strong>Price</strong></p></td><td  ><p><a href="https://www.amazon.com/CASABREWS-Espresso-Machine-Heating-System/dp/B0H4FHZ2TZ" target="_blank" rel="nofollow">$349</a> </p></td></tr><tr><td class="firstcol " ><p><strong>Weight</strong></p></td><td  ><p>Not specified </p></td></tr><tr><td class="firstcol " ><p><strong>Dimensions</strong></p></td><td  ><p>12.2 x 10.3 x 13 inches</p></td></tr><tr><td class="firstcol " ><p><strong>Grinder</strong></p></td><td  ><p>No</p></td></tr><tr><td class="firstcol " ><p><strong>Heating system </strong></p></td><td  ><p>Casabrews proprietary</p></td></tr><tr><td class="firstcol " ><p><strong>Pressure </strong></p></td><td  ><p>20 bar</p></td></tr><tr><td class="firstcol " ><p><strong>Water tank capacity</strong></p></td><td  ><p>34 fluid ounces</p></td></tr><tr><td class="firstcol " ><p><strong>Accessories</strong></p></td><td  ><p>Tamper, single shot filter (dual-walled and single-walled), double shot filter (dual walled and single-walled)</p></td></tr></tbody></table></div><h2 class="article-body__section" id="section-casabrews-ultra-pro-review-price-availability"><span>Casabrews Ultra Pro review: Price & availability</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="bRzVpvC3MmAePAG2s3chTF" name="Casabrews Ultra Pro 3 copy.JPG" alt="the casabrews ultra pro photographed against the blue tom's guide background" src="https://cdn.mos.cms.futurecdn.net/bRzVpvC3MmAePAG2s3chTF.jpg" mos="" align="middle" fullscreen="" width="1920" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The Casabrews Ultra Pro is <a href="https://www.amazon.com/CASABREWS-Espresso-Machine-Heating-System/dp/B0H4FHZ2TZ" target="_blank" rel="nofollow">$349 from Amazon U.S.</a> At time of writing, it’s not available in the U.K. </p><p>For a Casabrews machine, this is a pretty premium price. I mean, you can probably tell from the name, right? They don’t call it the “Ultra Pro” for no reason. I tested the <a href="https://www.tomsguide.com/home/coffee-makers/casabrews-ultra-review">original Ultra</a> last year and liked it, but it had some flaws, like a weak steam wand and boiler issues. More on that later, but I didn’t experience the same boiler problems. </p><p>The $349 asking price is a little too steep for this machine. When you can get the $299 <a href="https://www.tomsguide.com/home/coffee-makers/sage-breville-bambino-review">Breville Bambino</a>, PID controller and customizable pre-infusion included, or the $499 <a href="https://www.tomsguide.com/home/home-appliances/breville-sage-bambino-plus-review">Breville Bambino Plus</a>, there’s not a lot of wiggle room. </p><h2 class="article-body__section" id="section-casabrews-ultra-pro-review-design"><span>Casabrews Ultra Pro review: Design </span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="Bf8G4ai2E3t2EmE5WQAddE" name="Casabrews Ultra Pro copy.JPG" alt="the casabrews ultra pro photographed against the blue tom's guide background" src="https://cdn.mos.cms.futurecdn.net/Bf8G4ai2E3t2EmE5WQAddE.jpg" mos="" align="middle" fullscreen="" width="1920" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The new Casabrews Ultra Pro looks pretty identical to the original Ultra. I liked the original version, so I like the new version. I didn’t notice any tarnishing issues this time around, so I’m glad to see Casabrews has improved on that; however, there’s still no water tank alert on the screen. </p><p>Speaking of the screen, I love it, and it’s by far the best feature on this machine. You don’t have to scrabble with a coffee scale timer anymore. Of course, you still need a coffee scale to ensure you’re getting the proper 36g espresso out, but forget that timer function. It’s redundant to you now. The Ultra Pro times your shot for you — and it’s reliable, every single time. </p><p>The screen has a few more capabilities: it shows you the double or single shot, hot water, and steam wand functions. That’s it, but I’m not mad about it. All I need is that sweet, sweet timer function, and I’m happy. </p><p>Like the previous model, the Ultra Pro utilizes a steam button rather than a dial, which is good if you need a low-effort machine. </p><p>Also like the previous machine, there’s a nice little groove on the top so you can store your tamper. I liked this feature as much as I like the 58mm portafilter basket. This is the coffee-snob standard, so is ideal for getting higher-quality aftermarket accessories… which you will need to purchase, as the Ultra Pro doesn’t come with a milk jug. Many Casabrews machines omit the milk jug, which I’m not a fan of. It’s so stingy. It’s literally a milk jug. All Breville machines come with a milk jug, but the $149 <a href="https://www.tomsguide.com/home/coffee-makers/delonghi-stilosa-review">De’Longhi Stilosa</a> doesn’t. </p><h2 class="article-body__section" id="section-casabrews-ultra-pro-review-espresso"><span>Casabrews Ultra Pro review: Espresso</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="LcKr4CeXrwicUJsD7K2ZxF" name="Casabrews Ultra Pro 3.JPG" alt="the casabrews ultra pro photographed against the blue tom's guide background" src="https://cdn.mos.cms.futurecdn.net/LcKr4CeXrwicUJsD7K2ZxF.jpg" mos="" align="middle" fullscreen="" width="1920" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>I didn’t experience any boiler issues while using the Ultra Pro. On the previous version, it took ages for the machine to switch between milk and espresso. The Ultra Pro makes strange clicking noises after brewing espresso, but I was always able to get the steam wand up and running in a few seconds. </p><p>Despite these successes, I have a few espresso-related qualms with the Casabrews Ultra Pro. Casabrews claim “this espresso machine ensures consistent 9-bar extraction”, which isn’t true. I <em>know</em> it isn’t true because the Ultra Pro has an LCD screen that literally displays the bar pressure during extraction. </p><p>Not once did the bar pressure number stay the same. It fluctuated from 3 to 7 to 9 to 15 at one point, and down and up again throughout extraction. I know pressure is supposed to increase from low to 9-bar during infusion, but it’s not supposed to go back down when only 5g has extracted. </p><p>This is not a consistent 9-bar extraction. Casabrews kind of shot itself in the foot here. Why include a digital “manometer” (quotation marks necessary there) only for it to tell on itself? </p><p>Despite what Casabrews says on its website, there also doesn’t seem to be a solenoid valve, as all my pucks came out wet. Now I’ve grown accustomed to my Bambino Plus’s solenoid valve, I’m not sure I can ever go back. Cleanup is so much easier with dry pucks. </p><p>Here’s a photo of an espresso I made on the Casabrews Ultra Pro. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:4061px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="PBTaydyjieQpKVR9MVRQZb" name="espresso casabrews" alt="a photo of coffee made on the casabrews ultra pro" src="https://cdn.mos.cms.futurecdn.net/PBTaydyjieQpKVR9MVRQZb.jpg" mos="" align="middle" fullscreen="" width="4061" height="2284" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Erin Bashford)</span></figcaption></figure><p>I wasn’t a huge fan of this espresso. It tasted burnt and overextracted, despite extracting in 25 seconds. This is the “ideal” extraction time. It didn’t pour too quickly or too slowly, meaning it wasn’t over- or under-extracted. </p><p>However, perhaps I’m simply too picky. I gave my colleagues many coffees made on the Casabrews Ultra Pro, and the feedback ranged from “really nice actually” to “a nice fruitiness”. </p><p>There’s also the (customizable) PID controller (temperature controller to prevent burnt or weak brews) to mention. This is better than Breville’s entry-level models, which have a non-programmable PID. You can easily adjust the brew temperature in intervals from 194°F to 204°F. This is great to see on a cheaper machine. </p><p>Finally, there’s a cold brew mode. Here’s a photo of said cold brew. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:4474px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="95GHLnny8EjNSNbYKVFoBd" name="cold brew casabrews" alt="a photo of coffee made on the casabrews ultra pro" src="https://cdn.mos.cms.futurecdn.net/95GHLnny8EjNSNbYKVFoBd.jpg" mos="" align="middle" fullscreen="" width="4474" height="2517" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Erin Bashford)</span></figcaption></figure><p>The cold brew was bright and juicy, but quite astringent. It took 101 seconds to brew 160ml. I wouldn’t use this again, but it’s good if you like juicy, sharp flavors and you’re on a time crunch. </p><p>If you’re what you’d consider a “coffee snob”, this machine might not be the one for you. In that case, I’d recommend the aforementioned Breville Bambino or Breville Bambino Plus. You may even want to go for the $499 <a href="https://www.tomsguide.com/home/coffee-makers/gaggia-classic-e24-evo-pro-review">Gaggia Classic E24 Evo Pro</a>, which has no PID controller but is a coffee nerd goldmine. </p><h2 class="article-body__section" id="section-casabrews-ultra-pro-review-milk"><span>Casabrews Ultra Pro review: Milk</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="oAtvXgdhdidszGkCAzeDgF" name="Casabrews Ultra Pro 1 copy.JPG" alt="the casabrews ultra pro photographed against the blue tom's guide background" src="https://cdn.mos.cms.futurecdn.net/oAtvXgdhdidszGkCAzeDgF.jpg" mos="" align="middle" fullscreen="" width="1920" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>My biggest issue with the Casabrews Ultra was the weak steam wand. Seeing as Casabrews fixed the boiler issues, I hoped the steam wand weakness would have been fixed, too. </p><p>Unfortunately, I was wrong. It still takes a whole minute to steam half a jug of milk, and said milk is unevenly aerated. I found my milk separated into layers immediately after finishing steaming. I also struggled to obtain the ideal “vortex” while steaming, which is the marker of a low-quality steam wand. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:3949px;"><p class="vanilla-image-block" style="padding-top:56.27%;"><img id="6oySnhNaMetGww9WwzK8mb" name="casabrews milk" alt="a photo of coffee made on the casabrews ultra pro" src="https://cdn.mos.cms.futurecdn.net/6oySnhNaMetGww9WwzK8mb.jpg" mos="" align="middle" fullscreen="" width="3949" height="2222" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Erin Bashford)</span></figcaption></figure><p>As you can see, the latte art is squashed. This is because the foam wasn’t integrated into the milk, so when I poured, it separated into layers. This is not what I’d want to see. </p><p>The De’Longhi Stilosa, Breville Bambino, and Breville Bambino Plus don’t suffer from this issue, so I’d recommend grabbing one of those instead if you value latte art. Even the <a href="https://www.tomsguide.com/home/coffee-makers/ninja-luxe-cafe-mini-plus-review">Ninja Luxe Cafe Mini Plus</a> ($499)’s auto steam wand is better, if you can afford the extra $150 (but you get a grinder). </p><h2 class="article-body__section" id="section-casabrews-ultra-pro-review-storage-maintenance"><span>Casabrews Ultra Pro review: Storage & maintenance</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="Z5dtEzXNRLPENkeE7Ldf8G" name="Casabrews Ultra Pro 6.JPG" alt="the casabrews ultra pro photographed against the blue tom's guide background" src="https://cdn.mos.cms.futurecdn.net/Z5dtEzXNRLPENkeE7Ldf8G.jpg" mos="" align="middle" fullscreen="" width="1920" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The Ultra Pro is just 13 inches deep and 12 inches tall, which makes it a mid-sized espresso machine. While considerably larger than the 7-inch-wide Breville Bambino and the 5-inch wide Casabrews 3700 Essential, it’s nowhere near as massive as the frankly Titanic <a href="https://www.tomsguide.com/home/coffee-makers/breville-oracle-dual-boiler-review">Breville Oracle Dual Boiler</a> ($3,000, 18 inches tall). </p><p>Obviously, still check it will fit in your kitchen, but it’s not a large model, as far as espresso machines go. </p><p>In terms of cleaning, well, Casabrews doesn’t provide you with any accessories, unlike Breville and De’Longhi. You’ll need to buy backflush tablets and descaler yourself, which is around <a href="https://www.amazon.com/Urnex-Espresso-Machine-Cleaning-Powder/dp/B001418KNS" target="_blank" rel="nofollow">$20 for a huge bottle on Amazon</a>.</p><p>In terms of warranty, it’s also pretty slim pickings here. Casabrews offers just one year, while Breville, De’Longhi, and Ninja offer two as standard.</p><h2 class="article-body__section" id="section-casabrews-ultra-pro-review-verdict"><span>Casabrews Ultra Pro review: Verdict</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="aMg2SqGPfmx4jci48W5x5G" name="Casabrews Ultra Pro 1.JPG" alt="the casabrews ultra pro photographed against the blue tom's guide background" src="https://cdn.mos.cms.futurecdn.net/aMg2SqGPfmx4jci48W5x5G.jpg" mos="" align="middle" fullscreen="" width="1920" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>I gave the Casabrews Ultra Pro 3 stars. Yeah, I know. “You gave the Ultra 3.5 stars, so how does that work?” The most egregious issue — the steam wand — has not been fixed. Even though Casabrews has had time to fix this, it didn’t, hence the lower rating this time around. Do I think the Ultra Pro is worth $349? No. No I do not. </p><p>When you can get the Casabrews CM5148 Pro for $199 — PID controller included — I really cannot see why the Ultra Pro is so much more expensive. The on-screen timer is a nice addition, but is it worth an extra $150? I think not. </p><p>So while I’m sure you won’t be majorly disappointed by the Ultra Pro, I simply can’t recommend it when there are similar machines for cheaper, or much better machines for a little extra. Treat yourself to the $499 Breville Bambino Plus or Gaggia Classic E24 Evo Pro, or save a little and get the Breville Bambino or Casabrews CM5418 Pro. It’s a no-brainer. </p>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ I tested the Keurig K-Crema, and it’s my new go-to for fancy coffee drinks ]]></title>
                                                                                                <dc:content><![CDATA[ <div  class="fancy-box"><div class="fancy_box-title">Keurig K-Crema review: Specs</div><div class="fancy_box_body"><p class="fancy-box__body-text"><strong>Price: </strong>$219.99<br><strong>Dimensions: </strong>13.3 x 8.1 x 13.1 inches<br><strong>Reservoir capacity: </strong>72 ounces<br><strong>Brew sizes: </strong>Single shot, double shot, 6, 8, 10, or 12 ounces<br><strong>Strength control: </strong>No<br><strong>Features: </strong>Height-adjustable drip tray, High Altitude Brewing Mode<br><strong>Colors: </strong>Black</p></div></div><p>Ever since my dad got a fancy espresso machine, I’ve dreamed of brewing my own crema-topped coffee at home. But most at-home, <a href="https://www.tomsguide.com/home/coffee-makers/best-coffee-makers">coffee makers</a> don’t offer this feature — unless you want to pay hundreds of dollars and sacrifice a large chunk of your kitchen’s counter space. </p><p>When I saw that Keurig was coming out with the K-Crema, I wondered if it could be a good lower-cost option to my dad’s top-of-the-line model.</p><p>Ultimately, the K-Crema brews a tasty cup of coffee with a layer of foamy crema on top. It might not stack up to an espresso shot from a pricier machine or a coffee shop, but for those of us who want to save money while still enjoying a delicious shot of coffee, the K-Crema is a decent pick.</p><p>Read this Keurig K-Crema review to find out how it performed over several weeks in my kitchen, and why I think this is a top pick in the <a href="https://www.tomsguide.com/best-picks/the-best-keurig-coffee-makers">Keurig coffee maker</a> lineup.</p><h3 class="article-body__section" id="section-keurig-k-crema-review-price-and-availability"><span>Keurig K-Crema review: Price and availability</span></h3><p>The Keurig K-Crema is available for $219 at <a href="https://www.keurig.com/K-Crema%E2%84%A2-High-Pressure-Coffee-Maker/p/K-Crema-Coffee-Maker">Keurig</a> and <a href="https://www.amazon.com/dp/B0FFW5169X">Amazon</a>. You can also buy it at <a href="https://www.target.com/p/keurig-k-crema-single-serve-k-cup-pod-coffee-maker/-/A-94682461"><u>Target</u></a>, <a href="https://www.kohls.com/product/prd-7882845/keurig-k-crema-single-serve-coffee-maker-with-4-cup-2-shot-sizes.jsp"><u>Kohl’s</u></a>, <a href="https://www.walmart.com/ip/KEURIG-K-CREMA/15928404601"><u>Walmart</u></a>, and other major retailers. Plus, the machine is available in a single color: Black.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="H95sAzyz3snVQqLzFisxbB" name="Keurig K-Crema-3" alt="Keurig K-Crema coffee maker on a kitchen counter" src="https://cdn.mos.cms.futurecdn.net/H95sAzyz3snVQqLzFisxbB.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>You can use any K-Cup pod in the K-Crema, though mine came with Global Trek medium roast pods. The machine doesn’t come with a reusable pod, but you could buy one and use your own coffee if you prefer. For this review, I stuck with the provided K-Cups.</p><h3 class="article-body__section" id="section-keurig-k-crema-review-design"><span>Keurig K-Crema review: Design</span></h3><p>After initially unboxing the Keurig K-Crema, the first thing I noticed was its size. It’s bigger than your basic Keurig machine, like the K-Slim or the K-Mini, yet smaller than most coffee machines. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="qM7BpivXF9LF7vUkhYmjfB" name="Keurig K-Crema-5" alt="Keurig K-Crema coffee maker on a kitchen counter" src="https://cdn.mos.cms.futurecdn.net/qM7BpivXF9LF7vUkhYmjfB.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The K-Crema has a removable water reservoir that sits to the right of the machine, making it wider than some other single-brew coffee machines. But the reservoir was easy to fill: simply pick it up using the handle, fill it with water, and pop it back.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="f44KxQM9mqVCpVEW5ntqWB" name="Keurig K-Crema-4" alt="Keurig K-Crema coffee maker on a kitchen counter" src="https://cdn.mos.cms.futurecdn.net/f44KxQM9mqVCpVEW5ntqWB.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The K-Crema has six size options, from a single shot to a 12-ounce brew. The “Pressure” button brews coffee at five times the pressure of a standard cup, resulting in a silky layer of crema. That’s what sets the machine apart from other Keurigs, but can it justify the higher price tag?</p><h3 class="article-body__section" id="section-keurig-k-crema-review-performance"><span>Keurig K-Crema review: Performance</span></h3><p>To determine whether or not the Keurig K-Crema is a good buy, I put it to the test in my kitchen over several weeks. I timed each drink setting and took the temperature of multiple cups to gauge the average hotness of a cup of coffee.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="yAB3wLNKCpqHBacCdhmfgB" name="Keurig K-Crema-7" alt="Keurig K-Crema coffee maker on a kitchen counter" src="https://cdn.mos.cms.futurecdn.net/yAB3wLNKCpqHBacCdhmfgB.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>Here’s how the Keurig K-Crema performed:</p><div ><table><tbody><tr><td class="firstcol " ><p><strong>Cup size</strong></p></td><td  ><p><strong>Time for classic brew</strong></p></td><td  ><p><strong>Time for pressure brew</strong></p></td><td  ><p><strong>Temperature in Fahrenheit</strong></p></td></tr><tr><td class="firstcol " ><p><strong>Shot</strong></p></td><td  ><p>N/A</p></td><td  ><p>41 seconds</p></td><td  ><p>163 degrees</p></td></tr><tr><td class="firstcol " ><p><strong>Double shot</strong></p></td><td  ><p>N/A</p></td><td  ><p>51 seconds</p></td><td  ><p>168 degrees</p></td></tr><tr><td class="firstcol " ><p><strong>6 ounces</strong></p></td><td  ><p>1 minute 23 seconds</p></td><td  ><p>1 minute 2 seconds</p></td><td  ><p>171 degrees</p></td></tr><tr><td class="firstcol " ><p><strong>8 ounces</strong></p></td><td  ><p>1 minute 31 seconds</p></td><td  ><p>1 minute 11 seconds</p></td><td  ><p>170 degrees</p></td></tr><tr><td class="firstcol " ><p><strong>10 ounces</strong></p></td><td  ><p>1 minute 50 seconds</p></td><td  ><p>1 minute 23 seconds</p></td><td  ><p>174 degrees</p></td></tr><tr><td class="firstcol " ><p><strong>12 ounces</strong></p></td><td  ><p>2 minutes 8 seconds</p></td><td  ><p>1 minute 36 seconds</p></td><td  ><p>173 degrees</p></td></tr></tbody></table></div><p>These brew times are comparable to other Keurig machines, though it was interesting to note that the machine brewed faster when I used the pressure setting. Coffee temperature was a little colder than I expected, especially for the shot and double-shot sizes. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="AQu7MeSuJKE8GqxFEK55gB" name="Keurig K-Crema-6" alt="Keurig K-Crema coffee maker on a kitchen counter" src="https://cdn.mos.cms.futurecdn.net/AQu7MeSuJKE8GqxFEK55gB.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>I measured brew temps from a low of 163 degrees to a high of 174 degrees. Experts recommend a water temperature of 195 to 205 degrees for the best-testing coffee, but that’s not realistic from a single-serve machine like the Keurig K-Crema.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="RA5jwMLXgT8suPv8A9DbWB" name="Keurig K-Crema-8" alt="Keurig K-Crema coffee maker on a kitchen counter" src="https://cdn.mos.cms.futurecdn.net/RA5jwMLXgT8suPv8A9DbWB.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>Noise-wise, I measured a high of 68 decibels for both the Classic and Pressure settings, with an average in the 50 to 60 decibel range. That’s considered to be in the moderate range — and since the machine brews most sizes in under two minutes, it’s unlikely to cause much disruption.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="9EMJTncM8VqAZ8cc9pmsaB" name="Keurig K-Crema-9" alt="Keurig K-Crema coffee maker on a kitchen counter" src="https://cdn.mos.cms.futurecdn.net/9EMJTncM8VqAZ8cc9pmsaB.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>Now for the most important factor: taste. My only prior experience of a crema machine is in my dad’s kitchen, where he has a fancy (and expensive) espresso machine. I didn’t expect the K-Crema to measure up, yet I was still pleasantly surprised by the taste of the resulting cup. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="2XUxJHNAJt3sgZMkrNAnfB" name="Keurig K-Crema-10" alt="Keurig K-Crema coffee maker on a kitchen counter" src="https://cdn.mos.cms.futurecdn.net/2XUxJHNAJt3sgZMkrNAnfB.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>In the past, I’ve found K-Cups to taste too weak or artificial, but the Global Trek pods I tested were just right. I liked the addition of the crema, though it didn’t quite hold up when I mixed in milk and sugar. </p><h3 class="article-body__section" id="section-keurig-k-crema-review-comparison"><span>Keurig K-Crema review: Comparison</span></h3><p>The Keurig K-Crema is a solid single-serve coffee maker, but how does it compare to other Keurig models? I have previously tested the K-Mini Mate, and the K-Crema definitely brews a superior cup. But it comes at a cost: The <a href="https://www.tomsguide.com/home/coffee-makers/keurig-k-mini-mate-coffee-maker-review"><u>Keurig K-Mini Mate</u></a> costs $59.99, compared to $219.99 for the K-Crema.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="WeRshmU3pxkz3w5HcPV2kB" name="Keurig K-Crema-12" alt="Keurig K-Crema coffee maker on a kitchen counter" src="https://cdn.mos.cms.futurecdn.net/WeRshmU3pxkz3w5HcPV2kB.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>You might also consider the <a href="https://www.tomsguide.com/reviews/keurig-k-cafe"><u>Keurig K-Cafe</u></a>, which comes with a milk frother. This machine is ideal if you like coffee drinks, like lattes and cappuccinos. But if you prefer to drink straight shots of espresso, the K-Crema is the right choice.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="rxjRYLQzA4fNskvVXpKjiB" name="Keurig K-Crema-11" alt="Keurig K-Crema coffee maker on a kitchen counter" src="https://cdn.mos.cms.futurecdn.net/rxjRYLQzA4fNskvVXpKjiB.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>Ultimately, you’ll want to consider what you want out of your coffee machine. If you’ve always wanted an espresso machine but don’t want to spend the money, the Keurig K-Crema is a good budget-friendly option.</p><h3 class="article-body__section" id="section-keurig-k-crema-review-verdict"><span>Keurig K-Crema review: Verdict</span></h3><p>If you’re looking for an affordable coffee maker that can brew a decent cup of coffee or a shot of creamy espresso, I recommend looking into the Keurig K-Crema. While it doesn’t quite measure up to the expensive espresso machines on the market, it’s available for a fraction of the price, and the resulting coffee is smooth and enjoyable. </p><p>It’s the ideal middle ground for someone who wants to brew coffee drinks at home, but isn’t ready to commit to an espresso machine.</p> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/home/coffee-makers/coffee-makers/keurig-k-crema-review</link>
                                                                            <description>
                            <![CDATA[ The Keurig K-Crema is easy to use and can brew a shot in under a minute. It’s a shame that the taste could be better. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">fKzPeQzEuLCn48EZczurKL</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/DBgFUtLFv7DX6onacw5tdB-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Wed, 12 Aug 2026 05:00:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Coffee Makers]]></category>
                                                    <category><![CDATA[Home]]></category>
                                                    <category><![CDATA[Home Appliances]]></category>
                                                    <category><![CDATA[Kitchen & Dining]]></category>
                                                                                                                    <dc:creator><![CDATA[ Catherine Hiles ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/ehjj3r2KFzMLw5yobwSyrV.png ]]></dc:source>
                                                                <dc:description><![CDATA[ null ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/DBgFUtLFv7DX6onacw5tdB-1280-80.jpg">
                                                            <media:credit><![CDATA[Tom&#039;s Guide]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Keurig K-Crema coffee maker on a kitchen counter]]></media:description>                                                            <media:text><![CDATA[Keurig K-Crema coffee maker on a kitchen counter]]></media:text>
                                <media:title type="plain"><![CDATA[Keurig K-Crema coffee maker on a kitchen counter]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/DBgFUtLFv7DX6onacw5tdB-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <div  class="fancy-box"><div class="fancy_box-title">Keurig K-Crema review: Specs</div><div class="fancy_box_body"><p class="fancy-box__body-text"><strong>Price: </strong>$219.99<br><strong>Dimensions: </strong>13.3 x 8.1 x 13.1 inches<br><strong>Reservoir capacity: </strong>72 ounces<br><strong>Brew sizes: </strong>Single shot, double shot, 6, 8, 10, or 12 ounces<br><strong>Strength control: </strong>No<br><strong>Features: </strong>Height-adjustable drip tray, High Altitude Brewing Mode<br><strong>Colors: </strong>Black</p></div></div><p>Ever since my dad got a fancy espresso machine, I’ve dreamed of brewing my own crema-topped coffee at home. But most at-home, <a href="https://www.tomsguide.com/home/coffee-makers/best-coffee-makers">coffee makers</a> don’t offer this feature — unless you want to pay hundreds of dollars and sacrifice a large chunk of your kitchen’s counter space. </p><p>When I saw that Keurig was coming out with the K-Crema, I wondered if it could be a good lower-cost option to my dad’s top-of-the-line model.</p><p>Ultimately, the K-Crema brews a tasty cup of coffee with a layer of foamy crema on top. It might not stack up to an espresso shot from a pricier machine or a coffee shop, but for those of us who want to save money while still enjoying a delicious shot of coffee, the K-Crema is a decent pick.</p><p>Read this Keurig K-Crema review to find out how it performed over several weeks in my kitchen, and why I think this is a top pick in the <a href="https://www.tomsguide.com/best-picks/the-best-keurig-coffee-makers">Keurig coffee maker</a> lineup.</p><h3 class="article-body__section" id="section-keurig-k-crema-review-price-and-availability"><span>Keurig K-Crema review: Price and availability</span></h3><p>The Keurig K-Crema is available for $219 at <a href="https://www.keurig.com/K-Crema%E2%84%A2-High-Pressure-Coffee-Maker/p/K-Crema-Coffee-Maker">Keurig</a> and <a href="https://www.amazon.com/dp/B0FFW5169X">Amazon</a>. You can also buy it at <a href="https://www.target.com/p/keurig-k-crema-single-serve-k-cup-pod-coffee-maker/-/A-94682461"><u>Target</u></a>, <a href="https://www.kohls.com/product/prd-7882845/keurig-k-crema-single-serve-coffee-maker-with-4-cup-2-shot-sizes.jsp"><u>Kohl’s</u></a>, <a href="https://www.walmart.com/ip/KEURIG-K-CREMA/15928404601"><u>Walmart</u></a>, and other major retailers. Plus, the machine is available in a single color: Black.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="H95sAzyz3snVQqLzFisxbB" name="Keurig K-Crema-3" alt="Keurig K-Crema coffee maker on a kitchen counter" src="https://cdn.mos.cms.futurecdn.net/H95sAzyz3snVQqLzFisxbB.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>You can use any K-Cup pod in the K-Crema, though mine came with Global Trek medium roast pods. The machine doesn’t come with a reusable pod, but you could buy one and use your own coffee if you prefer. For this review, I stuck with the provided K-Cups.</p><h3 class="article-body__section" id="section-keurig-k-crema-review-design"><span>Keurig K-Crema review: Design</span></h3><p>After initially unboxing the Keurig K-Crema, the first thing I noticed was its size. It’s bigger than your basic Keurig machine, like the K-Slim or the K-Mini, yet smaller than most coffee machines. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="qM7BpivXF9LF7vUkhYmjfB" name="Keurig K-Crema-5" alt="Keurig K-Crema coffee maker on a kitchen counter" src="https://cdn.mos.cms.futurecdn.net/qM7BpivXF9LF7vUkhYmjfB.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The K-Crema has a removable water reservoir that sits to the right of the machine, making it wider than some other single-brew coffee machines. But the reservoir was easy to fill: simply pick it up using the handle, fill it with water, and pop it back.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="f44KxQM9mqVCpVEW5ntqWB" name="Keurig K-Crema-4" alt="Keurig K-Crema coffee maker on a kitchen counter" src="https://cdn.mos.cms.futurecdn.net/f44KxQM9mqVCpVEW5ntqWB.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The K-Crema has six size options, from a single shot to a 12-ounce brew. The “Pressure” button brews coffee at five times the pressure of a standard cup, resulting in a silky layer of crema. That’s what sets the machine apart from other Keurigs, but can it justify the higher price tag?</p><h3 class="article-body__section" id="section-keurig-k-crema-review-performance"><span>Keurig K-Crema review: Performance</span></h3><p>To determine whether or not the Keurig K-Crema is a good buy, I put it to the test in my kitchen over several weeks. I timed each drink setting and took the temperature of multiple cups to gauge the average hotness of a cup of coffee.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="yAB3wLNKCpqHBacCdhmfgB" name="Keurig K-Crema-7" alt="Keurig K-Crema coffee maker on a kitchen counter" src="https://cdn.mos.cms.futurecdn.net/yAB3wLNKCpqHBacCdhmfgB.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>Here’s how the Keurig K-Crema performed:</p><div ><table><tbody><tr><td class="firstcol " ><p><strong>Cup size</strong></p></td><td  ><p><strong>Time for classic brew</strong></p></td><td  ><p><strong>Time for pressure brew</strong></p></td><td  ><p><strong>Temperature in Fahrenheit</strong></p></td></tr><tr><td class="firstcol " ><p><strong>Shot</strong></p></td><td  ><p>N/A</p></td><td  ><p>41 seconds</p></td><td  ><p>163 degrees</p></td></tr><tr><td class="firstcol " ><p><strong>Double shot</strong></p></td><td  ><p>N/A</p></td><td  ><p>51 seconds</p></td><td  ><p>168 degrees</p></td></tr><tr><td class="firstcol " ><p><strong>6 ounces</strong></p></td><td  ><p>1 minute 23 seconds</p></td><td  ><p>1 minute 2 seconds</p></td><td  ><p>171 degrees</p></td></tr><tr><td class="firstcol " ><p><strong>8 ounces</strong></p></td><td  ><p>1 minute 31 seconds</p></td><td  ><p>1 minute 11 seconds</p></td><td  ><p>170 degrees</p></td></tr><tr><td class="firstcol " ><p><strong>10 ounces</strong></p></td><td  ><p>1 minute 50 seconds</p></td><td  ><p>1 minute 23 seconds</p></td><td  ><p>174 degrees</p></td></tr><tr><td class="firstcol " ><p><strong>12 ounces</strong></p></td><td  ><p>2 minutes 8 seconds</p></td><td  ><p>1 minute 36 seconds</p></td><td  ><p>173 degrees</p></td></tr></tbody></table></div><p>These brew times are comparable to other Keurig machines, though it was interesting to note that the machine brewed faster when I used the pressure setting. Coffee temperature was a little colder than I expected, especially for the shot and double-shot sizes. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="AQu7MeSuJKE8GqxFEK55gB" name="Keurig K-Crema-6" alt="Keurig K-Crema coffee maker on a kitchen counter" src="https://cdn.mos.cms.futurecdn.net/AQu7MeSuJKE8GqxFEK55gB.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>I measured brew temps from a low of 163 degrees to a high of 174 degrees. Experts recommend a water temperature of 195 to 205 degrees for the best-testing coffee, but that’s not realistic from a single-serve machine like the Keurig K-Crema.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="RA5jwMLXgT8suPv8A9DbWB" name="Keurig K-Crema-8" alt="Keurig K-Crema coffee maker on a kitchen counter" src="https://cdn.mos.cms.futurecdn.net/RA5jwMLXgT8suPv8A9DbWB.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>Noise-wise, I measured a high of 68 decibels for both the Classic and Pressure settings, with an average in the 50 to 60 decibel range. That’s considered to be in the moderate range — and since the machine brews most sizes in under two minutes, it’s unlikely to cause much disruption.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="9EMJTncM8VqAZ8cc9pmsaB" name="Keurig K-Crema-9" alt="Keurig K-Crema coffee maker on a kitchen counter" src="https://cdn.mos.cms.futurecdn.net/9EMJTncM8VqAZ8cc9pmsaB.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>Now for the most important factor: taste. My only prior experience of a crema machine is in my dad’s kitchen, where he has a fancy (and expensive) espresso machine. I didn’t expect the K-Crema to measure up, yet I was still pleasantly surprised by the taste of the resulting cup. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="2XUxJHNAJt3sgZMkrNAnfB" name="Keurig K-Crema-10" alt="Keurig K-Crema coffee maker on a kitchen counter" src="https://cdn.mos.cms.futurecdn.net/2XUxJHNAJt3sgZMkrNAnfB.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>In the past, I’ve found K-Cups to taste too weak or artificial, but the Global Trek pods I tested were just right. I liked the addition of the crema, though it didn’t quite hold up when I mixed in milk and sugar. </p><h3 class="article-body__section" id="section-keurig-k-crema-review-comparison"><span>Keurig K-Crema review: Comparison</span></h3><p>The Keurig K-Crema is a solid single-serve coffee maker, but how does it compare to other Keurig models? I have previously tested the K-Mini Mate, and the K-Crema definitely brews a superior cup. But it comes at a cost: The <a href="https://www.tomsguide.com/home/coffee-makers/keurig-k-mini-mate-coffee-maker-review"><u>Keurig K-Mini Mate</u></a> costs $59.99, compared to $219.99 for the K-Crema.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="WeRshmU3pxkz3w5HcPV2kB" name="Keurig K-Crema-12" alt="Keurig K-Crema coffee maker on a kitchen counter" src="https://cdn.mos.cms.futurecdn.net/WeRshmU3pxkz3w5HcPV2kB.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>You might also consider the <a href="https://www.tomsguide.com/reviews/keurig-k-cafe"><u>Keurig K-Cafe</u></a>, which comes with a milk frother. This machine is ideal if you like coffee drinks, like lattes and cappuccinos. But if you prefer to drink straight shots of espresso, the K-Crema is the right choice.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="rxjRYLQzA4fNskvVXpKjiB" name="Keurig K-Crema-11" alt="Keurig K-Crema coffee maker on a kitchen counter" src="https://cdn.mos.cms.futurecdn.net/rxjRYLQzA4fNskvVXpKjiB.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>Ultimately, you’ll want to consider what you want out of your coffee machine. If you’ve always wanted an espresso machine but don’t want to spend the money, the Keurig K-Crema is a good budget-friendly option.</p><h3 class="article-body__section" id="section-keurig-k-crema-review-verdict"><span>Keurig K-Crema review: Verdict</span></h3><p>If you’re looking for an affordable coffee maker that can brew a decent cup of coffee or a shot of creamy espresso, I recommend looking into the Keurig K-Crema. While it doesn’t quite measure up to the expensive espresso machines on the market, it’s available for a fraction of the price, and the resulting coffee is smooth and enjoyable. </p><p>It’s the ideal middle ground for someone who wants to brew coffee drinks at home, but isn’t ready to commit to an espresso machine.</p>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ 12 air purifier and dehumidifier deals to defeat allergies and dry air – up to 54% off ]]></title>
                                                                                                <dc:content><![CDATA[ <p>Your home should be your refuge from the outside world, but it's all too easy for them to become contaminated, especially in the heat of summer. That's where devices like air purifiers and humidifiers come in handy. </p><p>Air purifiers do what the name suggests, by removing pollutants like pollen and dust for cleaner air. Dehumidifiers, on the other hand, remove excess moisture from the air to stop mold and mildew and ensure your home is the right temperature.</p><p>For this article I've rounded up 12 deals on some of the best air purifiers and dehumidifiers on Amazon right now. As always, deals don't last forever, so if there's anything that catches your eye here then make sure to move fast before these items sell out.</p>        <div class="featured_product_block featured_block_hero" data-id="9a695bda-9597-11f1-b41d-9f18ae4b478f">            <a href="https://www.amazon.com/UBBO-Dehumidifiers-Sq-Ft-Dehumidifier-Drain/dp/B0H4PD3FY4/" data-model-name="Ubbo Dehumidifier for Home" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:125.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/sag8Eam82mMt9Zki5Jph9P.jpg" alt="Ubbo 95oz Dehumidifiers for Home, 1000 Sq.ft Dehumidifier With Drain Hose - Auto Shut Off, Timer, Sleep Mode & Drain Hose - 7 Color Light for Bedroom, Bathroom, Rv - White"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>ubbo</div>                                        <div class="featured__title">Ubbo Dehumidifier for Home</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="9a695c52-9597-11f1-ad71-9987d9d6cb96">            <a href="https://www.amazon.com/DREO-Purifier-VERIFIDE-Diffuser-DR-HAP008/dp/B0H699TJC3/" data-model-name="DREO Hepa Air Purifier for Home" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:129.87%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/gqFnXUknXDQCzUpQeQvCJN.jpg" alt="Dreo Hepa Air Purifier for Home, Aham Verifide Air Cleaner for Bedroom, Pets, Smoke, Dust, Pollen & Odors, Pm2.5 Monitor, Auto, Turbo & Quiet Sleep Mode, 4 Speeds, Scent Diffuser, Dr-Hap008 (dreo 338)"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>DREO</div>                                        <div class="featured__title">DREO Hepa Air Purifier for Home</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="9a695cb6-9597-11f1-8c47-a9050cac0742">            <a href="https://www.amazon.com/LEVOIT-Purifier-Allergies-Core-200S/dp/B08FJ678YK/" data-model-name="Levoit Air Purifier" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:116.28%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/ZqDeo8Xz6AEskfrFeD569P.jpg" alt="Levoit Air Purifier for Home Pets Bedroom Dorm Room, Smart & Voice Control"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Levoit</div>                                        <div class="featured__title">Levoit Air Purifier</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="9a695f04-9597-11f1-9a30-3757bc08925a">            <a href="https://www.amazon.com/FreAire-Purifiers-360%C2%B0Intake-Pet-Friendly-HAP606/dp/B0H7RM6L6V" data-model-name="Fre Aire Air Purifier for Large Rooms" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/AeTcgZFhTdwcNUrefipyQR.jpg" alt="Freaire Air Purifiers for Home Large Room Covers Up to 1800ft², Visionair 20db Sleep Mode for Bedroom, With Real-Time Aqi & Pm2.5 Display,360°intake&outlet Air Cleaner Pet-Friendly Hepa,hap606,white"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>FreAire</div>                                        <div class="featured__title">Fre Aire Air Purifier for Large Rooms</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="9a695d1a-9597-11f1-b753-d3c5e5fd8919">            <a href="https://www.amazon.com/KNKA-Purifier-Pre-Filter-Allergies-APH4000/dp/B0FNDG2TNK/" data-model-name="KNKA Air Purifier for Home Bedroom" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/oBkzM9zRkmPXz2hJKVxWPR.jpg" alt="Knka Air Purifiers for Home Bedroom Up to 1,695 Ft² in 1 Hr, Aph4000, White"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>KNKA</div>                                        <div class="featured__title">KNKA Air Purifier for Home Bedroom</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="9a695d7e-9597-11f1-82cf-6b1f3cfdf0b1">            <a href="https://www.amazon.com/34Pint-Dehumidifier-2500Sq-Ft-6-56Ft-Basement/dp/B0GT5NHD5G/" data-model-name="YTE Pro Air Dehumidifier" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/BRTydEZLmS7BQjghsiiRDN.jpg" alt="34pint Dehumidifier for 2500sq.ft With 6.56ft Drain Hose, for Basement"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>YTE PRO</div>                                        <div class="featured__title">YTE Pro Air Dehumidifier</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="9a695de2-9597-11f1-9e7f-0deb346ad0b5">            <a href="https://www.amazon.com/Midea-Pint-Dehumidifier-Basement-Energy/dp/B0GL7QFBJ9/" data-model-name="Midea Dehumidifier for Basement" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:129.87%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/uXBJTyNqRdvXNhi9sqpyXM.jpg" alt="Midea 50 Pint Dehumidifier for Basement, 4,500 Sq. Ft, Energy Star"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Midea</div>                                        <div class="featured__title">Midea Dehumidifier for Basement</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="9a695e46-9597-11f1-b13d-57fcce72a1d1">            <a href="https://www.amazon.com/Bufanli-Sq-Ft-Energy-Dehumidifier-Basement/dp/B0GYR67ZL7/" data-model-name="Bufanli Dehumidifier for Basement" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:125.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/6ey62R4dWcWKgcSxRHJgoN.jpg" alt="Bufanli 6000 Sq.ft Energy Star 2025 Dehumidifier for Basement 100 Pints/d"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Bufanli</div>                                        <div class="featured__title">Bufanli Dehumidifier for Basement</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="9a695ea0-9597-11f1-a312-d12e22610be8">            <a href="https://www.amazon.com/AEOCKY-Dehumidifier-Compressor-Intelligent-Humidistat/dp/B0G1TCG5QJ/" data-model-name="Aeocky Dehumidifier" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/fh4sXK4jwHrXxbYtThAJgM.jpg" alt="Aeocky 5500 Sq.ft 105 Pint/d Energy Star Version 6.0 Dehumidifier for Home"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>AEOCKY</div>                                        <div class="featured__title">Aeocky Dehumidifier</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="9a695f68-9597-11f1-be46-695f2b866162">            <a href="https://www.amazon.com/Waykar-Pints-Energy-Dehumidifier-Large/dp/B0HBQ2HKJH/" data-model-name="Waykar Dehumidifier With Pump for Large Rooms" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:125.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/KQzvoQw2AuPEpoommPxyCP.jpg" alt="Waykar 145 Pints 2025 Energy Star Dehumidifier With Pump for Large Rooms"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Waykar</div>                                        <div class="featured__title">Waykar Dehumidifier With Pump for Large Rooms</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="9a695fc2-9597-11f1-8582-f1c7b3ade04a">            <a href="https://www.amazon.com/Levoit-Smart-Purifiers-Large-600S-P/dp/B09BJMY8HL/" data-model-name="Levoit Smart Air Purifier" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/iDRQPHNnhmuycqCCdxedPR.jpg" alt="Levoit Smart Air Purifiers for Home Large Room Up to 2933 Ft², Core 600s-P"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Levoit</div>                                        <div class="featured__title">Levoit Smart Air Purifier</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="9a696026-9597-11f1-88f6-cdecda901ee9">            <a href="https://www.amazon.com/Dyson-Engineered-Whisper-quiet-Purification-Fully-sealed/dp/B0FJPYSFRH/" data-model-name="Dyson Hushjet Compact Air Purifier" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/AEAJg3CynWnFgKrvZ7LzHP.jpg" alt="Dyson Hushjet Compact Air Purifier, Powerful, Whisper-Quiet (white/silver)"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Dyson</div>                                        <div class="featured__title">Dyson Hushjet Compact Air Purifier</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/home/air-purifiers/12-air-purifier-and-dehumidifier-deals-to-defeat-allergies-and-dry-air-up-to-54-percent-off</link>
                                                                            <description>
                            <![CDATA[ If you're struggling with dry air or pollutants then adding an air purifier or a dehumidifier to your home is a great way to clear the air and get your home feeling just right. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">Q269tDrLqmuqRPTRguB8VV</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/x4L5yb4KXgoHDuFgJedG28-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Tue, 11 Aug 2026 18:00:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Air Purifiers]]></category>
                                                    <category><![CDATA[Home]]></category>
                                                    <category><![CDATA[Home Appliances]]></category>
                                                                                                                    <dc:creator><![CDATA[ Will Salmon ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/HpRWP7Mh9ErgRGoTvZBbBJ.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Will Salmon is Tom&#039;s Guide&#039;s Collections Editor, curating advice on the best products to spend your money on. Will has been writing about tech and entertainment for almost 20 years, including stints as GamesRadar+&#039;s Streaming Editor, editing comics website Newsarama, and writing for lots and lots of magazines.&lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/x4L5yb4KXgoHDuFgJedG28-1280-80.jpg">
                                                            <media:credit><![CDATA[Dyson, DREO, Levoit, FreAire, Ubbo / Edited by Gemini]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[A selection of air purifiers and dehumidifiers.]]></media:description>                                                            <media:text><![CDATA[A selection of air purifiers and dehumidifiers.]]></media:text>
                                <media:title type="plain"><![CDATA[A selection of air purifiers and dehumidifiers.]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/x4L5yb4KXgoHDuFgJedG28-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Your home should be your refuge from the outside world, but it's all too easy for them to become contaminated, especially in the heat of summer. That's where devices like air purifiers and humidifiers come in handy. </p><p>Air purifiers do what the name suggests, by removing pollutants like pollen and dust for cleaner air. Dehumidifiers, on the other hand, remove excess moisture from the air to stop mold and mildew and ensure your home is the right temperature.</p><p>For this article I've rounded up 12 deals on some of the best air purifiers and dehumidifiers on Amazon right now. As always, deals don't last forever, so if there's anything that catches your eye here then make sure to move fast before these items sell out.</p>        <div class="featured_product_block featured_block_hero" data-id="9a695bda-9597-11f1-b41d-9f18ae4b478f">            <a href="https://www.amazon.com/UBBO-Dehumidifiers-Sq-Ft-Dehumidifier-Drain/dp/B0H4PD3FY4/" data-model-name="Ubbo Dehumidifier for Home" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:125.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/sag8Eam82mMt9Zki5Jph9P.jpg" alt="Ubbo 95oz Dehumidifiers for Home, 1000 Sq.ft Dehumidifier With Drain Hose - Auto Shut Off, Timer, Sleep Mode & Drain Hose - 7 Color Light for Bedroom, Bathroom, Rv - White"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>ubbo</div>                                        <div class="featured__title">Ubbo Dehumidifier for Home</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="9a695c52-9597-11f1-ad71-9987d9d6cb96">            <a href="https://www.amazon.com/DREO-Purifier-VERIFIDE-Diffuser-DR-HAP008/dp/B0H699TJC3/" data-model-name="DREO Hepa Air Purifier for Home" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:129.87%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/gqFnXUknXDQCzUpQeQvCJN.jpg" alt="Dreo Hepa Air Purifier for Home, Aham Verifide Air Cleaner for Bedroom, Pets, Smoke, Dust, Pollen & Odors, Pm2.5 Monitor, Auto, Turbo & Quiet Sleep Mode, 4 Speeds, Scent Diffuser, Dr-Hap008 (dreo 338)"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>DREO</div>                                        <div class="featured__title">DREO Hepa Air Purifier for Home</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="9a695cb6-9597-11f1-8c47-a9050cac0742">            <a href="https://www.amazon.com/LEVOIT-Purifier-Allergies-Core-200S/dp/B08FJ678YK/" data-model-name="Levoit Air Purifier" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:116.28%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/ZqDeo8Xz6AEskfrFeD569P.jpg" alt="Levoit Air Purifier for Home Pets Bedroom Dorm Room, Smart & Voice Control"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Levoit</div>                                        <div class="featured__title">Levoit Air Purifier</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="9a695f04-9597-11f1-9a30-3757bc08925a">            <a href="https://www.amazon.com/FreAire-Purifiers-360%C2%B0Intake-Pet-Friendly-HAP606/dp/B0H7RM6L6V" data-model-name="Fre Aire Air Purifier for Large Rooms" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/AeTcgZFhTdwcNUrefipyQR.jpg" alt="Freaire Air Purifiers for Home Large Room Covers Up to 1800ft², Visionair 20db Sleep Mode for Bedroom, With Real-Time Aqi & Pm2.5 Display,360°intake&outlet Air Cleaner Pet-Friendly Hepa,hap606,white"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>FreAire</div>                                        <div class="featured__title">Fre Aire Air Purifier for Large Rooms</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="9a695d1a-9597-11f1-b753-d3c5e5fd8919">            <a href="https://www.amazon.com/KNKA-Purifier-Pre-Filter-Allergies-APH4000/dp/B0FNDG2TNK/" data-model-name="KNKA Air Purifier for Home Bedroom" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/oBkzM9zRkmPXz2hJKVxWPR.jpg" alt="Knka Air Purifiers for Home Bedroom Up to 1,695 Ft² in 1 Hr, Aph4000, White"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>KNKA</div>                                        <div class="featured__title">KNKA Air Purifier for Home Bedroom</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="9a695d7e-9597-11f1-82cf-6b1f3cfdf0b1">            <a href="https://www.amazon.com/34Pint-Dehumidifier-2500Sq-Ft-6-56Ft-Basement/dp/B0GT5NHD5G/" data-model-name="YTE Pro Air Dehumidifier" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/BRTydEZLmS7BQjghsiiRDN.jpg" alt="34pint Dehumidifier for 2500sq.ft With 6.56ft Drain Hose, for Basement"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>YTE PRO</div>                                        <div class="featured__title">YTE Pro Air Dehumidifier</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="9a695de2-9597-11f1-9e7f-0deb346ad0b5">            <a href="https://www.amazon.com/Midea-Pint-Dehumidifier-Basement-Energy/dp/B0GL7QFBJ9/" data-model-name="Midea Dehumidifier for Basement" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:129.87%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/uXBJTyNqRdvXNhi9sqpyXM.jpg" alt="Midea 50 Pint Dehumidifier for Basement, 4,500 Sq. Ft, Energy Star"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Midea</div>                                        <div class="featured__title">Midea Dehumidifier for Basement</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="9a695e46-9597-11f1-b13d-57fcce72a1d1">            <a href="https://www.amazon.com/Bufanli-Sq-Ft-Energy-Dehumidifier-Basement/dp/B0GYR67ZL7/" data-model-name="Bufanli Dehumidifier for Basement" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:125.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/6ey62R4dWcWKgcSxRHJgoN.jpg" alt="Bufanli 6000 Sq.ft Energy Star 2025 Dehumidifier for Basement 100 Pints/d"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Bufanli</div>                                        <div class="featured__title">Bufanli Dehumidifier for Basement</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="9a695ea0-9597-11f1-a312-d12e22610be8">            <a href="https://www.amazon.com/AEOCKY-Dehumidifier-Compressor-Intelligent-Humidistat/dp/B0G1TCG5QJ/" data-model-name="Aeocky Dehumidifier" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/fh4sXK4jwHrXxbYtThAJgM.jpg" alt="Aeocky 5500 Sq.ft 105 Pint/d Energy Star Version 6.0 Dehumidifier for Home"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>AEOCKY</div>                                        <div class="featured__title">Aeocky Dehumidifier</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="9a695f68-9597-11f1-be46-695f2b866162">            <a href="https://www.amazon.com/Waykar-Pints-Energy-Dehumidifier-Large/dp/B0HBQ2HKJH/" data-model-name="Waykar Dehumidifier With Pump for Large Rooms" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:125.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/KQzvoQw2AuPEpoommPxyCP.jpg" alt="Waykar 145 Pints 2025 Energy Star Dehumidifier With Pump for Large Rooms"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Waykar</div>                                        <div class="featured__title">Waykar Dehumidifier With Pump for Large Rooms</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="9a695fc2-9597-11f1-8582-f1c7b3ade04a">            <a href="https://www.amazon.com/Levoit-Smart-Purifiers-Large-600S-P/dp/B09BJMY8HL/" data-model-name="Levoit Smart Air Purifier" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/iDRQPHNnhmuycqCCdxedPR.jpg" alt="Levoit Smart Air Purifiers for Home Large Room Up to 2933 Ft², Core 600s-P"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Levoit</div>                                        <div class="featured__title">Levoit Smart Air Purifier</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="9a696026-9597-11f1-88f6-cdecda901ee9">            <a href="https://www.amazon.com/Dyson-Engineered-Whisper-quiet-Purification-Fully-sealed/dp/B0FJPYSFRH/" data-model-name="Dyson Hushjet Compact Air Purifier" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/AEAJg3CynWnFgKrvZ7LzHP.jpg" alt="Dyson Hushjet Compact Air Purifier, Powerful, Whisper-Quiet (white/silver)"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Dyson</div>                                        <div class="featured__title">Dyson Hushjet Compact Air Purifier</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ Dualit Design Series Kettle review ]]></title>
                                                                                                <dc:content><![CDATA[ <p>As a tea-drinking Brit, I have big opinions on kettles, and the Dualit Design Series Kettle is a good option for most people’s homes. It has an aesthetic stainless steel design which is easy to maintain with regular cleaning. It has good heat retention and is easy and accurate to pour with. </p><p>Unfortunately, though, the window design makes it hard to read the measurements when filling the kettle. The boiling is also a little slow when compared to other kettles. </p><p>To find out more about the kitchen appliance, you can keep reading this full Dualit Design Series Kettle review. </p><h2 class="article-body__section" id="section-dualit-design-series-kettle-review-specs"><span>Dualit Design Series Kettle review: Specs</span></h2><div ><table><tbody><tr><td class="firstcol " ><p><strong>Price</strong></p></td><td  ><p><a href="https://www.amazon.com/Dualit-72955-Design-Kettle-Black/dp/B00UHKSRMG" target="_blank" rel="nofollow">$178</a></p></td></tr><tr><td class="firstcol " ><p><strong>Capacity</strong></p></td><td  ><p>1.5L</p></td></tr><tr><td class="firstcol " ><p><strong>Rated power</strong></p></td><td  ><p>1.5kW</p></td></tr><tr><td class="firstcol " ><p><strong>Exterior material</strong></p></td><td  ><p>Stainless steel</p></td></tr><tr><td class="firstcol " ><p><strong>Dimensions</strong></p></td><td  ><p>9.4 x 8.6 x 5.5 inches</p></td></tr><tr><td class="firstcol " ><p><strong>Weight</strong></p></td><td  ><p>3.2 pounds</p></td></tr><tr><td class="firstcol " ><p><strong>Features</strong></p></td><td  ><p>Interchangeable panels, Boil-dry protection, Pure pour spout</p></td></tr></tbody></table></div><h2 class="article-body__section" id="section-dualit-design-series-kettle-review-price-availability"><span>Dualit Design Series Kettle review: Price & availability</span></h2><p>The Dualit Design Series Kettle is available to purchase from <a href="https://www.amazon.com/Dualit-72955-Design-Kettle-Black/dp/B00UHKSRMG" target="_blank" rel="nofollow">Amazon U.S. for $178</a> or directly from the <a href="https://us.dualit.com/products/design-series-kettle" target="_blank" rel="nofollow">Dualit online store for $179</a>. You can also purchase the kettle in the U.K., where it’s called the <a href="https://www.tomsguide.com/reviews/dualit-architect-kettle">Dualit Architect Kettle</a>. </p><p>The kettle has a stainless steel finish, but you can purchase <a href="https://www.dualit.com/products/architect-kettle-panels" target="_blank" rel="nofollow">interchangeable panels </a>for the bottom section from the Dualit store to make it your own. These include the colors Shadow, Metallic Silver, Copper, Brass, Evergreen and Eucalyptus. </p><p>Dualit also sells the <a href="https://www.tomsguide.com/home/home-appliances/dualit-classic-kettle-review">Classic Kettle</a> for $249, which is more of a fashion statement than a standard kettle. Its curved shape is much more interesting than the Design Series — the irony is not lost on me.</p><p>But you don’t need to spend the best part of $200 for a good kettle. I have also tested the <a href="https://www.tomsguide.com/home/home-appliances/dualit-classic-kettle-review">Cosori Electric Glass Kettle</a>, which, while not as dashing, is a fraction of the price at just $27. And honestly, it does just as good a job as the Design Series Kettle — you just have to be willing to put up with the odd leak while pouring, which isn’t a worry with the Dualit.</p><p>While the Dualit has a Pure pour spout to ensure zero leaks when pouring, if you need even more precision for drinks such as pour-over coffee, you may want to consider a gooseneck kettle such as the <a href="https://www.tomsguide.com/home/home-appliances/fellow-stagg-ekg-kettle-review">Fellow Stagg EKG</a> for $165. If you take your brews seriously, I’d recommend the Fellow over the Dualit.</p><h2 class="article-body__section" id="section-dualit-design-series-kettle-review-design-features"><span>Dualit Design Series Kettle review: Design & features</span></h2><p>The Dualit Design Series Kettle is certainly eye-catching. It measures 9.4 x 8.6 x 5.5 inches, weighs 3.2 pounds, and has a reflective surface that will have you checking out your hair while the water boils. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="vQQ7jxTzikipJHUeGEbBHW" name="Dualit Design Series Kettle" alt="Dualit Design Series Kettle photographed in front of a blue background" src="https://cdn.mos.cms.futurecdn.net/vQQ7jxTzikipJHUeGEbBHW.jpg" mos="" align="middle" fullscreen="" width="1920" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>It can boil a maximum capacity of 1.5 liters, enough for six cups. However, you’ll find yourself playing a guessing game when filling it because of the design and positioning of the measurement window. The window has a fish-eye effect, warping the water as you peer through, and it sits directly in line with the handle, so you need to look around that too. </p><p>The handle extends down most of the body, making it easy to hold. At the top of the handle there’s a button to release the flat, hinged lid. This means you can open it without touching it, but to close it you’ll need to push it down. If you’ve already boiled the kettle once, be wary as this part can get very hot. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="ugUvCUdXy2Q2SLczdobUiW" name="Dualit Design Series Kettle" alt="Dualit Design Series Kettle photographed in front of a blue background" src="https://cdn.mos.cms.futurecdn.net/ugUvCUdXy2Q2SLczdobUiW.jpg" mos="" align="middle" fullscreen="" width="1920" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The power switch is just below the handle at the base. This base is very cohesive with the rest of the kettle — it looks like one whole unit with the kettle on top. It has a three-foot power cord, so it is best set up near a power outlet. If you need to make this shorter, you can store the excess in the base.</p><h2 class="article-body__section" id="section-dualit-design-series-kettle-review-performance"><span>Dualit Design Series Kettle review: Performance </span></h2><p>I have to say, when testing the Dualit Design Series Kettle, I was a little confused. After testing the Dualit Classic Kettle, I was impressed at how fast it boiled the water. It boiled five cups in just two minutes and 35 seconds. The Design Series Kettle took three minutes and 11 seconds — a stark difference. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="3TE8WQrPykucFMwxWgcVwW" name="Dualit Design Series Kettle" alt="Dualit Design Series Kettle photographed in front of a blue background" src="https://cdn.mos.cms.futurecdn.net/3TE8WQrPykucFMwxWgcVwW.jpg" mos="" align="middle" fullscreen="" width="1920" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>All of my testing conditions were the same, so if you want an appliance that won’t have you waiting around all day, spring for the more expensive Classic. You may be spending a little extra, but hey, you’ll get to enjoy life with your fresh brew instead of staring into your lifeless eyes in the kettle’s reflection as the water boils for an extra minute. Just me? Well, as a tea-drinking Brit, by the time I’ve made my daily quota, all of those minutes add up.</p><div ><table><tbody><tr><td class="firstcol " ><p><strong>Capacity</strong></p></td><td  ><p><strong>Boiling time</strong></p></td></tr><tr><td class="firstcol " ><p><strong>2 cups</strong></p></td><td  ><p>1 minute, 35 seconds</p></td></tr><tr><td class="firstcol " ><p><strong>3 cups</strong></p></td><td  ><p>2 minutes, 5 seconds</p></td></tr><tr><td class="firstcol " ><p><strong>4 cups </strong></p></td><td  ><p>2 minutes, 41 seconds</p></td></tr><tr><td class="firstcol " ><p><strong>5 cups </strong></p></td><td  ><p>3 minutes, 11 seconds</p></td></tr><tr><td class="firstcol " ><p><strong>Max</strong></p></td><td  ><p>3 minutes, 53 seconds</p></td></tr></tbody></table></div><p>I measured the temperature of the water immediately after boiling and got a reading of 209.3ºF/98.5ºC. This was very slightly cooler than the 210ºF/99.3ºC reading I got from the Classic Kettle. But the Design Series holds heat pretty well. After an hour, I got a reading of 161.1ºF/71.7ºC. So, if you wanted to reboil the water, you won’t be waiting for the full *checks notes* three minutes and 53 seconds — yikes. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="ipma4RqBU5Rb5HruMitjYW" name="Dualit Design Series Kettle" alt="Dualit Design Series Kettle photographed in front of a blue background" src="https://cdn.mos.cms.futurecdn.net/ipma4RqBU5Rb5HruMitjYW.jpg" mos="" align="middle" fullscreen="" width="1920" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>Pouring with the kettle is a dream. If you’re a little shaky when pouring, I would fully recommend this kettle. I encountered no spillages. And the water went exactly where I needed it to. It can be a little heavy when you fill it to the top, so I only ever filled it about halfway so I could still use it with ease. </p><p>The kettle isn’t too loud either, and gave me a reading of 76dB on the Decibel X app.</p><h2 class="article-body__section" id="section-dualit-design-series-kettle-review-storage-maintenance"><span>Dualit Design Series Kettle review: Storage & maintenance </span></h2><p>The Dualit Design Series is a kettle, and as such, this is a generally straightforward affair. It’s easy to maintain; you’ll just find yourself wiping down the exterior more than your usual kettle given its reflective nature. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="iyrLxfLyPwcSnTSiRmWXuW" name="Dualit Design Series Kettle" alt="Dualit Design Series Kettle photographed in front of a blue background" src="https://cdn.mos.cms.futurecdn.net/iyrLxfLyPwcSnTSiRmWXuW.jpg" mos="" align="middle" fullscreen="" width="1920" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>If you live in a hard water area, you’ll also need to descale the kettle regularly. You can purchase descaling tablets for this or use natural <a href="https://www.tomsguide.com/home/how-to-clean-a-kettle-7-simple-steps">methods such as lemon juice or baking soda</a>. The spout of the kettle also has a removable limescale filter which is easy to remove, clean, and refit. </p><h2 class="article-body__section" id="section-dualit-design-series-kettle-review-verdict"><span>Dualit Design Series Kettle review: Verdict</span></h2><p>The Dualit Design Series Kettle is undeniably good-looking. The stainless steel finish is slick and will fit in with any kitchen. The kettle is also easy to maintain (if you don’t mind wiping it down a lot). It has good heat retention and is very easy to pour with. There were absolutely zero drips thanks to the Pure pour spout. </p><p>Unfortunately, it’s tricky to tell where the water has been filled up to because of the poor window design, and boiling is a little slow. It took a whole minute longer to boil the same volume of water as the Dualit Classic Kettle.</p><p>If sleek looks are your priority, this is a great kettle, but $178 is a lot of money to spend on a kettle that takes so long to boil. </p> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/home/kitchen-dining/dualit-design-series-kettle-review</link>
                                                                            <description>
                            <![CDATA[ The Dualit Design Series Kettle is eye-catching and prevents spills, but you may be waiting a while for it to boil. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">cXwSrBEZW5zGvnAtYzrL3k</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/boLRuFNtDaDzwRwUeNtDAW-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Fri, 07 Aug 2026 15:00:39 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Kitchen & Dining]]></category>
                                                    <category><![CDATA[Home]]></category>
                                                    <category><![CDATA[Home Appliances]]></category>
                                                                                                <author><![CDATA[ ashley.thieme@futurenet.com (Ashley Thieme) ]]></author>                    <dc:creator><![CDATA[ Ashley Thieme ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/3AWovHjApwuNrSGRS6WBcL.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Ashley Thieme is a staff writer on the Reviews team at Tom’s Guide where she tests out the latest tech so you can know what’s going to be worth your time and money. She has a master’s degree in Magazine Journalism and a bachelor’s degree in Journalism, Media and Sociology from Cardiff University. She has bylines in titles including Women’s Health UK, sharing the latest health and wellness news stories, and Virgin Radio UK, providing the latest entertainment news and working on celebrity interviews. She has experience reporting on a variety of topics including music, literature, motorsport, entertainment and health. In previously published work, she has reviewed live music events, books, and wellness products. She values the importance of tech enhancing your life rather than taking over, and as a music fanatic, she is always looking for the best way to listen to new music releases. Discovering the top audio equipment that enhances sound quality and provides optimum comfort is what Ashley does best. In her spare time, Ashley enjoys hitting her reading goals on Goodreads by getting into the latest novels with a cup of tea as well as getting out in the Welsh mountains for a good hike on the weekend.&lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/boLRuFNtDaDzwRwUeNtDAW-1280-80.jpg">
                                                            <media:credit><![CDATA[Tom&#039;s Guide]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Dualit Design Series Kettle photographed in front of a blue background]]></media:description>                                                            <media:text><![CDATA[Dualit Design Series Kettle photographed in front of a blue background]]></media:text>
                                <media:title type="plain"><![CDATA[Dualit Design Series Kettle photographed in front of a blue background]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/boLRuFNtDaDzwRwUeNtDAW-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>As a tea-drinking Brit, I have big opinions on kettles, and the Dualit Design Series Kettle is a good option for most people’s homes. It has an aesthetic stainless steel design which is easy to maintain with regular cleaning. It has good heat retention and is easy and accurate to pour with. </p><p>Unfortunately, though, the window design makes it hard to read the measurements when filling the kettle. The boiling is also a little slow when compared to other kettles. </p><p>To find out more about the kitchen appliance, you can keep reading this full Dualit Design Series Kettle review. </p><h2 class="article-body__section" id="section-dualit-design-series-kettle-review-specs"><span>Dualit Design Series Kettle review: Specs</span></h2><div ><table><tbody><tr><td class="firstcol " ><p><strong>Price</strong></p></td><td  ><p><a href="https://www.amazon.com/Dualit-72955-Design-Kettle-Black/dp/B00UHKSRMG" target="_blank" rel="nofollow">$178</a></p></td></tr><tr><td class="firstcol " ><p><strong>Capacity</strong></p></td><td  ><p>1.5L</p></td></tr><tr><td class="firstcol " ><p><strong>Rated power</strong></p></td><td  ><p>1.5kW</p></td></tr><tr><td class="firstcol " ><p><strong>Exterior material</strong></p></td><td  ><p>Stainless steel</p></td></tr><tr><td class="firstcol " ><p><strong>Dimensions</strong></p></td><td  ><p>9.4 x 8.6 x 5.5 inches</p></td></tr><tr><td class="firstcol " ><p><strong>Weight</strong></p></td><td  ><p>3.2 pounds</p></td></tr><tr><td class="firstcol " ><p><strong>Features</strong></p></td><td  ><p>Interchangeable panels, Boil-dry protection, Pure pour spout</p></td></tr></tbody></table></div><h2 class="article-body__section" id="section-dualit-design-series-kettle-review-price-availability"><span>Dualit Design Series Kettle review: Price & availability</span></h2><p>The Dualit Design Series Kettle is available to purchase from <a href="https://www.amazon.com/Dualit-72955-Design-Kettle-Black/dp/B00UHKSRMG" target="_blank" rel="nofollow">Amazon U.S. for $178</a> or directly from the <a href="https://us.dualit.com/products/design-series-kettle" target="_blank" rel="nofollow">Dualit online store for $179</a>. You can also purchase the kettle in the U.K., where it’s called the <a href="https://www.tomsguide.com/reviews/dualit-architect-kettle">Dualit Architect Kettle</a>. </p><p>The kettle has a stainless steel finish, but you can purchase <a href="https://www.dualit.com/products/architect-kettle-panels" target="_blank" rel="nofollow">interchangeable panels </a>for the bottom section from the Dualit store to make it your own. These include the colors Shadow, Metallic Silver, Copper, Brass, Evergreen and Eucalyptus. </p><p>Dualit also sells the <a href="https://www.tomsguide.com/home/home-appliances/dualit-classic-kettle-review">Classic Kettle</a> for $249, which is more of a fashion statement than a standard kettle. Its curved shape is much more interesting than the Design Series — the irony is not lost on me.</p><p>But you don’t need to spend the best part of $200 for a good kettle. I have also tested the <a href="https://www.tomsguide.com/home/home-appliances/dualit-classic-kettle-review">Cosori Electric Glass Kettle</a>, which, while not as dashing, is a fraction of the price at just $27. And honestly, it does just as good a job as the Design Series Kettle — you just have to be willing to put up with the odd leak while pouring, which isn’t a worry with the Dualit.</p><p>While the Dualit has a Pure pour spout to ensure zero leaks when pouring, if you need even more precision for drinks such as pour-over coffee, you may want to consider a gooseneck kettle such as the <a href="https://www.tomsguide.com/home/home-appliances/fellow-stagg-ekg-kettle-review">Fellow Stagg EKG</a> for $165. If you take your brews seriously, I’d recommend the Fellow over the Dualit.</p><h2 class="article-body__section" id="section-dualit-design-series-kettle-review-design-features"><span>Dualit Design Series Kettle review: Design & features</span></h2><p>The Dualit Design Series Kettle is certainly eye-catching. It measures 9.4 x 8.6 x 5.5 inches, weighs 3.2 pounds, and has a reflective surface that will have you checking out your hair while the water boils. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="vQQ7jxTzikipJHUeGEbBHW" name="Dualit Design Series Kettle" alt="Dualit Design Series Kettle photographed in front of a blue background" src="https://cdn.mos.cms.futurecdn.net/vQQ7jxTzikipJHUeGEbBHW.jpg" mos="" align="middle" fullscreen="" width="1920" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>It can boil a maximum capacity of 1.5 liters, enough for six cups. However, you’ll find yourself playing a guessing game when filling it because of the design and positioning of the measurement window. The window has a fish-eye effect, warping the water as you peer through, and it sits directly in line with the handle, so you need to look around that too. </p><p>The handle extends down most of the body, making it easy to hold. At the top of the handle there’s a button to release the flat, hinged lid. This means you can open it without touching it, but to close it you’ll need to push it down. If you’ve already boiled the kettle once, be wary as this part can get very hot. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="ugUvCUdXy2Q2SLczdobUiW" name="Dualit Design Series Kettle" alt="Dualit Design Series Kettle photographed in front of a blue background" src="https://cdn.mos.cms.futurecdn.net/ugUvCUdXy2Q2SLczdobUiW.jpg" mos="" align="middle" fullscreen="" width="1920" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The power switch is just below the handle at the base. This base is very cohesive with the rest of the kettle — it looks like one whole unit with the kettle on top. It has a three-foot power cord, so it is best set up near a power outlet. If you need to make this shorter, you can store the excess in the base.</p><h2 class="article-body__section" id="section-dualit-design-series-kettle-review-performance"><span>Dualit Design Series Kettle review: Performance </span></h2><p>I have to say, when testing the Dualit Design Series Kettle, I was a little confused. After testing the Dualit Classic Kettle, I was impressed at how fast it boiled the water. It boiled five cups in just two minutes and 35 seconds. The Design Series Kettle took three minutes and 11 seconds — a stark difference. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="3TE8WQrPykucFMwxWgcVwW" name="Dualit Design Series Kettle" alt="Dualit Design Series Kettle photographed in front of a blue background" src="https://cdn.mos.cms.futurecdn.net/3TE8WQrPykucFMwxWgcVwW.jpg" mos="" align="middle" fullscreen="" width="1920" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>All of my testing conditions were the same, so if you want an appliance that won’t have you waiting around all day, spring for the more expensive Classic. You may be spending a little extra, but hey, you’ll get to enjoy life with your fresh brew instead of staring into your lifeless eyes in the kettle’s reflection as the water boils for an extra minute. Just me? Well, as a tea-drinking Brit, by the time I’ve made my daily quota, all of those minutes add up.</p><div ><table><tbody><tr><td class="firstcol " ><p><strong>Capacity</strong></p></td><td  ><p><strong>Boiling time</strong></p></td></tr><tr><td class="firstcol " ><p><strong>2 cups</strong></p></td><td  ><p>1 minute, 35 seconds</p></td></tr><tr><td class="firstcol " ><p><strong>3 cups</strong></p></td><td  ><p>2 minutes, 5 seconds</p></td></tr><tr><td class="firstcol " ><p><strong>4 cups </strong></p></td><td  ><p>2 minutes, 41 seconds</p></td></tr><tr><td class="firstcol " ><p><strong>5 cups </strong></p></td><td  ><p>3 minutes, 11 seconds</p></td></tr><tr><td class="firstcol " ><p><strong>Max</strong></p></td><td  ><p>3 minutes, 53 seconds</p></td></tr></tbody></table></div><p>I measured the temperature of the water immediately after boiling and got a reading of 209.3ºF/98.5ºC. This was very slightly cooler than the 210ºF/99.3ºC reading I got from the Classic Kettle. But the Design Series holds heat pretty well. After an hour, I got a reading of 161.1ºF/71.7ºC. So, if you wanted to reboil the water, you won’t be waiting for the full *checks notes* three minutes and 53 seconds — yikes. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="ipma4RqBU5Rb5HruMitjYW" name="Dualit Design Series Kettle" alt="Dualit Design Series Kettle photographed in front of a blue background" src="https://cdn.mos.cms.futurecdn.net/ipma4RqBU5Rb5HruMitjYW.jpg" mos="" align="middle" fullscreen="" width="1920" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>Pouring with the kettle is a dream. If you’re a little shaky when pouring, I would fully recommend this kettle. I encountered no spillages. And the water went exactly where I needed it to. It can be a little heavy when you fill it to the top, so I only ever filled it about halfway so I could still use it with ease. </p><p>The kettle isn’t too loud either, and gave me a reading of 76dB on the Decibel X app.</p><h2 class="article-body__section" id="section-dualit-design-series-kettle-review-storage-maintenance"><span>Dualit Design Series Kettle review: Storage & maintenance </span></h2><p>The Dualit Design Series is a kettle, and as such, this is a generally straightforward affair. It’s easy to maintain; you’ll just find yourself wiping down the exterior more than your usual kettle given its reflective nature. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="iyrLxfLyPwcSnTSiRmWXuW" name="Dualit Design Series Kettle" alt="Dualit Design Series Kettle photographed in front of a blue background" src="https://cdn.mos.cms.futurecdn.net/iyrLxfLyPwcSnTSiRmWXuW.jpg" mos="" align="middle" fullscreen="" width="1920" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>If you live in a hard water area, you’ll also need to descale the kettle regularly. You can purchase descaling tablets for this or use natural <a href="https://www.tomsguide.com/home/how-to-clean-a-kettle-7-simple-steps">methods such as lemon juice or baking soda</a>. The spout of the kettle also has a removable limescale filter which is easy to remove, clean, and refit. </p><h2 class="article-body__section" id="section-dualit-design-series-kettle-review-verdict"><span>Dualit Design Series Kettle review: Verdict</span></h2><p>The Dualit Design Series Kettle is undeniably good-looking. The stainless steel finish is slick and will fit in with any kitchen. The kettle is also easy to maintain (if you don’t mind wiping it down a lot). It has good heat retention and is very easy to pour with. There were absolutely zero drips thanks to the Pure pour spout. </p><p>Unfortunately, it’s tricky to tell where the water has been filled up to because of the poor window design, and boiling is a little slow. It took a whole minute longer to boil the same volume of water as the Dualit Classic Kettle.</p><p>If sleek looks are your priority, this is a great kettle, but $178 is a lot of money to spend on a kettle that takes so long to boil. </p>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ I tested one of the coolest-looking drip coffee makers in the world — and it's not just a pretty face ]]></title>
                                                                                                <dc:content><![CDATA[ <p>The Smeg Retro Coffee Maker is certainly gorgeous enough to be on <em>the</em> catwalk model of coffee machines. As with seemingly everything else made by the Italian coffee brand, the Retro (DCF02) looks sleek, sophisticated, and effortlessly cool. </p><p>But is appearance enough to make it one of the <a href="https://www.tomsguide.com/best-picks/best-coffee-makers">best coffee maker</a>s? Thankfully, this time, the Smeg Retro Coffee Maker isn’t style over substance. I wasn’t a huge fan of the <a href="https://www.tomsguide.com/home/home-appliances/smeg-espresso-machine-review">Smeg ECF02’s </a>performance despite a premium appearance — but the Retro Coffee Maker can walk the walk <em>and</em> talk the talk. It brews clean-tasting, balanced coffee with minimal silt and zero bitterness. And all you have to do is press one button. </p><p>So, want to find out more about this gorgeous coffee machine? Spoiler alert: it’s an absolute treat. To get the full story, keep reading this Smeg Retro Coffee Maker review. </p><h2 class="article-body__section" id="section-smeg-retro-coffee-maker-specs"><span>Smeg Retro Coffee Maker: Specs</span></h2><div ><table><tbody><tr><td class="firstcol " ><p><strong>Price</strong></p></td><td  ><p><a href="https://www.crateandbarrel.com/smeg-matte-mocha-drip-coffee-maker/s644835" target="_blank" rel="nofollow">$259</a> / <a href="https://www.johnlewis.com/smeg-dcf02-drip-filter-coffee-machine/navy-blue/p5176025" target="_blank" rel="nofollow">£199-£219</a></p></td></tr><tr><td class="firstcol " ><p><strong>Weight</strong></p></td><td  ><p>7.5 pounds</p></td></tr><tr><td class="firstcol " ><p><strong>Dimensions</strong></p></td><td  ><p>10 x 10 x 14 inches</p></td></tr><tr><td class="firstcol " ><p><strong>Filters</strong></p></td><td  ><p>Permanent / #4</p></td></tr><tr><td class="firstcol " ><p><strong>Accessories</strong></p></td><td  ><p>Filter, scoop</p></td></tr><tr><td class="firstcol " ><p><strong>Capacity</strong></p></td><td  ><p>47.25 fluid ounces</p></td></tr><tr><td class="firstcol " ><p><strong>Colors/Materials</strong></p></td><td  ><p>Moonlight, cream, navy, black, pastel blue, pastel green, silver, gray, red, white / Stainless steel, plastic, chrome, glass</p></td></tr></tbody></table></div><h2 class="article-body__section" id="section-smeg-retro-coffee-maker-review-price-availability"><span>Smeg Retro Coffee Maker review: Price & availability</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1919px;"><p class="vanilla-image-block" style="padding-top:56.28%;"><img id="iqDpK6KWDxuTaxrm2BmEM6" name="Smeg_Drip_4" alt="the smeg retro coffee maker photographed against the blue tom's guide background" src="https://cdn.mos.cms.futurecdn.net/iqDpK6KWDxuTaxrm2BmEM6.jpg" mos="" align="middle" fullscreen="" width="1919" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The Smeg Retro Coffee Maker is <a href="https://www.crateandbarrel.com/smeg-matte-mocha-drip-coffee-maker/s644835" target="_blank" rel="nofollow">$259 from Crate&Barrel in the U.S.</a>, regardless of color, and <a href="https://www.johnlewis.com/smeg-dcf02-drip-filter-coffee-machine/navy-blue/p5176025" target="_blank" rel="nofollow">£199-£219 from John Lewis in the U.K</a><a href="https://www.johnlewis.com/smeg-dcf02-drip-filter-coffee-machine/navy-blue/p5176025" target="_blank">.</a> The Moonlight colorway, the model I tested, runs for £20 more than the standard colors: cream, navy, black, pastel blue, pastel green, silver, gray, red, and white. </p><p>In the U.S., though, Moonlight is the usual price of $259. Functionally, the “standard” colors and Moonlight are the same, so if you’re looking to save as much as possible, I’d go for the older colors. But isn’t the Moonlight oh so pretty? Just look at it!</p><p>In keeping with Smeg’s back catalogue, the Retro Coffee Maker is pretty pricey for what it is. This is a common theme with Smeg, though: you pay a premium for the style. </p><p>For $369, you could get the <a href="https://www.tomsguide.com/home/coffee-makers/technivorm-moccamaster-kgbv-select-review">Moccamaster KGBV Select</a>, which has a 5-year warranty and lifetime repairs. For $250, you could get the single-serve <a href="https://www.tomsguide.com/home/home-appliances/moccamaster-cup-one-review">Moccamaster Cup-One</a>, complete with the same after-purchase benefits.</p><p>I’ve also tested the SCA-accredited $329 <a href="https://www.tomsguide.com/home/coffee-makers/breville-luxe-brewer-review">Breville Luxe Brewer</a> and the low-plastic $319 Aarke Coffee Maker, alongside the low-plastic Ratio Four ($259), an automated pour-over. Although it’s not available in the U.K., so I haven’t tested it, I can assure you that the budget $90 Ninja 12-Cup Drip Brewer is a crowd pleaser in Tom’s Guide’s New York office. </p><p>Bonavita and Braun have also mastered the budget drip coffee maker: <a href="https://www.amazon.com/Bonavita-Connoisseur-One-Touch-Featuring-BV1901TS/dp/B076PFMRGX" target="_blank" rel="nofollow">Bonavita’s SCA-accredited 8-Cup Brewer</a> is just $189, the<a href="https://www.amazon.com/Bonavita-One-Touch-Featuring-Thermal-BV1500TS/dp/B00SK5IXPQ" target="_blank" rel="nofollow"> 5-Cup is even cheaper, at $149</a>. The <a href="https://www.amazon.com/Braun-KF7150BK-Sense-Coffee-Maker/dp/B01EA5ZHIA" target="_blank" rel="nofollow">12-Cup Braun Drip Coffee Maker</a> is $129. This is where I’d like to see the Smeg Retro Coffee Maker’s price due to its lack of SCA accreditation and mostly plastic build. </p><h2 class="article-body__section" id="section-smeg-retro-coffee-maker-review-design"><span>Smeg Retro Coffee Maker review: Design</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.20%;"><img id="oHksEmdhmWNcHy4uq9DUW6" name="Smeg_Drip_10" alt="the smeg retro coffee maker photographed against the blue tom's guide background" src="https://cdn.mos.cms.futurecdn.net/oHksEmdhmWNcHy4uq9DUW6.jpg" mos="" align="middle" fullscreen="" width="1920" height="1079" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>As with everything else under Smeg’s belt, the Retro Coffee Maker looks really cool. Per the name, it’s certainly retro, and would look at home in either a diner on a cheesy high school drama (I’m thinking Riverdale, anyone?), or in any sleek, sophisticated home kitchen. </p><p>I tested the gorgeous Moonlight shade, which has the same muted gray buttons as the rest of the color line. The buttons control power, brew amount, auto start, and flavor intensity. The lever is solely for adjusting the machine’s time display and the auto start timer. At first, I thought this was an unnecessary use of space, but it’s actually really fun to use. </p><p>It’s worth noting that the Retro Coffee Maker is bigger than it looks online: it’s 14 inches tall, 10 inches wide, and 10 inches deep. If you’ve got a small kitchen, I’d measure your space before purchasing. Comparatively, the Moccamaster KGBV Select is 6.5 x 12.8 x 14 inches, the Breville Luxe Brewer is 14.7 x 7 x 16.1 inches, and the Ninja 12-Cup is 8 x 10 x 14 inches. The Moccamaster is the narrowest, but it’s longer and the same height as the Smeg. </p><p>As for accessories, the Retro Coffee Maker comes with just two: a scoop and a permanent mesh filter. You can use single-use #4 conical filters, but I tested with the reusable filter as provided.</p><h2 class="article-body__section" id="section-smeg-retro-coffee-maker-review-performance"><span>Smeg Retro Coffee Maker review: Performance</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1919px;"><p class="vanilla-image-block" style="padding-top:56.28%;"><img id="XzLkjE5GhYvseJrd5rQfC6" name="Smeg_Drip_5" alt="the smeg retro coffee maker photographed against the blue tom's guide background" src="https://cdn.mos.cms.futurecdn.net/XzLkjE5GhYvseJrd5rQfC6.jpg" mos="" align="middle" fullscreen="" width="1919" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The Smeg Retro Coffee Maker is supremely easy to use. All you have to do is put your coffee in the filter, add your water, and press go. </p><p>Smeg recommends a recipe of one scoop per cup, so if you’re making a full batch, that would be 10 scoops. A half-batch requires 4 scoops. Of course, you can adjust this recipe to your tastes. </p><p>A full batch sometimes took seven minutes, sometimes eight, and a half batch took around three minutes. This is a little slower than the Moccamaster KGBV Select, but not by much at all. </p><p>The water tank isn’t removable, so I poured water in using the carafe. I have two qualms with this: one, the carafe is angled in such a way that it’s tricky to get the final dregs of water, and two, the water tank opening is on the right side, so if you’re left-handed like me, this will pose an issue. Alas, this will only irritate 11% of the population, so it’s not enough to knock half a star off (but justice for us devil-worshippers [for legal reasons, this is a joke]). </p><p>Here’s how I made delicious coffee on the Smeg Retro Coffee Maker. </p><h2 id="my-go-to-smeg-retro-coffee-maker-routine">My go-to Smeg Retro Coffee Maker routine </h2><p>Smeg recommends one scoop per cup. One scoop was between 8.5-10 grams depending on if I levelled it or not. </p><p>I used 87g of coffee (10 level scoops) for a full carafe, which works out to a ratio of 1:16.</p><ol start="1"><li>Fill the water tank to max.</li><li>Grind your coffee to a medium size. I used my Mazzer Philos, the best grinder in the world.</li><li>Put your desired amount of coffee in the filter. I used 87g for a full batch, a 1:16 ratio.</li><li>Select your desired intensity level. I used level 1.</li><li>Press the power button to start your brew.</li><li>Wait 7-8 minutes!</li></ol><p>And that’s it! </p><p>Here’s a photo of the grounds after brewing. As you can see, there’s very little funnelling here.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:4345px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="yFZVXxTCR72NySqvbNjdsa" name="smeg coffee maker funnelling" alt="a photo of the smeg retro coffee maker after brewing showing coffee grounds" src="https://cdn.mos.cms.futurecdn.net/yFZVXxTCR72NySqvbNjdsa.png" mos="" align="middle" fullscreen="" width="4345" height="2444" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Erin Bashford)</span></figcaption></figure><p>The Retro Coffee Maker brews clean, fresh-tasting coffee. You can obviously adjust the intensity using either the on-machine button or increasing the coffee dosage (or grinding finer), but the out-of-the-box flavor is great. </p><h2 class="article-body__section" id="section-smeg-retro-coffee-maker-review-storage-maintenance"><span>Smeg Retro Coffee Maker review: Storage & maintenance</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1919px;"><p class="vanilla-image-block" style="padding-top:56.28%;"><img id="y7hVofnDRNZuY72Btk6aP6" name="Smeg_Drip_8" alt="the smeg retro coffee maker photographed against the blue tom's guide background" src="https://cdn.mos.cms.futurecdn.net/y7hVofnDRNZuY72Btk6aP6.jpg" mos="" align="middle" fullscreen="" width="1919" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>I was pleasantly surprised to see the Smeg Retro Coffee Maker come with a 2-year warranty. This is better than Ninja’s 1-year warranty, but still not comparable to Moccamaster’s 5-year warranty (and lifetime repairs) or Simply Good Coffee’s new 5-year standard warranty. </p><p>To keep your Retro Coffee Maker lasting as long as possible, do not put the carafe in the dishwasher. I put the mesh filter in the dishwasher and it survived, but I’d recommend only washing by hand. </p><p>As mentioned earlier, the Retro Coffee Maker is pretty large — so make sure you’ve got enough counter space before buying!</p><h2 class="article-body__section" id="section-smeg-retro-coffee-maker-review-how-does-it-compare"><span>Smeg Retro Coffee Maker review: How does it compare? </span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.20%;"><img id="j9BEpPLzE92N3QSVchziJ6" name="Smeg_Drip_2" alt="the smeg retro coffee maker photographed against the blue tom's guide background" src="https://cdn.mos.cms.futurecdn.net/j9BEpPLzE92N3QSVchziJ6.jpg" mos="" align="middle" fullscreen="" width="1920" height="1079" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The Smeg Retro Coffee Maker looks just as cool as the industrial-chic Moccamaster, so I’d recommend either of these brands if you’re after that vintage vibe. I’d also put Simply Good Coffee’s Plastic-Free Brewer in this category — it looks sleek and effortlessly cool. </p><p>The Retro Coffee Maker isn’t as fast as the Breville Luxe Brewer, but it is $70 cheaper, so you win some, you lose some. It’s also considerably cheaper than the $319 Aarke Coffee Maker — but the Aarke is low-plastic, which is what a lot of consumers want these days. </p><p><em>But</em>, and that’s a relatively big but, I would say the Smeg Retro Coffee Maker is a touch overpriced for what it is. The Moccamaster is $369 because it has lifetime repairs and is SCA-accredited. The SGC Plastic-Free Brewer is $469 because it’s made almost entirely from glass and metal. The Breville Luxe Brewer is $329 because it brews in three minutes. </p><p>As mentioned earlier, I’d like to see Smeg’s pricing fall more in line with Ninja’s, Bonavita’s, and Braun (or get SCA accreditation or improve the materials/after-purchase care). Ninja’s 12-Cup Drip Brewer is just $89, and Bonavita’s SCA-accredited 8-Cup Brewer is just $189. The 5-Cup is even cheaper — $149. The 12-Cup Braun Drip Coffee Maker is $129. </p><p>The Smeg doesn’t really have any USPs other than looking really cool. While I do objectively like this coffee maker, I’ll be the first person to admit it falls into Smeg’s main pitfall: it’s expensive for what it is.</p><h2 class="article-body__section" id="section-smeg-retro-coffee-maker-review-verdict"><span> Smeg Retro Coffee Maker review: Verdict</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1919px;"><p class="vanilla-image-block" style="padding-top:56.28%;"><img id="HKZn7AcLGQso6zcD35TJY6" name="Smeg_Drip_9" alt="the smeg retro coffee maker photographed against the blue tom's guide background" src="https://cdn.mos.cms.futurecdn.net/HKZn7AcLGQso6zcD35TJY6.jpg" mos="" align="middle" fullscreen="" width="1919" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>Despite being a little pricey for what it is, the Smeg Retro Coffee Maker gets a big thumbs up from me. I thoroughly enjoyed testing this machine and would recommend it for people who value style and ease of use.</p><p>Yes, it’s expensive considering its plastic build and lack of SCA accreditation, and no, it doesn’t have any unique features like a lifetime repairs warranty or an SCA accreditation. The auto-start timer is cool, but the $89 Ninja 12-Cup has this, too. However, just look at it. Doesn’t that speak for itself? </p><p>So, if you want a kitchen centrepiece that’ll have guests going “Ooh” and “Aah” and “Where did you get that from?” then you’ll get on just fine with the Smeg Retro Coffee Maker. It’s literally plug-and-play, and tastes as good as it looks.</p> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/home/coffee-makers/smeg-retro-coffee-maker-review</link>
                                                                            <description>
                            <![CDATA[ The Smeg Retro Coffee Maker brews clean, delicious coffee with a single press of a button, and looks delightfully cool while doing so, too. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">S8FUcK3E8VNEZckVuHdGLd</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/SvTaZ7daV4Lbis8RvtwDU6-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Fri, 07 Aug 2026 14:58:19 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Coffee Makers]]></category>
                                                    <category><![CDATA[Home]]></category>
                                                    <category><![CDATA[Home Appliances]]></category>
                                                    <category><![CDATA[Kitchen & Dining]]></category>
                                                                                                <author><![CDATA[ erin.bashford@futurenet.com (Erin Bashford) ]]></author>                    <dc:creator><![CDATA[ Erin Bashford ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/rLvJvJVZx43hEzSsJy3BpL.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Erin Bashford is a senior reviews writer at Tom’s Guide. She has a Master’s in Broadcast and Digital Journalism from the University of East Anglia and 7 years of experience reviewing music and events for various publications. She has edited publications such as Outline Magazine’s Guide to Norwich, and she has written for a number of music magazines and websites such as Clash Magazine, Outline Magazine and Dork Magazine. She has a strong interest in audio gear and the music world. &lt;/p&gt;&lt;p&gt;As an ex-barista, Erin is passionate about coffee tech. She also loves finding the best cooking hacks and kitchen appliances, including her beloved Instant Pot. &lt;/p&gt;&lt;p&gt;In her spare time, you can find her reading, practising yoga, hiking, writing fantasy novels, or stressing over NYT Games.&lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/SvTaZ7daV4Lbis8RvtwDU6-1280-80.jpg">
                                                            <media:credit><![CDATA[Tom&#039;s Guide]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[the smeg retro coffee maker photographed against the blue tom&#039;s guide background]]></media:description>                                                            <media:text><![CDATA[the smeg retro coffee maker photographed against the blue tom&#039;s guide background]]></media:text>
                                <media:title type="plain"><![CDATA[the smeg retro coffee maker photographed against the blue tom&#039;s guide background]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/SvTaZ7daV4Lbis8RvtwDU6-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>The Smeg Retro Coffee Maker is certainly gorgeous enough to be on <em>the</em> catwalk model of coffee machines. As with seemingly everything else made by the Italian coffee brand, the Retro (DCF02) looks sleek, sophisticated, and effortlessly cool. </p><p>But is appearance enough to make it one of the <a href="https://www.tomsguide.com/best-picks/best-coffee-makers">best coffee maker</a>s? Thankfully, this time, the Smeg Retro Coffee Maker isn’t style over substance. I wasn’t a huge fan of the <a href="https://www.tomsguide.com/home/home-appliances/smeg-espresso-machine-review">Smeg ECF02’s </a>performance despite a premium appearance — but the Retro Coffee Maker can walk the walk <em>and</em> talk the talk. It brews clean-tasting, balanced coffee with minimal silt and zero bitterness. And all you have to do is press one button. </p><p>So, want to find out more about this gorgeous coffee machine? Spoiler alert: it’s an absolute treat. To get the full story, keep reading this Smeg Retro Coffee Maker review. </p><h2 class="article-body__section" id="section-smeg-retro-coffee-maker-specs"><span>Smeg Retro Coffee Maker: Specs</span></h2><div ><table><tbody><tr><td class="firstcol " ><p><strong>Price</strong></p></td><td  ><p><a href="https://www.crateandbarrel.com/smeg-matte-mocha-drip-coffee-maker/s644835" target="_blank" rel="nofollow">$259</a> / <a href="https://www.johnlewis.com/smeg-dcf02-drip-filter-coffee-machine/navy-blue/p5176025" target="_blank" rel="nofollow">£199-£219</a></p></td></tr><tr><td class="firstcol " ><p><strong>Weight</strong></p></td><td  ><p>7.5 pounds</p></td></tr><tr><td class="firstcol " ><p><strong>Dimensions</strong></p></td><td  ><p>10 x 10 x 14 inches</p></td></tr><tr><td class="firstcol " ><p><strong>Filters</strong></p></td><td  ><p>Permanent / #4</p></td></tr><tr><td class="firstcol " ><p><strong>Accessories</strong></p></td><td  ><p>Filter, scoop</p></td></tr><tr><td class="firstcol " ><p><strong>Capacity</strong></p></td><td  ><p>47.25 fluid ounces</p></td></tr><tr><td class="firstcol " ><p><strong>Colors/Materials</strong></p></td><td  ><p>Moonlight, cream, navy, black, pastel blue, pastel green, silver, gray, red, white / Stainless steel, plastic, chrome, glass</p></td></tr></tbody></table></div><h2 class="article-body__section" id="section-smeg-retro-coffee-maker-review-price-availability"><span>Smeg Retro Coffee Maker review: Price & availability</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1919px;"><p class="vanilla-image-block" style="padding-top:56.28%;"><img id="iqDpK6KWDxuTaxrm2BmEM6" name="Smeg_Drip_4" alt="the smeg retro coffee maker photographed against the blue tom's guide background" src="https://cdn.mos.cms.futurecdn.net/iqDpK6KWDxuTaxrm2BmEM6.jpg" mos="" align="middle" fullscreen="" width="1919" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The Smeg Retro Coffee Maker is <a href="https://www.crateandbarrel.com/smeg-matte-mocha-drip-coffee-maker/s644835" target="_blank" rel="nofollow">$259 from Crate&Barrel in the U.S.</a>, regardless of color, and <a href="https://www.johnlewis.com/smeg-dcf02-drip-filter-coffee-machine/navy-blue/p5176025" target="_blank" rel="nofollow">£199-£219 from John Lewis in the U.K</a><a href="https://www.johnlewis.com/smeg-dcf02-drip-filter-coffee-machine/navy-blue/p5176025" target="_blank">.</a> The Moonlight colorway, the model I tested, runs for £20 more than the standard colors: cream, navy, black, pastel blue, pastel green, silver, gray, red, and white. </p><p>In the U.S., though, Moonlight is the usual price of $259. Functionally, the “standard” colors and Moonlight are the same, so if you’re looking to save as much as possible, I’d go for the older colors. But isn’t the Moonlight oh so pretty? Just look at it!</p><p>In keeping with Smeg’s back catalogue, the Retro Coffee Maker is pretty pricey for what it is. This is a common theme with Smeg, though: you pay a premium for the style. </p><p>For $369, you could get the <a href="https://www.tomsguide.com/home/coffee-makers/technivorm-moccamaster-kgbv-select-review">Moccamaster KGBV Select</a>, which has a 5-year warranty and lifetime repairs. For $250, you could get the single-serve <a href="https://www.tomsguide.com/home/home-appliances/moccamaster-cup-one-review">Moccamaster Cup-One</a>, complete with the same after-purchase benefits.</p><p>I’ve also tested the SCA-accredited $329 <a href="https://www.tomsguide.com/home/coffee-makers/breville-luxe-brewer-review">Breville Luxe Brewer</a> and the low-plastic $319 Aarke Coffee Maker, alongside the low-plastic Ratio Four ($259), an automated pour-over. Although it’s not available in the U.K., so I haven’t tested it, I can assure you that the budget $90 Ninja 12-Cup Drip Brewer is a crowd pleaser in Tom’s Guide’s New York office. </p><p>Bonavita and Braun have also mastered the budget drip coffee maker: <a href="https://www.amazon.com/Bonavita-Connoisseur-One-Touch-Featuring-BV1901TS/dp/B076PFMRGX" target="_blank" rel="nofollow">Bonavita’s SCA-accredited 8-Cup Brewer</a> is just $189, the<a href="https://www.amazon.com/Bonavita-One-Touch-Featuring-Thermal-BV1500TS/dp/B00SK5IXPQ" target="_blank" rel="nofollow"> 5-Cup is even cheaper, at $149</a>. The <a href="https://www.amazon.com/Braun-KF7150BK-Sense-Coffee-Maker/dp/B01EA5ZHIA" target="_blank" rel="nofollow">12-Cup Braun Drip Coffee Maker</a> is $129. This is where I’d like to see the Smeg Retro Coffee Maker’s price due to its lack of SCA accreditation and mostly plastic build. </p><h2 class="article-body__section" id="section-smeg-retro-coffee-maker-review-design"><span>Smeg Retro Coffee Maker review: Design</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.20%;"><img id="oHksEmdhmWNcHy4uq9DUW6" name="Smeg_Drip_10" alt="the smeg retro coffee maker photographed against the blue tom's guide background" src="https://cdn.mos.cms.futurecdn.net/oHksEmdhmWNcHy4uq9DUW6.jpg" mos="" align="middle" fullscreen="" width="1920" height="1079" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>As with everything else under Smeg’s belt, the Retro Coffee Maker looks really cool. Per the name, it’s certainly retro, and would look at home in either a diner on a cheesy high school drama (I’m thinking Riverdale, anyone?), or in any sleek, sophisticated home kitchen. </p><p>I tested the gorgeous Moonlight shade, which has the same muted gray buttons as the rest of the color line. The buttons control power, brew amount, auto start, and flavor intensity. The lever is solely for adjusting the machine’s time display and the auto start timer. At first, I thought this was an unnecessary use of space, but it’s actually really fun to use. </p><p>It’s worth noting that the Retro Coffee Maker is bigger than it looks online: it’s 14 inches tall, 10 inches wide, and 10 inches deep. If you’ve got a small kitchen, I’d measure your space before purchasing. Comparatively, the Moccamaster KGBV Select is 6.5 x 12.8 x 14 inches, the Breville Luxe Brewer is 14.7 x 7 x 16.1 inches, and the Ninja 12-Cup is 8 x 10 x 14 inches. The Moccamaster is the narrowest, but it’s longer and the same height as the Smeg. </p><p>As for accessories, the Retro Coffee Maker comes with just two: a scoop and a permanent mesh filter. You can use single-use #4 conical filters, but I tested with the reusable filter as provided.</p><h2 class="article-body__section" id="section-smeg-retro-coffee-maker-review-performance"><span>Smeg Retro Coffee Maker review: Performance</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1919px;"><p class="vanilla-image-block" style="padding-top:56.28%;"><img id="XzLkjE5GhYvseJrd5rQfC6" name="Smeg_Drip_5" alt="the smeg retro coffee maker photographed against the blue tom's guide background" src="https://cdn.mos.cms.futurecdn.net/XzLkjE5GhYvseJrd5rQfC6.jpg" mos="" align="middle" fullscreen="" width="1919" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The Smeg Retro Coffee Maker is supremely easy to use. All you have to do is put your coffee in the filter, add your water, and press go. </p><p>Smeg recommends a recipe of one scoop per cup, so if you’re making a full batch, that would be 10 scoops. A half-batch requires 4 scoops. Of course, you can adjust this recipe to your tastes. </p><p>A full batch sometimes took seven minutes, sometimes eight, and a half batch took around three minutes. This is a little slower than the Moccamaster KGBV Select, but not by much at all. </p><p>The water tank isn’t removable, so I poured water in using the carafe. I have two qualms with this: one, the carafe is angled in such a way that it’s tricky to get the final dregs of water, and two, the water tank opening is on the right side, so if you’re left-handed like me, this will pose an issue. Alas, this will only irritate 11% of the population, so it’s not enough to knock half a star off (but justice for us devil-worshippers [for legal reasons, this is a joke]). </p><p>Here’s how I made delicious coffee on the Smeg Retro Coffee Maker. </p><h2 id="my-go-to-smeg-retro-coffee-maker-routine">My go-to Smeg Retro Coffee Maker routine </h2><p>Smeg recommends one scoop per cup. One scoop was between 8.5-10 grams depending on if I levelled it or not. </p><p>I used 87g of coffee (10 level scoops) for a full carafe, which works out to a ratio of 1:16.</p><ol start="1"><li>Fill the water tank to max.</li><li>Grind your coffee to a medium size. I used my Mazzer Philos, the best grinder in the world.</li><li>Put your desired amount of coffee in the filter. I used 87g for a full batch, a 1:16 ratio.</li><li>Select your desired intensity level. I used level 1.</li><li>Press the power button to start your brew.</li><li>Wait 7-8 minutes!</li></ol><p>And that’s it! </p><p>Here’s a photo of the grounds after brewing. As you can see, there’s very little funnelling here.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:4345px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="yFZVXxTCR72NySqvbNjdsa" name="smeg coffee maker funnelling" alt="a photo of the smeg retro coffee maker after brewing showing coffee grounds" src="https://cdn.mos.cms.futurecdn.net/yFZVXxTCR72NySqvbNjdsa.png" mos="" align="middle" fullscreen="" width="4345" height="2444" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Erin Bashford)</span></figcaption></figure><p>The Retro Coffee Maker brews clean, fresh-tasting coffee. You can obviously adjust the intensity using either the on-machine button or increasing the coffee dosage (or grinding finer), but the out-of-the-box flavor is great. </p><h2 class="article-body__section" id="section-smeg-retro-coffee-maker-review-storage-maintenance"><span>Smeg Retro Coffee Maker review: Storage & maintenance</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1919px;"><p class="vanilla-image-block" style="padding-top:56.28%;"><img id="y7hVofnDRNZuY72Btk6aP6" name="Smeg_Drip_8" alt="the smeg retro coffee maker photographed against the blue tom's guide background" src="https://cdn.mos.cms.futurecdn.net/y7hVofnDRNZuY72Btk6aP6.jpg" mos="" align="middle" fullscreen="" width="1919" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>I was pleasantly surprised to see the Smeg Retro Coffee Maker come with a 2-year warranty. This is better than Ninja’s 1-year warranty, but still not comparable to Moccamaster’s 5-year warranty (and lifetime repairs) or Simply Good Coffee’s new 5-year standard warranty. </p><p>To keep your Retro Coffee Maker lasting as long as possible, do not put the carafe in the dishwasher. I put the mesh filter in the dishwasher and it survived, but I’d recommend only washing by hand. </p><p>As mentioned earlier, the Retro Coffee Maker is pretty large — so make sure you’ve got enough counter space before buying!</p><h2 class="article-body__section" id="section-smeg-retro-coffee-maker-review-how-does-it-compare"><span>Smeg Retro Coffee Maker review: How does it compare? </span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.20%;"><img id="j9BEpPLzE92N3QSVchziJ6" name="Smeg_Drip_2" alt="the smeg retro coffee maker photographed against the blue tom's guide background" src="https://cdn.mos.cms.futurecdn.net/j9BEpPLzE92N3QSVchziJ6.jpg" mos="" align="middle" fullscreen="" width="1920" height="1079" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The Smeg Retro Coffee Maker looks just as cool as the industrial-chic Moccamaster, so I’d recommend either of these brands if you’re after that vintage vibe. I’d also put Simply Good Coffee’s Plastic-Free Brewer in this category — it looks sleek and effortlessly cool. </p><p>The Retro Coffee Maker isn’t as fast as the Breville Luxe Brewer, but it is $70 cheaper, so you win some, you lose some. It’s also considerably cheaper than the $319 Aarke Coffee Maker — but the Aarke is low-plastic, which is what a lot of consumers want these days. </p><p><em>But</em>, and that’s a relatively big but, I would say the Smeg Retro Coffee Maker is a touch overpriced for what it is. The Moccamaster is $369 because it has lifetime repairs and is SCA-accredited. The SGC Plastic-Free Brewer is $469 because it’s made almost entirely from glass and metal. The Breville Luxe Brewer is $329 because it brews in three minutes. </p><p>As mentioned earlier, I’d like to see Smeg’s pricing fall more in line with Ninja’s, Bonavita’s, and Braun (or get SCA accreditation or improve the materials/after-purchase care). Ninja’s 12-Cup Drip Brewer is just $89, and Bonavita’s SCA-accredited 8-Cup Brewer is just $189. The 5-Cup is even cheaper — $149. The 12-Cup Braun Drip Coffee Maker is $129. </p><p>The Smeg doesn’t really have any USPs other than looking really cool. While I do objectively like this coffee maker, I’ll be the first person to admit it falls into Smeg’s main pitfall: it’s expensive for what it is.</p><h2 class="article-body__section" id="section-smeg-retro-coffee-maker-review-verdict"><span> Smeg Retro Coffee Maker review: Verdict</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1919px;"><p class="vanilla-image-block" style="padding-top:56.28%;"><img id="HKZn7AcLGQso6zcD35TJY6" name="Smeg_Drip_9" alt="the smeg retro coffee maker photographed against the blue tom's guide background" src="https://cdn.mos.cms.futurecdn.net/HKZn7AcLGQso6zcD35TJY6.jpg" mos="" align="middle" fullscreen="" width="1919" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>Despite being a little pricey for what it is, the Smeg Retro Coffee Maker gets a big thumbs up from me. I thoroughly enjoyed testing this machine and would recommend it for people who value style and ease of use.</p><p>Yes, it’s expensive considering its plastic build and lack of SCA accreditation, and no, it doesn’t have any unique features like a lifetime repairs warranty or an SCA accreditation. The auto-start timer is cool, but the $89 Ninja 12-Cup has this, too. However, just look at it. Doesn’t that speak for itself? </p><p>So, if you want a kitchen centrepiece that’ll have guests going “Ooh” and “Aah” and “Where did you get that from?” then you’ll get on just fine with the Smeg Retro Coffee Maker. It’s literally plug-and-play, and tastes as good as it looks.</p>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ Overwhelmed by coffee jargon? Here are the 5 key espresso terms you need to know ]]></title>
                                                                                                <dc:content><![CDATA[ <div  class="fancy-box"><div class="fancy_box-title">The Coffee Lab</div><div class="fancy_box_body"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' ><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="UwFdgr6xkNzHUWjapZThcN" name="smeg edited2" caption="" alt="the smeg emc02 mini pro manual espresso machine in jade green" src="https://cdn.mos.cms.futurecdn.net/UwFdgr6xkNzHUWjapZThcN.jpg" mos="" link="" align="" fullscreen="" width="" height="" attribution="" endorsement="" class="pinterest-pin-exclude"></p></div></div><figcaption itemprop="caption description" class=""><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p class="fancy-box__body-text">I'm Erin, and welcome to the nineteenth episode of <a data-analytics-id="inline-link" href="https://www.tomsguide.com/tag/the-coffee-lab">The Coffee Lab</a>, the series where we forget coffee snobbery. The Coffee Lab is all about making coffee fun. Join me as I help you kickstart your coffee journey!</p></div></div><p>Getting into coffee can feel impossible at first. But fret not! I'm here to help. I'm an ex-barista and now a professional coffee tester, so I can help you understand the most important parts of your <a href="https://www.tomsguide.com/home/coffee-makers/best-espresso-machines">espresso machine</a>. </p><p>If you're a total newbie, forget everything you've learned so far. These five key terms are all you need to know right now. Of course, the more your confidence grows, the more you'll absorb and retain, but if you're pulling out your hair and stressing over niche jargon on the daily, you're doing yourself a disservice. You don't need to be perfect on the first try! All you need is an espresso machine and a clear head. I can take care of the rest. </p><p>So strap in as I teach you exactly what you need to know to start pulling shots like a professional barista. And, most importantly, have fun! Coffee is all about enjoyment. If you're doing things "wrong" but having fun, go you! That's all that matters.</p>                    <div class= "tiktok-wrapper" style="min-height: 750px;"><blockquote class="tiktok-embed" cite="https://www.tiktok.com/@tomsguide/video/7672401168542240031" data-video-id="7672401168542240031" style="max-width: 605px; min-width: 325px;">                        <section>                            <a target="_blank" title="@tomsguide" href="https://www.tiktok.com/@tomsguide">@tomsguide</a>                            <p></p><a target="_blank" title="♬ miffy cafe - sakuracloud" href="https://www.tiktok.com/music/miffy-cafe-7425305480727889936">♬ miffy cafe - sakuracloud</a></section>                    </blockquote></div>                <h2 id="what-s-a-portafilter">What's a portafilter?</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:4005px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="3q8RoMEyez5a5LZgLy6wZQ" name="complete portafilter" alt="an assembled portafilter" src="https://cdn.mos.cms.futurecdn.net/3q8RoMEyez5a5LZgLy6wZQ.jpg" mos="" align="middle" fullscreen="" width="4005" height="2253" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Erin Bashford)</span></figcaption></figure><p>A portafilter is the handle of the basket. I've also seen this called a group handle. </p><p>A portafilter basket is where you put your coffee. This is where the espresso machine will send water to extract your espresso.</p><p>That's it! I told you it was easy. </p><h2 id="what-s-a-tamper">What's a tamper?</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="8YvyWPttRVe2oK99sgwBFa" name="Sage_Breville_Bambino_Plus_ 3.JPG" alt="the breville bambino plus in stainless steel silver photographed against a blue background shown with its accessories including milk jug, tamper, portafilter, and shown in use extracting espresso" src="https://cdn.mos.cms.futurecdn.net/8YvyWPttRVe2oK99sgwBFa.jpg" mos="" align="middle" fullscreen="" width="1920" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The tamper is the circular accessory you use to tamp (press down on) the coffee grounds. If you hear someone say tamp the coffee, this is what they're referring to. You want to apply around 20kg of pressure — which basically means just push hard, but be mindful to keep the coffee level. </p><p>This is to flatten and compact the coffee grounds and create an even surface for the water to flow through (preventing channeling).</p><h2 id="what-s-channeling">What's channeling? </h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="geSoGaVosh2iqmkZZqJTzZ" name="Sage_bambino_ 11.JPG" alt="the breville bambino / sage bambino in silver photographed against a blue background with a wooden feature wall, showing the steam wand, group head, water tank, button controls, and espresso" src="https://cdn.mos.cms.futurecdn.net/geSoGaVosh2iqmkZZqJTzZ.jpg" mos="" align="middle" fullscreen="" width="1920" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>Channeling is where water flows through <em>channels</em> in the coffee rather than saturating the entire portafilter. This is caused by an uneven grind, uneven tamp, or an uneven dose. When you put coffee in the portafilter basket, you want to make sure it's flat, evenly distributed, and there are no major clumps. </p><p>A channeled espresso will taste sour and bitter and generally unpleasant. Nothing you wouldn't be able to mask with syrups, though!</p><h2 id="what-s-puck-prep">What's puck prep? </h2><figure role="gallery"><figure><img src="https://cdn.mos.cms.futurecdn.net/5i3fsSEGiFp3HBkwbH5DTQ.jpg" alt="The Gaggia Classic E24 Evo Pro portafilter with coffee grounds in it" /><figcaption>Before puck prep<small role="credit">Future</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/ACcps3Gws3ZGy9FkVb8MiP.jpg" alt="The Gaggia Classic E24 Evo Pro portafilter with coffee grounds tamped inside it" /><figcaption>After puck prep<small role="credit">Future</small></figcaption></figure></figure><p>Puck prep is kind of a coffee snob term. It refers to everything you do to prepare your espresso. When people say, "Make sure you do your puck prep right," they're referring to the following: </p><ul><li>Grinding your beans evenly, using one of the <a href="https://www.tomsguide.com/best-picks/best-coffee-grinder">best grinders</a></li><li>Weighing out the right amount of ground coffee, using one of the <a href="https://www.tomsguide.com/best-picks/best-coffee-scales">best coffee scales</a></li><li>Putting the coffee in your portafilter basket and making sure there are no huge clumps</li><li>Tamping with proper pressure</li></ul><h2 id="what-s-overextraction-underextraction">What's overextraction/underextraction?</h2><figure role="gallery"><figure><img src="https://cdn.mos.cms.futurecdn.net/YgGsA8oa8EVyabDHtEDWd5.png" alt="A photo of espresso made on the breville bambino plus espresso machine in a shot glass with the wacaco exagram pro scale" /><figcaption>Underextracted<small role="credit">Erin Bashford</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/z6zBaBfELEYmGUx7r2isY5.png" alt="A photo of espresso made on the breville bambino plus espresso machine in a shot glass with the wacaco exagram pro scale" /><figcaption>Perfect<small role="credit">Erin Bashford</small></figcaption></figure></figure><p>Both are bad! </p><p>Overextraction is where the coffee has spent too much time with water or pressure, resulting in a burned, bitter coffee. You have probably ground your coffee too coarsely.</p><p>Underextraction is where the coffee hasn't spent enough time with water or pressure, making a sour, acidic coffee. You have probably ground your coffee too finely. </p><p>If your coffee is coming out really slowly, that's overextraction. This will taste incredibly intense and burned, like charcoal. </p><p>If your coffee is coming out quickly, that's underextraction. This will taste like lemon juice. Nasty!</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-exV2aO"></div>                            </div>                            <script src="https://kwizly.com/embed/exV2aO.js" async></script><p>Did I answer all of your jargon-related questions? Let me know in the comments if you want me to explain anything else. </p><p>I release new episodes of The Coffee Lab every Friday, so be sure to check back next week for the next coffee adventure.</p><figure class="inline-layout"><div style="min-height: 400px;"><fw-embed-feed channel="toms_guide" playlist="ojE0pK" mode="row" player_placement="bottom-right"></fw-embed-feed></div></figure><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h3><ul><li><a href="https://www.tomsguide.com/home/coffee-makers/i-tried-the-new-nespresso-summer-flavors-heres-my-favorite"><strong>I tried the new Nespresso summer flavors — here's my favorite</strong></a></li><li><a href="https://www.tomsguide.com/home/coffee-makers/im-an-ex-starbucks-barista-you-can-make-the-iced-brown-sugar-oatmilk-shaken-espresso-at-home-for-a-fraction-of-the-cost"><strong>I'm an ex-Starbucks barista — you can make the Iced Brown Sugar Oatmilk Shaken Espresso at home for a fraction of the cost</strong></a></li><li><a href="https://www.tomsguide.com/home/coffee-makers/i-tried-lelits-brand-new-entry-level-espresso-machine-and-i-wish-i-had-usd2-000-so-i-could-buy-it"><strong>I tried Lelit's brand-new 'entry-level' espresso machine — and I wish I had $2,000 so I could buy it</strong></a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/home/coffee-makers/overwhelmed-by-coffee-jargon-here-are-the-5-key-espresso-terms-you-need-to-know</link>
                                                                            <description>
                            <![CDATA[ On Episode 19 of The Coffee Lab, I help you understand coffee equipment jargon. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">2LneZrbkc6EjjyYvC3TwWA</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/7YBnRoB7df7h9Gs3G9BjR4-1280-80.png" type="image/png" length="0"></enclosure>
                                                                        <pubDate>Fri, 07 Aug 2026 13:00:00 +0000</pubDate>                                                                                                                                <updated>Mon, 10 Aug 2026 14:06:58 +0000</updated>
                                                                                                                                            <category><![CDATA[Coffee Makers]]></category>
                                                    <category><![CDATA[Home]]></category>
                                                    <category><![CDATA[Home Appliances]]></category>
                                                    <category><![CDATA[Kitchen & Dining]]></category>
                                                                                                <author><![CDATA[ erin.bashford@futurenet.com (Erin Bashford) ]]></author>                    <dc:creator><![CDATA[ Erin Bashford ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/rLvJvJVZx43hEzSsJy3BpL.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Erin Bashford is a senior reviews writer at Tom’s Guide. She has a Master’s in Broadcast and Digital Journalism from the University of East Anglia and 7 years of experience reviewing music and events for various publications. She has edited publications such as Outline Magazine’s Guide to Norwich, and she has written for a number of music magazines and websites such as Clash Magazine, Outline Magazine and Dork Magazine. She has a strong interest in audio gear and the music world. &lt;/p&gt;&lt;p&gt;As an ex-barista, Erin is passionate about coffee tech. She also loves finding the best cooking hacks and kitchen appliances, including her beloved Instant Pot. &lt;/p&gt;&lt;p&gt;In her spare time, you can find her reading, practising yoga, hiking, writing fantasy novels, or stressing over NYT Games.&lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                <media:content type="image/png" url="https://cdn.mos.cms.futurecdn.net/7YBnRoB7df7h9Gs3G9BjR4-1280-80.png">
                                                            <media:credit><![CDATA[Tom&#039;s Guide]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[a photo of the author drinking a coffee with a full portafilter on the other side]]></media:description>                                                            <media:text><![CDATA[a photo of the author drinking a coffee with a full portafilter on the other side]]></media:text>
                                <media:title type="plain"><![CDATA[a photo of the author drinking a coffee with a full portafilter on the other side]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/7YBnRoB7df7h9Gs3G9BjR4-1280-80.png" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <div  class="fancy-box"><div class="fancy_box-title">The Coffee Lab</div><div class="fancy_box_body"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' ><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="UwFdgr6xkNzHUWjapZThcN" name="smeg edited2" caption="" alt="the smeg emc02 mini pro manual espresso machine in jade green" src="https://cdn.mos.cms.futurecdn.net/UwFdgr6xkNzHUWjapZThcN.jpg" mos="" link="" align="" fullscreen="" width="" height="" attribution="" endorsement="" class="pinterest-pin-exclude"></p></div></div><figcaption itemprop="caption description" class=""><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p class="fancy-box__body-text">I'm Erin, and welcome to the nineteenth episode of <a data-analytics-id="inline-link" href="https://www.tomsguide.com/tag/the-coffee-lab">The Coffee Lab</a>, the series where we forget coffee snobbery. The Coffee Lab is all about making coffee fun. Join me as I help you kickstart your coffee journey!</p></div></div><p>Getting into coffee can feel impossible at first. But fret not! I'm here to help. I'm an ex-barista and now a professional coffee tester, so I can help you understand the most important parts of your <a href="https://www.tomsguide.com/home/coffee-makers/best-espresso-machines">espresso machine</a>. </p><p>If you're a total newbie, forget everything you've learned so far. These five key terms are all you need to know right now. Of course, the more your confidence grows, the more you'll absorb and retain, but if you're pulling out your hair and stressing over niche jargon on the daily, you're doing yourself a disservice. You don't need to be perfect on the first try! All you need is an espresso machine and a clear head. I can take care of the rest. </p><p>So strap in as I teach you exactly what you need to know to start pulling shots like a professional barista. And, most importantly, have fun! Coffee is all about enjoyment. If you're doing things "wrong" but having fun, go you! That's all that matters.</p>                    <div class= "tiktok-wrapper" style="min-height: 750px;"><blockquote class="tiktok-embed" cite="https://www.tiktok.com/@tomsguide/video/7672401168542240031" data-video-id="7672401168542240031" style="max-width: 605px; min-width: 325px;">                        <section>                            <a target="_blank" title="@tomsguide" href="https://www.tiktok.com/@tomsguide">@tomsguide</a>                            <p></p><a target="_blank" title="♬ miffy cafe - sakuracloud" href="https://www.tiktok.com/music/miffy-cafe-7425305480727889936">♬ miffy cafe - sakuracloud</a></section>                    </blockquote></div>                <h2 id="what-s-a-portafilter">What's a portafilter?</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:4005px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="3q8RoMEyez5a5LZgLy6wZQ" name="complete portafilter" alt="an assembled portafilter" src="https://cdn.mos.cms.futurecdn.net/3q8RoMEyez5a5LZgLy6wZQ.jpg" mos="" align="middle" fullscreen="" width="4005" height="2253" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Erin Bashford)</span></figcaption></figure><p>A portafilter is the handle of the basket. I've also seen this called a group handle. </p><p>A portafilter basket is where you put your coffee. This is where the espresso machine will send water to extract your espresso.</p><p>That's it! I told you it was easy. </p><h2 id="what-s-a-tamper">What's a tamper?</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="8YvyWPttRVe2oK99sgwBFa" name="Sage_Breville_Bambino_Plus_ 3.JPG" alt="the breville bambino plus in stainless steel silver photographed against a blue background shown with its accessories including milk jug, tamper, portafilter, and shown in use extracting espresso" src="https://cdn.mos.cms.futurecdn.net/8YvyWPttRVe2oK99sgwBFa.jpg" mos="" align="middle" fullscreen="" width="1920" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The tamper is the circular accessory you use to tamp (press down on) the coffee grounds. If you hear someone say tamp the coffee, this is what they're referring to. You want to apply around 20kg of pressure — which basically means just push hard, but be mindful to keep the coffee level. </p><p>This is to flatten and compact the coffee grounds and create an even surface for the water to flow through (preventing channeling).</p><h2 id="what-s-channeling">What's channeling? </h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="geSoGaVosh2iqmkZZqJTzZ" name="Sage_bambino_ 11.JPG" alt="the breville bambino / sage bambino in silver photographed against a blue background with a wooden feature wall, showing the steam wand, group head, water tank, button controls, and espresso" src="https://cdn.mos.cms.futurecdn.net/geSoGaVosh2iqmkZZqJTzZ.jpg" mos="" align="middle" fullscreen="" width="1920" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>Channeling is where water flows through <em>channels</em> in the coffee rather than saturating the entire portafilter. This is caused by an uneven grind, uneven tamp, or an uneven dose. When you put coffee in the portafilter basket, you want to make sure it's flat, evenly distributed, and there are no major clumps. </p><p>A channeled espresso will taste sour and bitter and generally unpleasant. Nothing you wouldn't be able to mask with syrups, though!</p><h2 id="what-s-puck-prep">What's puck prep? </h2><figure role="gallery"><figure><img src="https://cdn.mos.cms.futurecdn.net/5i3fsSEGiFp3HBkwbH5DTQ.jpg" alt="The Gaggia Classic E24 Evo Pro portafilter with coffee grounds in it" /><figcaption>Before puck prep<small role="credit">Future</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/ACcps3Gws3ZGy9FkVb8MiP.jpg" alt="The Gaggia Classic E24 Evo Pro portafilter with coffee grounds tamped inside it" /><figcaption>After puck prep<small role="credit">Future</small></figcaption></figure></figure><p>Puck prep is kind of a coffee snob term. It refers to everything you do to prepare your espresso. When people say, "Make sure you do your puck prep right," they're referring to the following: </p><ul><li>Grinding your beans evenly, using one of the <a href="https://www.tomsguide.com/best-picks/best-coffee-grinder">best grinders</a></li><li>Weighing out the right amount of ground coffee, using one of the <a href="https://www.tomsguide.com/best-picks/best-coffee-scales">best coffee scales</a></li><li>Putting the coffee in your portafilter basket and making sure there are no huge clumps</li><li>Tamping with proper pressure</li></ul><h2 id="what-s-overextraction-underextraction">What's overextraction/underextraction?</h2><figure role="gallery"><figure><img src="https://cdn.mos.cms.futurecdn.net/YgGsA8oa8EVyabDHtEDWd5.png" alt="A photo of espresso made on the breville bambino plus espresso machine in a shot glass with the wacaco exagram pro scale" /><figcaption>Underextracted<small role="credit">Erin Bashford</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/z6zBaBfELEYmGUx7r2isY5.png" alt="A photo of espresso made on the breville bambino plus espresso machine in a shot glass with the wacaco exagram pro scale" /><figcaption>Perfect<small role="credit">Erin Bashford</small></figcaption></figure></figure><p>Both are bad! </p><p>Overextraction is where the coffee has spent too much time with water or pressure, resulting in a burned, bitter coffee. You have probably ground your coffee too coarsely.</p><p>Underextraction is where the coffee hasn't spent enough time with water or pressure, making a sour, acidic coffee. You have probably ground your coffee too finely. </p><p>If your coffee is coming out really slowly, that's overextraction. This will taste incredibly intense and burned, like charcoal. </p><p>If your coffee is coming out quickly, that's underextraction. This will taste like lemon juice. Nasty!</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-exV2aO"></div>                            </div>                            <script src="https://kwizly.com/embed/exV2aO.js" async></script><p>Did I answer all of your jargon-related questions? Let me know in the comments if you want me to explain anything else. </p><p>I release new episodes of The Coffee Lab every Friday, so be sure to check back next week for the next coffee adventure.</p><figure class="inline-layout"><div style="min-height: 400px;"><fw-embed-feed channel="toms_guide" playlist="ojE0pK" mode="row" player_placement="bottom-right"></fw-embed-feed></div></figure><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h3><ul><li><a href="https://www.tomsguide.com/home/coffee-makers/i-tried-the-new-nespresso-summer-flavors-heres-my-favorite"><strong>I tried the new Nespresso summer flavors — here's my favorite</strong></a></li><li><a href="https://www.tomsguide.com/home/coffee-makers/im-an-ex-starbucks-barista-you-can-make-the-iced-brown-sugar-oatmilk-shaken-espresso-at-home-for-a-fraction-of-the-cost"><strong>I'm an ex-Starbucks barista — you can make the Iced Brown Sugar Oatmilk Shaken Espresso at home for a fraction of the cost</strong></a></li><li><a href="https://www.tomsguide.com/home/coffee-makers/i-tried-lelits-brand-new-entry-level-espresso-machine-and-i-wish-i-had-usd2-000-so-i-could-buy-it"><strong>I tried Lelit's brand-new 'entry-level' espresso machine — and I wish I had $2,000 so I could buy it</strong></a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ Amazon just slashed prices on Ninja's best kitchen appliances — my 15 favorite deals start at $59 ]]></title>
                                                                                                <dc:content><![CDATA[ <p>Ninja makes some of my favorite kitchen appliances on the market — and right now, Amazon is offering some pretty impressive deals on the top-rated gadgets! You can score big savings on summer must-haves like coolers, slushy machines, grills, air fryers and much more.</p><p>Whether you're firing up the grill for a barbecue or you're hoping to simplify your weekly meal prep, <a href="https://www.amazon.com/stores/page/471F718E-0761-48DF-ABAF-0FC6590C695B?" target="_blank" rel="nofollow">Ninja is slashing up to 40% off its best-selling kitchen appliances</a>. And the best part? The deals start at just $59 and are the perfect finds for summer.</p><p>If you're in the market for some new cooking appliances, take it from me: Ninja is <em>the</em> brand to buy. Keep scrolling to check out my favorite Ninja picks from Amazon's sale. </p><h3 class="article-body__section" id="section-quick-links"><span>Quick Links</span></h3><ul><li><strong></strong><a href="https://www.sharkninja.com/sales-offers/shop-all-sale" target="_blank" rel="nofollow"><strong>shop all Ninja deals at Ninja</strong></a></li><li><a href="https://www.amazon.com/stores/page/471F718E-0761-48DF-ABAF-0FC6590C695B" target="_blank" rel="nofollow"><strong>shop all Ninja deals at Amazon</strong></a></li><li><strong>Ninja Blast Portable Blender: </strong><a href="https://www.amazon.com/dp/B0D2ZBNG9H?" target="_blank" rel="nofollow"><strong>was $69 now $59</strong></a></li><li><strong>Ninja Professional Blender: </strong><a href="https://www.amazon.com/Ninja-BR201AMZ-Professional-Smoothies-Dishwasher-Safe/dp/B00NGV4506?" target="_blank" rel="nofollow"><strong>was $109 now $89</strong></a><strong></strong></li><li><strong>Ninja Iced Coffee Maker: </strong><a href="https://www.amazon.com/Ninja-Specialty-Single-Serve-Compatible-PB055ABL/dp/B0C25Y15TL?" target="_blank" rel="nofollow"><strong>was $129 now $99</strong></a></li><li><strong>Ninja Backpack Cooler: </strong><a href="https://www.amazon.com/Ninja-Backpack-FrostVault-Leakproof-FF124CS/dp/B0F4Y5G8GF" target="_blank" rel="nofollow"><strong>was $199 now $179</strong></a></li><li><strong>Ninja Mega Kitchen System: </strong><a href="https://www.amazon.com/dp/B00939I7EK" target="_blank" rel="nofollow"><strong>was $219 now $179</strong></a></li><li><strong>Ninja FrostVault Cooler, 45qt: </strong><a href="https://www.amazon.com/Ninja-FrostVault-Insulated-Storage-FB245MR/dp/B0DPN8XSP3?" target="_blank" rel="nofollow"><strong>was $349 now $279</strong></a></li></ul><h3 class="article-body__section" id="section-ninja-deals"><span>Ninja Deals</span></h3><div class="product"><a data-dimension112="b6666144-90e6-11f1-9445-2586d3bf1a20" data-action="Deal Block" data-label="Blast Portable Blender" data-dimension48="Blast Portable Blender" data-dimension25="$59" href="https://www.amazon.com/dp/B0D2ZBNG9H?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:679px;"><p class="vanilla-image-block" style="padding-top:170.40%;"><img id="FCnJUW6WAsjjZShgBrxUa9" name="Ninja Blast.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/FCnJUW6WAsjjZShgBrxUa9.jpg" mos="" align="middle" fullscreen="" width="679" height="1157" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0D2ZBNG9H?" target="_blank" rel="nofollow" data-dimension112="b6666144-90e6-11f1-9445-2586d3bf1a20" data-action="Deal Block" data-label="Blast Portable Blender" data-dimension48="Blast Portable Blender" data-dimension25="$59">Blast Portable Blender: was $69 now $59</a></strong><br>We gave the <a href="https://www.tomsguide.com/home/home-appliances/ninja-blast-max-review">Blast a 4-star rating in our review</a>. While portable blenders struggle to compete with larger models, there's no denying that this portable model punches well above its weight in price and features. For $59, it's an absolute bargain.<a class="view-deal button" href="https://www.amazon.com/dp/B0D2ZBNG9H?" target="_blank" rel="nofollow" data-dimension112="b6666144-90e6-11f1-9445-2586d3bf1a20" data-action="Deal Block" data-label="Blast Portable Blender" data-dimension48="Blast Portable Blender" data-dimension25="$59">View Deal</a></p></div><div class="product"><a data-dimension112="b66661bc-90e6-11f1-81ec-df578338b884" data-action="Deal Block" data-label="Professional Blender" data-dimension48="Professional Blender" data-dimension25="$89" href="https://www.amazon.com/Ninja-BR201AMZ-Professional-Smoothies-Dishwasher-Safe/dp/B00NGV4506?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:679px;"><p class="vanilla-image-block" style="padding-top:162.30%;"><img id="sFftzctqbej7oaSQLEtBRj" name="Ninja Pro Blender" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/sFftzctqbej7oaSQLEtBRj.jpg" mos="" align="middle" fullscreen="" width="679" height="1102" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Ninja-BR201AMZ-Professional-Smoothies-Dishwasher-Safe/dp/B00NGV4506?" target="_blank" rel="nofollow" data-dimension112="b66661bc-90e6-11f1-81ec-df578338b884" data-action="Deal Block" data-label="Professional Blender" data-dimension48="Professional Blender" data-dimension25="$89">Professional Blender: was $109 now $89</a></strong><br>Be it daily smoothies or making ice cream, this blender can tackle it all, at the touch of a button. Also featured on our <a href="https://www.tomsguide.com/best-picks/best-blenders">best blenders</a> guide, this comes with 3 preset Auto-iQ programs that creates smoothies, frozen drinks, and ice cream, and its powerful blades can crush ice in no time. This is a great deal if you want an easy-to-use blender, with professional results.  <a class="view-deal button" href="https://www.amazon.com/Ninja-BR201AMZ-Professional-Smoothies-Dishwasher-Safe/dp/B00NGV4506?" target="_blank" rel="nofollow" data-dimension112="b66661bc-90e6-11f1-81ec-df578338b884" data-action="Deal Block" data-label="Professional Blender" data-dimension48="Professional Blender" data-dimension25="$89">View Deal</a></p></div><div class="product"><a data-dimension112="b666622a-90e6-11f1-bd1b-1db52dba49c6" data-action="Deal Block" data-label="Pods & Grounds Specialty Single-Serve Iced Coffee Maker" data-dimension48="Pods & Grounds Specialty Single-Serve Iced Coffee Maker" data-dimension25="$99" href="https://www.amazon.com/dp/B0C25Y15TL?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:679px;"><p class="vanilla-image-block" style="padding-top:99.56%;"><img id="4uiaRXRKY8Go6F4ZpM7UdA" name="Ninja coffee" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/4uiaRXRKY8Go6F4ZpM7UdA.jpg" mos="" align="middle" fullscreen="" width="679" height="676" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0C25Y15TL?" target="_blank" rel="nofollow" data-dimension112="b666622a-90e6-11f1-bd1b-1db52dba49c6" data-action="Deal Block" data-label="Pods & Grounds Specialty Single-Serve Iced Coffee Maker" data-dimension48="Pods & Grounds Specialty Single-Serve Iced Coffee Maker" data-dimension25="$99">Pods & Grounds Specialty Single-Serve Iced Coffee Maker: was $129 now $99</a></strong><br>This stylish Ninja coffee maker comes in a gorgeous Sage colorway and is now on sale for $30 off. Whether you prefer pods or grounds, this device makes tasty brews in 7 sizes (6-oz. to 24-oz) and has a built-in, fold-away milk frother!<a class="view-deal button" href="https://www.amazon.com/dp/B0C25Y15TL?" target="_blank" rel="nofollow" data-dimension112="b666622a-90e6-11f1-bd1b-1db52dba49c6" data-action="Deal Block" data-label="Pods & Grounds Specialty Single-Serve Iced Coffee Maker" data-dimension48="Pods & Grounds Specialty Single-Serve Iced Coffee Maker" data-dimension25="$99">View Deal</a></p></div><div class="product"><a data-dimension112="b66662a2-90e6-11f1-bc72-d9463eb6fedb" data-action="Deal Block" data-label="BlendBOSS Blender" data-dimension48="BlendBOSS Blender" data-dimension25="$109" href="https://www.amazon.com/Ninja-BlendbossTM-Detachable-Technology-DB351CY/dp/B0FSGSYF79?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1500px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="JkaewDaMJCoHarzBbjk5u8" name="Ninja BlendBOSS deal block" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/JkaewDaMJCoHarzBbjk5u8.jpg" mos="" align="middle" fullscreen="" width="1500" height="1500" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Ninja-BlendbossTM-Detachable-Technology-DB351CY/dp/B0FSGSYF79?" target="_blank" rel="nofollow" data-dimension112="b66662a2-90e6-11f1-bc72-d9463eb6fedb" data-action="Deal Block" data-label="BlendBOSS Blender" data-dimension48="BlendBOSS Blender" data-dimension25="$109">BlendBOSS Blender: was $129 now $109</a></strong><br>The Ninja BlendBOSS is one of the best personal blenders we've used. In our <a href="https://www.tomsguide.com/home/home-appliances/ninja-blendboss-review">Ninja BlendBOSS review</a>, we said the Editor's Choice blender is great at everything from making hummus to lump-free smoothies. Its' compact, comes in a range of colors, and it's simply the best personal blender you can buy at this price point. <a class="view-deal button" href="https://www.amazon.com/Ninja-BlendbossTM-Detachable-Technology-DB351CY/dp/B0FSGSYF79?" target="_blank" rel="nofollow" data-dimension112="b66662a2-90e6-11f1-bc72-d9463eb6fedb" data-action="Deal Block" data-label="BlendBOSS Blender" data-dimension48="BlendBOSS Blender" data-dimension25="$109">View Deal</a></p></div><div class="product"><a data-dimension112="b6666310-90e6-11f1-b1bf-834177ef4845" data-action="Deal Block" data-label="Flip Toaster Oven & Air Fryer" data-dimension48="Flip Toaster Oven & Air Fryer" data-dimension25="$149" href="https://www.amazon.com/Ninja-Functionality-Capability-Removable-SP151/dp/B0D1CXL52G" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:600px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="qey9zt42Hnq8ePgcaiiaR7" name="Ninja Flip" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/qey9zt42Hnq8ePgcaiiaR7.jpg" mos="" align="middle" fullscreen="" width="600" height="600" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Ninja-Functionality-Capability-Removable-SP151/dp/B0D1CXL52G" target="_blank" rel="nofollow" data-dimension112="b6666310-90e6-11f1-b1bf-834177ef4845" data-action="Deal Block" data-label="Flip Toaster Oven & Air Fryer" data-dimension48="Flip Toaster Oven & Air Fryer" data-dimension25="$149">Flip Toaster Oven & Air Fryer: was $249 now $149</a></strong><br>The Ninja Flip stainless steel model is also on sale. It has 8 functions in one convenient and versatile machine: air fry, roast, bake, toast, and more. When you're not using it, you can flip it up and away, which will give you 50% more counter space back.<a class="view-deal button" href="https://www.amazon.com/Ninja-Functionality-Capability-Removable-SP151/dp/B0D1CXL52G" target="_blank" rel="nofollow" data-dimension112="b6666310-90e6-11f1-b1bf-834177ef4845" data-action="Deal Block" data-label="Flip Toaster Oven & Air Fryer" data-dimension48="Flip Toaster Oven & Air Fryer" data-dimension25="$149">View Deal</a></p></div><div class="product"><a data-dimension112="b666637e-90e6-11f1-88ef-a5432b0ffbe6" data-action="Deal Block" data-label="Crispi 4-in-1 Portable Glass Air Fryer Cooking System" data-dimension48="Crispi 4-in-1 Portable Glass Air Fryer Cooking System" data-dimension25="$159" href="https://www.amazon.com/Ninja-Microwave-Dishwasher-Containers-FN101GY/dp/B0DDDD8WD6?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:679px;"><p class="vanilla-image-block" style="padding-top:85.86%;"><img id="zNkXNCVYCubXhCRwjaoGPj" name="Ninjs Crispi" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/zNkXNCVYCubXhCRwjaoGPj.jpg" mos="" align="middle" fullscreen="" width="679" height="583" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Ninja-Microwave-Dishwasher-Containers-FN101GY/dp/B0DDDD8WD6?" target="_blank" rel="nofollow" data-dimension112="b666637e-90e6-11f1-88ef-a5432b0ffbe6" data-action="Deal Block" data-label="Crispi 4-in-1 Portable Glass Air Fryer Cooking System" data-dimension48="Crispi 4-in-1 Portable Glass Air Fryer Cooking System" data-dimension25="$159">Crispi 4-in-1 Portable Glass Air Fryer Cooking System: was $179 now $159</a></strong><br>The Ninja Crispi is one of Ninja's most interesting releases. It features a removable cooking lid and interchangeable glass containers to cook meals of a range of sizes. In our <a href="https://www.tomsguide.com/home/air-fryers/ninja-crispi-air-fryer-review">Ninja Crispi review</a>, it earned a well-deserved 4.5 stars.  <a class="view-deal button" href="https://www.amazon.com/Ninja-Microwave-Dishwasher-Containers-FN101GY/dp/B0DDDD8WD6?" target="_blank" rel="nofollow" data-dimension112="b666637e-90e6-11f1-88ef-a5432b0ffbe6" data-action="Deal Block" data-label="Crispi 4-in-1 Portable Glass Air Fryer Cooking System" data-dimension48="Crispi 4-in-1 Portable Glass Air Fryer Cooking System" data-dimension25="$159">View Deal</a></p></div><div class="product"><a data-dimension112="b66663f6-90e6-11f1-bae6-83bce4e1c3b4" data-action="Deal Block" data-label="Backpack Cooler" data-dimension48="Backpack Cooler" data-dimension25="$179" href="https://www.amazon.com/Ninja-Backpack-FrostVault-Leakproof-FF124CS/dp/B0F4Y5G8GF" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:464px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="WW5AWCoTo6gey3CoZ7CHzk" name="Screenshot 2025-07-07 153631" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/WW5AWCoTo6gey3CoZ7CHzk.jpg" mos="" align="middle" fullscreen="" width="464" height="464" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>Ninja's backpack cooler is perfect for heading to the beach or having a picnic. It has a built-in cold dry zone to keep food dry and separate at under 40°F, holds ice for up to 24 hours, and has a top lid and side opening for easier access. It holds up to 24 cans, or 16 cans with ice. It even have a built in bottle opener.<a class="view-deal button" href="https://www.amazon.com/Ninja-Backpack-FrostVault-Leakproof-FF124CS/dp/B0F4Y5G8GF" target="_blank" rel="nofollow" data-dimension112="b66663f6-90e6-11f1-bae6-83bce4e1c3b4" data-action="Deal Block" data-label="Backpack Cooler" data-dimension48="Backpack Cooler" data-dimension25="$179">View Deal</a></p></div><div class="product"><a data-dimension112="b6666464-90e6-11f1-ba87-557c5b25b806" data-action="Deal Block" data-label="Mega Kitchen System" data-dimension48="Mega Kitchen System" data-dimension25="$179" href="https://www.amazon.com/dp/B00939I7EK" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1676px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="sWibiMn9jcqpLxyQRazy6f" name="Ninja Amazon 2.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/sWibiMn9jcqpLxyQRazy6f.jpg" mos="" align="middle" fullscreen="" width="1676" height="1676" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B00939I7EK" target="_blank" rel="nofollow" data-dimension112="b6666464-90e6-11f1-ba87-557c5b25b806" data-action="Deal Block" data-label="Mega Kitchen System" data-dimension48="Mega Kitchen System" data-dimension25="$179">Mega Kitchen System: was $219 now $179</a></strong><br>Leave all the multi-tasking in the kitchen to one appliance with this Ninja blender. With four functions for smoothies, processing, dough, drinks and more it will quickly become your go-to kitchen appliance. With this ultimate appliance, you’ll be enjoying fresh, healthy drinks, homemade bread and sweet bakes.<a class="view-deal button" href="https://www.amazon.com/dp/B00939I7EK" target="_blank" rel="nofollow" data-dimension112="b6666464-90e6-11f1-ba87-557c5b25b806" data-action="Deal Block" data-label="Mega Kitchen System" data-dimension48="Mega Kitchen System" data-dimension25="$179">View Deal</a></p></div><div class="product"><a data-dimension112="b66664d2-90e6-11f1-947c-7533996d7154" data-action="Deal Block" data-label="Foodi DualZone Air Fryer (DZ401)" data-dimension48="Foodi DualZone Air Fryer (DZ401)" data-dimension25="$199" href="https://www.amazon.com/Ninja-DZ401-Independent-Dehydrate-Family-Sized/dp/B0B15Q3HCQ?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1952px;"><p class="vanilla-image-block" style="padding-top:66.91%;"><img id="gibkomA9CKgWqZ8r2NX7f8" name="Ninja DZ401 Foodi" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/gibkomA9CKgWqZ8r2NX7f8.png" mos="" align="middle" fullscreen="" width="1952" height="1306" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Ninja-DZ401-Independent-Dehydrate-Family-Sized/dp/B0B15Q3HCQ?" target="_blank" rel="nofollow" data-dimension112="b66664d2-90e6-11f1-947c-7533996d7154" data-action="Deal Block" data-label="Foodi DualZone Air Fryer (DZ401)" data-dimension48="Foodi DualZone Air Fryer (DZ401)" data-dimension25="$199">Foodi DualZone Air Fryer (DZ401): was $229 now $199</a></strong><br>This relatively affordable dual-zone air fryer is one of Ninja's best. It's got the perks of SmartFinish and MatchCook, which will allow you to either sync two cooking settings to finish at the same time, or duplicate your settings to the other basket and maximize your space. <a class="view-deal button" href="https://www.amazon.com/Ninja-DZ401-Independent-Dehydrate-Family-Sized/dp/B0B15Q3HCQ?" target="_blank" rel="nofollow" data-dimension112="b66664d2-90e6-11f1-947c-7533996d7154" data-action="Deal Block" data-label="Foodi DualZone Air Fryer (DZ401)" data-dimension48="Foodi DualZone Air Fryer (DZ401)" data-dimension25="$199">View Deal</a></p></div><div class="product"><a data-dimension112="b6666540-90e6-11f1-a4c4-ab34db796060" data-action="Deal Block" data-label="FrostVault 30QT" data-dimension48="FrostVault 30QT" data-dimension25="$229" href="https://www.amazon.com/dp/B0DPNCDYCZ?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1509px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="zcrSfDSQ58GkQ5fatetyy9" name="1751644471.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/zcrSfDSQ58GkQ5fatetyy9.jpg" mos="" align="middle" fullscreen="" width="1509" height="1509" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0DPNCDYCZ?" target="_blank" rel="nofollow" data-dimension112="b6666540-90e6-11f1-a4c4-ab34db796060" data-action="Deal Block" data-label="FrostVault 30QT" data-dimension48="FrostVault 30QT" data-dimension25="$229">FrostVault 30QT: was $279 now $229</a></strong><br>If you don't think you need a massive cooler, you can still get a good deal on the 30QT model. This will fit 48 cans without ice or 28 cans with ice. It still keeps everything cold for days at a time, it's just smaller. It also has the cool dry zone, which lets you keep food and other items cool without all the moisture.<a class="view-deal button" href="https://www.amazon.com/dp/B0DPNCDYCZ?" target="_blank" rel="nofollow" data-dimension112="b6666540-90e6-11f1-a4c4-ab34db796060" data-action="Deal Block" data-label="FrostVault 30QT" data-dimension48="FrostVault 30QT" data-dimension25="$229">View Deal</a></p></div><div class="product"><a data-dimension112="b66665b8-90e6-11f1-a04a-438a5166aaf2" data-action="Deal Block" data-label="Double Stack XL Air Fryer & Toaster Oven Combo" data-dimension48="Double Stack XL Air Fryer & Toaster Oven Combo" data-dimension25="$249" href="https://www.amazon.com/Ninja-Countertop-Convection-Stainless-DT501/dp/B0D4R7DMYN?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:679px;"><p class="vanilla-image-block" style="padding-top:76.88%;"><img id="KybxnS8GerWMHfrZ6mQdvm" name="Ninja Air Fryer Toaster" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/KybxnS8GerWMHfrZ6mQdvm.jpg" mos="" align="middle" fullscreen="" width="679" height="522" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Ninja-Countertop-Convection-Stainless-DT501/dp/B0D4R7DMYN?" target="_blank" rel="nofollow" data-dimension112="b66665b8-90e6-11f1-a04a-438a5166aaf2" data-action="Deal Block" data-label="Double Stack XL Air Fryer & Toaster Oven Combo" data-dimension48="Double Stack XL Air Fryer & Toaster Oven Combo" data-dimension25="$249">Double Stack XL Air Fryer & Toaster Oven Combo: was $429 now $249</a></strong><br>When we got our hands on the <a href="https://www.tomsguide.com/home/home-appliances/ninja-prestige-smart-xl-air-fryer-oven-dt501-review">Ninja Prestige Smart XL Oven</a>, we were super impressed by its capacity, range of cooking functions and intuitive, easy-to-use controls. It's a great alternative for anyone not wanting a full-size oven or an XL air fryer in their kitchen. And right now the <a href="https://www.tomsguide.com/best-picks/best-toaster-ovens">best toaster oven</a> is $180 off. <a class="view-deal button" href="https://www.amazon.com/Ninja-Countertop-Convection-Stainless-DT501/dp/B0D4R7DMYN?" target="_blank" rel="nofollow" data-dimension112="b66665b8-90e6-11f1-a04a-438a5166aaf2" data-action="Deal Block" data-label="Double Stack XL Air Fryer & Toaster Oven Combo" data-dimension48="Double Stack XL Air Fryer & Toaster Oven Combo" data-dimension25="$249">View Deal</a></p></div><div class="product"><a data-dimension112="b6666626-90e6-11f1-b634-7b3f9ca7411a" data-action="Deal Block" data-label="FrostVault Cooler, 65qt" data-dimension48="FrostVault Cooler, 65qt" data-dimension25="$279" href="https://www.amazon.com/dp/B0DPN8XSP3?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1500px;"><p class="vanilla-image-block" style="padding-top:80.67%;"><img id="Aq25cPGp35tFCUDNNanm9A" name="FrostVault Cooler, 45-quart" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/Aq25cPGp35tFCUDNNanm9A.jpg" mos="" align="middle" fullscreen="" width="1500" height="1210" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0DPN8XSP3?" target="_blank" rel="nofollow" data-dimension112="b6666626-90e6-11f1-b634-7b3f9ca7411a" data-action="Deal Block" data-label="FrostVault Cooler, 65qt" data-dimension48="FrostVault Cooler, 65qt" data-dimension25="$279">FrostVault Cooler, 65qt: was $349 now $279</a></strong><br>The Ninja FrostVault cooler is a real star. With 65-quarts of capacity it can hold 97 cans, or 54 cans with ice, and will keep your food and beverages chilled for days. It also has a handy dry storage drawer, compartments to keep food separate, and 'all-terrain' wheels, It's a premium cooler that's worth snapping up.<a class="view-deal button" href="https://www.amazon.com/dp/B0DPN8XSP3?" target="_blank" rel="nofollow" data-dimension112="b6666626-90e6-11f1-b634-7b3f9ca7411a" data-action="Deal Block" data-label="FrostVault Cooler, 65qt" data-dimension48="FrostVault Cooler, 65qt" data-dimension25="$279">View Deal</a></p></div><div class="product"><a data-dimension112="b6666694-90e6-11f1-b7b3-b12bf3324e1e" data-action="Deal Block" data-label="Slushi Max Frozen Drink Maker" data-dimension48="Slushi Max Frozen Drink Maker" data-dimension25="$259" href="https://www.amazon.com/Ninja-FS301-Professional-RapidChill-Technology/dp/B0D2LZYQ2M?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:559px;"><p class="vanilla-image-block" style="padding-top:105.72%;"><img id="E3anx5fYk4a8xePxhgx2pZ" name="Ninja Slushi Max" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/E3anx5fYk4a8xePxhgx2pZ.png" mos="" align="middle" fullscreen="" width="559" height="591" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Ninja-FS301-Professional-RapidChill-Technology/dp/B0D2LZYQ2M?" target="_blank" rel="nofollow" data-dimension112="b6666694-90e6-11f1-b7b3-b12bf3324e1e" data-action="Deal Block" data-label="Slushi Max Frozen Drink Maker" data-dimension48="Slushi Max Frozen Drink Maker" data-dimension25="$259">Slushi Max Frozen Drink Maker: was $349 now $259</a></strong><br>The Slushi Max has a 88oz capacity that can make up to 7+drinks in one serving, making it ideal for hosting anytime of year. It's a relatively new release from Ninja, so this $90 discount is surprisingly generous. <a class="view-deal button" href="https://www.amazon.com/Ninja-FS301-Professional-RapidChill-Technology/dp/B0D2LZYQ2M?" target="_blank" rel="nofollow" data-dimension112="b6666694-90e6-11f1-b7b3-b12bf3324e1e" data-action="Deal Block" data-label="Slushi Max Frozen Drink Maker" data-dimension48="Slushi Max Frozen Drink Maker" data-dimension25="$259">View Deal</a></p></div><div class="product"><a data-dimension112="b6666702-90e6-11f1-81e2-65dff613702d" data-action="Deal Block" data-label="Woodfire Pizza Oven" data-dimension48="Woodfire Pizza Oven" data-dimension25="$299" href="https://www.amazon.com/Ninja-Woodfire-Technology-terracotta-OO101/dp/B0C6BQVDX3" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1666px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="W5gcaBRuDdjvCedzhvKyej" name="Outdoor oven.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/W5gcaBRuDdjvCedzhvKyej.jpg" mos="" align="middle" fullscreen="" width="1666" height="1666" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Ninja-Woodfire-Technology-terracotta-OO101/dp/B0C6BQVDX3" target="_blank" rel="nofollow" data-dimension112="b6666702-90e6-11f1-81e2-65dff613702d" data-action="Deal Block" data-label="Woodfire Pizza Oven" data-dimension48="Woodfire Pizza Oven" data-dimension25="$299">Woodfire Pizza Oven: was $399 now $299</a></strong><br>If you’re a fan of cooking outdoors, this is the deal for you. This outdoor pizza oven offers eight functions, including pizza, max roast, specialty roast and smoker amongst others, so it’s by no means limited to just pizza. Powered by electricity, it can reach up to 700°F, plus there’s the option to add wood pellets if you want smoked food too. The capacity can hold a 12 lb turkey or a 12-inch pizza, which is generous enough. <a class="view-deal button" href="https://www.amazon.com/Ninja-Woodfire-Technology-terracotta-OO101/dp/B0C6BQVDX3" target="_blank" rel="nofollow" data-dimension112="b6666702-90e6-11f1-81e2-65dff613702d" data-action="Deal Block" data-label="Woodfire Pizza Oven" data-dimension48="Woodfire Pizza Oven" data-dimension25="$299">View Deal</a></p></div><div class="product"><a data-dimension112="b6666770-90e6-11f1-ae55-77f3c466d6fb" data-action="Deal Block" data-label="FlexFlame Propane Grill" data-dimension48="FlexFlame Propane Grill" data-dimension25="$999" href="https://www.amazon.com/Ninja-FlexFlame-Electric-Stainless-PG301/dp/B0DSY91FF8?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1000px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="iaK255T8K7gB57X7ZEG77H" name="PG301_WEBR_GalleryImages_1 (1) copy" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/iaK255T8K7gB57X7ZEG77H.jpg" mos="" align="middle" fullscreen="" width="1000" height="1000" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Ninja-FlexFlame-Electric-Stainless-PG301/dp/B0DSY91FF8?" target="_blank" rel="nofollow" data-dimension112="b6666770-90e6-11f1-ae55-77f3c466d6fb" data-action="Deal Block" data-label="FlexFlame Propane Grill" data-dimension48="FlexFlame Propane Grill" data-dimension25="$999">FlexFlame Propane Grill: was $1119 now $999</a></strong><br>The Ninja FlexFlame is Ninja's first attempt at a propane grill, and it offers all the ingeniuity you'd expect from a Ninja product. It's got a pellet chamber to infuse your food with an authentic smoked flavor, but can also sear and even be converted to a griddle with the use of add-ons.<a class="view-deal button" href="https://www.amazon.com/Ninja-FlexFlame-Electric-Stainless-PG301/dp/B0DSY91FF8?" target="_blank" rel="nofollow" data-dimension112="b6666770-90e6-11f1-ae55-77f3c466d6fb" data-action="Deal Block" data-label="FlexFlame Propane Grill" data-dimension48="FlexFlame Propane Grill" data-dimension25="$999">View Deal</a></p></div> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/home/kitchen-dining/amazon-just-slashed-prices-on-ninjas-best-kitchen-appliances-my-15-favorite-deals-start-at-usd59</link>
                                                                            <description>
                            <![CDATA[ Amazon is knocking up to 40% off Ninja kitchen appliances. Check out my favorite deals on air fryers, grills, blenders, coolers and more. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">LaaFsVxTyXdC5h93KMrtTa</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/EohkcmcnKPPxAavEYyuLuj-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Thu, 06 Aug 2026 12:00:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Kitchen & Dining]]></category>
                                                    <category><![CDATA[Home]]></category>
                                                    <category><![CDATA[Home Appliances]]></category>
                                                                                                                    <dc:creator><![CDATA[ Olivia Halevy ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/YAg7Fmh9dGKbg3hULBMWiU.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Olivia is a Deals Writer at Tom’s Guide. She loves all things lifestyle, shopping and sourcing the best deals from some of the top brands, retailers and websites around. From fashion and beauty to smart home and tech, she has an eye for finding practical, stylish, and reasonably-priced items that help make life simpler (and a little more aesthetically-pleasing).&amp;nbsp;Olivia has over five years of experience writing lifestyle, commerce, and branded content for &lt;a href=&quot;http://patch.com/&quot;&gt;Patch.com&lt;/a&gt;. She&#039;s covered major shopping holidays like Amazon Prime Day, Black Friday and Cyber Monday. In her free time, she enjoys trying out new exercise classes, binge-watching the latest viral TV shows, cooking, spending time with family and taking long walks with her dog, Gus.&amp;nbsp;&lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/EohkcmcnKPPxAavEYyuLuj-1280-80.jpg">
                                                            <media:credit><![CDATA[Amazon]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Ninja]]></media:description>                                                            <media:text><![CDATA[Ninja]]></media:text>
                                <media:title type="plain"><![CDATA[Ninja]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/EohkcmcnKPPxAavEYyuLuj-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Ninja makes some of my favorite kitchen appliances on the market — and right now, Amazon is offering some pretty impressive deals on the top-rated gadgets! You can score big savings on summer must-haves like coolers, slushy machines, grills, air fryers and much more.</p><p>Whether you're firing up the grill for a barbecue or you're hoping to simplify your weekly meal prep, <a href="https://www.amazon.com/stores/page/471F718E-0761-48DF-ABAF-0FC6590C695B?" target="_blank" rel="nofollow">Ninja is slashing up to 40% off its best-selling kitchen appliances</a>. And the best part? The deals start at just $59 and are the perfect finds for summer.</p><p>If you're in the market for some new cooking appliances, take it from me: Ninja is <em>the</em> brand to buy. Keep scrolling to check out my favorite Ninja picks from Amazon's sale. </p><h3 class="article-body__section" id="section-quick-links"><span>Quick Links</span></h3><ul><li><strong></strong><a href="https://www.sharkninja.com/sales-offers/shop-all-sale" target="_blank" rel="nofollow"><strong>shop all Ninja deals at Ninja</strong></a></li><li><a href="https://www.amazon.com/stores/page/471F718E-0761-48DF-ABAF-0FC6590C695B" target="_blank" rel="nofollow"><strong>shop all Ninja deals at Amazon</strong></a></li><li><strong>Ninja Blast Portable Blender: </strong><a href="https://www.amazon.com/dp/B0D2ZBNG9H?" target="_blank" rel="nofollow"><strong>was $69 now $59</strong></a></li><li><strong>Ninja Professional Blender: </strong><a href="https://www.amazon.com/Ninja-BR201AMZ-Professional-Smoothies-Dishwasher-Safe/dp/B00NGV4506?" target="_blank" rel="nofollow"><strong>was $109 now $89</strong></a><strong></strong></li><li><strong>Ninja Iced Coffee Maker: </strong><a href="https://www.amazon.com/Ninja-Specialty-Single-Serve-Compatible-PB055ABL/dp/B0C25Y15TL?" target="_blank" rel="nofollow"><strong>was $129 now $99</strong></a></li><li><strong>Ninja Backpack Cooler: </strong><a href="https://www.amazon.com/Ninja-Backpack-FrostVault-Leakproof-FF124CS/dp/B0F4Y5G8GF" target="_blank" rel="nofollow"><strong>was $199 now $179</strong></a></li><li><strong>Ninja Mega Kitchen System: </strong><a href="https://www.amazon.com/dp/B00939I7EK" target="_blank" rel="nofollow"><strong>was $219 now $179</strong></a></li><li><strong>Ninja FrostVault Cooler, 45qt: </strong><a href="https://www.amazon.com/Ninja-FrostVault-Insulated-Storage-FB245MR/dp/B0DPN8XSP3?" target="_blank" rel="nofollow"><strong>was $349 now $279</strong></a></li></ul><h3 class="article-body__section" id="section-ninja-deals"><span>Ninja Deals</span></h3><div class="product"><a data-dimension112="b6666144-90e6-11f1-9445-2586d3bf1a20" data-action="Deal Block" data-label="Blast Portable Blender" data-dimension48="Blast Portable Blender" data-dimension25="$59" href="https://www.amazon.com/dp/B0D2ZBNG9H?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:679px;"><p class="vanilla-image-block" style="padding-top:170.40%;"><img id="FCnJUW6WAsjjZShgBrxUa9" name="Ninja Blast.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/FCnJUW6WAsjjZShgBrxUa9.jpg" mos="" align="middle" fullscreen="" width="679" height="1157" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0D2ZBNG9H?" target="_blank" rel="nofollow" data-dimension112="b6666144-90e6-11f1-9445-2586d3bf1a20" data-action="Deal Block" data-label="Blast Portable Blender" data-dimension48="Blast Portable Blender" data-dimension25="$59">Blast Portable Blender: was $69 now $59</a></strong><br>We gave the <a href="https://www.tomsguide.com/home/home-appliances/ninja-blast-max-review">Blast a 4-star rating in our review</a>. While portable blenders struggle to compete with larger models, there's no denying that this portable model punches well above its weight in price and features. For $59, it's an absolute bargain.<a class="view-deal button" href="https://www.amazon.com/dp/B0D2ZBNG9H?" target="_blank" rel="nofollow" data-dimension112="b6666144-90e6-11f1-9445-2586d3bf1a20" data-action="Deal Block" data-label="Blast Portable Blender" data-dimension48="Blast Portable Blender" data-dimension25="$59">View Deal</a></p></div><div class="product"><a data-dimension112="b66661bc-90e6-11f1-81ec-df578338b884" data-action="Deal Block" data-label="Professional Blender" data-dimension48="Professional Blender" data-dimension25="$89" href="https://www.amazon.com/Ninja-BR201AMZ-Professional-Smoothies-Dishwasher-Safe/dp/B00NGV4506?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:679px;"><p class="vanilla-image-block" style="padding-top:162.30%;"><img id="sFftzctqbej7oaSQLEtBRj" name="Ninja Pro Blender" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/sFftzctqbej7oaSQLEtBRj.jpg" mos="" align="middle" fullscreen="" width="679" height="1102" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Ninja-BR201AMZ-Professional-Smoothies-Dishwasher-Safe/dp/B00NGV4506?" target="_blank" rel="nofollow" data-dimension112="b66661bc-90e6-11f1-81ec-df578338b884" data-action="Deal Block" data-label="Professional Blender" data-dimension48="Professional Blender" data-dimension25="$89">Professional Blender: was $109 now $89</a></strong><br>Be it daily smoothies or making ice cream, this blender can tackle it all, at the touch of a button. Also featured on our <a href="https://www.tomsguide.com/best-picks/best-blenders">best blenders</a> guide, this comes with 3 preset Auto-iQ programs that creates smoothies, frozen drinks, and ice cream, and its powerful blades can crush ice in no time. This is a great deal if you want an easy-to-use blender, with professional results.  <a class="view-deal button" href="https://www.amazon.com/Ninja-BR201AMZ-Professional-Smoothies-Dishwasher-Safe/dp/B00NGV4506?" target="_blank" rel="nofollow" data-dimension112="b66661bc-90e6-11f1-81ec-df578338b884" data-action="Deal Block" data-label="Professional Blender" data-dimension48="Professional Blender" data-dimension25="$89">View Deal</a></p></div><div class="product"><a data-dimension112="b666622a-90e6-11f1-bd1b-1db52dba49c6" data-action="Deal Block" data-label="Pods & Grounds Specialty Single-Serve Iced Coffee Maker" data-dimension48="Pods & Grounds Specialty Single-Serve Iced Coffee Maker" data-dimension25="$99" href="https://www.amazon.com/dp/B0C25Y15TL?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:679px;"><p class="vanilla-image-block" style="padding-top:99.56%;"><img id="4uiaRXRKY8Go6F4ZpM7UdA" name="Ninja coffee" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/4uiaRXRKY8Go6F4ZpM7UdA.jpg" mos="" align="middle" fullscreen="" width="679" height="676" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0C25Y15TL?" target="_blank" rel="nofollow" data-dimension112="b666622a-90e6-11f1-bd1b-1db52dba49c6" data-action="Deal Block" data-label="Pods & Grounds Specialty Single-Serve Iced Coffee Maker" data-dimension48="Pods & Grounds Specialty Single-Serve Iced Coffee Maker" data-dimension25="$99">Pods & Grounds Specialty Single-Serve Iced Coffee Maker: was $129 now $99</a></strong><br>This stylish Ninja coffee maker comes in a gorgeous Sage colorway and is now on sale for $30 off. Whether you prefer pods or grounds, this device makes tasty brews in 7 sizes (6-oz. to 24-oz) and has a built-in, fold-away milk frother!<a class="view-deal button" href="https://www.amazon.com/dp/B0C25Y15TL?" target="_blank" rel="nofollow" data-dimension112="b666622a-90e6-11f1-bd1b-1db52dba49c6" data-action="Deal Block" data-label="Pods & Grounds Specialty Single-Serve Iced Coffee Maker" data-dimension48="Pods & Grounds Specialty Single-Serve Iced Coffee Maker" data-dimension25="$99">View Deal</a></p></div><div class="product"><a data-dimension112="b66662a2-90e6-11f1-bc72-d9463eb6fedb" data-action="Deal Block" data-label="BlendBOSS Blender" data-dimension48="BlendBOSS Blender" data-dimension25="$109" href="https://www.amazon.com/Ninja-BlendbossTM-Detachable-Technology-DB351CY/dp/B0FSGSYF79?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1500px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="JkaewDaMJCoHarzBbjk5u8" name="Ninja BlendBOSS deal block" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/JkaewDaMJCoHarzBbjk5u8.jpg" mos="" align="middle" fullscreen="" width="1500" height="1500" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Ninja-BlendbossTM-Detachable-Technology-DB351CY/dp/B0FSGSYF79?" target="_blank" rel="nofollow" data-dimension112="b66662a2-90e6-11f1-bc72-d9463eb6fedb" data-action="Deal Block" data-label="BlendBOSS Blender" data-dimension48="BlendBOSS Blender" data-dimension25="$109">BlendBOSS Blender: was $129 now $109</a></strong><br>The Ninja BlendBOSS is one of the best personal blenders we've used. In our <a href="https://www.tomsguide.com/home/home-appliances/ninja-blendboss-review">Ninja BlendBOSS review</a>, we said the Editor's Choice blender is great at everything from making hummus to lump-free smoothies. Its' compact, comes in a range of colors, and it's simply the best personal blender you can buy at this price point. <a class="view-deal button" href="https://www.amazon.com/Ninja-BlendbossTM-Detachable-Technology-DB351CY/dp/B0FSGSYF79?" target="_blank" rel="nofollow" data-dimension112="b66662a2-90e6-11f1-bc72-d9463eb6fedb" data-action="Deal Block" data-label="BlendBOSS Blender" data-dimension48="BlendBOSS Blender" data-dimension25="$109">View Deal</a></p></div><div class="product"><a data-dimension112="b6666310-90e6-11f1-b1bf-834177ef4845" data-action="Deal Block" data-label="Flip Toaster Oven & Air Fryer" data-dimension48="Flip Toaster Oven & Air Fryer" data-dimension25="$149" href="https://www.amazon.com/Ninja-Functionality-Capability-Removable-SP151/dp/B0D1CXL52G" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:600px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="qey9zt42Hnq8ePgcaiiaR7" name="Ninja Flip" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/qey9zt42Hnq8ePgcaiiaR7.jpg" mos="" align="middle" fullscreen="" width="600" height="600" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Ninja-Functionality-Capability-Removable-SP151/dp/B0D1CXL52G" target="_blank" rel="nofollow" data-dimension112="b6666310-90e6-11f1-b1bf-834177ef4845" data-action="Deal Block" data-label="Flip Toaster Oven & Air Fryer" data-dimension48="Flip Toaster Oven & Air Fryer" data-dimension25="$149">Flip Toaster Oven & Air Fryer: was $249 now $149</a></strong><br>The Ninja Flip stainless steel model is also on sale. It has 8 functions in one convenient and versatile machine: air fry, roast, bake, toast, and more. When you're not using it, you can flip it up and away, which will give you 50% more counter space back.<a class="view-deal button" href="https://www.amazon.com/Ninja-Functionality-Capability-Removable-SP151/dp/B0D1CXL52G" target="_blank" rel="nofollow" data-dimension112="b6666310-90e6-11f1-b1bf-834177ef4845" data-action="Deal Block" data-label="Flip Toaster Oven & Air Fryer" data-dimension48="Flip Toaster Oven & Air Fryer" data-dimension25="$149">View Deal</a></p></div><div class="product"><a data-dimension112="b666637e-90e6-11f1-88ef-a5432b0ffbe6" data-action="Deal Block" data-label="Crispi 4-in-1 Portable Glass Air Fryer Cooking System" data-dimension48="Crispi 4-in-1 Portable Glass Air Fryer Cooking System" data-dimension25="$159" href="https://www.amazon.com/Ninja-Microwave-Dishwasher-Containers-FN101GY/dp/B0DDDD8WD6?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:679px;"><p class="vanilla-image-block" style="padding-top:85.86%;"><img id="zNkXNCVYCubXhCRwjaoGPj" name="Ninjs Crispi" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/zNkXNCVYCubXhCRwjaoGPj.jpg" mos="" align="middle" fullscreen="" width="679" height="583" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Ninja-Microwave-Dishwasher-Containers-FN101GY/dp/B0DDDD8WD6?" target="_blank" rel="nofollow" data-dimension112="b666637e-90e6-11f1-88ef-a5432b0ffbe6" data-action="Deal Block" data-label="Crispi 4-in-1 Portable Glass Air Fryer Cooking System" data-dimension48="Crispi 4-in-1 Portable Glass Air Fryer Cooking System" data-dimension25="$159">Crispi 4-in-1 Portable Glass Air Fryer Cooking System: was $179 now $159</a></strong><br>The Ninja Crispi is one of Ninja's most interesting releases. It features a removable cooking lid and interchangeable glass containers to cook meals of a range of sizes. In our <a href="https://www.tomsguide.com/home/air-fryers/ninja-crispi-air-fryer-review">Ninja Crispi review</a>, it earned a well-deserved 4.5 stars.  <a class="view-deal button" href="https://www.amazon.com/Ninja-Microwave-Dishwasher-Containers-FN101GY/dp/B0DDDD8WD6?" target="_blank" rel="nofollow" data-dimension112="b666637e-90e6-11f1-88ef-a5432b0ffbe6" data-action="Deal Block" data-label="Crispi 4-in-1 Portable Glass Air Fryer Cooking System" data-dimension48="Crispi 4-in-1 Portable Glass Air Fryer Cooking System" data-dimension25="$159">View Deal</a></p></div><div class="product"><a data-dimension112="b66663f6-90e6-11f1-bae6-83bce4e1c3b4" data-action="Deal Block" data-label="Backpack Cooler" data-dimension48="Backpack Cooler" data-dimension25="$179" href="https://www.amazon.com/Ninja-Backpack-FrostVault-Leakproof-FF124CS/dp/B0F4Y5G8GF" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:464px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="WW5AWCoTo6gey3CoZ7CHzk" name="Screenshot 2025-07-07 153631" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/WW5AWCoTo6gey3CoZ7CHzk.jpg" mos="" align="middle" fullscreen="" width="464" height="464" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>Ninja's backpack cooler is perfect for heading to the beach or having a picnic. It has a built-in cold dry zone to keep food dry and separate at under 40°F, holds ice for up to 24 hours, and has a top lid and side opening for easier access. It holds up to 24 cans, or 16 cans with ice. It even have a built in bottle opener.<a class="view-deal button" href="https://www.amazon.com/Ninja-Backpack-FrostVault-Leakproof-FF124CS/dp/B0F4Y5G8GF" target="_blank" rel="nofollow" data-dimension112="b66663f6-90e6-11f1-bae6-83bce4e1c3b4" data-action="Deal Block" data-label="Backpack Cooler" data-dimension48="Backpack Cooler" data-dimension25="$179">View Deal</a></p></div><div class="product"><a data-dimension112="b6666464-90e6-11f1-ba87-557c5b25b806" data-action="Deal Block" data-label="Mega Kitchen System" data-dimension48="Mega Kitchen System" data-dimension25="$179" href="https://www.amazon.com/dp/B00939I7EK" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1676px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="sWibiMn9jcqpLxyQRazy6f" name="Ninja Amazon 2.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/sWibiMn9jcqpLxyQRazy6f.jpg" mos="" align="middle" fullscreen="" width="1676" height="1676" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B00939I7EK" target="_blank" rel="nofollow" data-dimension112="b6666464-90e6-11f1-ba87-557c5b25b806" data-action="Deal Block" data-label="Mega Kitchen System" data-dimension48="Mega Kitchen System" data-dimension25="$179">Mega Kitchen System: was $219 now $179</a></strong><br>Leave all the multi-tasking in the kitchen to one appliance with this Ninja blender. With four functions for smoothies, processing, dough, drinks and more it will quickly become your go-to kitchen appliance. With this ultimate appliance, you’ll be enjoying fresh, healthy drinks, homemade bread and sweet bakes.<a class="view-deal button" href="https://www.amazon.com/dp/B00939I7EK" target="_blank" rel="nofollow" data-dimension112="b6666464-90e6-11f1-ba87-557c5b25b806" data-action="Deal Block" data-label="Mega Kitchen System" data-dimension48="Mega Kitchen System" data-dimension25="$179">View Deal</a></p></div><div class="product"><a data-dimension112="b66664d2-90e6-11f1-947c-7533996d7154" data-action="Deal Block" data-label="Foodi DualZone Air Fryer (DZ401)" data-dimension48="Foodi DualZone Air Fryer (DZ401)" data-dimension25="$199" href="https://www.amazon.com/Ninja-DZ401-Independent-Dehydrate-Family-Sized/dp/B0B15Q3HCQ?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1952px;"><p class="vanilla-image-block" style="padding-top:66.91%;"><img id="gibkomA9CKgWqZ8r2NX7f8" name="Ninja DZ401 Foodi" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/gibkomA9CKgWqZ8r2NX7f8.png" mos="" align="middle" fullscreen="" width="1952" height="1306" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Ninja-DZ401-Independent-Dehydrate-Family-Sized/dp/B0B15Q3HCQ?" target="_blank" rel="nofollow" data-dimension112="b66664d2-90e6-11f1-947c-7533996d7154" data-action="Deal Block" data-label="Foodi DualZone Air Fryer (DZ401)" data-dimension48="Foodi DualZone Air Fryer (DZ401)" data-dimension25="$199">Foodi DualZone Air Fryer (DZ401): was $229 now $199</a></strong><br>This relatively affordable dual-zone air fryer is one of Ninja's best. It's got the perks of SmartFinish and MatchCook, which will allow you to either sync two cooking settings to finish at the same time, or duplicate your settings to the other basket and maximize your space. <a class="view-deal button" href="https://www.amazon.com/Ninja-DZ401-Independent-Dehydrate-Family-Sized/dp/B0B15Q3HCQ?" target="_blank" rel="nofollow" data-dimension112="b66664d2-90e6-11f1-947c-7533996d7154" data-action="Deal Block" data-label="Foodi DualZone Air Fryer (DZ401)" data-dimension48="Foodi DualZone Air Fryer (DZ401)" data-dimension25="$199">View Deal</a></p></div><div class="product"><a data-dimension112="b6666540-90e6-11f1-a4c4-ab34db796060" data-action="Deal Block" data-label="FrostVault 30QT" data-dimension48="FrostVault 30QT" data-dimension25="$229" href="https://www.amazon.com/dp/B0DPNCDYCZ?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1509px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="zcrSfDSQ58GkQ5fatetyy9" name="1751644471.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/zcrSfDSQ58GkQ5fatetyy9.jpg" mos="" align="middle" fullscreen="" width="1509" height="1509" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0DPNCDYCZ?" target="_blank" rel="nofollow" data-dimension112="b6666540-90e6-11f1-a4c4-ab34db796060" data-action="Deal Block" data-label="FrostVault 30QT" data-dimension48="FrostVault 30QT" data-dimension25="$229">FrostVault 30QT: was $279 now $229</a></strong><br>If you don't think you need a massive cooler, you can still get a good deal on the 30QT model. This will fit 48 cans without ice or 28 cans with ice. It still keeps everything cold for days at a time, it's just smaller. It also has the cool dry zone, which lets you keep food and other items cool without all the moisture.<a class="view-deal button" href="https://www.amazon.com/dp/B0DPNCDYCZ?" target="_blank" rel="nofollow" data-dimension112="b6666540-90e6-11f1-a4c4-ab34db796060" data-action="Deal Block" data-label="FrostVault 30QT" data-dimension48="FrostVault 30QT" data-dimension25="$229">View Deal</a></p></div><div class="product"><a data-dimension112="b66665b8-90e6-11f1-a04a-438a5166aaf2" data-action="Deal Block" data-label="Double Stack XL Air Fryer & Toaster Oven Combo" data-dimension48="Double Stack XL Air Fryer & Toaster Oven Combo" data-dimension25="$249" href="https://www.amazon.com/Ninja-Countertop-Convection-Stainless-DT501/dp/B0D4R7DMYN?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:679px;"><p class="vanilla-image-block" style="padding-top:76.88%;"><img id="KybxnS8GerWMHfrZ6mQdvm" name="Ninja Air Fryer Toaster" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/KybxnS8GerWMHfrZ6mQdvm.jpg" mos="" align="middle" fullscreen="" width="679" height="522" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Ninja-Countertop-Convection-Stainless-DT501/dp/B0D4R7DMYN?" target="_blank" rel="nofollow" data-dimension112="b66665b8-90e6-11f1-a04a-438a5166aaf2" data-action="Deal Block" data-label="Double Stack XL Air Fryer & Toaster Oven Combo" data-dimension48="Double Stack XL Air Fryer & Toaster Oven Combo" data-dimension25="$249">Double Stack XL Air Fryer & Toaster Oven Combo: was $429 now $249</a></strong><br>When we got our hands on the <a href="https://www.tomsguide.com/home/home-appliances/ninja-prestige-smart-xl-air-fryer-oven-dt501-review">Ninja Prestige Smart XL Oven</a>, we were super impressed by its capacity, range of cooking functions and intuitive, easy-to-use controls. It's a great alternative for anyone not wanting a full-size oven or an XL air fryer in their kitchen. And right now the <a href="https://www.tomsguide.com/best-picks/best-toaster-ovens">best toaster oven</a> is $180 off. <a class="view-deal button" href="https://www.amazon.com/Ninja-Countertop-Convection-Stainless-DT501/dp/B0D4R7DMYN?" target="_blank" rel="nofollow" data-dimension112="b66665b8-90e6-11f1-a04a-438a5166aaf2" data-action="Deal Block" data-label="Double Stack XL Air Fryer & Toaster Oven Combo" data-dimension48="Double Stack XL Air Fryer & Toaster Oven Combo" data-dimension25="$249">View Deal</a></p></div><div class="product"><a data-dimension112="b6666626-90e6-11f1-b634-7b3f9ca7411a" data-action="Deal Block" data-label="FrostVault Cooler, 65qt" data-dimension48="FrostVault Cooler, 65qt" data-dimension25="$279" href="https://www.amazon.com/dp/B0DPN8XSP3?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1500px;"><p class="vanilla-image-block" style="padding-top:80.67%;"><img id="Aq25cPGp35tFCUDNNanm9A" name="FrostVault Cooler, 45-quart" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/Aq25cPGp35tFCUDNNanm9A.jpg" mos="" align="middle" fullscreen="" width="1500" height="1210" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0DPN8XSP3?" target="_blank" rel="nofollow" data-dimension112="b6666626-90e6-11f1-b634-7b3f9ca7411a" data-action="Deal Block" data-label="FrostVault Cooler, 65qt" data-dimension48="FrostVault Cooler, 65qt" data-dimension25="$279">FrostVault Cooler, 65qt: was $349 now $279</a></strong><br>The Ninja FrostVault cooler is a real star. With 65-quarts of capacity it can hold 97 cans, or 54 cans with ice, and will keep your food and beverages chilled for days. It also has a handy dry storage drawer, compartments to keep food separate, and 'all-terrain' wheels, It's a premium cooler that's worth snapping up.<a class="view-deal button" href="https://www.amazon.com/dp/B0DPN8XSP3?" target="_blank" rel="nofollow" data-dimension112="b6666626-90e6-11f1-b634-7b3f9ca7411a" data-action="Deal Block" data-label="FrostVault Cooler, 65qt" data-dimension48="FrostVault Cooler, 65qt" data-dimension25="$279">View Deal</a></p></div><div class="product"><a data-dimension112="b6666694-90e6-11f1-b7b3-b12bf3324e1e" data-action="Deal Block" data-label="Slushi Max Frozen Drink Maker" data-dimension48="Slushi Max Frozen Drink Maker" data-dimension25="$259" href="https://www.amazon.com/Ninja-FS301-Professional-RapidChill-Technology/dp/B0D2LZYQ2M?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:559px;"><p class="vanilla-image-block" style="padding-top:105.72%;"><img id="E3anx5fYk4a8xePxhgx2pZ" name="Ninja Slushi Max" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/E3anx5fYk4a8xePxhgx2pZ.png" mos="" align="middle" fullscreen="" width="559" height="591" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Ninja-FS301-Professional-RapidChill-Technology/dp/B0D2LZYQ2M?" target="_blank" rel="nofollow" data-dimension112="b6666694-90e6-11f1-b7b3-b12bf3324e1e" data-action="Deal Block" data-label="Slushi Max Frozen Drink Maker" data-dimension48="Slushi Max Frozen Drink Maker" data-dimension25="$259">Slushi Max Frozen Drink Maker: was $349 now $259</a></strong><br>The Slushi Max has a 88oz capacity that can make up to 7+drinks in one serving, making it ideal for hosting anytime of year. It's a relatively new release from Ninja, so this $90 discount is surprisingly generous. <a class="view-deal button" href="https://www.amazon.com/Ninja-FS301-Professional-RapidChill-Technology/dp/B0D2LZYQ2M?" target="_blank" rel="nofollow" data-dimension112="b6666694-90e6-11f1-b7b3-b12bf3324e1e" data-action="Deal Block" data-label="Slushi Max Frozen Drink Maker" data-dimension48="Slushi Max Frozen Drink Maker" data-dimension25="$259">View Deal</a></p></div><div class="product"><a data-dimension112="b6666702-90e6-11f1-81e2-65dff613702d" data-action="Deal Block" data-label="Woodfire Pizza Oven" data-dimension48="Woodfire Pizza Oven" data-dimension25="$299" href="https://www.amazon.com/Ninja-Woodfire-Technology-terracotta-OO101/dp/B0C6BQVDX3" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1666px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="W5gcaBRuDdjvCedzhvKyej" name="Outdoor oven.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/W5gcaBRuDdjvCedzhvKyej.jpg" mos="" align="middle" fullscreen="" width="1666" height="1666" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Ninja-Woodfire-Technology-terracotta-OO101/dp/B0C6BQVDX3" target="_blank" rel="nofollow" data-dimension112="b6666702-90e6-11f1-81e2-65dff613702d" data-action="Deal Block" data-label="Woodfire Pizza Oven" data-dimension48="Woodfire Pizza Oven" data-dimension25="$299">Woodfire Pizza Oven: was $399 now $299</a></strong><br>If you’re a fan of cooking outdoors, this is the deal for you. This outdoor pizza oven offers eight functions, including pizza, max roast, specialty roast and smoker amongst others, so it’s by no means limited to just pizza. Powered by electricity, it can reach up to 700°F, plus there’s the option to add wood pellets if you want smoked food too. The capacity can hold a 12 lb turkey or a 12-inch pizza, which is generous enough. <a class="view-deal button" href="https://www.amazon.com/Ninja-Woodfire-Technology-terracotta-OO101/dp/B0C6BQVDX3" target="_blank" rel="nofollow" data-dimension112="b6666702-90e6-11f1-81e2-65dff613702d" data-action="Deal Block" data-label="Woodfire Pizza Oven" data-dimension48="Woodfire Pizza Oven" data-dimension25="$299">View Deal</a></p></div><div class="product"><a data-dimension112="b6666770-90e6-11f1-ae55-77f3c466d6fb" data-action="Deal Block" data-label="FlexFlame Propane Grill" data-dimension48="FlexFlame Propane Grill" data-dimension25="$999" href="https://www.amazon.com/Ninja-FlexFlame-Electric-Stainless-PG301/dp/B0DSY91FF8?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1000px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="iaK255T8K7gB57X7ZEG77H" name="PG301_WEBR_GalleryImages_1 (1) copy" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/iaK255T8K7gB57X7ZEG77H.jpg" mos="" align="middle" fullscreen="" width="1000" height="1000" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Ninja-FlexFlame-Electric-Stainless-PG301/dp/B0DSY91FF8?" target="_blank" rel="nofollow" data-dimension112="b6666770-90e6-11f1-ae55-77f3c466d6fb" data-action="Deal Block" data-label="FlexFlame Propane Grill" data-dimension48="FlexFlame Propane Grill" data-dimension25="$999">FlexFlame Propane Grill: was $1119 now $999</a></strong><br>The Ninja FlexFlame is Ninja's first attempt at a propane grill, and it offers all the ingeniuity you'd expect from a Ninja product. It's got a pellet chamber to infuse your food with an authentic smoked flavor, but can also sear and even be converted to a griddle with the use of add-ons.<a class="view-deal button" href="https://www.amazon.com/Ninja-FlexFlame-Electric-Stainless-PG301/dp/B0DSY91FF8?" target="_blank" rel="nofollow" data-dimension112="b6666770-90e6-11f1-ae55-77f3c466d6fb" data-action="Deal Block" data-label="FlexFlame Propane Grill" data-dimension48="FlexFlame Propane Grill" data-dimension25="$999">View Deal</a></p></div>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ Tefal X-Clean 7 review: this speedy, lightweight hardfloor washer is pet-approved, but its cleaning prompts had me confused ]]></title>
                                                                                                <dc:content><![CDATA[ <div  class="fancy-box"><div class="fancy_box-title">Tefal X-Clean 7 specs</div><div class="fancy_box_body"><p class="fancy-box__body-text"><strong>Price: </strong>£449 / AU$799<br><strong>Weight: </strong>1.9lbs / 0.9 kg<br><strong>Suction power: </strong>20,000Pa<br><strong>Maximum runtime:</strong> 50 minutes (on Eco mode)<br><strong>Charging time: </strong>4 hours<br><strong>Clean water tank size:</strong> 650ml<br><strong>Used water tank size: </strong>500ml</p></div></div><p>Founded in 1956, Tefal is a major brand in the kitchen and dining market, renowned for its non-stick pots, pans and home appliances. More recently, though, Tefal has entered into the realm of floorcare with its wet-and-dry vacuums, otherwise known as the X-Clean line. </p><p>The latest entry is the Tefal X-Clean 7, which debuted earlier this year. The machine is touted as able to clean hard floors faster with 20,000Pa suction power and weighing just 1.9lbs / 0.9 kg in the hand. </p><p>I was particularly intrigued by the brand's foray into floorcare, as it is synonymous with great kitchen appliances and cookware — I swear by my Tefal Non-Stick Fry pan — so the move felt left-of-field. However, there are only so many pans, pots and cooking utensils one company can make, and the brand prides itself on innovation, so it's only fair to switch things up. (And spoiler alert: the X-Clean 7 adds another good impression on the brand's name.) </p><p>As someone whose home features predominantly hardwood floors, which are regularly covered in muddy pawprints and kitty litter, I am no stranger to floorwashers. And after reviewing a few floorwashers and consequently ditching my mop bucket for the wet-dry life, I knew I was well placed to take on this review. But could the X-Clean 7 tackle stubborn stains, puppy accidents and everyday maintenance of my hard floors? I tested it for three months to find out. </p><h3 class="article-body__section" id="section-tefal-x-clean-7-review-price-and-availability"><span>Tefal X-Clean 7 review: Price and availability</span></h3><p>In Australia, where I'm based, the Tefal X-Clean 7 retails at AU$799. At the time of writing, it has been discounted at various retailers to AU$599, including on <a href="https://www.tefal.com.au/products/tefal-x-clean-7-cordless-vacuum-floor-washer-gf5736">Tefal's website</a>. In the U.K., it retails for £449. Unfortunately, it is currently not available in the U.S. The Tefal X-Clean 7 sits in the mid-range price bracket for floorwashers, fitting snugly between most Tineco and Dreame models. </p><h3 class="article-body__section" id="section-tefal-x-clean-7-review-design"><span>Tefal X-Clean 7 review: Design</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:4038px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="aWWGpWaYJhBaWtBFxEKT26" name="tefal-4" alt="Tefal X-Clean 7 in use on hardwood floors" src="https://cdn.mos.cms.futurecdn.net/aWWGpWaYJhBaWtBFxEKT26.jpg" mos="" align="middle" fullscreen="" width="4038" height="2271" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Lucy Scotting)</span></figcaption></figure><p>After reviewing several floorwashers, I can confidently say this is the lightest one I've ever used. Weighing only 1.9lbs / 0.9kg in the hand, the Tefal X-Clean 7 is easy to push around, carry up stairs and get under furniture with its 180° lay-flat design. However, when both water tanks are full (the dirty tank holds 17 fl oz / 500ml and the clean tank holds 22 fl oz / 650ml), the weight does, of course, increase. </p><p>Tefal's design mimics newer floorwashers of late, with a flush-sitting clean water tank atop the brush roller and the dirty tank located at the front of the machine. Tefal's machine eliminated a gripe I had while testing the Tineco S9 Artist Pro, as the opening for the clean water tank sits on top, rather than the side. This caused fewer leaks — you'll always have a small leak if the tank is too full when closing — but I had no issues with it leaking on the floor or during transit. Optionally, you can also purchase Tefal's cleaning solution for the clean water tank, but it's not necessary. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:5712px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="mr4JjR84VaQDxB47Hjjfx6" name="tefal-1" alt="Tefal X-Clean 7 in use on hardwood floors" src="https://cdn.mos.cms.futurecdn.net/mr4JjR84VaQDxB47Hjjfx6.jpg" mos="" align="middle" fullscreen="" width="5712" height="3213" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Lucy Scotting)</span></figcaption></figure><p>There's a round LED screen above the dirty water tank that displays battery life, cleaning modes and system alerts. The screen has an always-on setting and displays charging and battery life when on the dock. There are two accompanying buttons on the handle — the power button and the mode button, which cycle through the cleaning functions — above the LED screen, alongside the self-cleaning button at the very top of the handle. There's also a voice assistant — which can be switched on and off using a button on the back of the device — that provides alerts. I always knew which mode I was using, how much battery was left and when I needed to clean the dirty water tank. </p><p>However, I found the voice assistant was a bit limited in its responses (more on that later) and was rather loud during my first few uses. There is a volume button on the side of the device, and if you're sensitive to noise, I'd suggest cranking it down (or turning it off entirely). </p><p>There are three modes on the X-Clean 7: Auto, Max and Eco. If you're not sure which one to use, I'd suggest opting for Auto to begin with, as the X-Clean 7 will automatically detect dirt and adjust water flow and suction power to clean your floors. As per the manual, Max mode is for very dirty surfaces, with maximum suction and water flow levels, and Eco mode is for moderately dirty floors, with medium suction and water flow. </p><figure role="gallery"><figure><img src="https://cdn.mos.cms.futurecdn.net/w9p4JKVmag8FcPcHkhohe4.jpg" alt="Tefal X-Clean 7 in use on hardwood floors" /><figcaption><small role="credit">Future / Lucy Scotting</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/epZh3NJpYtGKYda8vW7ck.jpg" alt="Tefal X-Clean 7 in use on hardwood floors" /><figcaption><small role="credit">Future / Lucy Scotting</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/uCWsQoBgmzGNDc5GxhA6N3.jpg" alt="Tefal X-Clean 7 in use on hardwood floors" /><figcaption><small role="credit">Future / Lucy Scotting</small></figcaption></figure></figure><p>While cleaning in any mode, the X-Clean 7 uses 20,000Pa suction power and claims to deliver up to 50 minutes of runtime in Eco mode and up to 27 minutes in Max mode. Both of these claims are pretty standard for floorwashers. The X-Clean 7's roller also comes with an anti-tangle comb, which uses 164 metallic teeth to prevent any tangles. </p><p>The X-Clean 7 also offers great maneuverability, thanks to some seriously speedy self-propulsion. It's similar to an electric bike or e-scooter — it won't drive itself, but it can give you noticeable assistance when removing tough stains without overexerting yourself. The wheels are super durable and have a great range of motion for getting under furniture and into all the nooks and crannies of your home. Plus, when completely flat, it measures at 13cm high, so it'll easily fit under most couches or tables. It'll even light up any hidden dust bunnies, thanks to a strip of seriously bright LEDs on the front of the brush head.</p><p>Additionally, the box also contains the dock, a cleaning brush, an extra brush roller, and a new filter for the used water tank. You'll need to set up the dock before use, as it charges the device and runs the self-cleaning and drying programs. Do keep in mind that the dock requires a fair amount of floor real estate, so you'll need a dedicated room (or cupboard) for it. </p><h3 class="article-body__section" id="section-tefal-x-clean-7-review-performance"><span>Tefal X-Clean 7 review: Performance</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:3815px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="N74CZoaRZwQzUh9337bMc6" name="tefal-5" alt="Tefal X-Clean 7 in use on hardwood floors" src="https://cdn.mos.cms.futurecdn.net/N74CZoaRZwQzUh9337bMc6.jpg" mos="" align="middle" fullscreen="" width="3815" height="2146" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Lucy Scotting)</span></figcaption></figure><p>Over the past three months, I've used the Tefal X-Clean 7 daily on my hardwood floors and tiles in my home. It's helped clean up everyday messes in the kitchen, including spilt coffees, as well as the occasional accident of my not-fully-housetrained puppy. The X-Clean 7 has excelled in every situation it faced. </p><p>Before the first use, I popped it onto the dock, and it took 3.5 hours to reach a full battery. After charging, I put it to the test with some (inconveniently) spilled coffee in my kitchen after missing my cup while making my morning brew. And sure enough, Auto mode easily sucked it up without worry. It left a slightly damp patch in its wake; however, it was much less damp than grabbing my mop and swirling it around (and making more of a mess). </p><p>After a few minutes, the floor was rather dry and fine to walk on, so I cleaned the rest of my kitchen and connected living room floors. These are the most high-traffic areas in my house, and my floors are often covered in muddy pawprints, crumbs and copious amounts of dog hair left behind by my two Border Collies. I easily cleaned the entire area within 15 minutes on Auto mode, and still had plenty of battery life to spare. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:4390px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="QWNyMTtNf6D58UzfPmxyX7" name="tefal-10" alt="Tefal X-Clean 7 in use on hardwood floors" src="https://cdn.mos.cms.futurecdn.net/QWNyMTtNf6D58UzfPmxyX7.jpg" mos="" align="middle" fullscreen="" width="4390" height="2469" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Lucy Scotting)</span></figcaption></figure><p>Case in point, our puppy, who hasn't fully taken to housetraining just yet, would have the occasional accident inside, and I found Max mode tackled pee puddles with ease. The maximum suction completely vacuumed up puddles without a trace. And if there was any dog hair lying around, the roller didn't tangle or have any blockages, with most stray hairs sitting in between the teeth of the metal comb. Not only that, I could easily take on any spilled liquids in two passes on Max mode and call it a day, which was very much a win in my book. </p><p>Sticky messes took some extra pushes, but overall, the Tefal X-Clean 7 could just as easily tackle a stuck sauce stain. It also did a commendable job of collecting kitty litter and smaller wet crumbs in all three modes. </p><p>That said, I didn't opt for Eco mode much — I largely used Auto or Max mode depending on what I needed to clean — but I did use it a few times on my tiled bathroom floors and in my shower when I didn't want to break out my mop. I didn't notice any major differences between Eco and Auto modes in this instance, but it's a nice mode to have if you're conscious of conserving the battery life. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:5100px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="gFTfsr5c5xm9bWYtqa7kz8" name="tefal-12" alt="Tefal X-Clean 7 in use on hardwood floors" src="https://cdn.mos.cms.futurecdn.net/gFTfsr5c5xm9bWYtqa7kz8.jpg" mos="" align="middle" fullscreen="" width="5100" height="2869" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Lucy Scotting)</span></figcaption></figure><p>I also don't own a mansion — rather a two-bed, two-bath apartment — and I could easily clean my hard floors in 15 minutes on Max mode, if not less. If you're mindful of which mode you use, you could easily clean your entire house on a single charge. That said, I did have to frequently refill the clean water tank after every second clean, as it is considerably smaller than other floorwashers I've used. This isn't a big drawback — even high-end models, like the Dyson Wash G1, have smaller water tanks — but if you have a bigger home, you may need to refill it more regularly. </p><p>The X-Clean 7 can leave a bit of streaking on darker floors, but it didn't bother me too much and would easily fade a day or two post-clean. </p><h3 class="article-body__section" id="section-tefal-x-clean-7-review-ease-of-cleaning"><span>Tefal X-Clean 7 review: Ease of cleaning</span></h3><figure role="gallery"><figure><img src="https://cdn.mos.cms.futurecdn.net/tL9eJDUUBcaMLR7CppmdV9.jpg" alt="Tefal X-Clean 7 in use on hardwood floors" /><figcaption><small role="credit">Future / Lucy Scotting</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/VMaJKariKFJZW69HB4mP77.jpg" alt="Tefal X-Clean 7 in use on hardwood floors" /><figcaption><small role="credit">Future / Lucy Scotting</small></figcaption></figure></figure><p>Like other wet-dry vacuums, the Tefal X-Clean 7 requires regular cleaning and emptying of the water tanks to avoid odor and bacteria build-up. If you leave the voice assistant on, it will remind you to empty and clean the dirty water tank after each use and after a self-clean cycle. </p><p>However, I found the voice prompts aren't that detailed and will revert to using the same phrase for at least three manual cleaning tasks. In my case, the device would consistently alert me to empty the dirty water tank after emptying/self-cleaning, and wouldn't let me use the device. In most cases, I had emptied the tank, and the clean water tank was full, so in essence, it should have switched on just fine. However, some of these alerts meant I needed to clean the filter or the pipe underneath, rather than just empty the tank. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:4893px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="Ff99b9hTQGwnKFATZDsKt5" name="tefal-9" alt="Tefal X-Clean 7 in use on hardwood floors" src="https://cdn.mos.cms.futurecdn.net/Ff99b9hTQGwnKFATZDsKt5.jpg" mos="" align="middle" fullscreen="" width="4893" height="2752" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Lucy Scotting)</span></figcaption></figure><p>I'm not sure why the brand hasn't differentiated these tasks via the voice prompt — or at least provided a different alert on the LED screen — as they are completely different and largely separate from emptying the dirty water tank. Regardless, I just made sure to check all variables after each voice prompt from then on, as I couldn't rely on the machine just needing the dirty water tank emptied. However, this could be an issue with my particular unit and not impact all users. </p><p>Aside from this inconvenience, the self-cleaning and drying functions were easy enough to do by pressing the self-cleaning button on the handle. The self-clean function lasted about 3 minutes, and the dock rinsed the roller brush. Afterwards, the self-drying function dries the roller, and the whole process lasts around 30 minutes. </p><h3 class="article-body__section" id="section-tefal-x-clean-7-review-verdict"><span>Tefal X-Clean 7 review: Verdict</span></h3><p>Overall, I was thoroughly impressed by the Tefal X-Clean 7 for its powerful suction modes and lightweight maneuverability. It's easy to use, has speedy self-propulsion, and you won't wait long for your floors to dry after a clean. It can easily clean up spilled liquids, stuck-on stains and the occasional hair or crumb under its roller too, making it perfect for homes with pets or kids. </p><p>However, it could benefit from larger water tanks and an intuitive voice assistant with more detailed prompts. But if you regularly clean it and keep maintenance low by doing so, you'll have no trouble washing your hard floors with Tefal's X-Clean 7. </p> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/home/home-appliances/tefal-x-clean-7-review-this-speedy-lightweight-hardfloor-washer-is-pet-approved-but-its-bizarre-cleaning-prompts-have-me-confused</link>
                                                                            <description>
                            <![CDATA[ I've used the Tefal X-Clean 7 wet and dry vacuum in my home for the past three months — here's how it fared. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">TvU5b94rMgM9gBaG9WmFWR</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/eKXCfMjUr7VFiVgghD9bMP-1280-80.png" type="image/png" length="0"></enclosure>
                                                                        <pubDate>Tue, 04 Aug 2026 00:56:01 +0000</pubDate>                                                                                                                                <updated>Mon, 10 Aug 2026 08:28:39 +0000</updated>
                                                                                                                                            <category><![CDATA[Home Appliances]]></category>
                                                    <category><![CDATA[Home]]></category>
                                                                                                <author><![CDATA[ lucy.scotting@futurenet.com (Lucy Scotting) ]]></author>                    <dc:creator><![CDATA[ Lucy Scotting ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/UC9ncAYxkmJ5ipHEyX44ri.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Lucy Scotting is a staff writer for Tom’s Guide Australia, primarily covering lifestyle, streaming and internet-related news. Lucy started her career writing for HR and staffing industry publications, with articles covering emerging tech, business and finance.&lt;/p&gt;&lt;p&gt;In her spare time, Lucy can be found watching sci-fi movies, working on her dystopian fiction novel (in progress since 2017) or hanging out with her dog, Fletcher. If she’s not found doing any of the above, she’s likely on her next adventure to a new city, country, or continent. &lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                <media:content type="image/png" url="https://cdn.mos.cms.futurecdn.net/eKXCfMjUr7VFiVgghD9bMP-1280-80.png">
                                                            <media:credit><![CDATA[Tefal]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Tefal X-Clean lifestyle image]]></media:description>                                                            <media:text><![CDATA[Tefal X-Clean lifestyle image]]></media:text>
                                <media:title type="plain"><![CDATA[Tefal X-Clean lifestyle image]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/eKXCfMjUr7VFiVgghD9bMP-1280-80.png" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <div  class="fancy-box"><div class="fancy_box-title">Tefal X-Clean 7 specs</div><div class="fancy_box_body"><p class="fancy-box__body-text"><strong>Price: </strong>£449 / AU$799<br><strong>Weight: </strong>1.9lbs / 0.9 kg<br><strong>Suction power: </strong>20,000Pa<br><strong>Maximum runtime:</strong> 50 minutes (on Eco mode)<br><strong>Charging time: </strong>4 hours<br><strong>Clean water tank size:</strong> 650ml<br><strong>Used water tank size: </strong>500ml</p></div></div><p>Founded in 1956, Tefal is a major brand in the kitchen and dining market, renowned for its non-stick pots, pans and home appliances. More recently, though, Tefal has entered into the realm of floorcare with its wet-and-dry vacuums, otherwise known as the X-Clean line. </p><p>The latest entry is the Tefal X-Clean 7, which debuted earlier this year. The machine is touted as able to clean hard floors faster with 20,000Pa suction power and weighing just 1.9lbs / 0.9 kg in the hand. </p><p>I was particularly intrigued by the brand's foray into floorcare, as it is synonymous with great kitchen appliances and cookware — I swear by my Tefal Non-Stick Fry pan — so the move felt left-of-field. However, there are only so many pans, pots and cooking utensils one company can make, and the brand prides itself on innovation, so it's only fair to switch things up. (And spoiler alert: the X-Clean 7 adds another good impression on the brand's name.) </p><p>As someone whose home features predominantly hardwood floors, which are regularly covered in muddy pawprints and kitty litter, I am no stranger to floorwashers. And after reviewing a few floorwashers and consequently ditching my mop bucket for the wet-dry life, I knew I was well placed to take on this review. But could the X-Clean 7 tackle stubborn stains, puppy accidents and everyday maintenance of my hard floors? I tested it for three months to find out. </p><h3 class="article-body__section" id="section-tefal-x-clean-7-review-price-and-availability"><span>Tefal X-Clean 7 review: Price and availability</span></h3><p>In Australia, where I'm based, the Tefal X-Clean 7 retails at AU$799. At the time of writing, it has been discounted at various retailers to AU$599, including on <a href="https://www.tefal.com.au/products/tefal-x-clean-7-cordless-vacuum-floor-washer-gf5736">Tefal's website</a>. In the U.K., it retails for £449. Unfortunately, it is currently not available in the U.S. The Tefal X-Clean 7 sits in the mid-range price bracket for floorwashers, fitting snugly between most Tineco and Dreame models. </p><h3 class="article-body__section" id="section-tefal-x-clean-7-review-design"><span>Tefal X-Clean 7 review: Design</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:4038px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="aWWGpWaYJhBaWtBFxEKT26" name="tefal-4" alt="Tefal X-Clean 7 in use on hardwood floors" src="https://cdn.mos.cms.futurecdn.net/aWWGpWaYJhBaWtBFxEKT26.jpg" mos="" align="middle" fullscreen="" width="4038" height="2271" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Lucy Scotting)</span></figcaption></figure><p>After reviewing several floorwashers, I can confidently say this is the lightest one I've ever used. Weighing only 1.9lbs / 0.9kg in the hand, the Tefal X-Clean 7 is easy to push around, carry up stairs and get under furniture with its 180° lay-flat design. However, when both water tanks are full (the dirty tank holds 17 fl oz / 500ml and the clean tank holds 22 fl oz / 650ml), the weight does, of course, increase. </p><p>Tefal's design mimics newer floorwashers of late, with a flush-sitting clean water tank atop the brush roller and the dirty tank located at the front of the machine. Tefal's machine eliminated a gripe I had while testing the Tineco S9 Artist Pro, as the opening for the clean water tank sits on top, rather than the side. This caused fewer leaks — you'll always have a small leak if the tank is too full when closing — but I had no issues with it leaking on the floor or during transit. Optionally, you can also purchase Tefal's cleaning solution for the clean water tank, but it's not necessary. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:5712px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="mr4JjR84VaQDxB47Hjjfx6" name="tefal-1" alt="Tefal X-Clean 7 in use on hardwood floors" src="https://cdn.mos.cms.futurecdn.net/mr4JjR84VaQDxB47Hjjfx6.jpg" mos="" align="middle" fullscreen="" width="5712" height="3213" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Lucy Scotting)</span></figcaption></figure><p>There's a round LED screen above the dirty water tank that displays battery life, cleaning modes and system alerts. The screen has an always-on setting and displays charging and battery life when on the dock. There are two accompanying buttons on the handle — the power button and the mode button, which cycle through the cleaning functions — above the LED screen, alongside the self-cleaning button at the very top of the handle. There's also a voice assistant — which can be switched on and off using a button on the back of the device — that provides alerts. I always knew which mode I was using, how much battery was left and when I needed to clean the dirty water tank. </p><p>However, I found the voice assistant was a bit limited in its responses (more on that later) and was rather loud during my first few uses. There is a volume button on the side of the device, and if you're sensitive to noise, I'd suggest cranking it down (or turning it off entirely). </p><p>There are three modes on the X-Clean 7: Auto, Max and Eco. If you're not sure which one to use, I'd suggest opting for Auto to begin with, as the X-Clean 7 will automatically detect dirt and adjust water flow and suction power to clean your floors. As per the manual, Max mode is for very dirty surfaces, with maximum suction and water flow levels, and Eco mode is for moderately dirty floors, with medium suction and water flow. </p><figure role="gallery"><figure><img src="https://cdn.mos.cms.futurecdn.net/w9p4JKVmag8FcPcHkhohe4.jpg" alt="Tefal X-Clean 7 in use on hardwood floors" /><figcaption><small role="credit">Future / Lucy Scotting</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/epZh3NJpYtGKYda8vW7ck.jpg" alt="Tefal X-Clean 7 in use on hardwood floors" /><figcaption><small role="credit">Future / Lucy Scotting</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/uCWsQoBgmzGNDc5GxhA6N3.jpg" alt="Tefal X-Clean 7 in use on hardwood floors" /><figcaption><small role="credit">Future / Lucy Scotting</small></figcaption></figure></figure><p>While cleaning in any mode, the X-Clean 7 uses 20,000Pa suction power and claims to deliver up to 50 minutes of runtime in Eco mode and up to 27 minutes in Max mode. Both of these claims are pretty standard for floorwashers. The X-Clean 7's roller also comes with an anti-tangle comb, which uses 164 metallic teeth to prevent any tangles. </p><p>The X-Clean 7 also offers great maneuverability, thanks to some seriously speedy self-propulsion. It's similar to an electric bike or e-scooter — it won't drive itself, but it can give you noticeable assistance when removing tough stains without overexerting yourself. The wheels are super durable and have a great range of motion for getting under furniture and into all the nooks and crannies of your home. Plus, when completely flat, it measures at 13cm high, so it'll easily fit under most couches or tables. It'll even light up any hidden dust bunnies, thanks to a strip of seriously bright LEDs on the front of the brush head.</p><p>Additionally, the box also contains the dock, a cleaning brush, an extra brush roller, and a new filter for the used water tank. You'll need to set up the dock before use, as it charges the device and runs the self-cleaning and drying programs. Do keep in mind that the dock requires a fair amount of floor real estate, so you'll need a dedicated room (or cupboard) for it. </p><h3 class="article-body__section" id="section-tefal-x-clean-7-review-performance"><span>Tefal X-Clean 7 review: Performance</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:3815px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="N74CZoaRZwQzUh9337bMc6" name="tefal-5" alt="Tefal X-Clean 7 in use on hardwood floors" src="https://cdn.mos.cms.futurecdn.net/N74CZoaRZwQzUh9337bMc6.jpg" mos="" align="middle" fullscreen="" width="3815" height="2146" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Lucy Scotting)</span></figcaption></figure><p>Over the past three months, I've used the Tefal X-Clean 7 daily on my hardwood floors and tiles in my home. It's helped clean up everyday messes in the kitchen, including spilt coffees, as well as the occasional accident of my not-fully-housetrained puppy. The X-Clean 7 has excelled in every situation it faced. </p><p>Before the first use, I popped it onto the dock, and it took 3.5 hours to reach a full battery. After charging, I put it to the test with some (inconveniently) spilled coffee in my kitchen after missing my cup while making my morning brew. And sure enough, Auto mode easily sucked it up without worry. It left a slightly damp patch in its wake; however, it was much less damp than grabbing my mop and swirling it around (and making more of a mess). </p><p>After a few minutes, the floor was rather dry and fine to walk on, so I cleaned the rest of my kitchen and connected living room floors. These are the most high-traffic areas in my house, and my floors are often covered in muddy pawprints, crumbs and copious amounts of dog hair left behind by my two Border Collies. I easily cleaned the entire area within 15 minutes on Auto mode, and still had plenty of battery life to spare. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:4390px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="QWNyMTtNf6D58UzfPmxyX7" name="tefal-10" alt="Tefal X-Clean 7 in use on hardwood floors" src="https://cdn.mos.cms.futurecdn.net/QWNyMTtNf6D58UzfPmxyX7.jpg" mos="" align="middle" fullscreen="" width="4390" height="2469" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Lucy Scotting)</span></figcaption></figure><p>Case in point, our puppy, who hasn't fully taken to housetraining just yet, would have the occasional accident inside, and I found Max mode tackled pee puddles with ease. The maximum suction completely vacuumed up puddles without a trace. And if there was any dog hair lying around, the roller didn't tangle or have any blockages, with most stray hairs sitting in between the teeth of the metal comb. Not only that, I could easily take on any spilled liquids in two passes on Max mode and call it a day, which was very much a win in my book. </p><p>Sticky messes took some extra pushes, but overall, the Tefal X-Clean 7 could just as easily tackle a stuck sauce stain. It also did a commendable job of collecting kitty litter and smaller wet crumbs in all three modes. </p><p>That said, I didn't opt for Eco mode much — I largely used Auto or Max mode depending on what I needed to clean — but I did use it a few times on my tiled bathroom floors and in my shower when I didn't want to break out my mop. I didn't notice any major differences between Eco and Auto modes in this instance, but it's a nice mode to have if you're conscious of conserving the battery life. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:5100px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="gFTfsr5c5xm9bWYtqa7kz8" name="tefal-12" alt="Tefal X-Clean 7 in use on hardwood floors" src="https://cdn.mos.cms.futurecdn.net/gFTfsr5c5xm9bWYtqa7kz8.jpg" mos="" align="middle" fullscreen="" width="5100" height="2869" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Lucy Scotting)</span></figcaption></figure><p>I also don't own a mansion — rather a two-bed, two-bath apartment — and I could easily clean my hard floors in 15 minutes on Max mode, if not less. If you're mindful of which mode you use, you could easily clean your entire house on a single charge. That said, I did have to frequently refill the clean water tank after every second clean, as it is considerably smaller than other floorwashers I've used. This isn't a big drawback — even high-end models, like the Dyson Wash G1, have smaller water tanks — but if you have a bigger home, you may need to refill it more regularly. </p><p>The X-Clean 7 can leave a bit of streaking on darker floors, but it didn't bother me too much and would easily fade a day or two post-clean. </p><h3 class="article-body__section" id="section-tefal-x-clean-7-review-ease-of-cleaning"><span>Tefal X-Clean 7 review: Ease of cleaning</span></h3><figure role="gallery"><figure><img src="https://cdn.mos.cms.futurecdn.net/tL9eJDUUBcaMLR7CppmdV9.jpg" alt="Tefal X-Clean 7 in use on hardwood floors" /><figcaption><small role="credit">Future / Lucy Scotting</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/VMaJKariKFJZW69HB4mP77.jpg" alt="Tefal X-Clean 7 in use on hardwood floors" /><figcaption><small role="credit">Future / Lucy Scotting</small></figcaption></figure></figure><p>Like other wet-dry vacuums, the Tefal X-Clean 7 requires regular cleaning and emptying of the water tanks to avoid odor and bacteria build-up. If you leave the voice assistant on, it will remind you to empty and clean the dirty water tank after each use and after a self-clean cycle. </p><p>However, I found the voice prompts aren't that detailed and will revert to using the same phrase for at least three manual cleaning tasks. In my case, the device would consistently alert me to empty the dirty water tank after emptying/self-cleaning, and wouldn't let me use the device. In most cases, I had emptied the tank, and the clean water tank was full, so in essence, it should have switched on just fine. However, some of these alerts meant I needed to clean the filter or the pipe underneath, rather than just empty the tank. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:4893px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="Ff99b9hTQGwnKFATZDsKt5" name="tefal-9" alt="Tefal X-Clean 7 in use on hardwood floors" src="https://cdn.mos.cms.futurecdn.net/Ff99b9hTQGwnKFATZDsKt5.jpg" mos="" align="middle" fullscreen="" width="4893" height="2752" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Lucy Scotting)</span></figcaption></figure><p>I'm not sure why the brand hasn't differentiated these tasks via the voice prompt — or at least provided a different alert on the LED screen — as they are completely different and largely separate from emptying the dirty water tank. Regardless, I just made sure to check all variables after each voice prompt from then on, as I couldn't rely on the machine just needing the dirty water tank emptied. However, this could be an issue with my particular unit and not impact all users. </p><p>Aside from this inconvenience, the self-cleaning and drying functions were easy enough to do by pressing the self-cleaning button on the handle. The self-clean function lasted about 3 minutes, and the dock rinsed the roller brush. Afterwards, the self-drying function dries the roller, and the whole process lasts around 30 minutes. </p><h3 class="article-body__section" id="section-tefal-x-clean-7-review-verdict"><span>Tefal X-Clean 7 review: Verdict</span></h3><p>Overall, I was thoroughly impressed by the Tefal X-Clean 7 for its powerful suction modes and lightweight maneuverability. It's easy to use, has speedy self-propulsion, and you won't wait long for your floors to dry after a clean. It can easily clean up spilled liquids, stuck-on stains and the occasional hair or crumb under its roller too, making it perfect for homes with pets or kids. </p><p>However, it could benefit from larger water tanks and an intuitive voice assistant with more detailed prompts. But if you regularly clean it and keep maintenance low by doing so, you'll have no trouble washing your hard floors with Tefal's X-Clean 7. </p>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ KitchenAid KF2 review: this fully automatic coffee machine effortlessly takes the guesswork out of your morning brew ]]></title>
                                                                                                <dc:content><![CDATA[ <p>As a kitchen appliance reviewer, some of my favorite and top-rated products hail from KitchenAid. I've owned an Artisan Stand Mixer for years now, and use many KitchenAid appliances and accessories on a daily basis, so it's no surprise that when the opportunity arose to review the brand's new fully automatic coffee machine range, I volunteered immediately. </p><p>Now, I'm no stranger to a manual espresso maker — I love my Ninja Luxe Cafe more than anything else — so I really wanted to switch it up to see how a fully automatic machine compares to the manual control I'm used to. After all, these automatic coffee machines claim to deliver the perfect espresso in one touch, without worrying about grinds, milk or the like, so my curiosity was definitely piqued. (And spoiler alert: the KF2 did not disappoint). </p><p>Launched earlier this year, KitchenAid's new machines — the KF2, KF3 and KF4 — each have different functions, prices and colorways to suit every kind of one-touch coffee-lover. The machine reviewed here, the KitchenAid KF2, is the most affordable option and offers some hands-on time for hobbyist baristas who want manual control over their milk. </p><p>Over the course of a month, I put the KitchenAid KF2 through its paces and used it to make hot, iced and milk-based drinks.</p><h3 class="article-body__section" id="section-kitchenaid-kf2-review-specs"><span>KitchenAid KF2 review: Specs</span></h3><div ><table><caption>KitchenAid KF2 specs</caption><tbody><tr><td class="firstcol " ><p><strong>Price</strong></p></td><td  ><p>$799.99 / £699 / AU$1,099</p></td></tr><tr><td class="firstcol " ><p><strong>Weight</strong></p></td><td  ><p>22.2lbs / 10.1kg</p></td></tr><tr><td class="firstcol " ><p><strong>Dimensions</strong></p></td><td  ><p>14.2"H × 7.7"W × 18.5"D / 36.07cm H × 19.56cm W × 46.99cm D</p></td></tr><tr><td class="firstcol " ><p><strong>Drink options</strong></p></td><td  ><p>6 – including espresso, coffee and over ice</p></td></tr><tr><td class="firstcol " ><p><strong>Grind settings</strong></p></td><td  ><p>5</p></td></tr><tr><td class="firstcol " ><p><strong>Capacity</strong></p></td><td  ><p>250g bean hopper & 250g ground coffee</p></td></tr><tr><td class="firstcol " ><p><strong>Water tank</strong></p></td><td  ><p>1.8L</p></td></tr><tr><td class="firstcol " ><p><strong>Material</strong></p></td><td  ><p>Stainless steel</p></td></tr></tbody></table></div><h3 class="article-body__section" id="section-kitchenaid-kf2-review-price-and-availability"><span>KitchenAid KF2 review: Price and availability</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:5492px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="5kgtd9R3rJx4jo3k8ZHpK9" name="kf2-17" alt="KitchenAid KF2 coffee machine in lifestyle setting" src="https://cdn.mos.cms.futurecdn.net/5kgtd9R3rJx4jo3k8ZHpK9.jpg" mos="" align="middle" fullscreen="" width="5492" height="3089" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Lucy Scotting)</span></figcaption></figure><p>The KitchenAid KF2 in Australia, where I'm based, is priced at AU$1,099. For those in the UK, it's £699 and in the U.S., it's $799.99. When compared to the other coinciding releases of the KF3 ($999.99 / £749 / AU$1,349) and KF4 ($1,299.99 / £899 / AU$1,599), this is the "budget" or entry-level option in KitchenAid's new fully automatic lineup. </p><p>Now the word budget is a bit of a stretch — it's still pretty expensive — and it doesn't quite dazzle compared to similarly priced automatic machines. I’m talking largely about De’Longhi here, as you can often pick up one of the esteemed brand’s machines for less, in return for more extensive features, like one-touch drink presets and automatic milk-foaming systems. That said, the KF2 offers six drink presets and a steam wand (which some <a href="https://www.tomsguide.com/home/coffee-makers/best-coffee-makers#section-best-superautomatic">5-star automatic machines</a> neglect entirely). And, I won't lie, the KF2's sleek, matte black design is nice to look at. </p><h3 class="article-body__section" id="section-kitchenaid-kf2-review-design"><span>KitchenAid KF2 review: Design</span></h3><figure role="gallery"><figure><img src="https://cdn.mos.cms.futurecdn.net/B42ouYAGfY9UcZkv8FjnA9.jpg" alt="KitchenAid KF2 coffee machine in lifestyle setting" /><figcaption><small role="credit">Future / Lucy Scotting</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/qf4jvodr7TjtuFH6MYEgi3.jpg" alt="KitchenAid KF2 coffee machine in lifestyle setting" /><figcaption><small role="credit">Future / Lucy Scotting</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/7DBniEP8J5Udvh5mDMLRa8.jpg" alt="KitchenAid KF2 coffee machine in lifestyle setting" /><figcaption><small role="credit">Future / Lucy Scotting</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/HMQ7WNqCQYUNbNY54LWtc7.jpg" alt="KitchenAid KF2 coffee machine in lifestyle setting" /><figcaption><small role="credit">Future / Lucy Scotting</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/MoKzrMtAcqDguKeB6dAZQ8.jpg" alt="KitchenAid KF2 coffee machine in lifestyle setting" /><figcaption><small role="credit">Future / Lucy Scotting</small></figcaption></figure></figure><p>KitchenAid's newest fully automatic machines, including the KF2, have a much smaller footprint than their predecessors. Measuring just 14.2" x 7.7" x 18.5" / 36.07cm x 19.56cm x 46.99cm, the KF2 takes up very little counterspace, making it ideal for those with smaller kitchens. The KF2 has five function buttons on the front of its backlit LED screen, as well as a power button on the right side. It also features a 1.8L water tank at the back, a Pannarello steam wand, a drip tray and a concealed 250g bean hopper. </p><p>Unlike the KF3 and KF4, which are both available in matte black and KitchenAid's signature Porcelain white, the KF2 is limited to the former. I quite like the simplicity of the black colorway, but it isn't as visually appealing as the white or Juniper green colorways that the KitchenAid KF8 offers, in my opinion. The stainless steel accents in the drip tray and the steam wand are a nice contrast to the matte machine body, but I didn't love the feel of the function buttons.</p><p>A fun surprise discovered during set up were two wheels under the machine, making it easy to move around if you needed to fill the water tank. It's also not that heavy, at just 22lbs / 10.1kg, so I could easily lift it and move it into place.</p><h3 class="article-body__section" id="section-kitchenaid-kf2-review-performance"><span>KitchenAid KF2 review: Performance</span></h3><h2 id="grinder">Grinder</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:5399px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="z4MCQPoBhigQt97L7BzV98" name="kf2-19" alt="KitchenAid KF2 coffee machine in lifestyle setting" src="https://cdn.mos.cms.futurecdn.net/z4MCQPoBhigQt97L7BzV98.jpg" mos="" align="middle" fullscreen="" width="5399" height="3037" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Lucy Scotting)</span></figcaption></figure><p>The KF2 uses KitchenAid’s Intelligrind technology, which aims to take the guesswork out of selecting the best grind size for your chosen beans. For most users, it allows for a hands-off approach, just pour your beans into the top-mounted hopper and select a drink. If you do want to make some finer adjustments, you can open the machine's side panel, where you’ll find a slider to make the grind finer (to the left) or coarser (to the right). However, for most users, I don't think any adjustments would need to be made, as the automatic function takes away any manual hand tamping or grinding. </p><p>Regardless of whether you make adjustments or not, the KF2's grinder is so quiet. That's largely due to its Quiet Mark certification, meaning it won't make too much noise while you're brewing your early morning coffee. </p><p>If you prefer decaf or coffee grounds, the KF2 also has a 250g ground coffee section next to the bean hopper. It is worth noting that when you add in ground coffee, the machine will switch into its ground coffee mode and exclusively use it over any beans in the hopper. To fix this, you'll need to toggle the bean setting before every use. </p><h2 id="espresso">Espresso</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:3815px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="TWEoQeT5x7nJbUAns53bL5" name="kf2-9" alt="KitchenAid KF2 coffee machine in lifestyle setting" src="https://cdn.mos.cms.futurecdn.net/TWEoQeT5x7nJbUAns53bL5.jpg" mos="" align="middle" fullscreen="" width="3815" height="2146" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Lucy Scotting)</span></figcaption></figure><p>The KF2 can truly customise your coffee to your liking, thanks to its drink, strength and dosage settings. Once you choose your drink recipe — e.g. either an espresso, coffee or over ice — you can make your coffee or espresso shot as weak or strong as you'd like using the strength and dose buttons. If you make adjustments to the strength, the KF2 will grind fewer or more beans, resulting in a dose that’s between 7g and 14g.</p><p>Regardless of the strength setting you choose, the KF2 excels at pulling a consistently well-extracted shot of espresso. For the test brew, I used the double strength on the espresso setting to extract a single shot, and it was perfectly balanced. Just look at that crema! This was using medium-dark roast beans with notes of rich caramel, butterscotch and sweet red fruits. I'm not one to drink straight espresso — I prefer iced coffee all year round — but I really enjoyed the deep caramelly notes I achieved with the KF2. </p><p>When extracting an americano, I used the coffee setting with double strength, single cup dose, and it was pretty spot on for a black coffee. There was a bit of trial and error — initially, I opted for triple strength, and it was too strong for my liking — but the second time around, it worked a charm.</p><h2 id="milk">Milk</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:5041px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="NkdudSkHwUV3XLebfPES69" name="kf2-10" alt="KitchenAid KF2 coffee machine in lifestyle setting" src="https://cdn.mos.cms.futurecdn.net/NkdudSkHwUV3XLebfPES69.jpg" mos="" align="middle" fullscreen="" width="5041" height="2836" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Lucy Scotting)</span></figcaption></figure><p>If you have milk with your coffee, then you’ll likely want to know how well the KF2 can froth milk. You may also have an opinion as to the best method for foaming milk. For me, the fact that the KF2 uses a conventional steam wand as opposed to a hose system on the KF3 and KF4 is a huge plus point. While it might not be as hands-off as the other KitchenAid models — you have to pour the milk into the jug (sold separately) and then pour it into your mug — the result, in my opinion, is much better milk foam. Conversely, when using the KF3 and KF4, milk was silky in texture and did have <em>some </em>froth, but it paled in comparison to what the KF2 could achieve.</p><p>What’s more, having manual control means the KF2 inherently performs better with plant-based milks. This is because you can easily check the temperature whilst milk is heating up and turn it off when it reaches the optimal heat. </p><p>I am a big fan of manual control when milk frothing, so I was very eager to try the steam wand, and as a plant-based milk drinker, I preferred the wand to the milk jug/hose set-up. I could easily check the temperature and make sure my almond milk didn't burn, as most plant-based milks will burn at lower temperatures than dairy. The wand also has a side toggle where you can adjust the foam to your liking, so you don't have to second-guess too much when heating milk to your preferred foaminess.</p><figure role="gallery"><figure><img src="https://cdn.mos.cms.futurecdn.net/3f3A4m6Z2Z67BeCCQSvsT8.jpg" alt="KitchenAid KF2 coffee machine in lifestyle setting" /><figcaption><small role="credit">Future / Lucy Scotting</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/4M7dzDwz26tbGhwieukBo3.jpg" alt="KitchenAid KF2 coffee machine in lifestyle setting" /><figcaption><small role="credit">Future / Lucy Scotting</small></figcaption></figure></figure><p>Before using the steam wand, you need to wait a short while for the internal water system to preheat. It’s not a long process, just something to be aware of. When you’ve finished frothing your milk, you’ll want to purge the steam wand to remove any residue. The purge process can get quite messy as the wand is rather powerful and sits an inch or so above the drip tray. I resorted to purging it a few times inside an empty milk jug, just to avoid powerful steam explosions. </p><p>My first test was an Aussie staple, a flat white, which is typically made from steamed milk with very little foam. To do this, I flicked the foam setting to ‘less’ and put the wand in just below the surface. </p><p>The result clearly speaks for itself, as I made the most perfect flat white to ever exist. Even in my teenage barista days, I've never made glossy steamed milk like this, so it was a true feat to be admired for KitchenAid's steam wand. </p><figure role="gallery"><figure><img src="https://cdn.mos.cms.futurecdn.net/YdfX6AXKMmGte7U7P48FM7.jpg" alt="KitchenAid KF2 coffee machine in lifestyle setting" /><figcaption><small role="credit">Future / Lucy Scotting</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/nwiPJLmAeRgSVnYvNffX49.jpg" alt="KitchenAid KF2 coffee machine in lifestyle setting" /><figcaption><small role="credit">Future / Lucy Scotting</small></figcaption></figure></figure><p>Next up was a latte, so I moved the toggle to the highest foam setting and made sure to keep the wand under the surface of the milk. There were some bubbles initially, but after a few attempts, I ended up getting an equally perfect latte with some great microfoam. (My latte art definitely needs work, though.) </p><h2 id="iced-coffee">Iced coffee</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:5521px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="f3xyqNW4kHKovQ8hAvFtf9" name="kf2-8" alt="KitchenAid KF2 coffee machine in lifestyle setting" src="https://cdn.mos.cms.futurecdn.net/f3xyqNW4kHKovQ8hAvFtf9.jpg" mos="" align="middle" fullscreen="" width="5521" height="3106" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Lucy Scotting)</span></figcaption></figure><p>KitchenAid has given its new compact trio of coffee machines the ability to make iced drinks, although the method in which they make them gave me a little cause for concern, as they’re made ‘over ice’. By this, it means you still need to put ice in your cup or glass first, and the KF2 will then pour a shot of espresso over it. The company says it brews at a cooler temperature than a ‘regular’ shot of espresso, but it’s not quite the same as the Ninja Luxe Cafe I use daily, for example, which has dedicated settings for brewing cold shots of espresso.</p><p>The results were interesting to say the least. I was a little anxious before making my first iced drink, because I'm picky about iced lattes, and if it's too watery, I don't want it. The fact that an iced latte made with the KF2 has to include a few ice cubes indicated that it may indeed end up being a bit weak. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:5262px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="AND2Hynrk7YcpkTjABJr79" name="kf2-6" alt="KitchenAid KF2 coffee machine in lifestyle setting" src="https://cdn.mos.cms.futurecdn.net/AND2Hynrk7YcpkTjABJr79.jpg" mos="" align="middle" fullscreen="" width="5262" height="2960" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Lucy Scotting)</span></figcaption></figure><p>Fortunately, my worries weren’t necessary, as the KF2 did a commendable job of making an iced coffee. When coupled with cold milk and ice, it was particularly delicious, although it was, admittedly, on the weaker side due to the melted ice. </p><p>After the first try, I tweaked the strength higher as the machine automatically selects the lowest setting, and it made a better improvement to the taste. I also opted most days to not brew it immediately over ice to avoid watery shots, and that made the experience much more pleasant. </p><h3 class="article-body__section" id="section-kitchenaid-kf2-review-storage-and-maintenance"><span>KitchenAid KF2 review: Storage and maintenance</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:5280px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="SW6UYL2Wq3YWGMj28F8PS8" name="kf2-13" alt="KitchenAid KF2 coffee machine in lifestyle setting" src="https://cdn.mos.cms.futurecdn.net/SW6UYL2Wq3YWGMj28F8PS8.jpg" mos="" align="middle" fullscreen="" width="5280" height="2970" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Lucy Scotting)</span></figcaption></figure><p>When it comes to everyday maintenance of the KitchenAid KF2, it was pretty straightforward and I didn't need any handholding to keep the machine running. The drip tray has a handy full alert sign when it needs emptying, and can be easily removed. And if you need to add more coffee beans, the backlit screen will give you a helpful alert. </p><p>The KitchenAid KF2 comes with a couple of cleaning tablets for cleaning the brewing group and water filter inside the box. It also comes with a handy water filter insertion tool, which doubles as a ground coffee scoop. As per the manufacturer, the water filters will last two months if using tap water, but could last up to 6 months if you use filtered water. You will need to buy descaling solution separately.</p><p>KitchenAid's routine cleaning and maintenance is pretty easy, as the machine rinses itself before and after each use. This also clears the system of any blockages as well as warm the internal pipes to the right temperature before making a coffee.</p><p>If you need to descale the machine, clean the steam wand, add beans or water, the screen will give you an alert and guide you through the process if needed. Now, during my review period, I didn't need to descale the machine at all; however, I am certain that the machine would let me know if it needed an extra clean. </p><p>KitchenAid does sell additional water filters and brew units if you need more, and offers a 3-year limited warranty. </p><h3 class="article-body__section" id="section-kitchenaid-kf2-review-verdict"><span>KitchenAid KF2 review: Verdict</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:5139px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="LEcu8EymDE63dPTETwCTi7" name="kf2-14" alt="KitchenAid KF2 coffee machine in lifestyle setting" src="https://cdn.mos.cms.futurecdn.net/LEcu8EymDE63dPTETwCTi7.jpg" mos="" align="middle" fullscreen="" width="5139" height="2890" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Lucy Scotting)</span></figcaption></figure><p>If you prioritise time in the mornings, then the KitchenAid KF2 is something to consider and add to your routine. It's easy-to-use, delivers excellent crema, and offers some hands-on control for your milk. All you need to do is add your preferred beans (or grounds), and you've got the perfect morning brew. </p><p>That said, it doesn't offer full one-touch convenience — you'll need to tweak your strength and dose settings with each use — however, that doesn't knock too many marks off for me. And iced lattes could be better, but that won't matter to most non-iced coffee drinkers. </p><p>That being said, if you're interested in a fully automatic, low-maintenance coffee machine, the KitchenAid KF2 is hard to beat. </p> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/home/coffee-makers/kitchenaid-kf2-review-this-fully-automatic-coffee-machine-effortlessly-takes-the-guesswork-out-of-your-morning-brew</link>
                                                                            <description>
                            <![CDATA[ KitchenAid's new fully automatic espresso machines are here — and I put its most affordable option to the test. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">vJ2VCQf53NUc84C3m4RxRD</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/brMt98Yp2XX2QMeZfKYHV8-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Mon, 03 Aug 2026 04:35:18 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Coffee Makers]]></category>
                                                    <category><![CDATA[Home]]></category>
                                                    <category><![CDATA[Home Appliances]]></category>
                                                    <category><![CDATA[Kitchen & Dining]]></category>
                                                                                                <author><![CDATA[ lucy.scotting@futurenet.com (Lucy Scotting) ]]></author>                    <dc:creator><![CDATA[ Lucy Scotting ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/UC9ncAYxkmJ5ipHEyX44ri.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Lucy Scotting is a staff writer for Tom’s Guide Australia, primarily covering lifestyle, streaming and internet-related news. Lucy started her career writing for HR and staffing industry publications, with articles covering emerging tech, business and finance.&lt;/p&gt;&lt;p&gt;In her spare time, Lucy can be found watching sci-fi movies, working on her dystopian fiction novel (in progress since 2017) or hanging out with her dog, Fletcher. If she’s not found doing any of the above, she’s likely on her next adventure to a new city, country, or continent. &lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/brMt98Yp2XX2QMeZfKYHV8-1280-80.jpg">
                                                            <media:credit><![CDATA[Future / Lucy Scotting]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[KitchenAid KF2 coffee machine in lifestyle setting]]></media:description>                                                            <media:text><![CDATA[KitchenAid KF2 coffee machine in lifestyle setting]]></media:text>
                                <media:title type="plain"><![CDATA[KitchenAid KF2 coffee machine in lifestyle setting]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/brMt98Yp2XX2QMeZfKYHV8-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>As a kitchen appliance reviewer, some of my favorite and top-rated products hail from KitchenAid. I've owned an Artisan Stand Mixer for years now, and use many KitchenAid appliances and accessories on a daily basis, so it's no surprise that when the opportunity arose to review the brand's new fully automatic coffee machine range, I volunteered immediately. </p><p>Now, I'm no stranger to a manual espresso maker — I love my Ninja Luxe Cafe more than anything else — so I really wanted to switch it up to see how a fully automatic machine compares to the manual control I'm used to. After all, these automatic coffee machines claim to deliver the perfect espresso in one touch, without worrying about grinds, milk or the like, so my curiosity was definitely piqued. (And spoiler alert: the KF2 did not disappoint). </p><p>Launched earlier this year, KitchenAid's new machines — the KF2, KF3 and KF4 — each have different functions, prices and colorways to suit every kind of one-touch coffee-lover. The machine reviewed here, the KitchenAid KF2, is the most affordable option and offers some hands-on time for hobbyist baristas who want manual control over their milk. </p><p>Over the course of a month, I put the KitchenAid KF2 through its paces and used it to make hot, iced and milk-based drinks.</p><h3 class="article-body__section" id="section-kitchenaid-kf2-review-specs"><span>KitchenAid KF2 review: Specs</span></h3><div ><table><caption>KitchenAid KF2 specs</caption><tbody><tr><td class="firstcol " ><p><strong>Price</strong></p></td><td  ><p>$799.99 / £699 / AU$1,099</p></td></tr><tr><td class="firstcol " ><p><strong>Weight</strong></p></td><td  ><p>22.2lbs / 10.1kg</p></td></tr><tr><td class="firstcol " ><p><strong>Dimensions</strong></p></td><td  ><p>14.2"H × 7.7"W × 18.5"D / 36.07cm H × 19.56cm W × 46.99cm D</p></td></tr><tr><td class="firstcol " ><p><strong>Drink options</strong></p></td><td  ><p>6 – including espresso, coffee and over ice</p></td></tr><tr><td class="firstcol " ><p><strong>Grind settings</strong></p></td><td  ><p>5</p></td></tr><tr><td class="firstcol " ><p><strong>Capacity</strong></p></td><td  ><p>250g bean hopper & 250g ground coffee</p></td></tr><tr><td class="firstcol " ><p><strong>Water tank</strong></p></td><td  ><p>1.8L</p></td></tr><tr><td class="firstcol " ><p><strong>Material</strong></p></td><td  ><p>Stainless steel</p></td></tr></tbody></table></div><h3 class="article-body__section" id="section-kitchenaid-kf2-review-price-and-availability"><span>KitchenAid KF2 review: Price and availability</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:5492px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="5kgtd9R3rJx4jo3k8ZHpK9" name="kf2-17" alt="KitchenAid KF2 coffee machine in lifestyle setting" src="https://cdn.mos.cms.futurecdn.net/5kgtd9R3rJx4jo3k8ZHpK9.jpg" mos="" align="middle" fullscreen="" width="5492" height="3089" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Lucy Scotting)</span></figcaption></figure><p>The KitchenAid KF2 in Australia, where I'm based, is priced at AU$1,099. For those in the UK, it's £699 and in the U.S., it's $799.99. When compared to the other coinciding releases of the KF3 ($999.99 / £749 / AU$1,349) and KF4 ($1,299.99 / £899 / AU$1,599), this is the "budget" or entry-level option in KitchenAid's new fully automatic lineup. </p><p>Now the word budget is a bit of a stretch — it's still pretty expensive — and it doesn't quite dazzle compared to similarly priced automatic machines. I’m talking largely about De’Longhi here, as you can often pick up one of the esteemed brand’s machines for less, in return for more extensive features, like one-touch drink presets and automatic milk-foaming systems. That said, the KF2 offers six drink presets and a steam wand (which some <a href="https://www.tomsguide.com/home/coffee-makers/best-coffee-makers#section-best-superautomatic">5-star automatic machines</a> neglect entirely). And, I won't lie, the KF2's sleek, matte black design is nice to look at. </p><h3 class="article-body__section" id="section-kitchenaid-kf2-review-design"><span>KitchenAid KF2 review: Design</span></h3><figure role="gallery"><figure><img src="https://cdn.mos.cms.futurecdn.net/B42ouYAGfY9UcZkv8FjnA9.jpg" alt="KitchenAid KF2 coffee machine in lifestyle setting" /><figcaption><small role="credit">Future / Lucy Scotting</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/qf4jvodr7TjtuFH6MYEgi3.jpg" alt="KitchenAid KF2 coffee machine in lifestyle setting" /><figcaption><small role="credit">Future / Lucy Scotting</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/7DBniEP8J5Udvh5mDMLRa8.jpg" alt="KitchenAid KF2 coffee machine in lifestyle setting" /><figcaption><small role="credit">Future / Lucy Scotting</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/HMQ7WNqCQYUNbNY54LWtc7.jpg" alt="KitchenAid KF2 coffee machine in lifestyle setting" /><figcaption><small role="credit">Future / Lucy Scotting</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/MoKzrMtAcqDguKeB6dAZQ8.jpg" alt="KitchenAid KF2 coffee machine in lifestyle setting" /><figcaption><small role="credit">Future / Lucy Scotting</small></figcaption></figure></figure><p>KitchenAid's newest fully automatic machines, including the KF2, have a much smaller footprint than their predecessors. Measuring just 14.2" x 7.7" x 18.5" / 36.07cm x 19.56cm x 46.99cm, the KF2 takes up very little counterspace, making it ideal for those with smaller kitchens. The KF2 has five function buttons on the front of its backlit LED screen, as well as a power button on the right side. It also features a 1.8L water tank at the back, a Pannarello steam wand, a drip tray and a concealed 250g bean hopper. </p><p>Unlike the KF3 and KF4, which are both available in matte black and KitchenAid's signature Porcelain white, the KF2 is limited to the former. I quite like the simplicity of the black colorway, but it isn't as visually appealing as the white or Juniper green colorways that the KitchenAid KF8 offers, in my opinion. The stainless steel accents in the drip tray and the steam wand are a nice contrast to the matte machine body, but I didn't love the feel of the function buttons.</p><p>A fun surprise discovered during set up were two wheels under the machine, making it easy to move around if you needed to fill the water tank. It's also not that heavy, at just 22lbs / 10.1kg, so I could easily lift it and move it into place.</p><h3 class="article-body__section" id="section-kitchenaid-kf2-review-performance"><span>KitchenAid KF2 review: Performance</span></h3><h2 id="grinder">Grinder</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:5399px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="z4MCQPoBhigQt97L7BzV98" name="kf2-19" alt="KitchenAid KF2 coffee machine in lifestyle setting" src="https://cdn.mos.cms.futurecdn.net/z4MCQPoBhigQt97L7BzV98.jpg" mos="" align="middle" fullscreen="" width="5399" height="3037" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Lucy Scotting)</span></figcaption></figure><p>The KF2 uses KitchenAid’s Intelligrind technology, which aims to take the guesswork out of selecting the best grind size for your chosen beans. For most users, it allows for a hands-off approach, just pour your beans into the top-mounted hopper and select a drink. If you do want to make some finer adjustments, you can open the machine's side panel, where you’ll find a slider to make the grind finer (to the left) or coarser (to the right). However, for most users, I don't think any adjustments would need to be made, as the automatic function takes away any manual hand tamping or grinding. </p><p>Regardless of whether you make adjustments or not, the KF2's grinder is so quiet. That's largely due to its Quiet Mark certification, meaning it won't make too much noise while you're brewing your early morning coffee. </p><p>If you prefer decaf or coffee grounds, the KF2 also has a 250g ground coffee section next to the bean hopper. It is worth noting that when you add in ground coffee, the machine will switch into its ground coffee mode and exclusively use it over any beans in the hopper. To fix this, you'll need to toggle the bean setting before every use. </p><h2 id="espresso">Espresso</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:3815px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="TWEoQeT5x7nJbUAns53bL5" name="kf2-9" alt="KitchenAid KF2 coffee machine in lifestyle setting" src="https://cdn.mos.cms.futurecdn.net/TWEoQeT5x7nJbUAns53bL5.jpg" mos="" align="middle" fullscreen="" width="3815" height="2146" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Lucy Scotting)</span></figcaption></figure><p>The KF2 can truly customise your coffee to your liking, thanks to its drink, strength and dosage settings. Once you choose your drink recipe — e.g. either an espresso, coffee or over ice — you can make your coffee or espresso shot as weak or strong as you'd like using the strength and dose buttons. If you make adjustments to the strength, the KF2 will grind fewer or more beans, resulting in a dose that’s between 7g and 14g.</p><p>Regardless of the strength setting you choose, the KF2 excels at pulling a consistently well-extracted shot of espresso. For the test brew, I used the double strength on the espresso setting to extract a single shot, and it was perfectly balanced. Just look at that crema! This was using medium-dark roast beans with notes of rich caramel, butterscotch and sweet red fruits. I'm not one to drink straight espresso — I prefer iced coffee all year round — but I really enjoyed the deep caramelly notes I achieved with the KF2. </p><p>When extracting an americano, I used the coffee setting with double strength, single cup dose, and it was pretty spot on for a black coffee. There was a bit of trial and error — initially, I opted for triple strength, and it was too strong for my liking — but the second time around, it worked a charm.</p><h2 id="milk">Milk</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:5041px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="NkdudSkHwUV3XLebfPES69" name="kf2-10" alt="KitchenAid KF2 coffee machine in lifestyle setting" src="https://cdn.mos.cms.futurecdn.net/NkdudSkHwUV3XLebfPES69.jpg" mos="" align="middle" fullscreen="" width="5041" height="2836" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Lucy Scotting)</span></figcaption></figure><p>If you have milk with your coffee, then you’ll likely want to know how well the KF2 can froth milk. You may also have an opinion as to the best method for foaming milk. For me, the fact that the KF2 uses a conventional steam wand as opposed to a hose system on the KF3 and KF4 is a huge plus point. While it might not be as hands-off as the other KitchenAid models — you have to pour the milk into the jug (sold separately) and then pour it into your mug — the result, in my opinion, is much better milk foam. Conversely, when using the KF3 and KF4, milk was silky in texture and did have <em>some </em>froth, but it paled in comparison to what the KF2 could achieve.</p><p>What’s more, having manual control means the KF2 inherently performs better with plant-based milks. This is because you can easily check the temperature whilst milk is heating up and turn it off when it reaches the optimal heat. </p><p>I am a big fan of manual control when milk frothing, so I was very eager to try the steam wand, and as a plant-based milk drinker, I preferred the wand to the milk jug/hose set-up. I could easily check the temperature and make sure my almond milk didn't burn, as most plant-based milks will burn at lower temperatures than dairy. The wand also has a side toggle where you can adjust the foam to your liking, so you don't have to second-guess too much when heating milk to your preferred foaminess.</p><figure role="gallery"><figure><img src="https://cdn.mos.cms.futurecdn.net/3f3A4m6Z2Z67BeCCQSvsT8.jpg" alt="KitchenAid KF2 coffee machine in lifestyle setting" /><figcaption><small role="credit">Future / Lucy Scotting</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/4M7dzDwz26tbGhwieukBo3.jpg" alt="KitchenAid KF2 coffee machine in lifestyle setting" /><figcaption><small role="credit">Future / Lucy Scotting</small></figcaption></figure></figure><p>Before using the steam wand, you need to wait a short while for the internal water system to preheat. It’s not a long process, just something to be aware of. When you’ve finished frothing your milk, you’ll want to purge the steam wand to remove any residue. The purge process can get quite messy as the wand is rather powerful and sits an inch or so above the drip tray. I resorted to purging it a few times inside an empty milk jug, just to avoid powerful steam explosions. </p><p>My first test was an Aussie staple, a flat white, which is typically made from steamed milk with very little foam. To do this, I flicked the foam setting to ‘less’ and put the wand in just below the surface. </p><p>The result clearly speaks for itself, as I made the most perfect flat white to ever exist. Even in my teenage barista days, I've never made glossy steamed milk like this, so it was a true feat to be admired for KitchenAid's steam wand. </p><figure role="gallery"><figure><img src="https://cdn.mos.cms.futurecdn.net/YdfX6AXKMmGte7U7P48FM7.jpg" alt="KitchenAid KF2 coffee machine in lifestyle setting" /><figcaption><small role="credit">Future / Lucy Scotting</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/nwiPJLmAeRgSVnYvNffX49.jpg" alt="KitchenAid KF2 coffee machine in lifestyle setting" /><figcaption><small role="credit">Future / Lucy Scotting</small></figcaption></figure></figure><p>Next up was a latte, so I moved the toggle to the highest foam setting and made sure to keep the wand under the surface of the milk. There were some bubbles initially, but after a few attempts, I ended up getting an equally perfect latte with some great microfoam. (My latte art definitely needs work, though.) </p><h2 id="iced-coffee">Iced coffee</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:5521px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="f3xyqNW4kHKovQ8hAvFtf9" name="kf2-8" alt="KitchenAid KF2 coffee machine in lifestyle setting" src="https://cdn.mos.cms.futurecdn.net/f3xyqNW4kHKovQ8hAvFtf9.jpg" mos="" align="middle" fullscreen="" width="5521" height="3106" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Lucy Scotting)</span></figcaption></figure><p>KitchenAid has given its new compact trio of coffee machines the ability to make iced drinks, although the method in which they make them gave me a little cause for concern, as they’re made ‘over ice’. By this, it means you still need to put ice in your cup or glass first, and the KF2 will then pour a shot of espresso over it. The company says it brews at a cooler temperature than a ‘regular’ shot of espresso, but it’s not quite the same as the Ninja Luxe Cafe I use daily, for example, which has dedicated settings for brewing cold shots of espresso.</p><p>The results were interesting to say the least. I was a little anxious before making my first iced drink, because I'm picky about iced lattes, and if it's too watery, I don't want it. The fact that an iced latte made with the KF2 has to include a few ice cubes indicated that it may indeed end up being a bit weak. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:5262px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="AND2Hynrk7YcpkTjABJr79" name="kf2-6" alt="KitchenAid KF2 coffee machine in lifestyle setting" src="https://cdn.mos.cms.futurecdn.net/AND2Hynrk7YcpkTjABJr79.jpg" mos="" align="middle" fullscreen="" width="5262" height="2960" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Lucy Scotting)</span></figcaption></figure><p>Fortunately, my worries weren’t necessary, as the KF2 did a commendable job of making an iced coffee. When coupled with cold milk and ice, it was particularly delicious, although it was, admittedly, on the weaker side due to the melted ice. </p><p>After the first try, I tweaked the strength higher as the machine automatically selects the lowest setting, and it made a better improvement to the taste. I also opted most days to not brew it immediately over ice to avoid watery shots, and that made the experience much more pleasant. </p><h3 class="article-body__section" id="section-kitchenaid-kf2-review-storage-and-maintenance"><span>KitchenAid KF2 review: Storage and maintenance</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:5280px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="SW6UYL2Wq3YWGMj28F8PS8" name="kf2-13" alt="KitchenAid KF2 coffee machine in lifestyle setting" src="https://cdn.mos.cms.futurecdn.net/SW6UYL2Wq3YWGMj28F8PS8.jpg" mos="" align="middle" fullscreen="" width="5280" height="2970" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Lucy Scotting)</span></figcaption></figure><p>When it comes to everyday maintenance of the KitchenAid KF2, it was pretty straightforward and I didn't need any handholding to keep the machine running. The drip tray has a handy full alert sign when it needs emptying, and can be easily removed. And if you need to add more coffee beans, the backlit screen will give you a helpful alert. </p><p>The KitchenAid KF2 comes with a couple of cleaning tablets for cleaning the brewing group and water filter inside the box. It also comes with a handy water filter insertion tool, which doubles as a ground coffee scoop. As per the manufacturer, the water filters will last two months if using tap water, but could last up to 6 months if you use filtered water. You will need to buy descaling solution separately.</p><p>KitchenAid's routine cleaning and maintenance is pretty easy, as the machine rinses itself before and after each use. This also clears the system of any blockages as well as warm the internal pipes to the right temperature before making a coffee.</p><p>If you need to descale the machine, clean the steam wand, add beans or water, the screen will give you an alert and guide you through the process if needed. Now, during my review period, I didn't need to descale the machine at all; however, I am certain that the machine would let me know if it needed an extra clean. </p><p>KitchenAid does sell additional water filters and brew units if you need more, and offers a 3-year limited warranty. </p><h3 class="article-body__section" id="section-kitchenaid-kf2-review-verdict"><span>KitchenAid KF2 review: Verdict</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:5139px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="LEcu8EymDE63dPTETwCTi7" name="kf2-14" alt="KitchenAid KF2 coffee machine in lifestyle setting" src="https://cdn.mos.cms.futurecdn.net/LEcu8EymDE63dPTETwCTi7.jpg" mos="" align="middle" fullscreen="" width="5139" height="2890" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Lucy Scotting)</span></figcaption></figure><p>If you prioritise time in the mornings, then the KitchenAid KF2 is something to consider and add to your routine. It's easy-to-use, delivers excellent crema, and offers some hands-on control for your milk. All you need to do is add your preferred beans (or grounds), and you've got the perfect morning brew. </p><p>That said, it doesn't offer full one-touch convenience — you'll need to tweak your strength and dose settings with each use — however, that doesn't knock too many marks off for me. And iced lattes could be better, but that won't matter to most non-iced coffee drinkers. </p><p>That being said, if you're interested in a fully automatic, low-maintenance coffee machine, the KitchenAid KF2 is hard to beat. </p>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ I was spending $7 a day at coffee shops — now I spend $1 thanks to my Nespresso machine that’s 41% off at Amazon ]]></title>
                                                                                                <dc:content><![CDATA[ <p>I love going to coffee shops, whether I'm just quickly grabbing my favorite vanilla oat milk latte, meeting up with a friend for coffee or getting some work done. However, every time I step foot inside a cafe, I'm spending at least $7 — and that's just for a coffee. </p><p>After calculating how much I was spending weekly and monthly, I was astonished. That's when I decided I needed to cut back a bit — and <a href="https://www.amazon.com/Nespresso-DeLonghi-ENV120GYAE-Espresso-Aeroccino/dp/B084GY5FHN/" target="_blank" rel="nofollow">my Nespresso Vertuo Next coffee and espresso maker</a> made that possible. Even better? It's currently 41% off on Amazon. </p><div class="product"><a data-dimension112="85336e50-8cea-11f1-9071-8d73434d97ba" data-action="Deal Block" data-label="Vertuo Next w Aeroccino Milk Frother" data-dimension48="Vertuo Next w Aeroccino Milk Frother" data-dimension25="$134" href="https://www.amazon.com/Nespresso-DeLonghi-ENV120GYAE-Espresso-Aeroccino/dp/B084GY5FHN/" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1500px;"><p class="vanilla-image-block" style="padding-top:84.93%;"><img id="cqkR72BCgMgQiYg32kT4jW" name="Nespresso Vertuo" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/cqkR72BCgMgQiYg32kT4jW.jpg" mos="" align="middle" fullscreen="" width="1500" height="1274" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Nespresso-DeLonghi-ENV120GYAE-Espresso-Aeroccino/dp/B084GY5FHN/" target="_blank" rel="nofollow" data-dimension112="85336e50-8cea-11f1-9071-8d73434d97ba" data-action="Deal Block" data-label="Vertuo Next w Aeroccino Milk Frother" data-dimension48="Vertuo Next w Aeroccino Milk Frother" data-dimension25="$134">Vertuo Next w Aeroccino Milk Frother: was $229 now $134</a></strong><br>This Nespresso Vertuo Next machine can turn your home into a full on coffee shop. It supports six cup sizes including 5, 8, 12, and 18-oz., as well as single and double espressos brewed hot or over ice. The included Aeroccino frother provides hot or cold milk for your cappuccinos and lattes.<a class="view-deal button" href="https://www.amazon.com/Nespresso-DeLonghi-ENV120GYAE-Espresso-Aeroccino/dp/B084GY5FHN/" target="_blank" rel="nofollow" data-dimension112="85336e50-8cea-11f1-9071-8d73434d97ba" data-action="Deal Block" data-label="Vertuo Next w Aeroccino Milk Frother" data-dimension48="Vertuo Next w Aeroccino Milk Frother" data-dimension25="$134">View Deal</a></p></div><div class="product"><a data-dimension112="85336ef0-8cea-11f1-81ca-d9115b0a4f10" data-action="Deal Block" data-label="Capsules Vertuo" data-dimension48="Capsules Vertuo" data-dimension25="$42" href="https://www.amazon.com/Nespresso-Vertuoline-Seller-Assortment-Count/dp/B01N05APQY/" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1500px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="Yvm4K4QWtX9JaZ3avkGG6L" name="Nespresso capsules" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/Yvm4K4QWtX9JaZ3avkGG6L.jpg" mos="" align="middle" fullscreen="" width="1500" height="1500" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Nespresso-Vertuoline-Seller-Assortment-Count/dp/B01N05APQY/" target="_blank" rel="nofollow" data-dimension112="85336ef0-8cea-11f1-81ca-d9115b0a4f10" data-action="Deal Block" data-label="Capsules Vertuo" data-dimension48="Capsules Vertuo" data-dimension25="$42">Capsules Vertuo: $42</a></strong><br>These are the Nespresso capsules I buy on a monthly basis. The variety pack includes three different medium and dark roast coffee pods with rich flavors you'll love. They'll provide you with a 7.8 oz serving of coffee. <a class="view-deal button" href="https://www.amazon.com/Nespresso-Vertuoline-Seller-Assortment-Count/dp/B01N05APQY/" target="_blank" rel="nofollow" data-dimension112="85336ef0-8cea-11f1-81ca-d9115b0a4f10" data-action="Deal Block" data-label="Capsules Vertuo" data-dimension48="Capsules Vertuo" data-dimension25="$42">View Deal</a></p></div><p>At nearly $100 off, the Nespresso Vertuo Next is practically a steal — and it can quickly pay for itself compared to buying coffee from a café every day. I typically buy Nespresso Vertuo capsules, which cost $42 for a pack of 30. That works out to about $1.40 per cup, making it a much more affordable daily coffee habit than my typical coffee shop run.</p><p>The best part is, my Nespresso machine actually makes delicious coffees, lattes and cappuccinos, so I don't feel disappointed making coffee at home rather than buying one. The included Aeroccino Milk Frother is really the icing on the cake. I add my favorite oat milk to the frother and in seconds, I have creamy, frothy milk to add to my coffee or latte. </p><p>The machine is super easy to use — all you have to do is add your capsule, make sure the water tank is full and press the brewing button. You'll have a delicious, barista-style coffee in just seconds. You can also choose from six cup sizes including 5, 8, 12, and 18-oz., as well as single and double espressos brewed hot or over ice. The machine truly does it all! </p><p>Of course, I'll never fully stop indulging in my local coffee shops — but at least I can save a little bit of money by making my coffee at home a few days a week. If you're hoping to do the same, <a href="https://www.amazon.com/Nespresso-DeLonghi-ENV120GYAE-Espresso-Aeroccino/dp/B084GY5FHN/" target="_blank" rel="nofollow">I recommend grabbing the Nespresso Vertuo Next for just $134 on Amazon</a>. </p><div class="vizualizer-embed"><div class="tg-df-widget-host" data-widget-config="?search=coffee&view_mode=savings_squad&widget_title=Top+Deals+Handpicked+by+Our+Editors&widget_subtitle=Discover+the+best+discounts+currently+available%2C+curated+daily+by+the+Tom%27s+Guide+Savings+Squad.&bg_color=transparent" data-vizualizer-embed="true"></div>    <script>    /**     * Tom's Guide Deals Finder - Vanilla JS Encapsulated Engine     */    (function() {      // --- Freyr Analytics Adapter ---      function initAnalytics() {        window.dataLayer = window.dataLayer || [];        window.googletag = window.googletag || {};        window.googletag.cmd = window.googletag.cmd || [];        window.hawk = window.hawk || { analytics: { freyr: [] } };        window.hawk.analytics = window.hawk.analytics || { freyr: [] };        window.hawk.analytics.freyr = window.hawk.analytics.freyr || [];        window.freyr = window.freyr || { cmd: [] };        const scriptSrc = 'https://freyr.futurecdn.net/freyr.js';        const hostname = typeof window !== 'undefined' ? window.location.hostname : '';        const isTestEnv = typeof window.navigator !== 'undefined' && (window.navigator.webdriver || window.navigator.userAgent.includes('Headless'));        const shouldSendRealAnalytics = !isTestEnv && hostname && hostname !== 'localhost' && hostname !== '127.0.0.1' && !hostname.includes('run.app');        if (shouldSendRealAnalytics && !document.querySelector(`script[src="${scriptSrc}"]`)) {          const script = document.createElement('script');          script.src = scriptSrc;          script.async = true;          document.head.appendChild(script);        }      }      function storeEventForDebug(name, data) {        if (!window.hawk || !window.hawk.analytics || !window.hawk.analytics.freyr) return;        window.hawk.analytics.freyr.push({ name, data });        try {          if (typeof window !== 'undefined' && window.localStorage) {            window.localStorage.setItem("hawk", JSON.stringify(window.hawk));          }        } catch (e) {          // Ignore storage issues        }        try {          window.dispatchEvent(new CustomEvent("hawk-analytics-update"));        } catch (e) {}      }      function sendToFreyr(eventName, data) {        if (typeof window === 'undefined') return;        window.freyr = window.freyr || { cmd: [] };        window.freyr.cmd.push(() => {          if (window.freyr && window.freyr.pushAndUpdate) {            window.freyr.pushAndUpdate(eventName, data);          }        });      }      function sendEvent(event, skip = false) {        try {          storeEventForDebug(event.name, event.data);          if (!skip) {            sendToFreyr(event.name, event.data);          }        } catch (e) {          // Ensure tracking errors don't surface to the user        }      }      function getCookie(name) {        try {          const match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));          return match ? match[2] : null;        } catch (e) {          return null;        }      }      function getTimeAgo(dateString) {        if (!dateString) return '';        const date = new Date(dateString);        const now = new Date();        const diffInSeconds = Math.floor((now.getTime() - date.getTime()) / 1000);        if (diffInSeconds < 60) return 'Just now';        const diffInMinutes = Math.floor(diffInSeconds / 60);        if (diffInMinutes < 60) return `${diffInMinutes} min${diffInMinutes > 1 ? 's' : ''} ago`;        const diffInHours = Math.floor(diffInMinutes / 60);        if (diffInHours < 24) return `${diffInHours} hr${diffInHours > 1 ? 's' : ''} ago`;        const diffInDays = Math.floor(diffInHours / 24);        if (diffInDays < 30) return `${diffInDays} day${diffInDays > 1 ? 's' : ''} ago`;        const diffInMonths = Math.floor(diffInDays / 30);        if (diffInMonths < 12) return `${diffInMonths} mo${diffInMonths > 1 ? 's' : ''} ago`;        const diffInYears = Math.floor(diffInDays / 365);        return `${diffInYears} yr${diffInYears > 1 ? 's' : ''} ago`;      }      function normalizeCurrency(symbol) {        const map = {          '£': 'GBP',          '$': 'USD',          'A$': 'AUD',          'CA$': 'CAD',          '€': 'EUR'        };        return map[symbol] || symbol;      }      function trackElementInteraction(props) {        sendEvent({          name: 'elementInteraction',          data: {            element: {              action: props.action || "click",              id: props.id || undefined,              class: props.class || undefined,              name: props.name || undefined,              text: props.text || undefined,              label: props.label || undefined,              container: props.container || undefined,              url: props.url || undefined,              articleId: props.articleId || undefined            }          }        });      }      function generateRevenueId(url, productName, merchantName, modelId) {        const str = `${window.location.href}|${productName}|${merchantName}|${modelId || ''}|${new Date().toDateString()}|tomsguide`;        let hash = 0;        for (let i = 0; i < str.length; i++) {          const char = str.charCodeAt(i);          hash = ((hash << 5) - hash) + char;          hash = hash & hash;        }        let numericStr = Math.abs(hash).toString();        while (numericStr.length < 19) {          numericStr += Math.floor(Math.random() * 10).toString();        }        return numericStr.substring(0, 19);      }      function rewriteAffiliateLink(url, territory, revenueId) {        if (!url) return url;        const t = (territory || 'gb').toLowerCase();        return url.replace(/hawk-custom-tracking/g, `tomsguide-${t}-${revenueId}`);      }      function trackHawkEvent(params) {        const { clickType, widgetId, productCategoryName, product, productsArray, zeroBasedProductIndexOrNull, totalDealsOrProducts, areaClicked, merchant, revenueId, isoCurrencyCode, queryName, widgetTypeName } = params;        const data = {          event: "hawkEvent",          category: "Affiliates",          affiliate: {            action: {              type: clickType,              id: widgetId,              event: clickType === "appeared" ? "viewed" : "Click from",              timestamp: Date.now()            },            component: {              flag: "Editor",              product: productCategoryName || "deals",              category: `Signal Deal Finder ${widgetTypeName || "Carousel"} widget`,              type: clickType === "appeared" ? "review" : "signal product",              label: queryName || (product ? (product.name || "") : ""),              index: zeroBasedProductIndexOrNull === null || zeroBasedProductIndexOrNull === undefined ? -1 : zeroBasedProductIndexOrNull,              linkCount: totalDealsOrProducts || 0,              blockLayout: "",              areaClicked: areaClicked || ""            }          },          products: productsArray || (product && merchant ? [            {              product: {                primary: {                  id: product.id || product.matchId || null,                  name: product.name,                  type: "deal",                  price: product.price,                  previousPrice: product.previousPrice || null,                  currency: isoCurrencyCode || "USD",                  preorder: false,                  labels: [],                  link: product.link,                  originalLink: product.originalLink || null,                  revenueId: revenueId || null,                  startTime: null,                  endTime: null,                  voucherCode: null,                  voucherAudience: null,                  voucherPercentageSaving: null,                  voucherMoneySaving: null,                  voucherType: null,                  offerExclusive: false,                  offerScope: null,                  globalId: product.globalId || null,                  inStock: product.inStock !== false,                  contractProvider: null,                  contractMinutes: null,                  contractTexts: null,                  contractData: null,                  contractLength: null,                  contractMonthlyPrice: null,                  contractCurrency: isoCurrencyCode || "USD"                }              },              merchant: {                id: merchant.id || null,                name: merchant.name,                url: merchant.url || null,                network: merchant.network || null              },              model: {                id: product.modelId || null,                brand: product.brand || null,                name: product.name,                parent: product.parent || null              }            }          ] : []),          reviews: [],          _clear: true,          "gtm.uniqueEventId": Date.now() % 10000        };        sendEvent({ name: 'hawkEvent', data });      }      function trackDealClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Product Card" });      }      function trackViewSimilarClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Product Card View Similar" });      }      function trackPriceComparisonClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Price Comparison" });      }      function trackReviewClick(params) {        trackHawkEvent({ ...params, clickType: "review", areaClicked: "Signal Product Card Review Link" });      }      function trackShare(params) {        trackHawkEvent({ ...params, clickType: "share", areaClicked: "Signal Product Card Share" });      }      function trackDealsAppeared(widgetId, deals, revenueId, currency, queryName, widgetTypeName) {         if (!deals || deals.length === 0) return;                  const productsArray = deals.slice(0, 50).map((deal) => {            let voucherPct = null;            let rawPrice = parseFloat(deal.rawPrice) || parseFloat(deal.price) || null;            let rawMsrp = parseFloat(deal.rawMsrp) || parseFloat(deal.msrp) || null;            if (rawMsrp > rawPrice && rawPrice > 0) {              voucherPct = Math.round((1 - (rawPrice / rawMsrp)) * 100);            }            let numId = null;            if (deal.externalProductId && !isNaN(parseInt(deal.externalProductId))) {              numId = parseInt(deal.externalProductId);            } else if (deal.id && !isNaN(parseInt(deal.id))) {              numId = parseInt(deal.id);            } else {              numId = deal.matchId || null;            }            return {              product: {                primary: {                  id: numId,                  name: deal.productName || deal.title || "",                  type: "deal",                  price: rawPrice,                  previousPrice: rawMsrp,                  currency: currency || 'USD',                  preorder: false,                  labels: deal.modelBrand || deal.brand ? [                     { type: "brand", value: deal.modelBrand || deal.brand }                  ] : [],                  link: deal.url,                  originalLink: deal.url,                  revenueId: revenueId || null,                  startTime: null,                  endTime: null,                  voucherCode: null,                  voucherAudience: null,                  voucherPercentageSaving: voucherPct,                  voucherMoneySaving: null,                  voucherType: null,                  offerExclusive: false,                  offerScope: null,                  globalId: deal.productKey || null,                  inStock: deal.inStock !== false,                  contractProvider: null,                  contractMinutes: null,                  contractTexts: null,                  contractData: null,                  contractLength: null,                  contractMonthlyPrice: null,                  contractCurrency: currency || 'USD'                }              },              merchant: {                id: deal.merchantId ? parseInt(deal.merchantId) : null,                name: deal.merchant || "Retailer",                url: deal.merchantUrl || null,                network: deal.merchantNetwork || null              },              model: {                id: deal.modelId ? parseInt(deal.modelId) : null,                brand: deal.modelBrand || deal.brand || null,                name: deal.productName || deal.title || "",                parent: deal.modelParent || null              }            };         });                  trackHawkEvent({             clickType: "appeared",             widgetId: widgetId,             productCategoryName: "deals",             zeroBasedProductIndexOrNull: null,             totalDealsOrProducts: deals.length,             productsArray: productsArray,             queryName: queryName,             widgetTypeName: widgetTypeName         });      }      // 1. Setup Shadow DOM Sandbox      const currentScript = document.currentScript;      let hostContainer = null;      let template = null;            if (currentScript) {        let prev = currentScript.previousElementSibling;        while (prev) {          if (prev.tagName === 'TEMPLATE' && prev.classList.contains('tg-df-widget-template')) {            template = prev;          } else if (prev.tagName === 'DIV' && prev.classList.contains('tg-df-widget-host') && !prev.hasAttribute('data-initialized')) {            hostContainer = prev;            break;          }          prev = prev.previousElementSibling;        }      }            // Fallbacks in case script is deferred      if (!hostContainer) {        const hosts = document.querySelectorAll('.tg-df-widget-host:not([data-initialized])');        if (hosts.length > 0) hostContainer = hosts[0];      }            // Safely embedded template for CMS environments      const rawTemplate = `  \x3Cstyle>    /* --- Shadow DOM Base Reset --- */    *, *::before, *::after {      box-sizing: border-box;    }    img, picture, svg, video {      max-width: 100%;      height: auto;      display: block;    }    /*       1. Scoped CSS for Tom's Guide Deals Widget       All classes are prefixed with \`tg-df-\` to prevent CMS style leakage.    */    .tg-df-container {      container-type: inline-size;      container-name: tg-df;      --tg-df-blue: #1F69FF;      --tg-df-blue-hover: #004d8c;      --tg-df-text: #222222;      --tg-df-text-muted: #555555;      --tg-df-bg: #ffffff;      --tg-df-bg-secondary: #f4f4f4;      --tg-df-border: #e2e8f0;      font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;      color: var(--tg-df-text);      background-color: transparent;       width: 100%;      max-width: 1200px;      margin: 0 auto;      padding-bottom: 24px;    }    .tg-df-container *, .tg-df-container *::before, .tg-df-container *::after {      margin: 0;      padding: 0;      box-sizing: border-box;    }    .tg-df-container img {      border: none;      margin: 0;      padding: 0;    }    .tg-df-container a {      text-decoration: none;      color: inherit;    }    /*       2. Search & Filter Bar    */    .tg-df-controls {      display: flex;      flex-direction: column;      align-items: center;      gap: 20px;      margin-bottom: 32px;      width: 100%;      position: relative;      z-index: 20;    }    .tg-df-top-bar {      display: flex;      width: 100%;      max-width: 760px;      gap: 12px;      margin: 0 auto;      align-items: center;    }    .tg-df-search-wrapper {      position: relative;      flex: 1;      width: 100%;      box-shadow: 0 8px 24px rgba(0,0,0,0.06);      border-radius: 40px;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      z-index: 100;    }    .tg-df-autocomplete-dropdown {      position: absolute;      top: calc(100% + 4px);      left: 0;      right: 0;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 12px;      box-shadow: 0 8px 32px rgba(0,0,0,0.12);      max-height: 300px;      overflow-y: auto;      z-index: 200;      display: none;    }    .tg-df-autocomplete-dropdown.active {      display: block;    }    .tg-df-autocomplete-item {      padding: 12px 24px;      cursor: pointer;      font-size: 14px;      color: var(--tg-df-text);      transition: background 0.1s ease;    }    .tg-df-autocomplete-item:hover {      background: var(--tg-df-bg-secondary);    }    .tg-df-search-input {      width: 100%;      padding: 16px 64px 16px 24px;      font-size: 16px;      border: 2px solid transparent;      border-radius: 40px;      outline: none;      transition: border-color 0.2s ease, box-shadow 0.2s ease;      color: var(--tg-df-text);      background: transparent;    }    .tg-df-search-input:focus {      border-color: transparent;      box-shadow: 0 0 0 3px rgba(0, 108, 196, 0.15);    }    .tg-df-search-input::placeholder {      color: #999999;    }        .tg-df-search-btn {      position: absolute;      right: 8px;      top: 50%;      transform: translateY(-50%);      width: 40px;      height: 40px;      border-radius: 50%;      background: #222;      border: none;      display: flex;      align-items: center;      justify-content: center;      cursor: pointer;      transition: background 0.2s ease;    }        .tg-df-search-btn:hover {      background: #000;    }    .tg-df-search-icon {      width: 16px;      height: 16px;      fill: #fff;    }    .tg-df-settings-wrapper {      position: relative;    }        .tg-df-settings-btn {      width: 48px;      height: 48px;      border-radius: 50%;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      box-shadow: 0 4px 12px rgba(0,0,0,0.04);      display: flex;      align-items: center;      justify-content: center;      cursor: pointer;      transition: all 0.2s ease;      color: var(--tg-df-text-muted);      flex-shrink: 0;    }    .tg-df-settings-btn:hover {      background: var(--tg-df-bg-secondary);      border-color: #0000ff;      color: var(--tg-df-text);    }    .tg-df-settings-btn svg {      width: 24px;      height: 24px;      fill: currentColor;    }    .tg-df-settings-dropdown {      position: absolute;      top: calc(100% + 8px);      right: 0;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 12px;      box-shadow: 0 8px 32px rgba(0,0,0,0.12);      width: 280px;      padding: 20px;      display: none;      z-index: 100;      flex-direction: column;      gap: 20px;    }    .tg-df-settings-dropdown.active {      display: flex;    }        .tg-df-settings-dropdown-backdrop {      display: none;      position: fixed;      inset: 0;      z-index: 99;    }        .tg-df-settings-dropdown-backdrop.active {      display: block;    }    .tg-df-setting-item {      display: flex;      flex-direction: column;      gap: 10px;    }    .tg-df-setting-label {      font-size: 11px;      font-weight: 700;      color: var(--tg-df-text-muted);      text-transform: uppercase;      letter-spacing: 0.5px;    }        .tg-df-region-select {        padding: 10px 12px;        border-radius: 8px;        border: 1px solid var(--tg-df-border);        font-size: 15px;        outline: none;        background: var(--tg-df-bg-secondary);        color: var(--tg-df-text);        cursor: pointer;        width: 100%;    }    .tg-df-toggle {        position: relative;        display: inline-block;        width: 44px;        height: 24px;        flex-shrink: 0;    }    .tg-df-toggle input {        opacity: 0;        width: 0;        height: 0;    }    .tg-df-slider {        position: absolute;        cursor: pointer;        top: 0; left: 0; right: 0; bottom: 0;        background-color: #ccc;        transition: .2s;        border-radius: 24px;    }    .tg-df-slider:before {        position: absolute;        content: "";        height: 18px;        width: 18px;        left: 3px;        bottom: 3px;        background-color: white;        transition: .2s;        border-radius: 50%;    }    .tg-df-toggle input:checked + .tg-df-slider {        background-color: #1F69FF;    }    .tg-df-toggle input:checked + .tg-df-slider:before {        transform: translateX(20px);    }    .tg-df-dl-row {        flex-direction: row;        align-items: center;        justify-content: space-between;    }    .tg-df-dl-row-text {        font-size: 14px;        font-weight: 600;        color: var(--tg-df-text);    }    .tg-df-dl-row-subtext {        font-size: 12px;        font-weight: 400;        line-height: 1.3;        color: var(--tg-df-text-muted);        margin-top: 4px;        display: block;    }    .tg-df-filters-container {      position: relative;      width: 100%;      max-width: 800px;    }    .tg-df-scroll-btn {      display: none;      position: absolute;      top: 50%;      transform: translateY(-50%);      width: 32px;      height: 32px;      background: white;      border: 1px solid var(--tg-df-border);      border-radius: 50%;      align-items: center;      justify-content: center;      cursor: pointer;      z-index: 10;      box-shadow: 0 2px 8px rgba(0,0,0,0.1);      color: var(--tg-df-text-primary);      padding: 0;    }    .tg-df-scroll-btn svg {      width: 16px;      height: 16px;    }    .tg-df-scroll-btn:hover {      background: #f4f4f4;    }    .tg-df-scroll-btn.left {      left: 0px;    }    .tg-df-scroll-btn.right {      right: 0px;    }    @container tg-df (max-width: 768px) {      .tg-df-scroll-btn {        display: flex;        top: 22px; /* vertically center within the 44px high filter buttons */      }    }    .tg-df-filters {      display: grid;      width: 100%;      grid-template-columns: repeat(4, 1fr);      gap: 12px;      margin: 0 auto;      max-width: 800px;    }                 .tg-df-sort-wrapper {      position: relative;      display: flex;      align-items: center;      width: 100%;    }        .tg-df-sort-icon {      position: absolute;      left: 14px;      width: 14px;      height: 14px;      fill: var(--tg-df-text-muted);      pointer-events: none;    }    .tg-df-sort-select, .tg-df-filter-select {      width: 100%;      padding: 10px 36px 10px 38px;      font-size: 14px;      border: 1px solid var(--tg-df-border);      border-radius: 100px;      outline: none;      appearance: none;      background-color: var(--tg-df-bg-secondary);      background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 12 12'%3E%3Cpath fill='%23555555' d='M6 8L1 3h10z'/%3E%3C/svg%3E");      background-repeat: no-repeat;      background-position: right 14px center;      color: var(--tg-df-text);      cursor: pointer;      font-weight: 500;      transition: all 0.2s ease;    }        .tg-df-price-input::-webkit-outer-spin-button,    .tg-df-price-input::-webkit-inner-spin-button {      -webkit-appearance: none;      margin: 0;    }    .tg-df-price-input {      -moz-appearance: textfield;    }    .tg-df-sort-select:hover, .tg-df-filter-select:hover {      background-color: #e2e8f0;    }    .tg-df-multiselect-container {      position: relative;    }    @container tg-df (max-width: 768px) {      .tg-df-filters-container {      position: relative;      width: 100%;      max-width: 800px;    }    .tg-df-scroll-btn {      display: none;      position: absolute;      top: 50%;      transform: translateY(-50%);      width: 32px;      height: 32px;      background: white;      border: 1px solid var(--tg-df-border);      border-radius: 50%;      align-items: center;      justify-content: center;      cursor: pointer;      z-index: 10;      box-shadow: 0 2px 8px rgba(0,0,0,0.1);      color: var(--tg-df-text-primary);      padding: 0;    }    .tg-df-scroll-btn svg {      width: 16px;      height: 16px;    }    .tg-df-scroll-btn:hover {      background: #f4f4f4;    }    .tg-df-scroll-btn.left {      left: 0px;    }    .tg-df-scroll-btn.right {      right: 0px;    }    @container tg-df (max-width: 768px) {      .tg-df-scroll-btn {        display: flex;        top: 22px; /* vertically center within the 44px high filter buttons */      }    }    .tg-df-filters {        width: 100%;        margin: 0;        margin-bottom: -320px;        padding: 0 16px 320px 16px;        display: flex;        flex-wrap: nowrap;        gap: 8px;        overflow-x: auto;        overflow-y: hidden;        pointer-events: none;        scrollbar-width: none;        -webkit-overflow-scrolling: touch;      }      .tg-df-filters::-webkit-scrollbar {        display: none;      }      .tg-df-sort-wrapper {        pointer-events: auto;        flex: 0 0 auto;        width: 175px;        min-width: 175px;      }    }        .tg-df-multiselect-trigger {      display: block;      background: #fff;      user-select: none;      width: 100%;      overflow: hidden;      white-space: nowrap;      text-overflow: ellipsis;    }        .tg-df-multiselect-dropdown {      display: none;      position: absolute;      top: calc(100% + 4px);      left: 0;      width: 100%;      min-width: 220px;      max-height: 300px;      overflow-y: auto;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 8px;      box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);      z-index: 100;      padding: 8px 0;    }    .tg-df-multiselect-dropdown.active {      display: block;    }    .tg-df-ms-option {      padding: 8px 16px;      display: flex;      align-items: center;      gap: 8px;      cursor: pointer;      font-size: 14px;    }    .tg-df-ms-option:hover {      background-color: var(--tg-df-bg-secondary);    }        .tg-df-ms-option input {      cursor: pointer;      accent-color: #1f69ff;    }    .tg-df-sort-select:focus, .tg-df-filter-select:focus {      border-color: #0000ff;      box-shadow: 0 0 0 3px rgba(0, 0, 255, 0.2);      background-color: var(--tg-df-bg);    }    /*       3. Deal Grid Layout    */    .tg-df-grid.tg-df-grid-auto {      padding-top: 24px;    }    .tg-df-grid, .tg-df-grid.layout-grid {      display: grid;      grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));      gap: 10px;    }    .tg-df-grid.layout-row {      grid-template-columns: 1fr;      gap: 16px;    }        .tg-df-grid.layout-row .tg-df-card {      flex-direction: row;      align-items: stretch;      height: auto;      box-shadow: none;      border-bottom: 1px solid var(--tg-df-border);    }    .tg-df-grid.layout-row .tg-df-card:hover {      box-shadow: none;    }    .tg-df-grid.layout-row .tg-df-card-image-box {      width: 140px;      min-width: 140px;      aspect-ratio: 3/4;      border-right: none;      padding: 16px 16px 16px 32px;    }    .tg-df-grid.layout-row .tg-df-card-body {      padding: 16px;      justify-content: space-between;    }    .tg-df-grid.layout-row .tg-df-card-title {      font-size: 15px;      margin-bottom: 16px;    }    .tg-df-grid.layout-row .tg-df-card-stars { margin-bottom: 8px; }    .tg-df-grid.layout-row .tg-df-card-footer {      flex-direction: column;      align-items: flex-start;      gap: 0;    }    .tg-df-grid.layout-row .tg-df-card-merchant-pill {      margin-bottom: 4px;    }    .tg-df-grid.layout-row .tg-df-card-price-group {      margin-bottom: 8px;    }    .tg-df-grid.layout-row .tg-df-price-group {      width: auto;    }    .tg-df-grid.layout-row .tg-df-card-cta {      width: 100%;      max-width: 200px;      padding: 10px 24px;      font-size: 13px;      flex-shrink: 0;      text-align: center;      justify-content: center;    }    /*       4. Deal Card Design    */    .tg-df-card {      position: relative;      display: flex;      flex-direction: column;      background-color: #ffffff;      border-radius: 0;      overflow: hidden;      transition: transform 0.2s ease, box-shadow 0.2s ease;      text-decoration: none;      color: inherit;      height: 100%;      box-shadow: 0 0 16px rgba(0, 0, 0, 0.08);      border: 1px solid var(--tg-df-border);    }    .tg-df-card:hover {      box-shadow: 0 0 24px rgba(0, 0, 0, 0.12);    }    .tg-df-card-image-box {      width: 100%;      aspect-ratio: 3/4;      background-color: #f8f8f8;      display: flex;      align-items: center;      justify-content: center;      position: relative;      overflow: hidden;      padding: 32px;      flex: 0 0 auto;    }    .tg-df-card-image {      max-width: 100%;      max-height: 100%;      width: auto;      height: auto;      object-fit: contain;      mix-blend-mode: multiply; /* Helps white background images blend into secondary bg */      transition: transform 0.3s ease;    }    .tg-df-card:hover .tg-df-card-image {      transform: scale(1.05); /* Zoom in on hover */    }    .tg-df-card-discount-badge {      position: absolute;      top: 12px;      left: 12px;      background: #dc2626; /* Red */      color: #ffffff;      padding: 6px 8px;      font-size: 11px;      font-weight: 500;      text-transform: uppercase;      letter-spacing: 0.5px;      border-radius: 0;      z-index: 10;    }        .tg-df-card-merchant-pill {      display: block;      padding: 0;      font-size: 11px;      font-weight: 600;      text-transform: uppercase;      letter-spacing: 0.5px;      border-radius: 0;      color: var(--tg-df-text-muted);      margin-bottom: 8px;      white-space: nowrap;      overflow: hidden;      text-overflow: ellipsis;    }    .tg-df-card-body {      padding: 16px;      display: flex;      flex-direction: column;      flex-grow: 1;      min-width: 0;    }    .tg-df-card-badges {      display: flex;      flex-wrap: wrap;      gap: 6px;      margin-bottom: 8px;    }    .tg-df-tag {      display: inline-flex;      align-items: center;      padding: 4px 6px;      font-size: 11px;      font-weight: 700;      text-transform: uppercase;      border-radius: 4px;      gap: 4px;    }    .tg-df-tag-prime {      background-color: #00A8E1;      color: #fff;    }    .tg-df-tag-coupons {      background-color: #f1f5f9;      color: #334155;      border: 1px solid #cbd5e1;      cursor: pointer;      transition: background-color 0.2s;    }    .tg-df-tag-coupons:hover {      background-color: #e2e8f0;    }        .tg-df-tag-outline {      background-color: #f1f5f9;      color: #334155;      border: 1px solid #cbd5e1;      cursor: pointer;      transition: background-color 0.2s;    }    .tg-df-tag-outline:hover {      background-color: #e2e8f0;    }        @keyframes tg-df-spin {      0% { transform: rotate(0deg); }      100% { transform: rotate(360deg); }    }    .tg-df-coupon-spinner {      border: 2px solid #e2e8f0;      border-top: 2px solid #3b82f6;      border-radius: 50%;      width: 14px;      height: 14px;      animation: tg-df-spin 1s linear infinite;      margin: 4px 8px;      display: inline-block;    }        /* Vouchers Modal */    .tg-df-modal-backdrop {      position: fixed;      top: 0; left: 0; right: 0; bottom: 0;      background: rgba(0,0,0,0.5);      z-index: 10000;      display: flex;      align-items: center;      justify-content: center;      opacity: 0;      pointer-events: none;      transition: opacity 0.3s;    }    .tg-df-modal-backdrop.active {      opacity: 1;      pointer-events: auto;    }    .tg-df-modal {      background: #fff;      border-radius: 12px;      width: 90%;      max-width: 400px;      max-height: 80vh;      display: flex;      flex-direction: column;      box-shadow: 0 10px 40px rgba(0,0,0,0.2);      transform: translateY(20px);      transition: transform 0.3s;    }    .tg-df-modal-backdrop.active .tg-df-modal {      transform: translateY(0);    }    .tg-df-modal-header {      padding: 16px;      border-bottom: 1px solid #e2e8f0;      display: flex;      align-items: center;      justify-content: space-between;    }    .tg-df-modal-title {      font-size: 16px;      font-weight: 600;      margin: 0;    }    .tg-df-modal-close {      background: none;      border: none;      cursor: pointer;      padding: 4px;      color: #64748b;    }    .tg-df-modal-body {      padding: 16px;      overflow-y: auto;    }    .tg-df-voucher-item {      padding: 12px;      border: 1px dashed #cbd5e1;      border-radius: 8px;      margin-bottom: 10px;      background: #f8fafc;      display: flex;      align-items: center;      gap: 12px;      text-decoration: none;      color: inherit;      transition: background-color 0.2s, border-color 0.2s;    }    .tg-df-voucher-item:hover {      background: #f1f5f9;      border-color: #94a3b8;    }    .tg-df-voucher-item:last-child {      margin-bottom: 0;    }    .tg-df-voucher-logo {      width: 48px;      height: 48px;      object-fit: contain;      border-radius: 4px;      background: #fff;      border: 1px solid #e2e8f0;      flex-shrink: 0;    }    .tg-df-voucher-content {      flex: 1;      min-width: 0;    }    .tg-df-voucher-title {      font-size: 14px;      font-weight: 600;      margin: 0 0 4px 0;      line-height: 1.3;      color: #0f172a;    }    .tg-df-voucher-expiry {      font-size: 12px;      color: #64748b;      display: flex;      align-items: center;      gap: 4px;      margin-top: 6px;    }    .tg-df-voucher-code {      display: inline-flex;      align-items: center;      background: #f1f5f9;      border: 1px dashed #cbd5e1;      padding: 6px 10px;      font-family: monospace;      font-weight: 700;      font-size: 14px;      color: #0f172a;      border-radius: 4px;      margin-top: 8px;      cursor: pointer;      transition: all 0.2s ease;    }    .tg-df-voucher-code:hover {      background: #e2e8f0;      border-color: #94a3b8;    }    .tg-df-voucher-code.copied {      background: #ecfdf5;      border-color: #10b981;      color: #10b981;    }    .tg-df-voucher-cta {      display: inline-block;      margin-top: 8px;      font-size: 13px;      font-weight: 600;      color: #2563eb;      text-decoration: none;    }    .tg-df-card-title {      font-size: 15px;      font-weight: 400;      line-height: 1.4;      margin: 0 0 12px 0;      color: var(--tg-df-text);    }    .tg-df-card-footer {      margin-top: auto;      display: flex;      flex-direction: column;      width: 100%;    }    .tg-df-card-price-group {      display: flex;      flex-direction: row;      align-items: center;      gap: 8px;      margin-bottom: 12px;    }    .tg-df-card-price {      font-size: 16px;      font-weight: 700;      color: #dc2626; /* Red price */      line-height: 1;    }        .tg-df-card-msrp {      font-size: 13px;      color: var(--tg-df-text-muted);      text-decoration: line-through;    }    .tg-df-container .tg-df-card-cta {      display: flex;      align-items: center;      justify-content: center;      width: 100%;      box-sizing: border-box;      background-color: #1f69ff;      color: #ffffff;      font-size: 12px;      font-weight: 700;      text-transform: uppercase;      letter-spacing: 0.5px;      padding: 12px 16px;      border-radius: 0;      border: none;      cursor: pointer;      transition: background-color 0.2s ease;    }    .tg-df-card:hover .tg-df-card-cta,    .tg-df-card-cta:hover {      background-color: #1555cc;    }    /*       5. State & Skeleton Styles    */    .tg-df-message {      grid-column: 1 / -1;      text-align: center;      padding: 48px 24px;      color: var(--tg-df-text-muted);      font-size: 16px;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 8px;    }    @keyframes tg-df-shimmer {      0% { background-position: -200% 0; }      100% { background-position: 200% 0; }    }    .tg-df-skeleton {      background: linear-gradient(90deg, var(--tg-df-bg-secondary) 25%, #e2e8f0 50%, var(--tg-df-bg-secondary) 75%);      background-size: 200% 100%;      animation: tg-df-shimmer 1.5s infinite;      border-radius: 4px;    }    .tg-df-skeleton-img {      width: 100%;      height: 100%;      position: absolute;      top: 0; left: 0;    }        .tg-df-skeleton-text {      height: 16px;      margin-bottom: 8px;      width: 100%;    }    .tg-df-skeleton-text.short { width: 40%; }    .tg-df-skeleton-text.title { height: 20px; margin-bottom: 16px; }    /* Editor Floating Bar & Elements */    .tg-df-editor-bar {      position: sticky;      top: 120px;      z-index: 1000;      background: #111827;      color: #fff;      padding: 12px 16px;      border-radius: 8px;      margin-bottom: 16px;      display: flex;      align-items: center;      justify-content: space-between;      box-shadow: 0 4px 12px rgba(0,0,0,0.15);    }    .tg-df-editor-bar-text {      font-weight: 600;      font-size: 14px;    }    .tg-df-editor-copy-btn {      background: #10b981;      color: #fff;      padding: 6px 16px;      border: none;      border-radius: 4px;      font-weight: 600;      cursor: pointer;      display: flex;      align-items: center;      font-size: 13px;    }    .tg-df-editor-copy-btn:hover { background: #059669; }        .tg-df-deal-checkbox {      position: absolute;      top: 12px;      right: 12px;      z-index: 10;      width: 20px;      height: 20px;      cursor: pointer;      pointer-events: auto;    }    /*       6. Mobile List View (Stacks into a cleaner horizontal row/list)    */    @container tg-df (max-width: 599px) {      .tg-df-controls {        padding: 16px 16px 8px;      }            .tg-df-top-bar {        width: 100%;      }            .tg-df-settings-dropdown {        position: fixed;        top: auto;        bottom: 0;        left: 0;        right: 0;        width: 100%;        border-radius: 20px 20px 0 0;        padding: 24px;        box-shadow: 0 -8px 32px rgba(0,0,0,0.15);        z-index: 1000;        border: none;        border-top: 1px solid var(--tg-df-border);      }            .tg-df-settings-dropdown-backdrop.active {        background: rgba(0,0,0,0.4);      }            .tg-df-search-wrapper {        box-shadow: 0 0 16px rgba(0,0,0,0.08);      }                  .tg-df-sort-wrapper.tg-df-price-range-wrapper {        flex: 0 0 auto;        min-width: max-content;        width: auto;      }            .tg-df-sort-select, .tg-df-filter-select {        width: 100%;        text-align: left;        padding: 10px 24px 10px 32px;        background-position: right 8px center;        text-overflow: ellipsis;        white-space: nowrap;        overflow: hidden;      }      .tg-df-sort-icon {        left: 10px;      }      .tg-df-grid:not(.layout-grid):not(.layout-row),      .tg-df-grid.layout-row {        grid-template-columns: 1fr;        gap: 16px;      }            .tg-df-grid.tg-df-grid-auto {        padding-top: 24px;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card,      .tg-df-grid.layout-row .tg-df-card {        flex-direction: row;        align-items: stretch;        height: auto;        box-shadow: none; /* simple line on mobile if preferred, or keep */        border-bottom: 1px solid var(--tg-df-border);      }      .tg-df-grid.tg-df-grid-auto .tg-df-card:hover,      .tg-df-grid.layout-row .tg-df-card:hover {        box-shadow: none;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-image-box,      .tg-df-grid.layout-row .tg-df-card-image-box {        width: 120px;        min-width: 120px;        aspect-ratio: 3/4;        border-right: none;        padding: 12px;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-body,      .tg-df-grid.layout-row .tg-df-card-body {        padding: 12px;        justify-content: space-between;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-title,      .tg-df-grid.layout-row .tg-df-card-title {        font-size: 14px;        margin-bottom: 12px;      }      /* Single column mobile grid override */      .tg-df-grid.layout-grid {        grid-template-columns: 1fr;        gap: 16px;      }      .tg-df-grid.layout-grid .tg-df-card-image-box {        padding: 12px;      }      .tg-df-grid.layout-grid .tg-df-card-body {        padding: 10px;      }      .tg-df-grid.layout-grid .tg-df-card-title {        font-size: 13px;        margin-bottom: 8px;      }      .tg-df-grid.layout-grid .tg-df-card-price {        font-size: 14px;      }            .tg-df-card-footer {        flex-direction: column;        align-items: stretch;        gap: 0;        width: 100%;        min-width: 0;      }      .tg-df-card-merchant-pill {        margin-bottom: 4px;      }      .tg-df-card-price-group {        flex: 1 1 auto;        margin-bottom: 8px;      }      .tg-df-card-price {        font-size: 16px;      }      .tg-df-card-msrp {        display: block;       }      .tg-df-grid.layout-row .tg-df-card-cta,      .tg-df-container .tg-df-card-cta {        width: 100%;        max-width: none;        min-width: 0;        box-sizing: border-box;        padding: 8px 16px;        font-size: 12px;        flex: 0 0 auto;        text-align: center;        white-space: normal;        line-height: 1.2;      }    }    .tg-df-container.is-carousel {      min-height: 760px;      background-color: #E7F0FF;      padding: 0 0 24px 0;      border-radius: 24px;      width: 100vw;      max-width: 1200px;      position: relative;      left: 50%;      transform: translateX(-50%);    }    .tg-df-container.is-carousel.hide-header-details {      min-height: 480px;    }    /*       7. Carousel View Mode    */    .tg-df-container .tg-df-carousel-host {      /* Layout is now handled by container wrapper */    }    .tg-df-container .tg-df-carousel-eyebrow {      color: #1F69FF;      font-weight: 700;      font-size: 14px;      text-transform: uppercase;      letter-spacing: 1px;      padding: 24px 16px 0 16px;      display: none;    }    .tg-df-container .tg-df-carousel-query-title {      color: #011535;      font-size: 28px;      font-weight: 600;      padding: 0 16px 24px 16px;      line-height: 1.2;      display: none;    }    .tg-df-container .tg-df-carousel-blue-box {      background-color: transparent;      border-radius: 0;      padding: 24px 24px 0 24px;      margin: 0;      color: #1F69FF;          position: relative;      overflow: hidden;    }    .tg-df-container .tg-df-carousel-bg-circle-1 {      display: none;    }    .tg-df-container .tg-df-carousel-bg-circle-2 {      display: none;    }    .tg-df-container .tg-df-carousel-bg-circle-3 {      display: none;    }    .tg-df-container .tg-df-carousel-box-content {      position: relative;      z-index: 10;    }    .tg-df-container .tg-df-carousel-box-eyebrow {      background-color: transparent;      color: #1F69FF;      font-weight: 700;      font-size: 14px;      text-transform: uppercase;      letter-spacing: 1px;      display: inline-block;      padding: 0;      border-radius: 0;    }    .tg-df-container .tg-df-carousel-box-title {      font-size: 28px;      font-weight: 600;      line-height: 1.2;      margin-top: 8px;      color: #1e293b;    }    .tg-df-container .tg-df-countdown-wrapper {      position: absolute;      top: 0;      right: 0;      display: flex;      flex-direction: column;      align-items: flex-end;      gap: 12px;      transform: scale(0.67);      transform-origin: top right;    }    .tg-df-container .tg-df-countdown-title {      font-size: 14px;      font-weight: 600;      color: #011535;      margin: 0;    }    .tg-df-container .tg-df-countdown-blocks {      display: flex;      gap: 16px;    }    .tg-df-container .tg-df-countdown-item {      display: flex;      flex-direction: column;      align-items: center;      gap: 4px;    }    .tg-df-container .tg-df-countdown-box {      width: 59px;      height: 59px;      background: #03FE9E;      border-radius: 15px;      display: flex;      align-items: center;      justify-content: center;    }    .tg-df-container .tg-df-countdown-num {      font-family: 'Inter', sans-serif;      font-weight: 700;      font-size: 20px;      line-height: normal;      color: #011535;    }    .tg-df-container .tg-df-countdown-label {      font-family: 'Inter', sans-serif;      font-weight: 500;      font-size: 16px;      line-height: normal;      color: #1e293b;      text-transform: uppercase;    }    .tg-df-container .tg-df-carousel-box-subtitle {      font-size: 16px;      margin-top: 8px;      font-weight: 300;      color: #1e293b;      line-height: 24px;    }    .tg-df-container .tg-df-carousel-roundels-wrapper {      position: relative;      margin-top: 24px;      margin-left: -24px;      margin-right: -24px;    }    .tg-df-container .tg-df-carousel-roundels {      display: flex;      gap: 16px;      overflow-x: auto;            scrollbar-width: none;      padding-top: 12px;      padding-bottom: 24px;      padding-left: 24px;      padding-right: 24px;      margin-left: 0;      margin-right: 0;    }        .tg-df-container .tg-df-carousel-scroll-left,    .tg-df-container .tg-df-carousel-scroll-right {      position: absolute;      top: 50%;      transform: translateY(-50%);      height: 36px;      width: 36px;      display: flex;      align-items: center;      justify-content: center;      border-radius: 50%;      background-color: #ffffff;      border: 1px solid #e2e8f0;      box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);      color: #1F69FF;      cursor: pointer;      transition: all 0.2s;      margin-top: -4px;      z-index: 20;    }    .tg-df-container .tg-df-carousel-scroll-left { left: 8px; }    .tg-df-container .tg-df-carousel-scroll-right { right: 8px; }    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-left { left: 0px; }    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-right { right: 0px; }    .tg-df-carousel-filters-outer { margin-left: -24px; margin-right: -24px; padding-left: 24px; padding-right: 24px; }    .tg-df-grid-wrapper { position: relative; }    @container tg-df (max-width: 599px) { .tg-df-carousel-filters-outer { margin-left: -16px; margin-right: -16px; padding-left: 16px; padding-right: 16px; } }        .tg-df-container .tg-df-carousel-scroll-left:hover,    .tg-df-container .tg-df-carousel-scroll-right:hover {      background-color: rgba(255, 255, 255, 0.6);    }    .tg-df-container .tg-df-carousel-roundels::-webkit-scrollbar {      display: none;    }    .tg-df-container .tg-df-roundel {      display: flex;      flex-direction: column;      align-items: center;      gap: 8px;      cursor: pointer;      min-width: 120px;      flex-shrink: 0;    }    .tg-df-container .tg-df-roundel-img-box {      width: 120px;      height: 120px;      border-radius: 50%;      background: white;      display: flex;      align-items: center;      justify-content: center;      overflow: hidden;      box-shadow: 0px 3px 14px 0px rgba(30, 41, 59, 0.08);      transition: box-shadow 0.2s;    }    .tg-df-container .tg-df-roundel:hover .tg-df-roundel-img-box {      box-shadow: 0 0 0 2px #E7F0FF, 0 0 0 4px #1F69FF;    }    .tg-df-container .tg-df-roundel.active .tg-df-roundel-img-box {      box-shadow: 0 0 0 2px #E7F0FF, 0 0 0 4px #1F69FF;    }    .tg-df-container .tg-df-roundel:hover .tg-df-roundel-img-box img {      transform: scale(1.08);    }    .tg-df-container .tg-df-roundel-img-box img {      width: 100%;      height: 100%;      object-fit: contain;      padding: 10px;      box-sizing: border-box;      transition: transform 0.3s ease;    }    .tg-df-container .tg-df-roundel-label {      font-size: 13px;      font-weight: 400;      color: #1e293b;      text-align: center;    }    .tg-df-container .tg-df-carousel-filters-label {      font-size: 16px;      font-weight: 400;      color: #1e293b;      white-space: nowrap;      margin-right: 4px;    }    .tg-df-container .tg-df-carousel-filters-wrap {      display: flex;      align-items: center;      flex-wrap: nowrap;      gap: 8px;      margin-top: 8px;      overflow-x: auto;      scrollbar-width: none;      -webkit-overflow-scrolling: touch;      padding-bottom: 8px;      margin-left: -24px;      margin-right: -24px;      padding-left: 24px;      padding-right: 24px;    }    .tg-df-container .tg-df-carousel-filters-wrap::-webkit-scrollbar {      display: none;    }        .tg-df-container .tg-df-carousel-filter-btn img,    .tg-df-container .tg-df-carousel-filter-btn picture {      height: 20px;      width: 20px;      object-fit: contain;      object-position: center;      display: inline-flex;      align-items: center;      justify-content: center;      margin-right: 6px;    }    .tg-df-container .tg-df-carousel-filter-btn picture img {      margin-right: 0;      height: 100%;      width: 100%;    }    .tg-df-container .tg-df-carousel-filter-btn img.active-img,    .tg-df-container .tg-df-carousel-filter-btn picture:has(.active-img) {      display: none;    }    .tg-df-container .tg-df-carousel-filter-btn:hover img.inactive-img,    .tg-df-container .tg-df-carousel-filter-btn.active img.inactive-img,    .tg-df-container .tg-df-carousel-filter-btn:hover picture:has(.inactive-img),    .tg-df-container .tg-df-carousel-filter-btn.active picture:has(.inactive-img) {      display: none;    }    .tg-df-container .tg-df-carousel-filter-btn:hover img.active-img,    .tg-df-container .tg-df-carousel-filter-btn.active img.active-img,    .tg-df-container .tg-df-carousel-filter-btn:hover picture:has(.active-img),    .tg-df-container .tg-df-carousel-filter-btn.active picture:has(.active-img) {      display: inline-flex;    }    .tg-df-container .tg-df-carousel-filter-btn {      background: #ffffff;      border: 2px solid #1e293b;      color: #1e293b;      border-radius: 24px;      padding: 6px 16px;      font-size: 14px;      font-weight: 600;      cursor: pointer;      transition: all 0.2s;      flex-shrink: 0;      white-space: nowrap;    }    .tg-df-container .tg-df-carousel-filter-btn svg {      margin-right: 6px;    }    .tg-df-container .tg-df-carousel-filter-btn {      display: inline-flex;      align-items: center;    }    .tg-df-container .tg-df-carousel-filter-btn:hover {      background: #1e293b;      color: white;      border-color: #1e293b;    }    .tg-df-container .tg-df-carousel-filter-btn.active {      background: #1e293b;      color: white;      border-color: #1e293b;    }        .tg-df-grid.carousel-compact {      display: flex;      flex-wrap: nowrap;      overflow-x: auto;      gap: 16px;      padding: 16px 24px;      align-items: stretch;      scrollbar-width: none;    }    .tg-df-grid.carousel-compact::-webkit-scrollbar {      display: none;    }    .tg-df-grid.carousel-compact .tg-df-card {      flex: 0 0 auto;      width: 200px;      min-height: auto;      height: auto;      display: flex;      flex-direction: column;      border-radius: 15px;      border: none;      box-shadow: 0 0 16px rgba(0,0,0,0.08);      overflow: visible;    }    .tg-df-grid.carousel-compact .tg-df-card-image-box {      padding: 12px;      background-color: transparent;      border-radius: 15px 15px 0 0;      height: 130px;    }    .tg-df-grid.carousel-compact .tg-df-card-image {      mix-blend-mode: normal;    }    .tg-df-grid.carousel-compact .tg-df-card-discount-badge {      border-radius: 0;      top: 0px;      left: 0px;      padding: 4px 8px;      font-size: 11px;    }    .tg-df-grid.carousel-compact .tg-df-card-body {      padding: 8px 12px 12px 12px;    }    .tg-df-grid.carousel-compact .tg-df-card-title {      font-size: 14px;      font-weight: 400;      margin-bottom: 8px;      color: #011535;    }    .tg-df-grid.carousel-compact .tg-df-card-body:not(:has(.tg-df-card-stars)):not(:has(.tg-df-tag-prime)):not(:has(.tg-df-coupon-wrapper:not([style*="none"]))) > .tg-df-card-title,    .tg-df-grid.carousel-compact .tg-df-card-body:not(:has(.tg-df-card-stars)):has(> .tg-df-card-title:first-child) > .tg-df-card-title {    }    .tg-df-grid.carousel-compact .tg-df-card-cta {      border-radius: 5px;      padding: 8px 10px;      margin-top: 4px;      background-color: #1F69FF;    }    .tg-df-grid.carousel-compact .tg-df-card-price-group {      margin-bottom: 2px;    }    .tg-df-grid.carousel-compact .tg-df-card-merchant-pill {      margin-bottom: 2px;    }    @container tg-df (max-width: 599px) {      .tg-df-container .tg-df-carousel-blue-box-title {        font-size: 24px;      }      .tg-df-container .tg-df-countdown-title {        display: none;      }      .tg-df-container .tg-df-countdown-wrapper {        position: absolute;        top: 0;        right: 0;        align-items: flex-end;        transform: scale(0.40);        transform-origin: top right;      }      .tg-df-container .tg-df-roundel {        min-width: 88px;      }      .tg-df-container .tg-df-roundel-img-box {        width: 88px;        height: 88px;      }    }    /* REPLICA BLOCK STYLES */    .tg-df-grid.layout-replica-2 { grid-template-columns: repeat(2, 1fr) !important; gap: 20px; }    .tg-df-grid.layout-replica-1 { grid-template-columns: 1fr !important; gap: 20px; }        .tg-df-container .hawk-deal-widget-container { border-bottom: 1px solid #e5e7eb; display: flex; flex-direction: column; margin: 0; padding: 20px 0; box-sizing: border-box; font-family: inherit; }    .tg-df-container .hawk-deal-widget-wrap { display: flex; flex-direction: row; align-items: flex-start; width: 100%; gap: 24px; }    .tg-df-container .hawk-deal-widget-image-container { display: flex; flex-shrink: 0; justify-content: center; width: 160px; height: 160px; align-items: center; background: white; margin-bottom: 0px; }    .tg-df-container .hawk-deal-widget-title-product-title { color: #111827; font-size: 18px; font-weight: 700; line-height: 1.4; display: inline; }    .tg-df-container .hawk-deal-widget-title-price { font-size: 18px; font-weight: 700; line-height: 1.4; white-space: nowrap; color: #2563eb; }    .tg-df-container .hawk-deal-widget-title-price-now { font-weight: 700; }    .tg-df-container .hawk-deal-widget-title-retailer-price:hover { text-decoration: underline; }    .tg-df-container .hawk-deal-widget-title-retailer { font-size: 18px; font-weight: 700; line-height: 1.4; color: #2563eb; }    .tg-df-container .hawk-deal-widget-title-was-price { color: #dc2626; font-size: 16px; font-weight: 500; line-height: 1.4; text-decoration: line-through; white-space: nowrap; margin-left: 8px; margin-right: 8px; }    .tg-df-container .hawk-deal-widget-text-body-container { position: relative; width: 100%; box-sizing: border-box; }    .tg-df-container .hawk-deal-widget-text-body-main { font-size: 16px; width: 100%; margin-bottom: 12px; }    .tg-df-container .hawk-deal-widget-text-body-description { display: block; font-size: 15px; margin-top: 12px; color: #4b5563; line-height: 1.6; }    .tg-df-container .hawk-deal-widget-text-body-description p { margin: 0; line-height: 1.6; }    .tg-df-container .hawk-deal-widget-text-cta-container { display: flex; flex-direction: column; gap: 12px; width: 100%; flex: 1; min-width: 0; box-sizing: border-box; }    .tg-df-container .hawk-deal-widget-footer { display: flex; justify-content: flex-end; width: 100%; margin-top: auto; }    .tg-df-container .hawk-deal-widget-button-wrapper { display: flex; flex-direction: column; align-items: flex-end; justify-content: flex-end; width: 100%; }    .tg-df-container .hawk-deal-widget-preferred-partner-wrapper { display: flex; flex-direction: row; }        @container tg-df (min-width: 600px) {      .tg-df-mobile-only { display: none !important; }    }    @container tg-df (max-width: 599px) {      .tg-df-desktop-only { display: none !important; }      .tg-df-grid.layout-replica-2 { grid-template-columns: 1fr !important; }      .tg-df-grid.savings-squad-cards { grid-template-columns: 1fr !important; display: flex; flex-direction: column; }    }    .tg-df-grid.savings-squad-cards .tg-df-card-title {      -webkit-line-clamp: unset !important;      display: block !important;      overflow: visible !important;    }    @container tg-df (max-width: 500px) {      .tg-df-container .hawk-deal-widget-wrap { display: block; }      .tg-df-container .hawk-deal-widget-image-container { display: block; float: left; margin: 0 16px 8px 0; width: 120px; max-width: 120px; height: auto; align-items: normal; justify-content: normal; }      .tg-df-container .hawk-deal-widget-text-cta-container { display: block; text-align: left; }      .tg-df-container .hawk-deal-widget-footer { display: block; margin-top: 16px; clear: both; width: 100%; }      .tg-df-container .hawk-deal-widget-button-wrapper { display: block; width: 100%; }      .tg-df-container .hawk-deal-widget-button-wrapper .hawk-deal-widget-preferred-partner-wrapper { display: block; width: 100%; }      .tg-df-container .hawk-affiliate-link-deal-button { box-sizing: border-box !important; display: flex !important; max-width: none !important; width: 100% !important; margin: 0 !important; }    }        .tg-df-container .hawk-affiliate-link-deal-button {       align-items: center; background-color: #1f69ff; box-sizing: border-box; color: #ffffff !important; display: flex; font-size: 14px; font-weight: 700; justify-content: center; letter-spacing: 0.5px; line-height: 1; min-width: 160px; padding: 14px 24px; text-align: center; text-decoration: none; text-transform: uppercase; width: 100%; word-break: normal; border-radius: 4px; border: 0; transition: background-color 0.2s;     }    .tg-df-container .hawk-affiliate-link-deal-button:hover { background-color: #0056e0; text-decoration: none; }    .tg-df-container .hawk-lazy-image-deal-widget { display: block; height: auto; margin: auto; max-height: 160px; max-width: 100%; mix-blend-mode: multiply; object-fit: contain; }    .tg-df-container .hawk-deal-widget-text-cta-container a { color: #2563eb; text-decoration: none; display: inline; }    .tg-df-container .hawk-deal-widget-text-cta-container a:hover { text-decoration: underline; }    .tg-df-container .hawk-deal-widget-text-cta-container a:has(.hawk-deal-widget-title-product-title) { color: #111827; }    .tg-df-container .hawk-deal-widget-text-cta-container a:hover .hawk-deal-widget-title-product-title,    .tg-df-container .hawk-deal-widget-text-cta-container a:hover .hawk-deal-widget-title-retailer-price { text-decoration: underline; }    .tg-df-savings-squad-header { margin-bottom: 24px; text-align: center; display: none; }    .tg-df-banner-img-desktop { display: block; width: 100%; height: auto; margin-bottom: 32px; }    .tg-df-banner-img-mobile { display: none; width: 100%; height: auto; margin-bottom: 32px; }    @container tg-df (max-width: 600px) {      .tg-df-banner-img-desktop { display: none; }      .tg-df-banner-img-mobile { display: block; }    }    .tg-df-header-title { font-size: 28px; font-weight: 700; color: var(--tg-df-text); margin: 32px 0 12px 0; line-height: 1.3; }    .tg-df-header-subtitle { font-size: 16px; color: var(--tg-df-text-muted); margin: 0 0 32px 0; line-height: 1.5; }  \x3C/style>  \x3C!-- Widget Container --\x3E  \x3Cdiv class="tg-df-container" id="signal-deals-finder-root">    \x3Cdiv class="tg-df-savings-squad-header" id="tg-df-savings-squad-header">      \x3Cpicture>        \x3Cimg src="https://cdn.mos.cms.futurecdn.net/flexiimages/xkh2og7m3d1778189998.png" alt="Deals Banner" class="tg-df-banner-img-desktop" />        \x3Cimg src="https://cdn.mos.cms.futurecdn.net/flexiimages/gmak6rtdf41778245089.png" alt="Deals Banner Mobile" class="tg-df-banner-img-mobile" />      \x3C/picture>      \x3Cdiv class="tg-df-header-text">        \x3Ch2 class="tg-df-header-title" id="tg-df-header-title">Editor's Choice Deals\x3C/h2>        \x3Cp class="tg-df-header-subtitle" id="tg-df-header-subtitle">Discover the best discounts currently available, curated daily by the Tom's Guide Savings Squad.\x3C/p>      \x3C/div>    \x3C/div>    \x3C!-- Editor Floating Bar --\x3E    \x3Cdiv class="tg-df-editor-bar" id="tg-df-editor-bar" style="display:none;">      \x3Cdiv class="tg-df-editor-bar-text" style="display: flex; align-items: center;">        \x3Cspan id="tg-df-selected-count">0\x3C/span>\x26nbsp;Deals Selected        \x3Cbutton class="tg-df-editor-clear-btn" id="tg-df-editor-clear" type="button" style="margin-left: 12px; font-size: 13px; color: #9ca3af; background: none; border: none; cursor: pointer; text-decoration: underline;">Clear All\x3C/button>      \x3C/div>      \x3Cbutton class="tg-df-editor-copy-btn" id="tg-df-editor-copy" type="button">        \x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2">\x3C/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1">\x3C/path>\x3C/svg>        Copy to CMS      \x3C/button>    \x3C/div>    \x3Cdiv class="tg-df-carousel-host" id="tg-df-carousel-host" style="display: none;">      \x3Cdiv class="tg-df-carousel-eyebrow">DEAL FINDER\x3C/div>      \x3Cdiv class="tg-df-carousel-query-title" id="tg-df-carousel-title-label">Best Deals\x3C/div>            \x3Cdiv class="tg-df-carousel-blue-box">        \x3Cdiv class="tg-df-carousel-bg-circle-1" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-bg-circle-2" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-bg-circle-3" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-box-content">          \x3Cdiv class="tg-df-countdown-wrapper" id="tg-df-countdown-wrapper" style="display:none;">            \x3Cdiv class="tg-df-countdown-title" id="tg-df-countdown-title">Prime Day starts in\x3C/div>            \x3Cdiv class="tg-df-countdown-blocks">              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-days">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">DAYS\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-hrs">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">HRS\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-min">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">MIN\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-sec">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">SEC\x3C/div>\x3C/div>            \x3C/div>          \x3C/div>          \x3Cdiv class="tg-df-carousel-box-eyebrow">DEAL FINDER\x3C/div>          \x3Cdiv class="tg-df-carousel-box-title">Find Deals Fast\x3C/div>          \x3Cdiv class="tg-df-carousel-box-subtitle">The latest deals from the biggest retailers, all in one place\x3C/div>                    \x3Cdiv class="tg-df-carousel-roundels-wrapper">          \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-roundels').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>          \x3Cdiv class="tg-df-carousel-roundels">                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Televisions" data-pr="all">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/wcMxTsHgqu3roMbAx7RLnT-132-100.png" alt="TVs" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">TVs\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Phones" data-pr="over50">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/G3KGaRGzj24F6PUsw4bWpT-132-100.png" alt="Phones" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Phones\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Computing" data-pr="all">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/znNvsLzx8NEgNkD9HSFSnT-132-100.png" alt="Computing" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Computing\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Gaming" data-pr="all">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/Pgew8yaRQeZFHqHjTzvBnT-132-100.png" alt="Gaming" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Gaming\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Mattresses" data-pr="over500">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/cW7xsaLyesxkHFVSiC4kmT-132-100.png" alt="Mattresses" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Mattresses\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Audio" data-pr="over30">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/pCvBVHuhaQVjKt3VgCjbqT-132-100.png" alt="Audio" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Audio\x3C/span>            \x3C/div>                  \x3C/div>        \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" onclick="this.parentElement.querySelector('.tg-df-carousel-roundels').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>        \x3C/div>        \x3C/div>        \x3Cdiv class="tg-df-carousel-filters-outer" style="position: relative;">          \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-filters-wrap').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>          \x3Cdiv class="tg-df-carousel-filters-wrap">                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="0">All\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-ot="amazon_lightning">              \x3Cimg src="https://cdn.mos.cms.futurecdn.net/HqAui7w97ft2NPqBtQ5r38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/yWPQ5yyQRhUwVKzGwYbh38-600-100.png" class="active-img" alt="" /> Lightning deals\x3C/button>            \x3Cbutton class="tg-df-carousel-filter-btn" data-ot="amazon_prime">              \x3Cimg src="https://cdn.mos.cms.futurecdn.net/fwoVXvL79turN3Ph535m38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/u75QjVpt3w2EsMimJiRo38-600-100.png" class="active-img" alt="" /> Prime deals\x3C/button>            \x3Cbutton class="tg-df-carousel-filter-btn" data-d="10">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 10% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="15">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 15% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="25">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 25% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-pr="under50">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-badge-dollar-sign">\x3Cpath d="M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z">\x3C/path>\x3Cpath d="M16 8h-6a2 2 0 1 0 0 4h4a2 2 0 1 1 0 4H8">\x3C/path>\x3Cpath d="M12 18V6">\x3C/path>\x3C/svg>            Under $50\x3C/button>        \x3C/div>        \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-filters-wrap').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>      \x3C/div>    \x3C/div>    \x3C/div>      \x3C!-- Search & Filter Controls --\x3E      \x3Cdiv class="tg-df-top-bar" id="tg-df-top-bar" style="position: relative; z-index: 100; margin: 0 auto 20px;">        \x3Cdiv class="tg-df-search-wrapper">          \x3Cinput type="text" class="tg-df-search-input" placeholder="Search for deals, products, or brands...">          \x3Cbutton type="button" class="tg-df-search-btn" aria-label="Search">              \x3Csvg class="tg-df-search-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">                \x3Cpath d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/>              \x3C/svg>          \x3C/button>          \x3Cdiv class="tg-df-autocomplete-dropdown" id="tg-df-autocomplete">\x3C/div>        \x3C/div>      \x3C/div>    \x3Cdiv class="tg-df-controls" id="tg-df-controls" style="display:flex;">              \x3Cdiv class="tg-df-filters-container" style="position: relative; width: 100%; max-width: 800px; margin: 0 auto;">          \x3Cbutton class="tg-df-scroll-btn left" style="display: none;" onclick="this.parentElement.querySelector('.tg-df-filters').scrollBy({left: -200, behavior: 'smooth'})">            \x3Csvg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\x3Cpath d="M15 18l-6-6 6-6"/>\x3C/svg>          \x3C/button>          \x3Cbutton class="tg-df-scroll-btn right" style="display: none;" onclick="this.parentElement.querySelector('.tg-df-filters').scrollBy({left: 200, behavior: 'smooth'})">            \x3Csvg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\x3Cpath d="M9 18l6-6-6-6"/>\x3C/svg>          \x3C/button>          \x3Cdiv class="tg-df-filters">          \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-category-filter-wrapper" style="display: none;">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-category-filter" aria-label="Category">            \x3Coption value="all">All Categories\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper tg-df-multiselect-container" id="tg-df-brand-filter-wrapper" style="display:none;">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M4.25 5.61C6.27 8.2 10 13 10 13v6c0 .55.45 1 1 1h2c.55 0 1-.45 1-1v-6s3.72-4.8 5.74-7.39A.998.998 0 0 0 18.95 4H5.04c-.83 0-1.3.95-.79 1.61z"/>          \x3C/svg>          \x3Cdiv class="tg-df-filter-select tg-df-multiselect-trigger" id="tg-df-brand-trigger" tabindex="0">            Any Brand          \x3C/div>          \x3Cdiv class="tg-df-multiselect-dropdown" id="tg-df-brand-dropdown">            \x3C!-- Populated via script --\x3E          \x3C/div>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper tg-df-price-range-wrapper" id="tg-df-custom-price-wrapper" style="display: flex; align-items:center; justify-content:center; padding: 10px 20px; gap: 8px; border: 1px solid var(--tg-df-border); border-radius: 100px; background-color: var(--tg-df-bg);">          \x3Cspan style="font-size:14px; font-weight:500; color:var(--tg-df-text-primary);">Price\x3C/span>          \x3Cinput type="number" class="tg-df-price-input" id="tg-df-custom-price-min" placeholder="Min" style="width: 48px; background: transparent; border: none; color: var(--tg-df-text-primary); outline: none; font-size: 14px; text-align: center; padding: 0;">          \x3Cspan style="color:var(--tg-df-text-muted)">-\x3C/span>          \x3Cinput type="number" class="tg-df-price-input" id="tg-df-custom-price-max" placeholder="Max" style="width: 48px; background: transparent; border: none; color: var(--tg-df-text-primary); outline: none; font-size: 14px; text-align: center; padding: 0;">        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-legacy-price-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58.55 0 1.05-.22 1.41-.59l7-7c.37-.36.59-.86.59-1.41 0-.55-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-price-filter" aria-label="Filter Prices">            \x3Coption value="all">All Prices\x3C/option>            \x3Coption value="under50">Under $50\x3C/option>            \x3Coption value="50_100">$50 - $100\x3C/option>            \x3Coption value="100_200">$100 - $200\x3C/option>            \x3Coption value="200_500">$200 - $500\x3C/option>            \x3Coption value="over500">Over $500\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-discount-filter-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">            \x3Cpath d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58.55 0 1.05-.22 1.41-.59l7-7c.37-.36.59-.86.59-1.41 0-.55-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-discount-filter" aria-label="Discount Amount">            \x3Coption value="all">Any discount\x3C/option>            \x3Coption value="5">Min 5%\x3C/option>            \x3Coption value="10">Min 10%\x3C/option>            \x3Coption value="15">Min 15%\x3C/option>            \x3Coption value="20">Min 20%\x3C/option>            \x3Coption value="25">Min 25%\x3C/option>            \x3Coption value="30">Min 30%\x3C/option>            \x3Coption value="40">Min 40%\x3C/option>            \x3Coption value="50">Min 50%\x3C/option>            \x3Coption value="60">Min 60%\x3C/option>            \x3Coption value="70">Min 70%\x3C/option>          \x3C/select>          \x3C/div>        \x3C/div>        \x3C/div>      \x3C/div>    \x3C!-- Deals Grid Wrapper --\x3E    \x3Cdiv class="tg-df-grid-wrapper tg-df-carousel-cards-wrapper" id="tg-df-grid-wrapper">      \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('#tg-df-grid').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>      \x3Cdiv class="tg-df-grid" id="tg-df-grid">        \x3C!-- Content populated by JavaScript --\x3E      \x3C/div>      \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" style="display:none;" onclick="this.parentElement.querySelector('#tg-df-grid').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>    \x3C/div>        \x3C!-- Vouchers Modal --\x3E    \x3Cdiv class="tg-df-modal-backdrop" id="tg-df-vouchers-modal">      \x3Cdiv class="tg-df-modal">        \x3Cdiv class="tg-df-modal-header">          \x3Ch3 class="tg-df-modal-title" id="tg-df-vouchers-title">Available Coupons & Deals\x3C/h3>          \x3Cbutton class="tg-df-modal-close" id="tg-df-vouchers-close">            \x3Csvg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">              \x3Cline x1="18" y1="6" x2="6" y2="18">\x3C/line>              \x3Cline x1="6" y1="6" x2="18" y2="18">\x3C/line>            \x3C/svg>          \x3C/button>        \x3C/div>        \x3Cdiv class="tg-df-modal-body" id="tg-df-vouchers-content">          \x3C!-- Vouchers injected here --\x3E        \x3C/div>      \x3C/div>    \x3C/div>  \x3C/div>`;      if (!template) {        template = document.createElement('template');        template.innerHTML = rawTemplate;      }      let shadowRoot = null;      if (hostContainer && template) {        hostContainer.setAttribute('data-initialized', 'true');        shadowRoot = hostContainer.attachShadow({ mode: 'open' });        shadowRoot.appendChild(template.content.cloneNode(true));      }      class DealsFinderWidget {        constructor(config) {          this.rootNode = config.rootNode || document;          this.hostContainer = config.hostContainer || null;          this.rootId = config.rootId || 'signal-deals-finder-root';          this.root = this.rootNode.querySelector('#' + this.rootId);          if (!this.root) return;          this.widgetId = (window.crypto && window.crypto.randomUUID) ? window.crypto.randomUUID() : 'widget-' + Date.now() + '-' + Math.random().toString(36).slice(2);          this.grid = this.root.querySelector('#tg-df-grid');          this.tagsContainer = this.root.querySelector('#tg-df-tags-container');          this.categoryFilter = this.root.querySelector('#tg-df-category-filter');          this.categoryFilterWrapper = this.root.querySelector('#tg-df-category-filter-wrapper');          this.searchInput = this.root.querySelector('.tg-df-search-input');          this.autocompleteDropdown = this.root.querySelector('#tg-df-autocomplete');          this.sortSelect = this.root.querySelector('.tg-df-sort-select');          this.searchBtn = this.root.querySelector('.tg-df-search-btn');                    this.settingsToggle = this.root.querySelector('#tg-df-settings-toggle');          this.settingsPanel = this.root.querySelector('#tg-df-settings-panel');          this.settingsBackdrop = this.root.querySelector('#tg-df-settings-backdrop');          this.regionSelect = this.root.querySelector('#tg-df-region-select');          this.retailerSelect = this.root.querySelector('#tg-df-retailer-select');          this.offerTypeSelect = this.root.querySelector('#tg-df-offer-type-select');          this.viewModeSelect = this.root.querySelector('#tg-df-view-mode-select');          this.rowsSelect = this.root.querySelector('#tg-df-rows-select');          this.dealModeToggle = this.root.querySelector('#tg-df-deal-mode');          this.editorModeToggle = this.root.querySelector('#tg-df-editor-mode');          this.priceFilter = this.root.querySelector('#tg-df-price-filter');          this.discountFilter = this.root.querySelector('#tg-df-discount-filter');                    this.editorBar = this.root.querySelector('#tg-df-editor-bar');          this.editorSelectedCount = this.root.querySelector('#tg-df-selected-count');          this.editorCopyBtn = this.root.querySelector('#tg-df-editor-copy');          this.editorClearBtn = this.root.querySelector('#tg-df-editor-clear');                    this.apiUrl = 'https://search-api.fie.future.net.uk/widget.php';          this.deals = [];          this.displayLimit = 12;          this.airedaleArticles = null;          this.airedaleTags = [];          this.airedaleTagCounts = {};          this.activeDealTag = null;          this.selectedBrands = [];          this.currentQuery = '';          this.editorMode = this.hostContainer ? this.hostContainer.hasAttribute('data-editor-mode') : false;          this.viewModeOverride = this.hostContainer ? this.hostContainer.getAttribute('data-view-mode') : null;          this.selectedDeals = new Map();                    this.brandFilterWrapper = this.root.querySelector('#tg-df-brand-filter-wrapper');          this.brandTrigger = this.root.querySelector('#tg-df-brand-trigger');          this.brandDropdown = this.root.querySelector('#tg-df-brand-dropdown');                    this.customPriceWrapper = this.root.querySelector('#tg-df-custom-price-wrapper');          this.customPriceMin = this.root.querySelector('#tg-df-custom-price-min');          this.customPriceMax = this.root.querySelector('#tg-df-custom-price-max');          this.legacyPriceWrapper = this.root.querySelector('#tg-df-legacy-price-wrapper');          this.discountFilterWrapper = this.root.querySelector('#tg-df-discount-filter-wrapper');          this.initResizeObserver();          this.init();        }        getViewMode() {          console.log("DEBUG getViewMode -> override:", this.viewModeOverride, "editorMode:", this.editorMode);          if (this.viewModeOverride && (!this.editorMode || !this.viewModeSelect)) {            return this.viewModeOverride;          }          return (this.viewModeSelect && this.viewModeSelect.value) ? this.viewModeSelect.value : (this.viewModeOverride || 'auto');        }        applyLayoutMode() {          if (!this.grid) return;          const mode = this.getViewMode();          console.log("[DEBUG] applyLayoutMode CALLED! mode=", mode);          this.grid.classList.remove('layout-row', 'layout-grid', 'tg-df-grid-auto', 'carousel-compact', 'layout-replica-1', 'layout-replica-2');                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          const showHeaderDetails = params.get('show_header_details') !== 'false';          const carouselHost = this.root.querySelector('#tg-df-carousel-host');          const controlsDiv = this.root.querySelector('#tg-df-controls');          const topBarDiv = this.root.querySelector('#tg-df-top-bar');          const headerElement = this.root.querySelector('#tg-df-savings-squad-header');          if (headerElement) {             headerElement.style.display = (mode === 'savings_squad' && showHeaderDetails) ? 'block' : 'none';          }          if (mode === 'carousel') {             this.grid.classList.add('carousel-compact');             if (carouselHost) carouselHost.style.display = 'block';             if (controlsDiv) controlsDiv.style.display = 'none';             if (topBarDiv) topBarDiv.style.display = 'none';             if (this.root.classList.contains('tg-df-container')) {               this.root.classList.add('is-carousel');             }          } else {             if (carouselHost) carouselHost.style.display = 'none';             if (controlsDiv) controlsDiv.style.display = 'flex';             if (topBarDiv) topBarDiv.style.display = 'block';             if (this.root.classList.contains('tg-df-container')) {               this.root.classList.remove('is-carousel');             }          }          if (mode === 'grid') {            this.grid.classList.add('layout-grid');          } else if (mode === 'row') {            this.grid.classList.add('layout-row');          } else if (mode === 'savings_squad') {            this.grid.classList.add('tg-df-grid-auto', 'savings-squad-cards');          } else if (mode !== 'carousel') {            this.grid.classList.add('tg-df-grid-auto');          }                    const settingsWrapper = this.root.querySelector('.tg-df-settings-wrapper');          if (settingsWrapper) {            settingsWrapper.style.display = mode === 'auto' ? 'none' : 'block';          }          if (this.customPriceWrapper) {             this.customPriceWrapper.style.display = mode === 'auto' ? 'flex' : 'none';          }          if (this.legacyPriceWrapper) {             this.legacyPriceWrapper.style.display = mode === 'auto' ? 'none' : 'flex';          }          if (this.discountFilterWrapper) {             this.discountFilterWrapper.style.display = mode === 'auto' ? 'none' : 'flex';          }        }        initResizeObserver() {          try {            if (window.parent === window) return;          } catch (e) {            // cross origin frame check threw          }          const emitHeight = () => {            try {              const height = document.documentElement.scrollHeight || document.body.scrollHeight;              const msg = { type: 'embed-size', height: height };              if (window.parent && window.parent !== window) {                window.parent.postMessage(msg, '*');                window.parent.postMessage(JSON.stringify({ ...msg, sentinel: 'amp' }), '*');              }            } catch (e) {}          };                    if (window.ResizeObserver) {            try {              const ro = new ResizeObserver(() => emitHeight());              ro.observe(document.body);              if (this.root) ro.observe(this.root);            } catch(e){ console.warn(e); }          }          window.addEventListener('resize', emitHeight);          setTimeout(emitHeight, 300);        }        initCountdown() {          this.cdWrapper = this.root.querySelector('#tg-df-countdown-wrapper');                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          this.showCountdown = params.get('show_countdown') === 'true';          const showHeaderDetails = params.get('show_header_details') !== 'false';          const eyebrow = this.root.querySelector('.tg-df-carousel-box-eyebrow');          const title = this.root.querySelector('.tg-df-carousel-box-title');          const subtitle = this.root.querySelector('.tg-df-carousel-box-subtitle');          if (!showHeaderDetails) {            let containerElement = this.root.classList.contains('tg-df-container') ? this.root : this.root.querySelector('.tg-df-container');            if (containerElement) containerElement.classList.add('hide-header-details');            if (eyebrow) eyebrow.style.display = 'none';            if (title) title.style.display = 'none';            if (subtitle) subtitle.style.display = 'none';          }          if (!this.cdWrapper) return;          this.cdTitle = this.root.querySelector('#tg-df-countdown-title');          this.cdDays = this.root.querySelector('#tg-df-cd-days');          this.cdHrs = this.root.querySelector('#tg-df-cd-hrs');          this.cdMin = this.root.querySelector('#tg-df-cd-min');          this.cdSec = this.root.querySelector('#tg-df-cd-sec');          this.updateCountdown();          this.cdInterval = setInterval(() => this.updateCountdown(), 1000);        }        updateCountdown() {          if (!this.cdWrapper) return;          if (!this.showCountdown) {            this.cdWrapper.style.display = 'none';            return;          }          const area = this.getAreaCode();          let offset = '-04:00';          if (['DE', 'FR', 'IT', 'ES', 'NL'].includes(area)) {             offset = '+02:00';          } else if (['GB', 'IE', 'UK'].includes(area)) {             offset = '+01:00';          }          const startTime = new Date('2026-06-23T00:00:00' + offset).getTime();          const endTime = new Date('2026-06-26T00:00:00' + offset).getTime();          const now = Date.now();          let targetTime = 0;          if (now < startTime) {             targetTime = startTime;             if (this.cdTitle) this.cdTitle.textContent = 'Prime Day starts in';             this.cdWrapper.style.display = 'flex';          } else if (now < endTime) {             targetTime = endTime;             if (this.cdTitle) this.cdTitle.textContent = 'Prime Day ends in';             this.cdWrapper.style.display = 'flex';          } else {             this.cdWrapper.style.display = 'none';             if (this.cdInterval) clearInterval(this.cdInterval);             return;          }          const diff = Math.max(0, targetTime - now);          const d = Math.floor(diff / (1000 * 60 * 60 * 24));          const h = Math.floor((diff / (1000 * 60 * 60)) % 24);          const m = Math.floor((diff / 1000 / 60) % 60);          const s = Math.floor((diff / 1000) % 60);          if (this.cdDays) this.cdDays.textContent = d;          if (this.cdHrs) this.cdHrs.textContent = h;          if (this.cdMin) this.cdMin.textContent = m;          if (this.cdSec) this.cdSec.textContent = s;        }        init() {          this.initCountdown();          try {            initAnalytics();          } catch (e) {            console.warn('Deals Widget Analytics Error:', e);          }                    this.bindEvents();                    let initialQuery = '';                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          let initialViewMode = params.get('view_mode');          if (!this.viewModeOverride && initialViewMode) {            this.viewModeOverride = initialViewMode;          }          if (!params.has('search') && !params.has('q') && !params.has('query') && initialViewMode !== 'savings_squad') {             initialQuery = 'Gaming laptops';          }          const website = params.get('website') || 'tomsguide';          this.website = website;          if (website === 'techradar') {            const squadHeader = this.root.querySelector('.tg-df-savings-squad-header');            if (squadHeader) {               const pic = squadHeader.querySelector('picture');               if (pic) pic.style.display = 'none';            }            const style = document.createElement('style');            style.innerHTML = `              .tg-df-container .hawk-affiliate-link-deal-button, .tg-df-container .tg-df-card-cta { background-color: #5DAF08 !important; }              .tg-df-container .hawk-affiliate-link-deal-button:hover, .tg-df-container .tg-df-card-cta:hover { background-color: #4a8c06 !important; }            `;            this.root.appendChild(style);          }                    if (this.regionSelect) {            this.regionSelect.value = params.get('region') || 'auto';            this.updatePriceDropdownCurrency();          }                    if (this.retailerSelect && params.has('retailer')) {            this.retailerSelect.value = params.get('retailer');          }                    if (params.has('brands')) {            const b = params.get('brands');            if (b) {              this.selectedBrands = b.split(',');            }          }                    if (this.offerTypeSelect && params.has('offer_type')) {            this.offerTypeSelect.value = params.get('offer_type');          }          if (this.viewModeSelect && params.has('view_mode')) {            this.viewModeSelect.value = params.get('view_mode');          }          if (this.rowsSelect && params.has('rows')) {            this.rowsSelect.value = params.get('rows');          }          if (params.has('price')) {            const priceVal = params.get('price');            if (this.priceFilter) {               // Try assigning it directly to select. If it's not present implicitly ignores               this.priceFilter.value = priceVal;            }            if (priceVal.includes('_')) {               const parts = priceVal.split('_');               if (this.customPriceMin && parts[0]) this.customPriceMin.value = parts[0];               if (this.customPriceMax && parts[1]) this.customPriceMax.value = parts[1];            }          }          if (this.discountFilter && params.has('min_discount_ratio')) {            // Need to convert back from ratio (e.g. 0.8) to select value (e.g. "20")            const ratioStr = params.get('min_discount_ratio');            const ratioFloat = parseFloat(ratioStr);            if (!isNaN(ratioFloat)) {               const percentage = Math.round((1 - ratioFloat) * 100);               this.discountFilter.value = percentage.toString();            }          }          if (this.sortSelect) {            this.sortSelect.value = params.get('sort') || 'date_desc';          }          if (this.dealModeToggle && params.has('deal_mode')) {            this.dealModeToggle.checked = params.get('deal_mode') === 'true' || params.get('deal_mode') === '1';          }          const headerTitleEl = this.root.querySelector('#tg-df-header-title');          const headerSubtitleEl = this.root.querySelector('#tg-df-header-subtitle');          if (params.has('widget_title') && headerTitleEl) {             headerTitleEl.textContent = params.get('widget_title');          }          if (params.has('widget_subtitle') && headerSubtitleEl) {             headerSubtitleEl.textContent = params.get('widget_subtitle');          }                    // Re-apply layout after params have updated control values          this.applyLayoutMode();                    if (params.get('search')) {            initialQuery = params.get('search');          } else if (params.get('q')) {            initialQuery = params.get('q');          } else if (params.get('query')) {            initialQuery = params.get('query');          }                    this.currentQuery = initialQuery;          if (this.searchInput) {            if (this.getViewMode() === 'savings_squad') {              this.searchInput.value = '';            } else {              this.searchInput.value = this.currentQuery;            }          }                    if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {            this.fetchDeals(this.currentQuery);          } else {            this.render();          }        }        updatePriceDropdownCurrency() {          if (!this.priceFilter || !this.regionSelect) return;          const currencySymbols = {            'US': '$',            'GB': '£',            'CA': '$CA',            'AU': '$AU',            'DE': '€',            'FR': '€',            'IT': '€',          };          const area = this.getAreaCode();          const cur = currencySymbols[area || 'US'] || '$';                    const options = this.priceFilter.options;          for (let i = 0; i < options.length; i++) {            const opt = options[i];            if (opt.value === 'all') {              opt.innerText = 'All Prices';            } else if (opt.value === 'under50') {              opt.innerText = `Under ${cur}50`;            } else if (opt.value === '50_100') {              opt.innerText = `${cur}50 - ${cur}100`;            } else if (opt.value === '100_200') {              opt.innerText = `${cur}100 - ${cur}200`;            } else if (opt.value === '200_500') {              opt.innerText = `${cur}200 - ${cur}500`;            } else if (opt.value === 'over500') {              opt.innerText = `Over ${cur}500`;            }          }        }        populateBrandDropdown(values) {          if (!this.brandDropdown || !this.brandFilterWrapper) return;          this.brandFilterWrapper.style.display = 'flex'; // show the wrapper                    let html = '';          const allChecked = this.selectedBrands.length === 0 ? 'checked' : '';          const _div = '<' + '/div>';          const _span = '<' + '/span>';          html += `\x3Cdiv class="tg-df-ms-option">\x3Cinput type="checkbox" value="" ${allChecked} class="tg-df-brand-chk"> Any Brand${_div}`;                    values.forEach(v => {             if (!v.formatted_value || v.formatted_value === 'Any Brand') return;             const isChecked = this.selectedBrands.includes(v.formatted_value) ? 'checked' : '';             html += `\x3Cdiv class="tg-df-ms-option">\x3Cinput type="checkbox" value="${this.escapeHTML(v.formatted_value)}" ${isChecked} class="tg-df-brand-chk"> ${this.escapeHTML(v.formatted_value)} \x3Cspan style="color:var(--tg-df-text-muted);font-size:12px">(${v.count || 0})${_span}${_div}`;          });                    this.brandDropdown.innerHTML = html;                    // Re-bind listeners          const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');          chks.forEach(chk => {            chk.addEventListener('change', (e) => {              const val = e.target.value;              if (val === '') {                this.selectedBrands = [];              } else {                if (e.target.checked) {                   if (!this.selectedBrands.includes(val)) this.selectedBrands.push(val);                } else {                   this.selectedBrands = this.selectedBrands.filter(b => b !== val);                }              }                            if (this.selectedBrands.length === 0) {                 this.brandTrigger.innerText = 'Any Brand';              } else if (this.selectedBrands.length === 1) {                 this.brandTrigger.innerText = this.selectedBrands[0];              } else {                 this.brandTrigger.innerText = `${this.selectedBrands.length} Brands selected`;              }                            // Only call API if changed from UI interactions              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                 this.updateURLParams();                 this.fetchDeals(this.currentQuery);              }            });          });                    // Update button text on load          if (this.selectedBrands.length === 0) {             this.brandTrigger.innerText = 'Any Brand';          } else if (this.selectedBrands.length === 1) {             this.brandTrigger.innerText = this.selectedBrands[0];          } else {             this.brandTrigger.innerText = `${this.selectedBrands.length} Brands selected`;          }        }        updateURLParams() {          const url = new URL(window.location);          if (this.currentQuery && this.currentQuery !== 'Gaming laptops') {            url.searchParams.set('q', this.currentQuery);          } else {            url.searchParams.delete('q');            url.searchParams.delete('search');            url.searchParams.delete('query');          }                    if (this.regionSelect && this.regionSelect.value !== 'auto') {            url.searchParams.set('region', this.regionSelect.value);          } else {            url.searchParams.delete('region');          }                    if (this.retailerSelect && this.retailerSelect.value) {            url.searchParams.set('retailer', this.retailerSelect.value);          } else {            url.searchParams.delete('retailer');          }                    if (this.selectedBrands && this.selectedBrands.length > 0) {            url.searchParams.set('brands', this.selectedBrands.join(','));          } else {            url.searchParams.delete('brands');          }                    if (this.offerTypeSelect && this.offerTypeSelect.value) {            url.searchParams.set('offer_type', this.offerTypeSelect.value);          } else {            url.searchParams.delete('offer_type');          }                    if (this.viewModeSelect && this.viewModeSelect.value !== 'auto') {            url.searchParams.set('view_mode', this.viewModeSelect.value);          } else {            url.searchParams.delete('view_mode');          }                    if (this.rowsSelect && this.rowsSelect.value !== '12') {            url.searchParams.set('rows', this.rowsSelect.value);          } else {            url.searchParams.delete('rows');          }                    const min = this.customPriceMin ? this.customPriceMin.value : '';          const max = this.customPriceMax ? this.customPriceMax.value : '';          if (min || max) {             url.searchParams.set('price', `${min}_${max}`);          } else if (this.priceFilter && this.priceFilter.value !== 'all') {            url.searchParams.set('price', this.priceFilter.value);          } else {            url.searchParams.delete('price');          }                    if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {            const v = parseInt(this.discountFilter.value);            if (!isNaN(v) && v > 0) {               const ratio = (100 - v) / 100;               url.searchParams.set('min_discount_ratio', ratio.toString());            }          } else {            url.searchParams.delete('min_discount_ratio');          }                    if (this.sortSelect && this.sortSelect.value !== 'date_desc') {            url.searchParams.set('sort', this.sortSelect.value);          } else {            url.searchParams.delete('sort');          }                    if (this.dealModeToggle && this.dealModeToggle.checked) {            url.searchParams.set('deal_mode', 'true');          } else {            url.searchParams.delete('deal_mode');          }                    window.history.replaceState({}, '', url);        }        bindEvents() {          const handleFiltersScroll = () => {            const filters = this.root.querySelector('.tg-df-filters');            const leftBtn = this.root.querySelector('.tg-df-scroll-btn.left');            const rightBtn = this.root.querySelector('.tg-df-scroll-btn.right');            if (filters && leftBtn && rightBtn) {              const { scrollLeft, scrollWidth, clientWidth } = filters;              leftBtn.style.display = scrollLeft > 0 ? 'flex' : 'none';              rightBtn.style.display = Math.ceil(scrollLeft + clientWidth) < scrollWidth - 5 ? 'flex' : 'none';            }          };          const filters = this.root.querySelector('.tg-df-filters');          if (filters) {            filters.addEventListener('scroll', handleFiltersScroll);            window.addEventListener('resize', handleFiltersScroll);            setTimeout(handleFiltersScroll, 100);                        // Also call after rendering dropdowns            const origRenderCategories = this.renderCategories;            if (origRenderCategories) {               this.renderCategories = (...args) => {                 origRenderCategories.apply(this, args);                 setTimeout(handleFiltersScroll, 50);               };            }          }                const roundels = this.root.querySelectorAll('.tg-df-carousel-cat');          roundels.forEach(r => {             r.addEventListener('click', () => {                const q = r.getAttribute('data-query');                const pr = r.getAttribute('data-pr');                if (typeof trackHawkEvent !== 'undefined') {                     trackHawkEvent({                         clickType: "CC",                         widgetId: this.widgetId,                         productCategoryName: "deals",                         zeroBasedProductIndexOrNull: null,                         totalDealsOrProducts: null,                         areaClicked: "Category Roundel",                         revenueId: this.revenueId,                         isoCurrencyCode: typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD',                         queryName: q,                         widgetTypeName: this.widgetTypeName                     });                 }                this.currentQuery = q;                const label = this.root.querySelector('#tg-df-carousel-title-label');                if (label) label.textContent = 'Best ' + q;                if (this.priceFilter) this.priceFilter.value = pr || 'all';                if (this.discountFilter) this.discountFilter.value = '5';                if (this.searchInput) this.searchInput.value = q;                                roundels.forEach(ro => ro.classList.remove('active'));                r.classList.add('active');                this.fetchDeals(this.currentQuery);             });          });          const discBtns = this.root.querySelectorAll('.tg-df-carousel-filter-btn');          discBtns.forEach(b => {             b.addEventListener('click', () => {                const d = b.getAttribute('data-d');                const pr = b.getAttribute('data-pr');                const ot = b.getAttribute('data-ot');                let label = b.innerText ? b.innerText.trim() : '';                let filterType = 'unknown';                let filterVal = 'unknown';                if (d !== null) { filterType = 'discount'; filterVal = d; }                else if (pr !== null) { filterType = 'price'; filterVal = pr; }                else if (ot !== null) { filterType = 'offertype'; filterVal = ot; }                if (typeof trackElementInteraction === 'function') trackElementInteraction({ id: `filter-${filterType}-${filterVal}`, name: 'Filter Button', label: label });                                if (d !== null) {                   if (this.discountFilter) this.discountFilter.value = this.discountFilter.value === d ? '0' : d;                } else if (pr !== null) {                   if (this.priceFilter) this.priceFilter.value = this.priceFilter.value === pr ? 'all' : pr;                } else if (ot !== null) {                   if (this.offerTypeSelect) this.offerTypeSelect.value = this.offerTypeSelect.value === ot ? 'all' : ot;                } else {                   if (this.discountFilter) this.discountFilter.value = '0';                   if (this.priceFilter) this.priceFilter.value = 'all';                   if (this.offerTypeSelect) this.offerTypeSelect.value = 'all';                }                if (d === null && pr === null && ot === null && b.getAttribute("data-type") !== "custom") {                   discBtns.forEach(ro => ro.classList.remove('active'));                   b.classList.add('active');                } else if (b.getAttribute("data-type") !== "custom") {                   // Only operate on hardcoded buttons (those without data-type)                   discBtns.forEach(ro => {                      if (!ro.getAttribute('data-d') && !ro.getAttribute('data-pr') && !ro.getAttribute('data-ot') && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active');                   });                                      let makeActive = true;                   if (d !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-d') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   } else if (pr !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-pr') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   } else if (ot !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-ot') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   }                                      if (makeActive) b.classList.add('active');                                      // Check if anything is active, if not activate "All"                   let anyActive = false;                   discBtns.forEach(ro => { if (ro.classList.contains('active') && ro.getAttribute('data-type') !== 'custom') anyActive = true; });                   if (!anyActive) {                       discBtns.forEach(ro => { if (!ro.getAttribute('data-d') && !ro.getAttribute('data-pr') && !ro.getAttribute('data-ot') && ro.getAttribute('data-type') !== 'custom') ro.classList.add('active'); });                   }                }                                this.fetchDeals(this.currentQuery);             });          });          if (this.brandTrigger && this.brandDropdown) {            this.brandTrigger.addEventListener('click', () => {              this.brandDropdown.classList.toggle('active');            });            document.addEventListener('click', (e) => {              if (this.brandFilterWrapper && !e.composedPath().includes(this.brandFilterWrapper)) {                this.brandDropdown.classList.remove('active');              }            });          }          const showAutocomplete = () => {             if (this.getViewMode() !== 'savings_squad' || !this.autocompleteDropdown || !this.airedaleTags) return;                          let terms = this.airedaleTags;             if (this.airedaleBrands) {                terms = terms.concat(this.airedaleBrands.map(b => b.formatted_value));             }             terms = [...new Set(terms)];                          const query = this.searchInput.value.trim();             let matches = [];             if (query.length > 0) {                 matches = terms.filter(t => t.toLowerCase().includes(query.toLowerCase()) && t.toLowerCase() !== query.toLowerCase());             } else {                 matches = terms;             }                          if (matches.length > 0) {                 this.autocompleteDropdown.innerHTML = matches.map(m => `\x3Cdiv class="tg-df-autocomplete-item" data-tag="${this.escapeHTML(m)}">${this.escapeHTML(m)}<` + `/div>`).join('');                 this.autocompleteDropdown.classList.add('active');             } else {                 this.autocompleteDropdown.classList.remove('active');             }          };          let debounceTimer;          if(this.searchInput) {            this.searchInput.addEventListener('focus', showAutocomplete);            this.searchInput.addEventListener('input', (e) => {              clearTimeout(debounceTimer);              const query = e.target.value.trim();              this.currentQuery = query;              showAutocomplete();              debounceTimer = setTimeout(() => {                this.updateURLParams();                if (query.length > 2) {                  this.fetchDeals(query);                } else if (query.length === 0) {                  if (this.getViewMode() === 'savings_squad') {                    this.activeDealTag = null;                    this.currentQuery = '';                    if (this.categoryFilter) this.categoryFilter.value = 'all';                    this.fetchDeals('');                  } else {                    this.deals = [];                    this.render();                  }                }              }, 400);            });            this.searchInput.addEventListener('keypress', (e) => {              if (e.key === 'Enter') {                if (this.autocompleteDropdown) this.autocompleteDropdown.classList.remove('active');                clearTimeout(debounceTimer);                const query = e.target.value.trim();                this.currentQuery = query;                                let isTag = false;                if (this.airedaleTags && this.airedaleTags.includes(query)) isTag = true;                if (this.airedaleBrands && this.airedaleBrands.some(b => b.formatted_value === query)) isTag = true;                this.activeDealTag = isTag ? query : null;                                trackElementInteraction({ id: 'search-submit', name: 'Ask', label: 'Ask (main search)', text: query });                this.updateURLParams();                if (query.length > 2 || (this.getViewMode() === 'savings_squad')) {                   if (query.length === 0 && this.getViewMode() === 'savings_squad') {                       if (this.categoryFilter) this.categoryFilter.value = 'all';                   }                   this.fetchDeals(query);                }              }            });          }          if (this.autocompleteDropdown) {             this.autocompleteDropdown.addEventListener('click', (e) => {                const item = e.target.closest('.tg-df-autocomplete-item');                if (item) {                   const tag = item.getAttribute('data-tag');                   this.currentQuery = tag;                   if (this.searchInput) this.searchInput.value = tag;                   this.activeDealTag = tag;                   if (this.categoryFilter && this.airedaleTags.includes(tag)) {                       this.categoryFilter.value = tag;                   }                   this.autocompleteDropdown.classList.remove('active');                   this.updateURLParams();                   this.fetchDeals(tag);                }             });             document.addEventListener('click', (e) => {               if (this.autocompleteDropdown && this.searchInput && !e.composedPath().includes(this.searchInput) && !e.composedPath().includes(this.autocompleteDropdown)) {                 this.autocompleteDropdown.classList.remove('active');               }             });          }          if (this.searchBtn) {            this.searchBtn.addEventListener('click', () => {              if (this.autocompleteDropdown) this.autocompleteDropdown.classList.remove('active');              clearTimeout(debounceTimer);              const query = this.searchInput.value.trim();              trackElementInteraction({ id: 'search-submit', name: 'Ask', label: 'Ask (main search)', text: query });                            let isTag = false;              if (this.airedaleTags && this.airedaleTags.includes(query)) isTag = true;              if (this.airedaleBrands && this.airedaleBrands.some(b => b.formatted_value === query)) isTag = true;              this.activeDealTag = isTag ? query : null;                            this.currentQuery = query;              this.updateURLParams();              if (query.length > 2 || (this.getViewMode() === 'savings_squad')) {                 if (query.length === 0 && this.getViewMode() === 'savings_squad') {                     if (this.categoryFilter) this.categoryFilter.value = 'all';                 }                 this.fetchDeals(query);              }            });          }          if(this.sortSelect && this.sortSelect.querySelector('option[value="date_desc"]') === null) {              const option = document.createElement('option');              option.value = "date_desc";              option.text = "Newest First";              this.sortSelect.insertBefore(option, this.sortSelect.firstChild);          }          if(this.sortSelect) this.sortSelect.addEventListener('change', () => {            trackElementInteraction({ id: `sort-option-${this.sortSelect.value}`, name: 'Sort', label: `Sort: ${this.sortSelect.options[this.sortSelect.selectedIndex].text}` });            this.updateURLParams();            if (this.deals.length > 0) {              this.sortData();              this.render();            }          });                    const priceFilter = this.root.querySelector('#tg-df-price-filter');          if (priceFilter) {            this.priceFilter = priceFilter;            this.priceFilter.addEventListener('change', () => {              trackElementInteraction({ id: `filter-price-${this.priceFilter.value}`, name: 'Price', label: this.priceFilter.options[this.priceFilter.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }            });          }          const updateCustomPrice = () => {             this.updateURLParams();             if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);             } else {                this.render();             }          };          if (this.customPriceMin) {             this.customPriceMin.addEventListener('change', updateCustomPrice);             this.customPriceMin.addEventListener('keypress', (e) => {                if (e.key === 'Enter') updateCustomPrice();             });          }          if (this.customPriceMax) {             this.customPriceMax.addEventListener('change', updateCustomPrice);             this.customPriceMax.addEventListener('keypress', (e) => {                if (e.key === 'Enter') updateCustomPrice();             });          }          const discountFilter = this.root.querySelector('#tg-df-discount-filter');          if (discountFilter) {            this.discountFilter = discountFilter;            this.discountFilter.addEventListener('change', () => {              trackElementInteraction({ id: `filter-discount-${this.discountFilter.value}`, name: 'Discount', label: this.discountFilter.options[this.discountFilter.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }            });          }          if (this.categoryFilter) {            this.categoryFilter.addEventListener('change', (e) => {               const val = e.target.value === 'all' ? null : e.target.value;               this.activeDealTag = val;               if (val) {                 this.currentQuery = val;               } else {                 if (this.searchInput && this.currentQuery === document.querySelector('#tg-df-brand-trigger')?.getAttribute('data-active-brand')) {                     // don't clear current query if a brand is selected                 } else if (this.searchInput) {                     this.currentQuery = '';                     this.searchInput.value = '';                 }               }               this.fetchSavingsSquad();            });          }                    if (this.settingsToggle) {            this.settingsToggle.addEventListener('click', () => {              const o = this.settingsPanel.classList.toggle('active');              this.settingsBackdrop.classList.toggle('active');              if (o) trackElementInteraction({ id: 'filter-open', name: 'Filters', label: 'Open filters' });            });          }                    if (this.settingsBackdrop) {            this.settingsBackdrop.addEventListener('click', () => {              this.settingsPanel.classList.remove('active');              this.settingsBackdrop.classList.remove('active');            });          }                    if (this.regionSelect) {            this.regionSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-region-${this.regionSelect.value}`, name: 'Region', label: this.regionSelect.options[this.regionSelect.selectedIndex].text });              this.updateURLParams();              this.updatePriceDropdownCurrency();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.retailerSelect) {            this.retailerSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-merchant-${this.retailerSelect.value}`, name: 'Retailer', label: this.retailerSelect.options[this.retailerSelect.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.offerTypeSelect) {            this.offerTypeSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-offertype-${this.offerTypeSelect.value}`, name: 'Offer Type', label: this.offerTypeSelect.options[this.offerTypeSelect.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.viewModeSelect) {            this._prevViewMode = this.viewModeSelect.value;            this.viewModeSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-viewmode-${this.viewModeSelect.value}`, name: 'View Mode', label: this.viewModeSelect.options[this.viewModeSelect.selectedIndex].text });                            // Reset all active toggles and filters to prevent config carry-over              this.selectedBrands = [];              if (this.brandTrigger) this.brandTrigger.innerText = 'Select Brands';              if (this.brandDropdown) {                const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                chks.forEach(chk => { chk.checked = false; });              }              if (this.priceFilter) this.priceFilter.value = 'all';              if (this.customPriceMin) this.customPriceMin.value = '';              if (this.customPriceMax) this.customPriceMax.value = '';              if (this.sortSelect) this.sortSelect.value = 'date_desc';              if (this.discountFilter) this.discountFilter.value = '0';              if (this.retailerSelect) this.retailerSelect.value = '';              if (this.offerTypeSelect) this.offerTypeSelect.value = '';              if (this.rowsSelect) this.rowsSelect.value = '12';              if (this.categoryFilter) this.categoryFilter.value = 'all';              this.activeDealTag = null;              this.updateURLParams();              this.applyLayoutMode();                            if (this.getViewMode() === 'savings_squad' || this._prevViewMode === 'savings_squad') {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }              this._prevViewMode = this.viewModeSelect.value;            });          }                    if (this.rowsSelect) {            this.rowsSelect.addEventListener('change', () => {              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.dealModeToggle) {            this.dealModeToggle.addEventListener('change', () => {              this.updateURLParams();              this.render();            });          }          if (this.editorModeToggle) {             this.editorModeToggle.addEventListener('change', (e) => {                this.editorMode = e.target.checked;                this.render();                this.updateFloatingCopyBar();             });          }          if (this.editorCopyBtn) {             this.editorCopyBtn.addEventListener('click', () => {                this.copySelectedDealsToCMS();             });          }          if (this.editorClearBtn) {             this.editorClearBtn.addEventListener('click', () => {                this.selectedDeals.clear();                this.render();                this.updateFloatingCopyBar();             });          }          if (this.grid) {            this.grid.addEventListener('change', (e) => {               if (e.target.classList.contains('tg-df-deal-checkbox')) {                  const dealId = e.target.getAttribute('data-id');                  if (e.target.checked) {                     const dealObj = this.deals.find(d => d.id === dealId);                     if (dealObj) this.selectedDeals.set(dealId, dealObj);                  } else {                     this.selectedDeals.delete(dealId);                  }                  this.updateFloatingCopyBar();               }            });            this.grid.addEventListener('click', (e) => {              const dealCard = e.target.closest('[data-action="deal-click"]');              const similarCard = e.target.closest('[data-action="view-similar-click"]');              const cardLink = dealCard || similarCard;              if (cardLink) {                const productName = cardLink.getAttribute('data-product-name');                const merchantName = cardLink.getAttribute('data-merchant-name');                const productId = cardLink.getAttribute('data-analytics-id');                const price = parseFloat(cardLink.getAttribute('data-price')) || null;                const prevPriceStr = cardLink.getAttribute('data-previous-price');                const previousPrice = prevPriceStr ? parseFloat(prevPriceStr) : null;                const originalLink = cardLink.getAttribute('data-original-link');                const rewrittenLink = cardLink.getAttribute('href');                const revenueId = cardLink.getAttribute('data-revenue-id');                const index = parseInt(cardLink.getAttribute('data-index'), 10) || 0;                const inStock = cardLink.getAttribute('data-in-stock') === 'true';                const totalText = cardLink.getAttribute('data-total');                const totalDeals = parseInt(totalText, 10) || 0;                const productCategoryName = 'deals';                const trackingParams = {                  widgetId: this.widgetId,                  productCategoryName: productCategoryName,                  product: {                    modelId: cardLink.getAttribute('data-model-id') || null,                    matchId: cardLink.getAttribute('data-match-id') || null,                    brand: cardLink.getAttribute('data-model-brand') || null,                    parent: cardLink.getAttribute('data-model-parent') || null,                    name: productName,                    price: price,                    previousPrice: previousPrice,                    link: rewrittenLink,                    originalLink: originalLink,                    inStock: inStock                  },                  zeroBasedProductIndexOrNull: index,                  totalDealsOrProducts: totalDeals,                   merchant: {                    id: cardLink.getAttribute('data-merchant-id') || null,                    network: cardLink.getAttribute('data-merchant-network') || null,                    url: cardLink.getAttribute('data-merchant-url') || null,                    name: merchantName                  },                  revenueId: revenueId,                  widgetTypeName: this.widgetTypeName,                  isoCurrencyCode: normalizeCurrency(this.escapeHTML(cardLink.getAttribute('data-currency') || '$'))                };                if (dealCard) {                  trackDealClick(trackingParams);                } else {                  trackViewSimilarClick(trackingParams);                }              }              const couponsBtn = e.target.closest('[data-action="coupons-click"]');              if (couponsBtn) {                trackElementInteraction({                  id: 'product-card-show-coupons',                  name: 'Coupons',                  label: `Product card coupons: ${couponsBtn.getAttribute('data-merchant')}`                });              }            });          }          this.setupScrollListeners();        }        setupScrollListeners() {          const containers = [             this.root.querySelector('.tg-df-carousel-roundels'),             this.root.querySelector('.tg-df-carousel-filters-wrap'),             this.root.querySelector('#tg-df-grid')          ];                    containers.forEach(container => {             if (!container) return;                          const checkScroll = () => {                if (!container.parentElement) return;                const leftBtn = container.parentElement.querySelector('.tg-df-carousel-scroll-left');                const rightBtn = container.parentElement.querySelector('.tg-df-carousel-scroll-right');                                if (leftBtn) {                   if (container.scrollLeft <= 5) leftBtn.style.display = 'none';                   else leftBtn.style.display = 'flex';                }                                if (rightBtn) {                   if (container.scrollWidth <= container.clientWidth) {                       rightBtn.style.display = 'none';                   } else if (container.scrollLeft >= container.scrollWidth - container.clientWidth - 5) {                       rightBtn.style.display = 'none';                   } else {                       rightBtn.style.display = 'flex';                   }                }             };                          container.addEventListener('scroll', checkScroll);             checkScroll();                          window.addEventListener('resize', checkScroll);                          const observer = new MutationObserver(checkScroll);             observer.observe(container, { childList: true, subtree: true, characterData: false });          });        }        get widgetTypeName() {          const mode = this.viewModeSelect ? this.viewModeSelect.value : (this.viewModeOverride || 'auto');          switch(mode) {              case 'carousel': return 'Carousel';              case 'savings_squad': return 'Savings Squad';              case 'grid': return 'Grid';              case 'row': return 'Row';              default: return 'Auto Collection';          }        }        getRowsLimit() {          if (this.rowsSelect && this.rowsSelect.value) return parseInt(this.rowsSelect.value, 10);          let configSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {             configSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {             configSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(configSource);          if (params.has('rows')) return parseInt(params.get('rows'), 10) || 12;          return 12;        }        getAreaCode() {          if (this.regionSelect && this.regionSelect.value) {            if (this.regionSelect.value === 'auto') return null;            return this.regionSelect.value;          }          let area = null;          try {            const locale = window.navigator.language || window.navigator.userLanguage;            if (locale && locale.includes('-')) {              area = locale.split('-')[1].toUpperCase();            } else if (locale && locale.length === 2) {              if (locale.toUpperCase() === 'EN') { area = 'US'; }              else { area = locale.toUpperCase(); }            }          } catch (e) { /* Ignore */ }                    // Map to known valid options or fallback to US          const valid = ['US', 'GB', 'CA', 'AU', 'DE', 'FR', 'IT'];          if (area === 'UK') area = 'GB';          if (valid.includes(area)) {             return area;          }          return 'US';        }        async fetchDeals(query) {          this.showLoading();          this.deals = [];          this.displayLimit = this.getRowsLimit();                    try {            console.log("getViewMode returns:", this.getViewMode());            if (this.getViewMode() === 'savings_squad') {               await this.fetchSavingsSquad();            } else {               if (this.isBroadQuery(query)) {                 await this.fetchAdviserDeals(query);               } else {                 await this.fetchHawkDeals(query);                 if (this.deals.length === 0) {                   await this.fetchAdviserDeals(query);                 }               }            }          } catch (error) {            console.warn("[Tom's Guide Widget] Fetch error:", error);            this.showError();          }        }        async fetchSavingsSquad() {          let topArticles = this.airedaleArticles;          if (!topArticles) {            const siteParam = this.website || 'tomsguide';            const airedaleUrl = `https://airedale.futurecdn.net/feeds/feed_1781000519267.json?site=${siteParam}&articleType=deals&limit=50`;            let res;            try {               res = await fetch(airedaleUrl);            } catch(e) {               try { res = await fetch(`https://airedale.futurecdn.net/feeds/feed_1776420579726.json?site=${siteParam}&articleType=deals&limit=50`); } catch (err) { console.warn("Fallback fetch failed", err); return; }            }            if (!res.ok) throw new Error('Airedale API Error');            const articles = await res.json();            topArticles = Array.isArray(articles) ? articles.slice(0, 50) : ((articles.data && Array.isArray(articles.data)) ? articles.data.slice(0, 50) : []);            this.airedaleArticles = topArticles;                        let tagCounts = {};            topArticles.forEach((a) => {              let articleTags = new Set();              if (a.articlecategory && Array.isArray(a.articlecategory)) {                 a.articlecategory.forEach((t) => articleTags.add(t));              }              articleTags.forEach(t => {                 tagCounts[t] = (tagCounts[t] || 0) + 1;              });            });                        this.airedaleTags = Object.keys(tagCounts).sort((a, b) => tagCounts[b] - tagCounts[a]);            this.airedaleTagCounts = tagCounts;          }                    let targetArticles = topArticles;          if (!this.activeDealTag && this.currentQuery) {             const tagMatch = this.airedaleTags.find(t => t.toLowerCase() === this.currentQuery.toLowerCase());             if (tagMatch) {                this.activeDealTag = tagMatch;             }          }          if (this.activeDealTag) {             const cleanTag = this.activeDealTag.toLowerCase().replace(/&/g, '').replace(/[^a-z0-9]+/g, '-').replace(/-+/g, '-').replace(/^-|-$/g, '');             const encodedTag = encodeURIComponent(cleanTag);             const siteParam = this.website || 'tomsguide';             const url = `https://airedale.futurecdn.net/feeds/feed_1781000519267.json?site=${siteParam}&articleType=deals&limit=50&articleCategoryHandle=${encodedTag}`;             try {                const res = await fetch(url);                if (res.ok) {                   const articles = await res.json();                   targetArticles = Array.isArray(articles) ? articles.slice(0, 50) : ((articles.data && Array.isArray(articles.data)) ? articles.data.slice(0, 50) : []);                }             } catch(e) {                console.warn("Failed to fetch by activeDealTag", e);             }          }          let extractedDeals = [];          let seenUrls = new Set();                    let overallBrandsCounts = {};                    // First pass: extract ALL brands from topArticles so the dropdown has all options          topArticles.forEach((article) => {             if (!article.articlepage) return;             let pageData = [];             try { pageData = JSON.parse(article.articlepage[0]); } catch(e){ console.warn(e); }             const savingsSquad = pageData.filter((p) => p.type === 'deal' || p.type === 'featured-product');             savingsSquad.forEach((block) => {                const data = block.data || {};                if (data.brand) {                   const cleanBrand = data.brand.replace(/^\d+\.\s*/, '').trim();                   overallBrandsCounts[cleanBrand] = (overallBrandsCounts[cleanBrand] || 0) + 1;                }             });          });          targetArticles.forEach((article) => {             if (!article.articlepage) return;                          let pageData = [];             try {                pageData = JSON.parse(article.articlepage[0]);             } catch(e){ console.warn(e); }                          const savingsSquad = pageData.filter((p) => p.type === 'deal' || p.type === 'featured-product');                          savingsSquad.forEach((block, idx) => {                const data = block.data || {};                const isFeatured = block.type === 'featured-product';                                const link = data.link || {};                const priceObj = data.price || {};                const image = data.image || {};                                if (data.brand) {                   data.brand = data.brand.replace(/^\d+\.\s*/, '').trim();                }                const externalUrl = isFeatured ? data.url : (link.href || null);                let summaryTitle = isFeatured ? (data.name || data.brand) : (data.productName || link.label || article.articlename);                let description = isFeatured ? (data.strapline || '') : (data.text || '');                                if (!isFeatured && !data.productName && data.text) {                   const brSplit = data.text.split(new RegExp('\x3Cbr\\s*\\/?\\x3E', 'i'));                   if (brSplit.length > 1) {                     summaryTitle = brSplit[0].replace(/<[^>]+>/g, '').trim();                     description = brSplit.slice(1).join(' ').replace(/<br\s*\/?>/gi, ' ').replace(/<\/?(p|div)[^>]*>/gi, ' ').replace(/<[^>]+>/g, '').replace(/\s+/g, ' ').trim();                   } else {                     const match = data.text.match(/\x3Cstrong>(.*?)<\/strong>/);                     if (match) {                       summaryTitle = match[1].replace(/<[^>]+>/g, '').trim();                       if (summaryTitle.endsWith(':')) summaryTitle = summaryTitle.slice(0, -1);                     }                   }                }                                let imageUrl = isFeatured ? image.mos : (image.src || null);                if (imageUrl && imageUrl.startsWith('//')) imageUrl = 'https:' + imageUrl;                                description = description.replace(/<br\s*\/?>/gi, ' ').replace(/<\/?(p|div)[^>]*>/gi, ' ').replace(/<[^>]+>/g, '').replace(/\s+/g, ' ').replace(/View Deal$/i, '').trim();                                let merchantName = data.retailer || '';                if (!merchantName && externalUrl) {                   try {                     merchantName = new URL(externalUrl).hostname.replace('www.', '').split('.')[0];                     merchantName = merchantName.charAt(0).toUpperCase() + merchantName.slice(1);                   }catch(e){ console.warn(e); }                }                if (!merchantName) merchantName = 'Retailer';                const q = (this.currentQuery || '').toLowerCase();                const activeTagLogic = (this.activeDealTag || '').toLowerCase();                if (q.length > 2 && q !== activeTagLogic) {                   const searchTarget = `${summaryTitle || ''} ${description || ''}`.toLowerCase();                   if (!searchTarget.includes(q)) return;                }                let rawPrice = 0;                let rawMsrp = 0;                let currencyStr = '$';                if (isFeatured) {                   rawPrice = typeof data.salePrice === 'number' && data.salePrice > 0 ? data.salePrice : (typeof data.price === 'number' ? data.price : 0);                   rawMsrp = typeof data.salePrice === 'number' && typeof data.price === 'number' && data.price > data.salePrice ? data.price : 0;                   currencyStr = data.currency === 'GBP' ? '£' : '$';                } else {                   rawPrice = priceObj.amount ? parseFloat(priceObj.amount) : 0;                   rawMsrp = priceObj.amountWas ? parseFloat(priceObj.amountWas) : 0;                   currencyStr = priceObj.currency === 'GBP' ? '£' : '$';                }                                let savingAmt = 0;                let savingLabel = '';                if (rawPrice > 0 && rawMsrp > rawPrice) {                   savingAmt = parseFloat((rawMsrp - rawPrice).toFixed(2));                   savingLabel = `Save ${currencyStr}${savingAmt}`;                }                                // Apply Brand filter                if (this.selectedBrands && this.selectedBrands.length > 0) {                   const itemBrand = (data.brand || '').toLowerCase();                   const hasMatch = this.selectedBrands.some(sb => sb.toLowerCase() === itemBrand);                   if (!hasMatch) return;                }                // Apply Price filter                let priceFilterVal = null;                const min = this.customPriceMin ? this.customPriceMin.value : '';                const max = this.customPriceMax ? this.customPriceMax.value : '';                if (min || max) {                   priceFilterVal = `${min}_${max}`;                } else if (this.priceFilter && this.priceFilter.value !== 'all') {                   priceFilterVal = this.priceFilter.value;                }                if (priceFilterVal && rawPrice > 0) {                   if (priceFilterVal === 'under50' && rawPrice >= 50) return;                   if (priceFilterVal === 'over50' && rawPrice <= 50) return;                   if (priceFilterVal === 'over30' && rawPrice <= 30) return;                   if (priceFilterVal === 'over500' && rawPrice <= 500) return;                   if (priceFilterVal.includes('_')) {                      const parts = priceFilterVal.split('_');                      const min = parseFloat(parts[0]);                      const max = parseFloat(parts[1]);                      if (!isNaN(min) && rawPrice < min) return;                      if (!isNaN(max) && rawPrice > max) return;                   }                }                // Apply Discount filter                if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {                   const requiredDiscount = parseInt(this.discountFilter.value);                   if (!isNaN(requiredDiscount) && requiredDiscount > 0) {                      if (!rawMsrp || rawMsrp <= rawPrice) return;                      const ratio = Math.round((1 - (rawPrice / rawMsrp)) * 100);                      if (ratio < requiredDiscount) return;                   }                }                                if (externalUrl) {                   if (seenUrls.has(externalUrl)) return;                  seenUrls.add(externalUrl);                }                                extractedDeals.push({                   id: `airedale-${article.id || Math.random()}-${idx}`,                   url: externalUrl,                   image: imageUrl,                   fallbackImage: imageUrl,                   title: summaryTitle,                   brand: data.brand || '',                   productName: data.productName || '',                   merchant: merchantName,                   rawPrice: rawPrice,                   rawMsrp: rawMsrp,                   price: rawPrice > 0 ? rawPrice.toString() : '',                   msrp: rawMsrp > 0 ? rawMsrp.toString() : '',                   currency: currencyStr,                   isCheckPrice: !rawPrice,                   savingLabel: savingLabel,                   savingType: rawMsrp > rawPrice ? 'amount' : 'none',                   isPrime: false,                   starRating: null,                   description: description,                   text: data.text || '',                   authorName: article.articleauthortext ? article.articleauthortext[0] : (article.articleauthor ? article.articleauthor[0] : ''),                   authorRole: article.articleauthorrole ? article.articleauthorrole[0] : '',                   authorImage: article.articleauthormedia ? article.articleauthormedia[0] : '',                   documentUrl: article.documenturl ? article.documenturl[0] : '',                   modifiedDate: article.contentmodifieddate || article.modifieddate || ''                });             });          });                    const airedaleBrandsList = Object.keys(overallBrandsCounts).map(b => ({              formatted_value: b,              count: overallBrandsCounts[b]          })).sort((a,b) => b.count - a.count);                    if (this.getViewMode() === 'savings_squad') {             this.populateBrandDropdown(airedaleBrandsList.slice(0, 15));             if (this.brandFilterWrapper) {                if (airedaleBrandsList.length === 0) {                    this.brandFilterWrapper.style.display = 'none';                } else {                    this.brandFilterWrapper.style.display = 'flex';                }             }          }                    this.deals = extractedDeals;          this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        isBroadQuery(query) {          const q = query.toLowerCase();          const intentModifiers = ['deals', 'best', 'sale', 'under', 'cheap', 'offers', 'discount'];          return intentModifiers.some(term => q.includes(term));        }        async fetchHawkDeals(query) {          const url = new URL(this.apiUrl);          url.searchParams.append('model_name', query);          const areaCode = this.getAreaCode();          if (areaCode) {            url.searchParams.append('area', areaCode);          }                    if (this.retailerSelect && this.retailerSelect.value) {            url.searchParams.append('filter_merchant_name', this.retailerSelect.value);          }                    if (this.selectedBrands && this.selectedBrands.length > 0) {            url.searchParams.append('filter_label[text_brand]', this.selectedBrands.join(','));          }                    let priceVal = null;          const min = this.customPriceMin ? this.customPriceMin.value : '';          const max = this.customPriceMax ? this.customPriceMax.value : '';          if (min || max) {             priceVal = `${min}_${max}`;          } else if (this.priceFilter && this.priceFilter.value !== 'all') {             priceVal = this.priceFilter.value;          }          if (priceVal) {            if (priceVal === 'under50') {              url.searchParams.append('filter_max_price', '50');            } else if (priceVal === 'over50') {              url.searchParams.append('filter_min_price', '50');            } else if (priceVal === 'over30') {              url.searchParams.append('filter_min_price', '30');            } else if (priceVal === 'over500') {              url.searchParams.append('filter_min_price', '500');            } else if (priceVal.includes('_')) {              const parts = priceVal.split('_');              if (parts[0]) url.searchParams.append('filter_min_price', parts[0]);              if (parts[1]) url.searchParams.append('filter_max_price', parts[1]);            }          }                    if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {            const v = parseInt(this.discountFilter.value);            if (!isNaN(v) && v > 0) {              const ratio = (100 - v) / 100;              url.searchParams.append('min_discount_ratio', ratio.toString());            }          }                    if (this.offerTypeSelect && this.offerTypeSelect.value) {            url.searchParams.append('offer', this.offerTypeSelect.value);          }                    url.searchParams.append('filter_product_types', 'deals');                    url.searchParams.append('rows', this.getRowsLimit().toString());          let response;          try {             response = await fetch(url.toString());          } catch(e) {             if (window.location.protocol === 'file:') {                console.warn("[Tom's Guide Widget] fetch from file:// blocked by local CORS policy, falling back to Adviser mock.");                await this.fetchAdviserDeals(query);                return;             }             console.warn("Hawk fetch failed", e);             this.deals = [];             this.render();             return;          }          if (!response.ok) {            throw new Error('Hawk API Response Error');          }          const rawData = await response.json();          // Safely locate data array from potentially wrapped response          let offers = [];          let modelInfoArray = [];                    let brandFilterData = null;          if (rawData && rawData.widget && rawData.widget.data && Array.isArray(rawData.widget.data.filters)) {             brandFilterData = rawData.widget.data.filters.find(f => f.type === 'label_text_brand');          } else if (rawData && rawData.data && Array.isArray(rawData.data.filters)) {             brandFilterData = rawData.data.filters.find(f => f.type === 'label_text_brand');          }          if (brandFilterData && Array.isArray(brandFilterData.values) && brandFilterData.values.length > 0) {             this.populateBrandDropdown(brandFilterData.values);          } else {             if (this.brandFilterWrapper && this.selectedBrands.length === 0) {                this.brandFilterWrapper.style.display = 'none';             }          }                    if (rawData && rawData.widget && rawData.widget.data) {            if (Array.isArray(rawData.widget.data.offers)) offers = rawData.widget.data.offers;            if (rawData.widget.data.model_info && typeof rawData.widget.data.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.widget.data.model_info) ? rawData.widget.data.model_info : Object.values(rawData.widget.data.model_info);            }          } else if (rawData && rawData.data) {            if (Array.isArray(rawData.data.offers)) offers = rawData.data.offers;            if (rawData.data.model_info && typeof rawData.data.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.data.model_info) ? rawData.data.model_info : Object.values(rawData.data.model_info);            }          } else {            if (Array.isArray(rawData)) offers = rawData;            else if (rawData && Array.isArray(rawData.offers)) offers = rawData.offers;            else if (rawData && rawData.offers && Array.isArray(rawData.offers.offer)) offers = rawData.offers.offer;            else if (rawData && rawData.offers) offers = [].concat(rawData.offers);                        if (rawData && rawData.model_info && typeof rawData.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.model_info) ? rawData.model_info : Object.values(rawData.model_info);            }          }          let modelDetails = {};          modelInfoArray.forEach(m => {            const mId = m.model_id || m.id;            if (mId) {              modelDetails[mId] = {                score: m.score != null ? parseFloat(m.score) : null,                brand: m.brand || null,                parent: (m.parents && Array.isArray(m.parents) && m.parents.length > 0) ? m.parents[0].name : null              };            }          });          offers.forEach(item => {            let data = { ...item };            const mId = data.model_id;            if (mId && modelDetails[mId]) {              data.review_score = modelDetails[mId].score;              data.model_brand = modelDetails[mId].brand;              data.model_parent = modelDetails[mId].parent;            } else {              data.review_score = null;            }                        let itemOffers = [];            if (Array.isArray(item.offers)) itemOffers = item.offers;            else if (Array.isArray(item.offer)) itemOffers = item.offer;            else if (item.offers && typeof item.offers === 'object') itemOffers = [item.offers];            else if (item.offer && typeof item.offer === 'object') itemOffers = [item.offer];            if (itemOffers.length > 0) {              itemOffers.forEach(subItem => {                let subData = { ...item, ...subItem };                const subId = subData.model_id;                if (subId && modelDetails[subId]) {                  subData.review_score = modelDetails[subId].score;                  subData.model_brand = modelDetails[subId].brand;                  subData.model_parent = modelDetails[subId].parent;                } else if (data.review_score != null) {                  subData.review_score = data.review_score;                }                if (subData.merchant && typeof subData.merchant === 'object') {                  subData.merchant_name = subData.merchant.name;                }                this.deals.push(this.extractDealData(subData));              });              return;            }                        if (item.merchant && typeof item.merchant === 'object') {              data.merchant_name = item.merchant.name;            }                        this.deals.push(this.extractDealData(data));          });                    this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        async fetchAdviserDeals(query) {          // ======================================================================          // TODO: ADVISER API REPLACEMENT          // The code below simulates the Adviser API response using mock data.          // Once the real endpoint is ready, remove getAdviserMockData() and           // perform an actual fetch() request similar to fetchHawkDeals().          // Example:          // const area = this.getAreaCode();          // let apiUrl = `https://your-adviser-api.com/search?q=${query}&area=${area}`;          // if (this.priceFilter && this.priceFilter.value !== 'all') {          //   const val = this.priceFilter.value;          //   if (val === 'under50') apiUrl += '&filter_max_price=50';          //   else if (val === '50_100') apiUrl += '&filter_max_price=100';          //   else if (val === '100_200') apiUrl += '&filter_max_price=200';          //   else if (val === '200_500') apiUrl += '&filter_max_price=500';          // }          // const res = await fetch(apiUrl);          // const rawData = await res.json();          // ======================================================================          // Simulating network latency          await new Promise(resolve => setTimeout(resolve, 400));                    const rawData = this.getAdviserMockData();          let offers = [];                    if (rawData && rawData.data && rawData.data.Get && Array.isArray(rawData.data.Get.Deal)) {            offers = rawData.data.Get.Deal;          }                    // Basic client-side filtering for the mock if we want it to react to the query          const q = query.toLowerCase();          const selectedRetailer = (this.retailerSelect && this.retailerSelect.value) ? this.retailerSelect.value.toLowerCase() : null;                    offers.forEach(item => {            const dataObj = item;                        // Apply retailer filter            const itemRetailer = (dataObj.dataRetailer || '').toLowerCase();            if (selectedRetailer && itemRetailer !== selectedRetailer && !itemRetailer.includes(selectedRetailer)) {              return;            }                        // Apply mock price filter            let price = dataObj.dataDiscountedPrice || 0;            if (typeof price === 'string') {              price = parseFloat(price.replace(/[^0-9.]/g, ''));            }            let priceVal = null;            const min = this.customPriceMin ? this.customPriceMin.value : '';            const max = this.customPriceMax ? this.customPriceMax.value : '';            if (min || max) {               priceVal = `${min}_${max}`;            } else if (this.priceFilter && this.priceFilter.value !== 'all') {               priceVal = this.priceFilter.value;            }            if (priceVal) {              if (priceVal === 'under50' && price >= 50) return;              if (priceVal === 'over50' && price <= 50) return;              if (priceVal === 'over30' && price <= 30) return;              if (priceVal === 'over500' && price <= 500) return;              if (priceVal.includes('_')) {                 const parts = priceVal.split('_');                 if (parts[0] && price < parseFloat(parts[0])) return;                 if (parts[1] && price > parseFloat(parts[1])) return;              }            }                        // Map Adviser schema to our widget's expected schema            const mappedData = {              url: dataObj.linkHREF || dataObj.dataLink || '#',              image: dataObj.imageURL || (dataObj.image && dataObj.image.src) || '',              title: dataObj.dataProduct || (dataObj.product && dataObj.product.name) || 'Product Deal',              merchant: dataObj.dataRetailer || 'Retailer',              price: dataObj.dataDiscountedPrice || 0,              currency: dataObj.dataCurrency === 'USD' ? '$' : (dataObj.dataCurrency || '$'),              msrp: dataObj.dataOriginalPrice || null            };                        const titleLow = mappedData.title.toLowerCase();            const merchLow = mappedData.merchant.toLowerCase();                        // Smarter mock filtering            let isMatch = false;            if (q === '' || this.isBroadQuery(q)) {              isMatch = true;            } else if (titleLow.includes(q) || merchLow.includes(q)) {              isMatch = true;            } else if ((q.includes('laptop') || q.includes('mac') || q.includes('pc')) && (titleLow.includes('macbook') || titleLow.includes('laptop'))) {              isMatch = true;            } else if ((q.includes('tv') || q.includes('television')) && (titleLow.includes('tv') || titleLow.includes('oled') || titleLow.includes('qled'))) {              isMatch = true;            } else if ((q.includes('phone') || q.includes('smartphone')) && (titleLow.includes('galaxy') || titleLow.includes('phone'))) {              isMatch = true;            } else if ((q.match(/watch|fitness|run|shoe/)) && (titleLow.includes('forerunner') || titleLow.includes('saucony') || titleLow.includes('watch'))) {              isMatch = true;            }                        if (isMatch) {               this.deals.push(this.extractDealData(mappedData));            }          });                    let rowLimit = this.getRowsLimit();          // Intentionally omitting the slice here to allow "Load More" to work if the API returns more                    this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        getAdviserMockData() {          return {            "data": {              "Get": {                "Deal": [                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 300,                    "dataOriginalPrice": 399,                    "dataProduct": "Samsung Galaxy A36",                    "dataRetailer": "Samsung",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/MqDYsukV3JBG54te6dEs7j.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 14,                    "dataOriginalPrice": 24,                    "dataProduct": "Blink Mini",                    "dataRetailer": "Amazon",                    "imageURL": "http://cdn.mos.cms.futurecdn.net/3JurmAjHsDa5tPdaHAwEV8.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 59,                    "dataOriginalPrice": 99,                    "dataProduct": "Ring Video Doorbell",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/rAh4uR7AsAsALCCLTXnLNJ.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 10,                    "dataOriginalPrice": 599,                    "dataProduct": "MacBook Neo",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/Lg4Dvg68j9SbB5CPNrTEpH.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 749,                    "dataOriginalPrice": 849,                    "dataProduct": "65\\\" Fire TV Omni 4K QLED TV",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/SG34ZWodUkLTxJvMTbjPYR.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 71,                    "dataOriginalPrice": 160,                    "dataProduct": "Saucony Hurricane 24",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/vxf7UD5T2Am7guVzFoFcZ4.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 649,                    "dataOriginalPrice": 749,                    "dataProduct": "Garmin Forerunner 970",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/3GKnEu7CdhtxPMfnPCMCiA.png"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 1049,                    "dataOriginalPrice": 1499,                    "dataProduct": "LG 48\\\" C4 4K OLED TV",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/imvwZV9zoMD6fn9Afuge35.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 1499,                    "dataOriginalPrice": 2199,                    "dataProduct": "Samsung 49\\\" Odyssey Neo G9 4K Gaming Monitor",                    "dataRetailer": "Amazon",                    "imageURL": "http://cdn.mos.cms.futurecdn.net/XWDEJ5dUAE2nhK8k3Jk7k7.png"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 299,                    "dataOriginalPrice": 699,                    "dataProduct": "EGOHOME Black Memory Foam Mattress (queen)",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/hMUemtAejNETLVYxNrktzm.jpg"                  }                ]              }            }          };        }        decodeHTML(html) {          if (!html) return '';          const txt = document.createElement("textarea");          txt.innerHTML = String(html);          return txt.value;        }        extractDealData(item) {          const priceRawStr = String(item.price || item.current_price || '0');          const msrpRawStr = String(item.was_price || item.msrp || item.original_price || '0');          const rawPrice = parseFloat(priceRawStr.replace(/[^\d.]/g, '')) || 0;          const rawMsrp = parseFloat(msrpRawStr.replace(/[^\d.]/g, '')) || 0;          const isCheckPrice = rawPrice === 0 || priceRawStr === '0.00' || priceRawStr === '0';                    let originalImageUrl = item.image || item.image_url || item.product_image || '';          let imageUrl = originalImageUrl;          if ((!imageUrl || isCheckPrice) && item.model_image_url) {             imageUrl = item.model_image_url;             originalImageUrl = imageUrl;          } else if ((!imageUrl || isCheckPrice) && item.model_image) {             imageUrl = item.model_image;             originalImageUrl = imageUrl;          }                    if (imageUrl) {            imageUrl = imageUrl.replace(/-(\d+)-(\d+)(\.[a-z.]+)$/i, '$3');          }                    let fallbackImage = '';          if (originalImageUrl && originalImageUrl !== imageUrl) {             fallbackImage = originalImageUrl;          } else if (item.model_image && item.model_image !== imageUrl) {             fallbackImage = item.model_image;          } else if (item.model_image_url && item.model_image_url !== imageUrl) {             fallbackImage = item.model_image_url;          }                    const rawCurrency = item.currency || item.currency_symbol || '$';                    let savingLabel = item.percentage_saving_label || '';          if (!savingLabel && rawMsrp > rawPrice && rawPrice > 0) {            const pct = Math.round(((rawMsrp - rawPrice) / rawMsrp) * 100);            if (pct > 0) {              savingLabel = `${pct}% OFF`;            }          }                    const isPrime = item.shipping && item.shipping.prime === true;                    let scoreRaw = (item.review_score !== undefined && item.review_score !== null && item.review_score > 0) ? parseFloat(item.review_score) : null;          let starRating = 0;          if (scoreRaw !== null) {            starRating = Math.round((scoreRaw > 10 ? scoreRaw / 20 : scoreRaw / 2) * 2) / 2;          }                    return {            id: item.offer_id || item.link || item.url || item.offer_link || Math.random().toString(),            url: item.link || item.url || item.offer_link || '#',            image: imageUrl,            fallbackImage: fallbackImage,            title: item.name || item.title || item.model_name || item.product_name || 'Unknown Product',            brand: item.brand || '',            productName: item.model_name || item.product_name || item.name || '',            merchant: item.merchant_name || item.merchant || item.retailer || 'Retailer',            price: item.price !== undefined ? String(item.price) : '0.00',            currency: this.decodeHTML(rawCurrency),            msrp: item.was_price || item.msrp || item.original_price || null,            rawPrice: rawPrice,            rawMsrp: rawMsrp,            hasWasPrice: (item.was_price !== undefined && item.was_price !== null),            isCheckPrice: isCheckPrice,            savingLabel: savingLabel,            isPrime: isPrime,            starRating: starRating > 0 ? starRating : null,            modelId: item.model_id || '',            productKey: item.product_key || '',            merchantId: (item.merchant && typeof item.merchant === 'object') ? item.merchant.id || '' : '',            matchId: item.match_id || '',            merchantNetwork: (item.merchant && typeof item.merchant === 'object') ? item.merchant.an || '' : '',            merchantUrl: (item.merchant && typeof item.merchant === 'object') ? item.merchant.url || '' : '',            modelBrand: item.model_brand || item.brand || '',            modelParent: item.model_parent || ''          };        }        sortData() {          const sortVal = this.sortSelect ? this.sortSelect.value : 'date_desc';          if (sortVal === 'price_asc') {            this.deals.sort((a, b) => a.rawPrice - b.rawPrice);          } else if (sortVal === 'price_desc') {            this.deals.sort((a, b) => b.rawPrice - a.rawPrice);          } else if (sortVal === 'discount_desc') {            this.deals.sort((a, b) => {              const aDiscount = a.rawMsrp > a.rawPrice ? (a.rawMsrp - a.rawPrice) : 0;              const bDiscount = b.rawMsrp > b.rawPrice ? (b.rawMsrp - b.rawPrice) : 0;              return bDiscount - aDiscount;            });          } else if (sortVal === 'date_desc') {             this.deals.sort((a, b) => {                let dateA = 0;                let dateB = 0;                if (a && a.modifiedDate) {                   const valA = Array.isArray(a.modifiedDate) ? a.modifiedDate[0] : a.modifiedDate;                   dateA = new Date(valA).getTime();                   if (isNaN(dateA)) dateA = 0;                }                if (b && b.modifiedDate) {                   const valB = Array.isArray(b.modifiedDate) ? b.modifiedDate[0] : b.modifiedDate;                   dateB = new Date(valB).getTime();                   if (isNaN(dateB)) dateB = 0;                }                return dateB - dateA;             });          }        }        getFilteredDeals() {          let filteredDeals = [...this.deals];                    if (this.dealModeToggle && this.dealModeToggle.checked) {            filteredDeals = filteredDeals.filter(d => d.hasWasPrice || (d.msrp && d.rawMsrp > d.rawPrice));          }                    return filteredDeals;        }        showLoading() {          const _div = '<' + '/div>';          const skeletonCardHtml = `            \x3Cdiv class="tg-df-card">              \x3Cdiv class="tg-df-card-image-box">                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-img">${_div}              ${_div}              \x3Cdiv class="tg-df-card-body">                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short">${_div}                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text title">${_div}                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text title">${_div}                \x3Cdiv class="tg-df-card-footer mt-auto">                  \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="height:24px;">${_div}                ${_div}              ${_div}              \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text" style="height:44px; margin:0; border-radius:0;">${_div}            ${_div}`;          this.grid.innerHTML = Array(4).fill(skeletonCardHtml).join('');        }        showError() {          const _div = '<' + '/div>';          this.grid.innerHTML = `\x3Cdiv class="tg-df-message">            An error occurred while finding deals. Please check your connection and try again.          ${_div}`;        }        escapeHTML(str) {          if (!str) return '';          return String(str).replace(/[&<>'"]/g, tag => ({              '&': '&', '<': '<', '>': '>', "'": ''', '"': '"'          }[tag] || tag));        }                bindCouponButtons() {          const btns = this.root.querySelectorAll('.tg-df-tag-coupons');          btns.forEach(btn => {            btn.addEventListener('click', (e) => {              e.preventDefault();              e.stopPropagation();              const merchant = btn.getAttribute('data-merchant');              this.openVouchersModal(merchant);            });          });                    const closeBtn = this.root.querySelector('#tg-df-vouchers-close');          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          if (closeBtn) {            closeBtn.onclick = () => this.closeVouchersModal();          }          if (backdrop) {            backdrop.onclick = (e) => {              if (e.target === backdrop) this.closeVouchersModal();            };          }        }                closeVouchersModal() {          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          if (backdrop) backdrop.classList.remove('active');        }                async checkMerchantsCouponsBulk(merchants) {          if (!merchants || merchants.length === 0) return {};          const controller = new AbortController();          const timeoutId = setTimeout(() => controller.abort(), 4000);          try {            const area = this.getAreaCode();            const url = new URL('https://search-api.fie.future.net.uk/widget.php');            url.searchParams.append('model_name', 'Everything');            url.searchParams.append('language', 'en-GB');            if (area) url.searchParams.append('area', area);            url.searchParams.append('combine_product_types', '1');            url.searchParams.append('filter_merchant_name', merchants.join(','));            url.searchParams.append('all_filters', 'false');            url.searchParams.append('exclude_unlabelled', 'false');            url.searchParams.append('include_specs', 'false');            url.searchParams.append('sort', 'voucher');            url.searchParams.append('distinct_merchants', 'natural');            url.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');            url.searchParams.append('rows', '120');            url.searchParams.append('origin', 'widgets-clientside');                        let res; try { res = await fetch(url.toString(), { signal: controller.signal }); } catch (e) { return {}; }            clearTimeout(timeoutId);            if (!res.ok) return {};            const data = await res.json();                        let offers = [];            if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {              offers = data.widget.data.offers;            } else if (data && data.data && Array.isArray(data.data.offers)) {              offers = data.data.offers;            } else if (Array.isArray(data)) {              offers = data;            } else if (data && Array.isArray(data.offers)) {              offers = data.offers;            } else if (data && data.offers && Array.isArray(data.offers.offer)) {              offers = data.offers.offer;            } else if (data && Array.isArray(data.data)) {              offers = data.data;            }                        const foundMerchants = new Set();            offers.forEach(o => {              let mName = o.merchant_name || o.merchant || o.retailer;              if (mName && typeof mName === 'object') mName = mName.name;              if (mName) foundMerchants.add(String(mName).toLowerCase());            });            const resultMap = {};            merchants.forEach(m => {              if (m) resultMap[m] = foundMerchants.has(String(m).toLowerCase());            });            return resultMap;          } catch (e) {            return {};          }        }                async openVouchersModal(merchantName) {          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          const title = this.root.querySelector('#tg-df-vouchers-title');          const content = this.root.querySelector('#tg-df-vouchers-content');                    if (!backdrop || !content) return;                    // HACK: Hide closing tags          const _div = '<' + '/div>';          const _span = '<' + '/span>';          const _a = '<' + '/a>';          const _h4 = '<' + '/h4>';          const _svg = '<' + '/svg>';          const _circle = '<' + '/circle>';          const _polyline = '<' + '/polyline>';          const _rect = '<' + '/rect>';          const _path = '<' + '/path>';                    title.innerText = `${merchantName} Coupons & Deals`;          content.innerHTML = `\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text">${_div}                               \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text">${_div}`;          backdrop.classList.add('active');                    try {            const area = this.getAreaCode();            const url = new URL('https://search-api.fie.future.net.uk/widget.php');            url.searchParams.append('model_name', 'Everything');            url.searchParams.append('language', 'en-GB');            if (area) url.searchParams.append('area', area);            url.searchParams.append('combine_product_types', '1');            url.searchParams.append('filter_merchant_name', merchantName);            url.searchParams.append('all_filters', 'false');            url.searchParams.append('exclude_unlabelled', 'false');            url.searchParams.append('include_specs', 'false');            url.searchParams.append('sort', 'voucher');            url.searchParams.append('distinct_merchants', 'natural');            url.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');            url.searchParams.append('rows', '50');            url.searchParams.append('origin', 'widgets-clientside');                        const res = await fetch(url.toString());            if (!res.ok) throw new Error('API Error');            const data = await res.json();                        let offers = [];            if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {              offers = data.widget.data.offers;            } else if (data && data.data && Array.isArray(data.data.offers)) {              offers = data.data.offers;            } else if (Array.isArray(data)) {              offers = data;            } else if (data && Array.isArray(data.offers)) {              offers = data.offers;            } else if (data && data.offers && Array.isArray(data.offers.offer)) {              offers = data.offers.offer;            } else if (data && Array.isArray(data.data)) {              offers = data.data;            }                        if (offers.length === 0) {              content.innerHTML = `\x3Cdiv class="tg-df-message">No vouchers currently available for ${this.escapeHTML(merchantName)}.${_div}`;              return;            }                        content.innerHTML = offers.map((v, idx) => {              let offerObj = v;              if (v.offers && v.offers.offer) {                offerObj = Array.isArray(v.offers.offer) ? v.offers.offer[0] : v.offers.offer;              } else if (v.offer) {                offerObj = Array.isArray(v.offer) ? v.offer[0] : v.offer;              }              let logoUrl = v.logo_url || offerObj.logo_url || '';              if (!logoUrl && v.merchant) {                if (Array.isArray(v.merchant) && v.merchant.length > 0) logoUrl = v.merchant[0].logo_url || '';                else logoUrl = v.merchant.logo_url || '';              }                            const offerName = offerObj.name || offerObj.title || v.name || v.title || 'Special Offer';              const endTime = offerObj.end_time || v.end_time || '';              const linkUrl = offerObj.link || offerObj.url || v.link || v.url || '#';                            let foundVoucherCode = '';              const findVoucherCode = (obj) => {                if (!obj || typeof obj !== 'object') return;                if (obj.type === 'voucher_code' && obj.display_value) {                  foundVoucherCode = obj.display_value;                  return;                }                if (Array.isArray(obj)) {                  for (const item of obj) {                    findVoucherCode(item);                    if (foundVoucherCode) return;                  }                } else {                  for (const k in obj) {                    if (Object.prototype.hasOwnProperty.call(obj, k)) {                      findVoucherCode(obj[k]);                      if (foundVoucherCode) return;                    }                  }                }              };              findVoucherCode(offerObj);              if (!foundVoucherCode) findVoucherCode(v);                            const voucherCode = foundVoucherCode || offerObj.voucher_code || v.voucher_code || '';              const codeHtml = voucherCode ? `\x3Cspan class="tg-df-voucher-code" data-action="copy-code" data-code="${this.escapeHTML(voucherCode)}" title="Copy to clipboard">                \x3Cspan class="tg-df-voucher-code-text">${this.escapeHTML(voucherCode)}${_span}                \x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-left:6px;flex-shrink:0;" class="tg-df-voucher-copy-icon">                  \x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2">${_rect}                  \x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1">${_path}                ${_svg}              ${_span}` : '';                            const logoHtml = logoUrl                 ? `\x3Cimg src="${this.escapeHTML(logoUrl)}" alt="${this.escapeHTML(offerName)}" class="tg-df-voucher-logo" />`                 : `\x3Cdiv class="tg-df-voucher-logo" style="background:#e2e8f0;">${_div}`;                            let expiryHtml = '';              if (endTime) {                let dStr = endTime;                if (!isNaN(dStr) && String(dStr).length === 10) dStr = Number(dStr) * 1000;                const d = new Date(dStr);                if (!isNaN(d.getTime())) {                  const options = { year: 'numeric', month: 'short', day: 'numeric' };                  expiryHtml = `                    \x3Cdiv class="tg-df-voucher-expiry">                      \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">                        \x3Ccircle cx="12" cy="12" r="10">${_circle}                        \x3Cpolyline points="12 6 12 12 16 14">${_polyline}                      ${_svg}                      Expires ${d.toLocaleDateString(undefined, options)}                    ${_div}`;                }              }              const revenueIdVal = generateRevenueId(linkUrl, offerName, merchantName, null);              const rewrittenLinkUrl = rewriteAffiliateLink(linkUrl, area, revenueIdVal);              return `                \x3Ca href="${this.escapeHTML(rewrittenLinkUrl)}" target="_blank" rel="noopener nofollow" class="tg-df-voucher-item"                  data-action="voucher-click"                  data-product-name="${this.escapeHTML(offerName)}"                  data-merchant-name="${this.escapeHTML(merchantName)}"                  data-analytics-id="${this.escapeHTML(offerObj.offer_id || offerObj.id || v.id || '')}"                  data-price=""                  data-previous-price=""                  data-original-link="${this.escapeHTML(linkUrl)}"                  data-revenue-id="${revenueIdVal}"                  data-index="${idx}"                  data-total="${offers.length}"                  data-in-stock="true"                  data-currency="USD"                  data-model-id="${this.escapeHTML(offerObj.model_id || v.model_id || offerObj.id || v.id || '')}"                  data-merchant-id="${this.escapeHTML(offerObj.merchant_id || offerObj.merchant?.id || '')}"                >                  ${logoHtml}                  \x3Cdiv class="tg-df-voucher-content">                    \x3Ch4 class="tg-df-voucher-title">${this.escapeHTML(offerName)}${_h4}                    ${codeHtml}                    ${expiryHtml}                  ${_div}                ${_a}              `;            }).join('');                        // Attach copy functionality            const copyBtns = content.querySelectorAll('[data-action="copy-code"]');            copyBtns.forEach(btn => {              btn.addEventListener('click', async (e) => {                e.preventDefault();                e.stopPropagation();                                const code = btn.getAttribute('data-code');                if (!code) return;                                try {                  const copyToClipboard = async (text) => {                     if (window.navigator.clipboard && window.isSecureContext) {                        try { await window.navigator.clipboard.writeText(text); return; } catch (e) {}                     }                     const textArea = document.createElement("textarea");                     textArea.value = text;                     textArea.style.position = "fixed";                     document.body.appendChild(textArea);                     textArea.focus();                     textArea.select();                     document.execCommand('copy');                     textArea.remove();                  };                  await copyToClipboard(code);                                    // Visual feedback                  btn.classList.add('copied');                  const textSpan = btn.querySelector('.tg-df-voucher-code-text');                  const iconSvg = btn.querySelector('.tg-df-voucher-copy-icon');                                    const origText = textSpan.innerText;                  const origIcon = iconSvg.innerHTML;                                    textSpan.innerText = 'Copied!';                  iconSvg.innerHTML = `\x3Cpolyline points="20 6 9 17 4 12">${_polyline}`;                                    setTimeout(() => {                    if (btn) {                      btn.classList.remove('copied');                      if (textSpan) textSpan.innerText = origText;                      if (iconSvg) iconSvg.innerHTML = origIcon;                    }                  }, 2000);                                    trackElementInteraction({                    id: 'voucher-code-copy',                    name: 'Copy Voucher Code',                    label: `Copied ${code} for ${merchantName}`                  });                } catch (err) {                  console.warn('Failed to copy text: ', err);                }              });            });            // Attach voucher click tracking            const voucherBtns = content.querySelectorAll('[data-action="voucher-click"]');            voucherBtns.forEach(btn => {              btn.addEventListener('click', (e) => {                if (e.target.closest('[data-action="copy-code"]')) return;                                const productName = btn.getAttribute('data-product-name');                const merchantNameAttr = btn.getAttribute('data-merchant-name');                const productId = btn.getAttribute('data-analytics-id');                const price = parseFloat(btn.getAttribute('data-price')) || null;                const prevPriceStr = btn.getAttribute('data-previous-price');                const previousPrice = prevPriceStr ? parseFloat(prevPriceStr) : null;                const originalLink = btn.getAttribute('data-original-link');                const rewrittenLink = btn.getAttribute('href');                const revenueId = btn.getAttribute('data-revenue-id');                const index = parseInt(btn.getAttribute('data-index'), 10) || 0;                const inStock = btn.getAttribute('data-in-stock') === 'true';                const totalText = btn.getAttribute('data-total');                const totalDeals = parseInt(totalText, 10) || 0;                const productCategoryName = 'deals';                const trackingParams = {                  widgetId: this.widgetId,                  productCategoryName: productCategoryName,                  product: {                    modelId: btn.getAttribute('data-model-id') || null,                    matchId: btn.getAttribute('data-match-id') || null,                    brand: btn.getAttribute('data-model-brand') || null,                    parent: btn.getAttribute('data-model-parent') || null,                    name: productName,                    price: price,                    previousPrice: previousPrice,                    link: rewrittenLink,                    originalLink: originalLink,                    inStock: inStock                  },                  zeroBasedProductIndexOrNull: index,                  totalDealsOrProducts: totalDeals,                   merchant: {                    id: btn.getAttribute('data-merchant-id') || null,                    network: btn.getAttribute('data-merchant-network') || null,                    url: btn.getAttribute('data-merchant-url') || null,                    name: merchantNameAttr                  },                  revenueId: revenueId,                  widgetTypeName: this.widgetTypeName,                  isoCurrencyCode: btn.getAttribute('data-currency') || 'USD'                };                if (typeof trackDealClick === 'function') {                  trackDealClick(trackingParams);                }              });            });                                  } catch (e) {            console.warn(e);            content.innerHTML = `\x3Cdiv class="tg-df-message">Failed to load vouchers.${_div}`;          }        }        render() {          try {            if (this.getViewMode() === 'savings_squad' && this.airedaleTags.length > 0) {              if (this.categoryFilterWrapper) {                 this.categoryFilterWrapper.style.display = 'flex';              }              if (this.categoryFilter) {                 const _option = '<' + '/option>';                 let optionsHtml = `\x3Coption value="all">All Categories${_option}`;                 this.airedaleTags.forEach(tag => {                    const isSelected = this.activeDealTag === tag ? 'selected' : '';                    optionsHtml += `\x3Coption value="${this.escapeHTML(tag)}" ${isSelected}>${this.escapeHTML(tag)}${_option}`;                 });                 this.categoryFilter.innerHTML = optionsHtml;                 this.categoryFilter.value = this.activeDealTag || 'all';              }            } else {               if (this.categoryFilterWrapper) {                  this.categoryFilterWrapper.style.display = 'none';               }            }            const displayDeals = this.getFilteredDeals();          // HACK: Hide closing tags from the CMS HTML sanitizer so it doesn't strip them during in-page injection          const _div = '<' + '/div>';          const _span = '<' + '/span>';          const _a = '<' + '/a>';          const _h3 = '<' + '/h3>';          const _p = '<' + '/p>';          const _strong = '<' + '/strong>';          const _sup = '<' + '/sup>';          const _button = '<' + '/button>';          if (displayDeals.length === 0) {            if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {              if (this.deals.length > 0) {                 this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                  No deals match your selected filters.                ${_div}`;              } else if (this.getViewMode() === 'savings_squad' && this.currentQuery.length <= 2) {                 // Do not show "no exact matches" if query is empty for savings_squad                 this.grid.innerHTML = '';              } else {                 this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                  No exact matches found for "\x3Cstrong>${this.escapeHTML(this.currentQuery)}${_strong}". Try adjusting your search term.                ${_div}`;              }            } else {              this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                Search product or category names to discover the best deals from across the web.              ${_div}`;            }            return;          }          let dealsHtml = displayDeals.slice(0, this.displayLimit).map((deal, index) => {            try {               const currencySym = this.escapeHTML(deal.currency);               const isoCurrencyCode = normalizeCurrency(currencySym);               const escapedPrice = this.escapeHTML(deal.price);               const escapedMsrp = this.escapeHTML(deal.msrp);               const areaCode = this.getAreaCode();                              const revenueId = generateRevenueId(deal.url, deal.title, deal.merchant, null);               const originalLink = deal.url;               const rewrittenLink = rewriteAffiliateLink(deal.url, areaCode, revenueId);                        const productCategoryName = 'deals';            const dataAttr = `              data-action="${deal.isCheckPrice ? 'view-similar-click' : 'deal-click'}"              data-analytics-id="${this.escapeHTML(deal.externalProductId || deal.id || '')}"              data-product-name="${this.escapeHTML(deal.title)}"              data-merchant-name="${this.escapeHTML(deal.merchant)}"              data-price="${deal.rawPrice || ''}"              data-previous-price="${deal.rawMsrp || ''}"              data-original-link="${this.escapeHTML(originalLink)}"              data-revenue-id="${revenueId}"              data-index="${index}"              data-total="${displayDeals.length}"              data-in-stock="${deal.inStock !== false}"              data-currency="${this.escapeHTML(isoCurrencyCode)}"              data-model-id="${this.escapeHTML(deal.modelId || '')}"              data-product-key="${this.escapeHTML(deal.productKey || '')}"              data-merchant-id="${this.escapeHTML(deal.merchantId || '')}"            `;                        let priceGroupHtml = '';            let isSavingsSquadMode = this.getViewMode() === 'savings_squad';            let ctaText = 'View Deal';            let formattedPrice = '';            let msrpHtml = '';                        if (deal.isCheckPrice) {              ctaText = 'View Deal';              if (isSavingsSquadMode) {                priceGroupHtml = ``;              } else {                priceGroupHtml = `                  \x3Cdiv class="tg-df-card-price-group">                    \x3Cspan class="tg-df-card-price" style="font-size: 15px; font-weight: 500; font-style: italic;">See price at retailer${_span}                  ${_div}                `;              }            } else {              // Format Price              formattedPrice = escapedPrice.includes(currencySym)                 ? escapedPrice                 : `${currencySym}${escapedPrice}`;                              // Format MSRP              msrpHtml = deal.msrp && deal.rawMsrp > deal.rawPrice                ? `\x3Cspan class="tg-df-card-msrp">${escapedMsrp.includes(currencySym) ? escapedMsrp : currencySym + escapedMsrp}${_span}`                : '';                              priceGroupHtml = isSavingsSquadMode ? `` : `                \x3Cdiv class="tg-df-card-price-group">                  \x3Cspan class="tg-df-card-price">${formattedPrice}${_span}                  ${msrpHtml}                ${_div}              `;            }                        const discountBadgeHtml = deal.savingLabel && !deal.isCheckPrice              ? `\x3Cspan class="tg-df-card-discount-badge">${this.escapeHTML(deal.savingLabel)}${_span}`              : '';                          // HACK for CMS            const _button = '<' + '/button>';            const _svg = '<' + '/svg>';            const _path = '<' + '/path>';            const _rect = '<' + '/rect>';            const _circle = '<' + '/circle>';            const _polyline = '<' + '/polyline>';            const _line = '<' + '/line>';                        let badgesHtml = '';            const primeBadge = deal.isPrime ? `              \x3Cspan class="tg-df-tag tg-df-tag-prime">                \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="currentColor">                  \x3Cpath d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z">${_path}                ${_svg} Prime              ${_span}            ` : '';                        const couponsBadge = deal.merchant && deal.merchant.toLowerCase().includes('amazon') ? '' : `              \x3Cdiv class="tg-df-coupon-wrapper" data-merchant="${this.escapeHTML(deal.merchant)}" style="display:inline-flex; align-items:center;">                \x3Cdiv class="tg-df-coupon-spinner">${_div}                \x3Cbutton type="button" class="tg-df-tag tg-df-tag-coupons" data-action="coupons-click" data-merchant="${this.escapeHTML(deal.merchant)}" style="display:none;">                  \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">                    \x3Cpath d="M20.59 13.41l-7.17 7.17a2 2 0 0 1-2.83 0L2 12V2h10l8.59 8.59a2 2 0 0 1 0 2.82z">${_path}                    \x3Cline x1="7" y1="7" x2="7.01" y2="7">${_line}                  ${_svg} Coupons                ${_button}              ${_div}            `;                        // Note: We always add coupons badge if there's a chance, but to allow 3-line titles we check wrapper display state            badgesHtml = `              \x3Cdiv class="tg-df-card-badges">                ${primeBadge}                ${couponsBadge}              ${_div}            `;            const _linearGradient = '<' + '/linearGradient>';            const _polygon = '<' + '/polygon>';            const _stop = '<' + '/stop>';            const _defs = '<' + '/defs>';                        let starHtml = '';            if (deal.starRating) {              let rating = deal.starRating;                            if (rating > 0) {                const fullStars = Math.floor(rating);                const halfStar = (rating - fullStars) >= 0.5 ? 1 : 0;                const emptyStars = Math.max(0, 5 - fullStars - halfStar);                const blue = '#1f69ff'; // Tom's guide brand color from VIEW DEAL button                const gray = '#cbd5e1';                                const starSvgFull = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="${blue}" stroke="${blue}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26">${_polygon}${_svg}`;                                const gradId = 'half_grad_' + Math.floor(Math.random()*1000000);                const starSvgHalf = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" stroke="${blue}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cdefs>\x3ClinearGradient id="${gradId}" x1="0" x2="1" y1="0" y2="0">\x3Cstop offset="50%" stop-color="${blue}">${_stop}\x3Cstop offset="50%" stop-color="transparent">${_stop}${_linearGradient}${_defs}                  \x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26" fill="url(#${gradId})">${_polygon}${_svg}`;                                  const starSvgEmpty = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="${gray}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26">${_polygon}${_svg}`;                                let stars = [];                for (let i=0; i<fullStars; i++) stars.push(starSvgFull);                if (halfStar) stars.push(starSvgHalf);                for (let i=0; i<emptyStars; i++) stars.push(starSvgEmpty);                                starHtml = `\x3Cdiv class="tg-df-card-stars" style="display:flex;align-items:center;margin-bottom:8px;font-size:13px;font-weight:600;color:var(--tg-df-text-muted);">                  \x3Cspan style="margin-right:6px;">Tom's Guide:${_span}                  \x3Cdiv style="display:flex;gap:2px;">                    ${stars.join('')}                  ${_div}                ${_div}`;              }            }            let htmlOutput = '';            if (isSavingsSquadMode) {              htmlOutput += `              \x3Cdiv class="hawk-deal-widget-container tg-df-mobile-only" data-collapsible="true">                ${this.editorMode ? `\x3Cinput type="checkbox" class="tg-df-deal-checkbox" data-id="${this.escapeHTML(deal.id)}" ${this.selectedDeals.has(deal.id) ? 'checked' : ''} style="margin-bottom: 10px;">` : ''}                \x3Cdiv class="hawk-deal-widget-wrap">                  \x3Cdiv class="hawk-deal-widget-image-container">                    \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" rel="sponsored noopener" target="_blank" class="hawk-affiliate-link-deal-widget" ${dataAttr}>                      \x3Cimg ${deal.image ? `src="${this.escapeHTML(deal.image)}"` : ''} alt="${this.escapeHTML(deal.title)}" class="hawk-lazy-image-deal-widget" loading="lazy" width="140" height="160" onerror="${deal.fallbackImage ? `if(!this.dataset.fb) { this.dataset.fb='1'; this.src='${this.escapeHTML(deal.fallbackImage)}'; } else { this.style.opacity='0'; }` : `this.style.opacity='0';`}">                    ${_a}                  ${_div}                  \x3Cdiv class="hawk-deal-widget-text-cta-container">                    \x3Cdiv class="hawk-deal-widget-text-body-container">                      \x3Cdiv class="hawk-deal-widget-text-body-main">                        \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                          ${deal.isCheckPrice ? `                            \x3Cspan class="hawk-deal-widget-title-product-title">${this.escapeHTML(deal.title)}${_span}                          ` : `                            \x3Cspan class="hawk-deal-widget-title-product-title">${deal.brand ? this.escapeHTML(deal.brand) + ' ' : ''}${this.escapeHTML(deal.productName || deal.title || '')}:${_span}                          `}                        ${_a}                        ${!deal.isCheckPrice && deal.rawMsrp && deal.rawMsrp > deal.rawPrice ? `                          \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                            \x3Cspan class="hawk-deal-widget-title-was-price">was ${currencySym}${escapedMsrp}${_span}                          ${_a}                        ` : ''}                        \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                          \x3Cspan class="hawk-deal-widget-title-retailer-price">                            ${!deal.isCheckPrice ? `                              \x3Cspan class="hawk-deal-widget-title-price">now ${formattedPrice}${_span}                              \x3Cspan class="hawk-deal-widget-title-retailer"> at ${this.escapeHTML(deal.merchant)}${_span}                            ` : `                              \x3Cspan class="hawk-deal-widget-title-price">See price at ${this.escapeHTML(deal.merchant)}${_span}                            `}                          ${_span}                        ${_a}                        ${deal.description ? `\x3Cdiv class="hawk-deal-widget-text-body-description tg-df-card-desc-container" style="margin-bottom: 12px; position: relative;">                          \x3Cp class="tg-df-card-desc-content" style="font-size: 13px; color: var(--tg-df-text-muted); margin-bottom: 0; line-height: 1.4; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;">${this.escapeHTML(deal.description)}${_p}                          \x3Cbutton type="button" class="tg-df-card-desc-btn" style="display: none; appearance: none; border: none; color: #000000; font-size: 11px; font-weight: 700; text-transform: uppercase; cursor: pointer; font-family: inherit; position: absolute; bottom: 2px; right: 0; background: linear-gradient(to right, transparent, #fff 20%, #fff); padding: 0 0 0 16px;" onclick="                            var c = this.parentNode;                            if (this.dataset.expanded === 'true') {                              var pd = (c.tagName === 'P') ? c : this.previousElementSibling;                              if (c.tagName === 'P') { c.parentNode.appendChild(this); pd = c; }                              pd.style.display = '-webkit-box';                              pd.style.webkitLineClamp = '3';                              this.textContent = 'READ MORE';                              this.style.position = 'absolute';                              this.style.background = 'linear-gradient(to right, transparent, #fff 20%, #fff)';                              this.style.paddingLeft = '16px';                              this.dataset.expanded = 'false';                            } else {                              var pd = this.previousElementSibling;                              pd.style.display = 'inline';                              pd.style.webkitLineClamp = 'unset';                              this.textContent = 'READ LESS';                              this.style.position = 'static';                              this.style.background = 'transparent';                              this.style.paddingLeft = '4px';                              this.dataset.expanded = 'true';                              pd.appendChild(this);                            }                          ">READ MORE${_button}                        \x3C/div>` : ''}                      ${_div}                    ${_div}                    ${deal.authorName ? `                      \x3Cdiv class="tg-df-author-line-mobile" style="padding: 0 0 12px 0; background: transparent;">                         \x3Cdiv style="display: flex; align-items: center; gap: 12px;">                            ${deal.authorImage ? `\x3Cimg src="${this.escapeHTML(deal.authorImage)}" alt="${this.escapeHTML(deal.authorName)}" class="tg-df-author-img" width="40" height="40" style="border-radius: 50%; object-fit: cover; flex-shrink: 0; aspect-ratio: 1 / 1; min-width: 40px; min-height: 40px;">` : ''}                            \x3Cdiv style="display: flex; flex-direction: column;">                               \x3Cdiv style="font-size: 10px; color: var(--tg-df-text-muted); text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 2px; font-weight: 600;">\x3Cspan style="color: #FF6600;">${this.escapeHTML(deal.merchant)}${_span} deal recommended by:${_div}                               \x3Cdiv style="font-size: 11px; color: var(--tg-df-text); line-height: 1.3;">                                  \x3Cstrong>\x3Ca href="https://www.tomsguide.com/${this.escapeHTML(deal.documentUrl || '').replace(/^\/+/, '')}" target="_blank" rel="noopener nofollow" style="text-decoration: none; color: inherit; border-bottom: 1px dotted var(--tg-df-text-muted);">${this.escapeHTML(deal.authorName)}${_a}${_strong}                                  ${deal.authorRole && !['null', 'nul', 'undefined'].includes(String(deal.authorRole).toLowerCase()) ? ` • ${this.escapeHTML(deal.authorRole)}` : ''}                                  ${deal.modifiedDate ? `\x3Cdiv style="color: var(--tg-df-text-muted); margin-top: 2px;">${getTimeAgo(deal.modifiedDate)}${_div}` : ''}                               ${_div}                            ${_div}                         ${_div}                      ${_div}                    ` : ''}                    \x3Cdiv class="hawk-deal-widget-footer">                      \x3Cdiv class="hawk-deal-widget-button-wrapper">                        \x3Cdiv class="hawk-deal-widget-preferred-partner-wrapper">                          \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-deal-button" rel="sponsored noopener" target="_blank" ${dataAttr}>                            \x3Cspan>View Deal${_span}                          ${_a}                        ${_div}                      ${_div}                    ${_div}                  ${_div}                ${_div}              ${_div}              `;            }            htmlOutput += `              \x3Cdiv class="tg-df-card ${isSavingsSquadMode ? 'tg-df-desktop-only' : ''}">                ${this.editorMode ? `\x3Cinput type="checkbox" class="tg-df-deal-checkbox" data-id="${this.escapeHTML(deal.id)}" ${this.selectedDeals.has(deal.id) ? 'checked' : ''}>` : ''}                \x3Cdiv class="tg-df-card-image-box">                  ${discountBadgeHtml}                  \x3Ca href="${this.escapeHTML(rewrittenLink)}" ${dataAttr} target="_blank" rel="noopener nofollow" style="display: flex; align-items: center; justify-content: center; width: 100%; height: 100%;">                    \x3Cimg ${deal.image ? `src="${this.escapeHTML(deal.image)}"` : ''} alt="${this.escapeHTML(deal.title)}" class="tg-df-card-image" loading="lazy" onerror="${deal.fallbackImage ? `if(!this.dataset.fb) { this.dataset.fb='1'; this.src='${this.escapeHTML(deal.fallbackImage)}'; } else { this.style.opacity='0'; }` : `this.style.opacity='0';`}">                  ${_a}                  \x3Cdiv class="tg-df-card-merchant-wrapper" style="position: absolute; bottom: 0; right: 0; background: transparent; padding: 8px 12px; z-index: 10;">                     \x3Cspan class="tg-df-card-merchant-pill" style="text-align: right; margin-bottom: 0;" title="${this.escapeHTML(deal.merchant)}">${this.escapeHTML(deal.merchant)}${_span}                  ${_div}                ${_div}                \x3Cdiv class="tg-df-card-body">                  ${starHtml}                  ${badgesHtml}                  \x3Ch3 class="tg-df-card-title tg-df-custom-savings-squad-title" title="${this.escapeHTML(deal.title)}">                    \x3Ca href="${this.escapeHTML(rewrittenLink)}" disable-tracking="true" target="_blank" rel="noopener nofollow" style="text-decoration: none; color: inherit;">                      ${isSavingsSquadMode                         ? (deal.isCheckPrice                             ? (deal.title && deal.title.includes(':')                                 ? `\x3Cstrong>${this.escapeHTML(deal.title.substring(0, deal.title.indexOf(':') + 1))}${_strong}\x3Cspan style="color: #1f69ff; font-weight: normal;">${this.escapeHTML(deal.title.substring(deal.title.indexOf(':') + 1))}${_span}`                                : this.escapeHTML(deal.title)                              )                             : `\x3Cstrong>${deal.brand ? this.escapeHTML(deal.brand) + ' ' : ''}${this.escapeHTML(deal.productName || deal.title || '')}:${_strong} ${deal.rawMsrp && deal.rawMsrp > deal.rawPrice ? `\x3Cspan style="color: #d0021b; text-decoration: line-through; font-weight: normal; margin-right: 4px;">was ${currencySym}${escapedMsrp}${_span} ` : ''}\x3Cspan style="color: #1f69ff; font-weight: normal;">now ${formattedPrice} at ${this.escapeHTML(deal.merchant)}${_span}`                          )                        : this.escapeHTML(deal.title)                      }                    ${_a}                  ${_h3}                  ${deal.description ? `\x3Cdiv class="tg-df-card-desc-container" style="margin-bottom: 12px; position: relative;">                    \x3Cp class="tg-df-card-desc-content" style="font-size: 13px; color: var(--tg-df-text-muted); margin-bottom: 0; line-height: 1.4; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;">${this.escapeHTML(deal.description)}${_p}                    \x3Cbutton type="button" class="tg-df-card-desc-btn" style="display: none; appearance: none; border: none; color: #000000; font-size: 11px; font-weight: 700; text-transform: uppercase; cursor: pointer; font-family: inherit; position: absolute; bottom: 2px; right: 0; background: linear-gradient(to right, transparent, #fff 20%, #fff); padding: 0 0 0 16px;" onclick="                      var c = this.parentNode;                      if (this.dataset.expanded === 'true') {                        var pd = (c.tagName === 'P') ? c : this.previousElementSibling;                        if (c.tagName === 'P') { c.parentNode.appendChild(this); pd = c; }                        pd.style.display = '-webkit-box';                        pd.style.webkitLineClamp = '3';                        this.textContent = 'READ MORE';                        this.style.position = 'absolute';                        this.style.background = 'linear-gradient(to right, transparent, #fff 20%, #fff)';                        this.style.paddingLeft = '16px';                        this.dataset.expanded = 'false';                      } else {                        var pd = this.previousElementSibling;                        pd.style.display = 'inline';                        pd.style.webkitLineClamp = 'unset';                        this.textContent = 'READ LESS';                        this.style.position = 'static';                        this.style.background = 'transparent';                        this.style.paddingLeft = '4px';                        this.dataset.expanded = 'true';                        pd.appendChild(this);                      }                    ">READ MORE${_button}                  \x3C/div>` : ''}                  \x3Cdiv class="tg-df-card-footer">                    ${deal.authorName ? `                    \x3Cdiv class="tg-df-author-line-desktop" style="padding: 0 0 ${isSavingsSquadMode ? 0 : 12}px 0;">                       \x3Cdiv style="display: flex; align-items: center; gap: 10px;">                          ${deal.authorImage ? `\x3Cimg src="${this.escapeHTML(deal.authorImage)}" alt="${this.escapeHTML(deal.authorName)}" class="tg-df-author-img" width="36" height="36" style="border-radius: 50%; object-fit: cover; flex-shrink: 0; aspect-ratio: 1 / 1; min-width: 36px; min-height: 36px;">` : ''}                          \x3Cdiv style="display: flex; flex-direction: column;">                             \x3Cdiv style="font-size: 10px; color: var(--tg-df-text-muted); text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 2px; font-weight: 600;">Recommended by:${_div}                             \x3Cdiv style="font-size: 11px; color: var(--tg-df-text); line-height: 1.2;">                                \x3Cstrong>\x3Ca href="https://www.tomsguide.com/${this.escapeHTML(deal.documentUrl || '').replace(/^\/+/, '')}" target="_blank" rel="noopener nofollow" style="text-decoration: none; color: inherit; border-bottom: 1px dotted var(--tg-df-text-muted);">${this.escapeHTML(deal.authorName)}${_a}${_strong}                                ${deal.authorRole && !['null', 'nul', 'undefined'].includes(String(deal.authorRole).toLowerCase()) ? ` • ${this.escapeHTML(deal.authorRole)}` : ''}                                ${deal.modifiedDate ? `\x3Cspan style="color: var(--tg-df-text-muted);"> • ${getTimeAgo(deal.modifiedDate)}${_span}` : ''}                             ${_div}                          ${_div}                       ${_div}                    ${_div}                    ` : ''}                    ${priceGroupHtml}                  ${_div}                ${_div}                \x3Ca href="${this.escapeHTML(rewrittenLink)}" ${dataAttr} target="_blank" rel="noopener nofollow" class="tg-df-card-cta" style="text-decoration: none; border-radius: 0;">${ctaText}${_a}              ${_div}            `;                        return htmlOutput;            } catch (e) {               console.log("Error rendering deal in map for index", index, typeof deal === 'object' ? JSON.stringify(deal) : deal, "MSG:", e.message);               return '';            }          }).join('');                    if (displayDeals.length > this.displayLimit) {            dealsHtml += `              \x3Cdiv style="width: 100%; display: flex; justify-content: center; margin-top: 16px; grid-column: 1 / -1;">                \x3Cbutton type="button" class="tg-df-tag-outline tg-df-load-more" style="padding: 8px 24px; border-radius: 100px; font-weight: 600; font-size: 14px; cursor: pointer;">Load More${_button}              ${_div}            `;          }                    this.grid.innerHTML = dealsHtml;          // Inject JSON-LD          try {            let targetNode = this.hostContainer || document.head;            let jsonLdScript = targetNode.querySelector('#tg-df-json-ld-' + this.widgetId);            if (!jsonLdScript) {                jsonLdScript = document.createElement('script');                jsonLdScript.type = 'application/ld+json';                jsonLdScript.id = 'tg-df-json-ld-' + this.widgetId;                targetNode.appendChild(jsonLdScript);            }            const jsonLdData = {              "@context": "https://schema.org",              "@type": "ItemList",              "itemListElement": displayDeals.slice(0, this.displayLimit).map((deal, index) => {                 let isoCurrency = "USD";                 if (deal.currency === '£') isoCurrency = "GBP";                 else if (deal.currency === '€') isoCurrency = "EUR";                 else if (deal.currency === 'A$') isoCurrency = "AUD";                 else if (deal.currency === 'CA$') isoCurrency = "CAD";                 const areaCode = typeof this.getAreaCode === 'function' ? this.getAreaCode() : 'US';                 const revenueId = typeof generateRevenueId === 'function' ? generateRevenueId(deal.url, deal.title, deal.merchant, null) : '';                 const rewrittenLink = typeof rewriteAffiliateLink === 'function' ? rewriteAffiliateLink(deal.url, areaCode, revenueId) : deal.url;                 return {                   "@type": "ListItem",                   "position": index + 1,                   "item": {                     "@type": "Product",                     "name": deal.title,                     "image": deal.image || "",                     "description": deal.description || "",                     "brand": {                       "@type": "Brand",                       "name": deal.brand || ""                     },                     "offers": {                       "@type": "Offer",                       "priceCurrency": isoCurrency,                       "price": deal.rawPrice || 0,                       "url": rewrittenLink,                       "seller": {                         "@type": "Organization",                         "name": deal.merchant || ""                       }                     }                   }                 };              }).filter(item => item.item.name)            };            jsonLdScript.textContent = JSON.stringify(jsonLdData);          } catch(e) { console.warn("JSON-LD generation failed", e); }          setTimeout(() => {            const contents = this.root.querySelectorAll('.tg-df-card-desc-content');            contents.forEach(p => {              if (p.scrollHeight > p.clientHeight || p.scrollHeight > 60) {                if (p.nextElementSibling) {                  p.nextElementSibling.style.display = 'block';                }              }            });                        // Allow hawklinks.js to discover and rewrite our widget links             // by appending the .article-body class and manually triggering processArticle.            let container = this.root.classList.contains('tg-df-container') ? this.root : this.root.querySelector('.tg-df-container');            if (container && !container.classList.contains('article-body')) {               container.classList.add('article-body');            }            if (this.grid && !this.grid.classList.contains('article-body')) this.grid.classList.add('article-body');            document.dispatchEvent(new CustomEvent('processArticle', { detail: { element: this.root } }));          }, 50);          const loadMoreBtn = this.grid.querySelector('.tg-df-load-more');          if (loadMoreBtn) {            loadMoreBtn.addEventListener('click', () => {              if (typeof trackElementInteraction === 'function') {                trackElementInteraction({ id: 'load-more', name: 'Load more', label: 'Load More Results' });              }              this.displayLimit += this.getRowsLimit();              this.render();            });          }                      this.bindCouponButtons();            this.checkAndUpdateCoupons();          } catch(e) {            console.warn("Widget render error", e);          }        }                async checkAndUpdateCoupons() {          const wrappers = Array.from(this.root.querySelectorAll('.tg-df-coupon-wrapper'));          if (wrappers.length === 0) return;                    const merchants = [...new Set(wrappers.map(w => w.getAttribute('data-merchant')).filter(Boolean))];          if (merchants.length === 0) return;          const couponResultsMap = await this.checkMerchantsCouponsBulk(merchants);                    for (const merchant of merchants) {            const hasCoupons = !!couponResultsMap[merchant];            const merchantWrappers = wrappers.filter(w => w.getAttribute('data-merchant') === merchant);            merchantWrappers.forEach(wrapper => {              const spinner = wrapper.querySelector('.tg-df-coupon-spinner');              const btn = wrapper.querySelector('.tg-df-tag-coupons');                            if (spinner) spinner.style.display = 'none';                            if (hasCoupons && btn) {                btn.style.display = 'inline-flex';              } else if (!hasCoupons) {                wrapper.style.display = 'none';              }            });          }        }        updateFloatingCopyBar() {          if (!this.editorBar || !this.editorSelectedCount) return;          if (this.editorMode && this.selectedDeals.size > 0) {            this.editorBar.style.display = 'flex';            this.editorSelectedCount.innerText = this.selectedDeals.size;          } else {            this.editorBar.style.display = 'none';          }        }        async copySelectedDealsToCMS() {           function htmlToSlate(htmlString) {              if (!htmlString) return [{ type: 'paragraph', children: [{ text: '' }] }];              let doc;              if (typeof window !== 'undefined' && window.DOMParser) {                 doc = new DOMParser().parseFromString(htmlString, 'text/html');              } else {                 doc = document.implementation.createHTMLDocument('');                 doc.body.innerHTML = htmlString;              }                            function parseNode(node, marks = {}) {                  if (node.nodeType === 3) {                      const text = node.textContent;                      if (!text) return null;                      return { text: text, ...marks };                  }                  if (node.nodeType === 1) {                      const tagName = node.tagName.toLowerCase();                      if (tagName === 'br') {                          return { type: 'line-break', children: [{ text: '' }] };                      }                      if (tagName === 'p') {                          let children = Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                          if (children.length === 0) children.push({ text: "" });                          return { type: 'paragraph', children };                      }                      if (tagName === 'strong' || tagName === 'b') {                          const newMarks = { ...marks, bold: true };                          return Array.from(node.childNodes).map(child => parseNode(child, newMarks)).flat().filter(Boolean);                      }                      if (tagName === 'em' || tagName === 'i') {                          const newMarks = { ...marks, italic: true };                          return Array.from(node.childNodes).map(child => parseNode(child, newMarks)).flat().filter(Boolean);                      }                      if (tagName === 'a') {                          const href = node.getAttribute('href') || '';                          let children = Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                          if (children.length === 0) children.push({ text: "" });                          return {                              type: 'link',                              url: href,                              isNoFollow: (node.getAttribute('rel') || '').includes('nofollow'),                              isSponsored: (node.getAttribute('rel') || '').includes('sponsored'),                              isOpenNewTab: node.getAttribute('target') === '_blank',                              isPreventDataRewrite: false,                              children: children                          };                      }                      return Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                  }                  return null;              }                            let blocksArray = [];              let currentParagraphChildren = [];              function flushParagraph() {                  if (currentParagraphChildren.length > 0) {                      blocksArray.push({ type: 'paragraph', children: currentParagraphChildren });                      currentParagraphChildren = [];                  }              }              Array.from(doc.body.childNodes).forEach(node => {                  const parsed = parseNode(node, {});                  const parsedItems = Array.isArray(parsed) ? parsed : (parsed ? [parsed] : []);                  parsedItems.forEach(item => {                      if (item.type === 'paragraph') {                          flushParagraph();                          blocksArray.push(item);                      } else {                          currentParagraphChildren.push(item);                      }                  });              });              flushParagraph();              if (blocksArray.length === 0) {                  blocksArray = [{ type: 'paragraph', children: [{ text: '' }] }];              }              return blocksArray;           }           const blocks = [];                      this.editorCopyBtn.innerHTML = '\x3Cspan class="tg-df-coupon-spinner" style="display:inline-block; margin-right:8px; border-top-color:#fff;">' + '<' + '/span> Copying...';           for (const deal of Array.from(this.selectedDeals.values())) {              const url = deal.url;              const merchant = deal.merchant;              const title = deal.title;              const image = deal.image;              const currentPrice = deal.currency + deal.rawPrice;              const wasPrice = deal.hasWasPrice && deal.rawMsrp > deal.rawPrice ? deal.currency + deal.rawMsrp : '';                            let couponsChildren = [];              try {                  const area = this.getAreaCode();                  const apiUrl = new URL('https://search-api.fie.future.net.uk/widget.php');                  apiUrl.searchParams.append('model_name', 'Everything');                  apiUrl.searchParams.append('language', 'en-GB');                  apiUrl.searchParams.append('area', area);                  apiUrl.searchParams.append('combine_product_types', '1');                  apiUrl.searchParams.append('filter_merchant_name', merchant);                  apiUrl.searchParams.append('all_filters', 'false');                  apiUrl.searchParams.append('exclude_unlabelled', 'false');                  apiUrl.searchParams.append('include_specs', 'false');                  apiUrl.searchParams.append('sort', 'voucher');                  apiUrl.searchParams.append('distinct_merchants', 'natural');                  apiUrl.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');                  apiUrl.searchParams.append('rows', '3');                  apiUrl.searchParams.append('origin', 'widgets-clientside');                                    let res; try { res = await fetch(apiUrl.toString()); } catch (e) { return; }                  if (res.ok) {                      const data = await res.json();                      let offers = [];                      if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {                        offers = data.widget.data.offers;                      } else if (data && data.data && Array.isArray(data.data.offers)) {                        offers = data.data.offers;                      }                                            if (offers.length > 0) {                          couponsChildren.push({ text: "Also check out these coupons: ", bold: true });                          offers.slice(0, 3).forEach((offer, idx) => {                              const actualOffer = offer.offer || offer;                              const offerName = actualOffer.name || actualOffer.title || offer.model_name || offer.title || offer.name || 'Coupon';                              const linkUrl = actualOffer.link || actualOffer.url || actualOffer.offer_link || '#';                              couponsChildren.push({ type: "line-break", children: [{ text: "" }] });                              couponsChildren.push({ text: "🎟️ " });                              couponsChildren.push({                                  type: "link",                                  url: linkUrl,                                  isNoFollow: true,                                  isSponsored: false,                                  isOpenNewTab: true,                                  isPreventDataRewrite: false,                                  children: [{ text: offerName, bold: true }]                              });                          });                      }                  }              } catch (err) {                  console.warn('Failed to fetch coupons for', merchant, err);              }              let descriptionValue = [];              if (deal.text) {                 descriptionValue = htmlToSlate(deal.text);              } else {                 const dealDescriptions = [                   `Don't miss out on this fantastic deal for the ${title}. It is currently available at ${merchant} for a highly competitive price.`,                   `We've spotted an excellent price drop on the ${title}. Grab it now at ${merchant} before it's gone.`,                   `The ${title} is currently seeing a generous discount over at ${merchant}. This is a perfect time to buy if you've been holding out.`,                   `If you're in the market for the ${title}, ${merchant} has just the deal for you.`,                   `Score the ${title} for less at ${merchant} right now. This is a rare chance to save big.`,                   `Upgrade your setup with the ${title}, now available at a stellar price via ${merchant}.`                 ];                 const randomDescription = dealDescriptions[Math.floor(Math.random() * dealDescriptions.length)];                 descriptionValue = [                    { type: "paragraph", children: [{ text: randomDescription }] }                 ];              }                            if (couponsChildren.length > 0) {                 let lastBlock = descriptionValue[descriptionValue.length - 1];                 if (lastBlock && lastBlock.type === 'paragraph') {                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children.push({ text: "Also check out these coupons: ", bold: true });                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children = lastBlock.children.concat(couponsChildren);                 } else {                     descriptionValue.push({                         type: "paragraph",                         children: [                             { type: "line-break", children: [{ text: "" }] },                             { type: "line-break", children: [{ text: "" }] },                             { text: "Also check out these coupons: ", bold: true },                             { type: "line-break", children: [{ text: "" }] },                             ...couponsChildren                         ]                     });                 }              }              function normalizeCurrencyToISO(symbol) {                const map = { '£': 'GBP', '$': 'USD', 'A$': 'AUD', 'CA$': 'CAD', '€': 'EUR' };                return map[symbol] || symbol;              }              const isoCurrency = normalizeCurrencyToISO(deal.currency);              blocks.push({                 id: (window.crypto && window.crypto.randomUUID) ? window.crypto.randomUUID() : 'cms-' + Date.now() + Math.random(),                 blockTypeName: "deal",                 excludeFrom: [],                 collapsible: false,                 props: {                    description: {                       value: descriptionValue,                       touched: false,                       validationMessage: ""                    },                    image: {                       value: {                          credit: [{ type: "paragraph", children: [{ text: merchant }] }],                          dateCreated: Date.now(),                          dateModified: Date.now(),                          distribution: [],                          fileSize: 0,                          height: 1000,                          id: deal.id,                          imageRights: "",                          src: image,                          name: title + ".jpg",                          tags: [],                          width: 1000                       },                       touched: false,                       validationMessage: ""                    },                    showDealButton: { value: true, touched: false, validationMessage: "" },                    isPreferredPartner: { value: false, touched: false, validationMessage: "" },                    linkHref: { value: url, touched: false, validationMessage: "" },                    linkLabel: { value: "", touched: false, validationMessage: "" },                    linkIsNoFollow: { value: true, touched: false, validationMessage: "" },                    linkIsSponsored: { value: false, touched: false, validationMessage: "" },                    linkIsOpenNewWindow: { value: true, touched: false, validationMessage: "" },                    customPromoFlags: { value: [], touched: false, validationMessage: "" },                    showStarDeal: { value: false, touched: false, validationMessage: "" },                    savingType: { value: "none", touched: false, validationMessage: "" },                    starDealPromoFlag: { value: "", touched: false, validationMessage: "" },                    showEditorsChoice: { value: false, touched: false, validationMessage: "" },                    editorsChoiceTitle: { value: "", touched: false, validationMessage: "" },                    hawkPriceCurrency: { value: { value: isoCurrency, label: isoCurrency }, touched: false, validationMessage: "" },                    hawkPrice: { value: deal.hasWasPrice ? String(deal.rawMsrp) : String(deal.rawPrice), touched: false, validationMessage: "" },                    hawkSalePrice: { value: String(deal.rawPrice), touched: false, validationMessage: "" },                    lastCheckedPriceDate: { value: "", touched: false, validationMessage: "" },                    hawkModel: { touched: false, validationMessage: "" },                    productId: { value: "", touched: false, validationMessage: "" },                    voucherId: { value: "", touched: false, validationMessage: "" },                    brand: { value: deal.brand || merchant, touched: false, validationMessage: "" },                    productName: { value: title, touched: false, validationMessage: "" },                    label: { value: "", touched: false, validationMessage: "" },                    retailer: { value: merchant, touched: false, validationMessage: "" },                    priceCheckError: false                 },                 failedFetchError: ""              });           }           const payload = {              type: "articleBuilderPages",              data: blocks           };           const jsonStr = JSON.stringify(payload);                      if (navigator.clipboard && navigator.clipboard.writeText) {              navigator.clipboard.writeText(jsonStr).then(() => {                 this.editorCopyBtn.innerHTML = 'Copied!';                 setTimeout(() => {                    this.editorCopyBtn.innerHTML = '\x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2"><' + '/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"><' + '/path><' + '/svg> Copy to CMS';                 }, 2000);              }).catch(err => {                 console.warn('Failed to copy text: ', err);                 alert('Failed to copy deals to clipboard. See console.');              });           } else {              // Fallback              const textArea = document.createElement("textarea");              textArea.value = jsonStr;              document.body.appendChild(textArea);              textArea.focus();              textArea.select();              try {                 document.execCommand('copy');                 this.editorCopyBtn.innerHTML = 'Copied!';                 setTimeout(() => {                    this.editorCopyBtn.innerHTML = '\x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2"><' + '/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"><' + '/path><' + '/svg> Copy to CMS';                 }, 2000);              } catch (err) {                 console.warn('Fallback: Oops, unable to copy', err);                 alert('Fallback: Failed to copy deals to clipboard.');              }              document.body.removeChild(textArea);           }        }      }      // Initialize the Widget      if (document.readyState === 'loading') {        document.addEventListener('DOMContentLoaded', () => new DealsFinderWidget({ rootId: 'signal-deals-finder-root', rootNode: shadowRoot, hostContainer: hostContainer }));      } else {        new DealsFinderWidget({ rootId: 'signal-deals-finder-root', rootNode: shadowRoot, hostContainer: hostContainer });      }    })();  </script></div> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/home/coffee-makers/i-was-spending-usd7-a-day-at-coffee-shops-now-i-spend-usd1-thanks-to-my-nespresso-machine-thats-41-percent-off-at-amazon</link>
                                                                            <description>
                            <![CDATA[ Is your morning coffee routine getting too expensive? I recommend grabbing this Nespresso machine that's nearly $100 off on Amazon. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">Z6K9XtrM3uy5LTtMeDFvhR</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/vwmLMwL4yTWWgj23T9q46f-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Fri, 31 Jul 2026 16:22:20 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Coffee Makers]]></category>
                                                    <category><![CDATA[Home]]></category>
                                                    <category><![CDATA[Home Appliances]]></category>
                                                    <category><![CDATA[Kitchen & Dining]]></category>
                                                                                                                    <dc:creator><![CDATA[ Olivia Halevy ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/YAg7Fmh9dGKbg3hULBMWiU.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Olivia is a Deals Writer at Tom’s Guide. She loves all things lifestyle, shopping and sourcing the best deals from some of the top brands, retailers and websites around. From fashion and beauty to smart home and tech, she has an eye for finding practical, stylish, and reasonably-priced items that help make life simpler (and a little more aesthetically-pleasing).&amp;nbsp;Olivia has over five years of experience writing lifestyle, commerce, and branded content for &lt;a href=&quot;http://patch.com/&quot;&gt;Patch.com&lt;/a&gt;. She&#039;s covered major shopping holidays like Amazon Prime Day, Black Friday and Cyber Monday. In her free time, she enjoys trying out new exercise classes, binge-watching the latest viral TV shows, cooking, spending time with family and taking long walks with her dog, Gus.&amp;nbsp;&lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/vwmLMwL4yTWWgj23T9q46f-1280-80.jpg">
                                                            <media:credit><![CDATA[Future / Olivia Halevy]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Nespresso]]></media:description>                                                            <media:text><![CDATA[Nespresso]]></media:text>
                                <media:title type="plain"><![CDATA[Nespresso]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/vwmLMwL4yTWWgj23T9q46f-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>I love going to coffee shops, whether I'm just quickly grabbing my favorite vanilla oat milk latte, meeting up with a friend for coffee or getting some work done. However, every time I step foot inside a cafe, I'm spending at least $7 — and that's just for a coffee. </p><p>After calculating how much I was spending weekly and monthly, I was astonished. That's when I decided I needed to cut back a bit — and <a href="https://www.amazon.com/Nespresso-DeLonghi-ENV120GYAE-Espresso-Aeroccino/dp/B084GY5FHN/" target="_blank" rel="nofollow">my Nespresso Vertuo Next coffee and espresso maker</a> made that possible. Even better? It's currently 41% off on Amazon. </p><div class="product"><a data-dimension112="85336e50-8cea-11f1-9071-8d73434d97ba" data-action="Deal Block" data-label="Vertuo Next w Aeroccino Milk Frother" data-dimension48="Vertuo Next w Aeroccino Milk Frother" data-dimension25="$134" href="https://www.amazon.com/Nespresso-DeLonghi-ENV120GYAE-Espresso-Aeroccino/dp/B084GY5FHN/" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1500px;"><p class="vanilla-image-block" style="padding-top:84.93%;"><img id="cqkR72BCgMgQiYg32kT4jW" name="Nespresso Vertuo" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/cqkR72BCgMgQiYg32kT4jW.jpg" mos="" align="middle" fullscreen="" width="1500" height="1274" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Nespresso-DeLonghi-ENV120GYAE-Espresso-Aeroccino/dp/B084GY5FHN/" target="_blank" rel="nofollow" data-dimension112="85336e50-8cea-11f1-9071-8d73434d97ba" data-action="Deal Block" data-label="Vertuo Next w Aeroccino Milk Frother" data-dimension48="Vertuo Next w Aeroccino Milk Frother" data-dimension25="$134">Vertuo Next w Aeroccino Milk Frother: was $229 now $134</a></strong><br>This Nespresso Vertuo Next machine can turn your home into a full on coffee shop. It supports six cup sizes including 5, 8, 12, and 18-oz., as well as single and double espressos brewed hot or over ice. The included Aeroccino frother provides hot or cold milk for your cappuccinos and lattes.<a class="view-deal button" href="https://www.amazon.com/Nespresso-DeLonghi-ENV120GYAE-Espresso-Aeroccino/dp/B084GY5FHN/" target="_blank" rel="nofollow" data-dimension112="85336e50-8cea-11f1-9071-8d73434d97ba" data-action="Deal Block" data-label="Vertuo Next w Aeroccino Milk Frother" data-dimension48="Vertuo Next w Aeroccino Milk Frother" data-dimension25="$134">View Deal</a></p></div><div class="product"><a data-dimension112="85336ef0-8cea-11f1-81ca-d9115b0a4f10" data-action="Deal Block" data-label="Capsules Vertuo" data-dimension48="Capsules Vertuo" data-dimension25="$42" href="https://www.amazon.com/Nespresso-Vertuoline-Seller-Assortment-Count/dp/B01N05APQY/" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1500px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="Yvm4K4QWtX9JaZ3avkGG6L" name="Nespresso capsules" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/Yvm4K4QWtX9JaZ3avkGG6L.jpg" mos="" align="middle" fullscreen="" width="1500" height="1500" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Nespresso-Vertuoline-Seller-Assortment-Count/dp/B01N05APQY/" target="_blank" rel="nofollow" data-dimension112="85336ef0-8cea-11f1-81ca-d9115b0a4f10" data-action="Deal Block" data-label="Capsules Vertuo" data-dimension48="Capsules Vertuo" data-dimension25="$42">Capsules Vertuo: $42</a></strong><br>These are the Nespresso capsules I buy on a monthly basis. The variety pack includes three different medium and dark roast coffee pods with rich flavors you'll love. They'll provide you with a 7.8 oz serving of coffee. <a class="view-deal button" href="https://www.amazon.com/Nespresso-Vertuoline-Seller-Assortment-Count/dp/B01N05APQY/" target="_blank" rel="nofollow" data-dimension112="85336ef0-8cea-11f1-81ca-d9115b0a4f10" data-action="Deal Block" data-label="Capsules Vertuo" data-dimension48="Capsules Vertuo" data-dimension25="$42">View Deal</a></p></div><p>At nearly $100 off, the Nespresso Vertuo Next is practically a steal — and it can quickly pay for itself compared to buying coffee from a café every day. I typically buy Nespresso Vertuo capsules, which cost $42 for a pack of 30. That works out to about $1.40 per cup, making it a much more affordable daily coffee habit than my typical coffee shop run.</p><p>The best part is, my Nespresso machine actually makes delicious coffees, lattes and cappuccinos, so I don't feel disappointed making coffee at home rather than buying one. The included Aeroccino Milk Frother is really the icing on the cake. I add my favorite oat milk to the frother and in seconds, I have creamy, frothy milk to add to my coffee or latte. </p><p>The machine is super easy to use — all you have to do is add your capsule, make sure the water tank is full and press the brewing button. You'll have a delicious, barista-style coffee in just seconds. You can also choose from six cup sizes including 5, 8, 12, and 18-oz., as well as single and double espressos brewed hot or over ice. The machine truly does it all! </p><p>Of course, I'll never fully stop indulging in my local coffee shops — but at least I can save a little bit of money by making my coffee at home a few days a week. If you're hoping to do the same, <a href="https://www.amazon.com/Nespresso-DeLonghi-ENV120GYAE-Espresso-Aeroccino/dp/B084GY5FHN/" target="_blank" rel="nofollow">I recommend grabbing the Nespresso Vertuo Next for just $134 on Amazon</a>. </p><div class="vizualizer-embed"><div class="tg-df-widget-host" data-widget-config="?search=coffee&view_mode=savings_squad&widget_title=Top+Deals+Handpicked+by+Our+Editors&widget_subtitle=Discover+the+best+discounts+currently+available%2C+curated+daily+by+the+Tom%27s+Guide+Savings+Squad.&bg_color=transparent" data-vizualizer-embed="true"></div>    <script>    /**     * Tom's Guide Deals Finder - Vanilla JS Encapsulated Engine     */    (function() {      // --- Freyr Analytics Adapter ---      function initAnalytics() {        window.dataLayer = window.dataLayer || [];        window.googletag = window.googletag || {};        window.googletag.cmd = window.googletag.cmd || [];        window.hawk = window.hawk || { analytics: { freyr: [] } };        window.hawk.analytics = window.hawk.analytics || { freyr: [] };        window.hawk.analytics.freyr = window.hawk.analytics.freyr || [];        window.freyr = window.freyr || { cmd: [] };        const scriptSrc = 'https://freyr.futurecdn.net/freyr.js';        const hostname = typeof window !== 'undefined' ? window.location.hostname : '';        const isTestEnv = typeof window.navigator !== 'undefined' && (window.navigator.webdriver || window.navigator.userAgent.includes('Headless'));        const shouldSendRealAnalytics = !isTestEnv && hostname && hostname !== 'localhost' && hostname !== '127.0.0.1' && !hostname.includes('run.app');        if (shouldSendRealAnalytics && !document.querySelector(`script[src="${scriptSrc}"]`)) {          const script = document.createElement('script');          script.src = scriptSrc;          script.async = true;          document.head.appendChild(script);        }      }      function storeEventForDebug(name, data) {        if (!window.hawk || !window.hawk.analytics || !window.hawk.analytics.freyr) return;        window.hawk.analytics.freyr.push({ name, data });        try {          if (typeof window !== 'undefined' && window.localStorage) {            window.localStorage.setItem("hawk", JSON.stringify(window.hawk));          }        } catch (e) {          // Ignore storage issues        }        try {          window.dispatchEvent(new CustomEvent("hawk-analytics-update"));        } catch (e) {}      }      function sendToFreyr(eventName, data) {        if (typeof window === 'undefined') return;        window.freyr = window.freyr || { cmd: [] };        window.freyr.cmd.push(() => {          if (window.freyr && window.freyr.pushAndUpdate) {            window.freyr.pushAndUpdate(eventName, data);          }        });      }      function sendEvent(event, skip = false) {        try {          storeEventForDebug(event.name, event.data);          if (!skip) {            sendToFreyr(event.name, event.data);          }        } catch (e) {          // Ensure tracking errors don't surface to the user        }      }      function getCookie(name) {        try {          const match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));          return match ? match[2] : null;        } catch (e) {          return null;        }      }      function getTimeAgo(dateString) {        if (!dateString) return '';        const date = new Date(dateString);        const now = new Date();        const diffInSeconds = Math.floor((now.getTime() - date.getTime()) / 1000);        if (diffInSeconds < 60) return 'Just now';        const diffInMinutes = Math.floor(diffInSeconds / 60);        if (diffInMinutes < 60) return `${diffInMinutes} min${diffInMinutes > 1 ? 's' : ''} ago`;        const diffInHours = Math.floor(diffInMinutes / 60);        if (diffInHours < 24) return `${diffInHours} hr${diffInHours > 1 ? 's' : ''} ago`;        const diffInDays = Math.floor(diffInHours / 24);        if (diffInDays < 30) return `${diffInDays} day${diffInDays > 1 ? 's' : ''} ago`;        const diffInMonths = Math.floor(diffInDays / 30);        if (diffInMonths < 12) return `${diffInMonths} mo${diffInMonths > 1 ? 's' : ''} ago`;        const diffInYears = Math.floor(diffInDays / 365);        return `${diffInYears} yr${diffInYears > 1 ? 's' : ''} ago`;      }      function normalizeCurrency(symbol) {        const map = {          '£': 'GBP',          '$': 'USD',          'A$': 'AUD',          'CA$': 'CAD',          '€': 'EUR'        };        return map[symbol] || symbol;      }      function trackElementInteraction(props) {        sendEvent({          name: 'elementInteraction',          data: {            element: {              action: props.action || "click",              id: props.id || undefined,              class: props.class || undefined,              name: props.name || undefined,              text: props.text || undefined,              label: props.label || undefined,              container: props.container || undefined,              url: props.url || undefined,              articleId: props.articleId || undefined            }          }        });      }      function generateRevenueId(url, productName, merchantName, modelId) {        const str = `${window.location.href}|${productName}|${merchantName}|${modelId || ''}|${new Date().toDateString()}|tomsguide`;        let hash = 0;        for (let i = 0; i < str.length; i++) {          const char = str.charCodeAt(i);          hash = ((hash << 5) - hash) + char;          hash = hash & hash;        }        let numericStr = Math.abs(hash).toString();        while (numericStr.length < 19) {          numericStr += Math.floor(Math.random() * 10).toString();        }        return numericStr.substring(0, 19);      }      function rewriteAffiliateLink(url, territory, revenueId) {        if (!url) return url;        const t = (territory || 'gb').toLowerCase();        return url.replace(/hawk-custom-tracking/g, `tomsguide-${t}-${revenueId}`);      }      function trackHawkEvent(params) {        const { clickType, widgetId, productCategoryName, product, productsArray, zeroBasedProductIndexOrNull, totalDealsOrProducts, areaClicked, merchant, revenueId, isoCurrencyCode, queryName, widgetTypeName } = params;        const data = {          event: "hawkEvent",          category: "Affiliates",          affiliate: {            action: {              type: clickType,              id: widgetId,              event: clickType === "appeared" ? "viewed" : "Click from",              timestamp: Date.now()            },            component: {              flag: "Editor",              product: productCategoryName || "deals",              category: `Signal Deal Finder ${widgetTypeName || "Carousel"} widget`,              type: clickType === "appeared" ? "review" : "signal product",              label: queryName || (product ? (product.name || "") : ""),              index: zeroBasedProductIndexOrNull === null || zeroBasedProductIndexOrNull === undefined ? -1 : zeroBasedProductIndexOrNull,              linkCount: totalDealsOrProducts || 0,              blockLayout: "",              areaClicked: areaClicked || ""            }          },          products: productsArray || (product && merchant ? [            {              product: {                primary: {                  id: product.id || product.matchId || null,                  name: product.name,                  type: "deal",                  price: product.price,                  previousPrice: product.previousPrice || null,                  currency: isoCurrencyCode || "USD",                  preorder: false,                  labels: [],                  link: product.link,                  originalLink: product.originalLink || null,                  revenueId: revenueId || null,                  startTime: null,                  endTime: null,                  voucherCode: null,                  voucherAudience: null,                  voucherPercentageSaving: null,                  voucherMoneySaving: null,                  voucherType: null,                  offerExclusive: false,                  offerScope: null,                  globalId: product.globalId || null,                  inStock: product.inStock !== false,                  contractProvider: null,                  contractMinutes: null,                  contractTexts: null,                  contractData: null,                  contractLength: null,                  contractMonthlyPrice: null,                  contractCurrency: isoCurrencyCode || "USD"                }              },              merchant: {                id: merchant.id || null,                name: merchant.name,                url: merchant.url || null,                network: merchant.network || null              },              model: {                id: product.modelId || null,                brand: product.brand || null,                name: product.name,                parent: product.parent || null              }            }          ] : []),          reviews: [],          _clear: true,          "gtm.uniqueEventId": Date.now() % 10000        };        sendEvent({ name: 'hawkEvent', data });      }      function trackDealClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Product Card" });      }      function trackViewSimilarClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Product Card View Similar" });      }      function trackPriceComparisonClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Price Comparison" });      }      function trackReviewClick(params) {        trackHawkEvent({ ...params, clickType: "review", areaClicked: "Signal Product Card Review Link" });      }      function trackShare(params) {        trackHawkEvent({ ...params, clickType: "share", areaClicked: "Signal Product Card Share" });      }      function trackDealsAppeared(widgetId, deals, revenueId, currency, queryName, widgetTypeName) {         if (!deals || deals.length === 0) return;                  const productsArray = deals.slice(0, 50).map((deal) => {            let voucherPct = null;            let rawPrice = parseFloat(deal.rawPrice) || parseFloat(deal.price) || null;            let rawMsrp = parseFloat(deal.rawMsrp) || parseFloat(deal.msrp) || null;            if (rawMsrp > rawPrice && rawPrice > 0) {              voucherPct = Math.round((1 - (rawPrice / rawMsrp)) * 100);            }            let numId = null;            if (deal.externalProductId && !isNaN(parseInt(deal.externalProductId))) {              numId = parseInt(deal.externalProductId);            } else if (deal.id && !isNaN(parseInt(deal.id))) {              numId = parseInt(deal.id);            } else {              numId = deal.matchId || null;            }            return {              product: {                primary: {                  id: numId,                  name: deal.productName || deal.title || "",                  type: "deal",                  price: rawPrice,                  previousPrice: rawMsrp,                  currency: currency || 'USD',                  preorder: false,                  labels: deal.modelBrand || deal.brand ? [                     { type: "brand", value: deal.modelBrand || deal.brand }                  ] : [],                  link: deal.url,                  originalLink: deal.url,                  revenueId: revenueId || null,                  startTime: null,                  endTime: null,                  voucherCode: null,                  voucherAudience: null,                  voucherPercentageSaving: voucherPct,                  voucherMoneySaving: null,                  voucherType: null,                  offerExclusive: false,                  offerScope: null,                  globalId: deal.productKey || null,                  inStock: deal.inStock !== false,                  contractProvider: null,                  contractMinutes: null,                  contractTexts: null,                  contractData: null,                  contractLength: null,                  contractMonthlyPrice: null,                  contractCurrency: currency || 'USD'                }              },              merchant: {                id: deal.merchantId ? parseInt(deal.merchantId) : null,                name: deal.merchant || "Retailer",                url: deal.merchantUrl || null,                network: deal.merchantNetwork || null              },              model: {                id: deal.modelId ? parseInt(deal.modelId) : null,                brand: deal.modelBrand || deal.brand || null,                name: deal.productName || deal.title || "",                parent: deal.modelParent || null              }            };         });                  trackHawkEvent({             clickType: "appeared",             widgetId: widgetId,             productCategoryName: "deals",             zeroBasedProductIndexOrNull: null,             totalDealsOrProducts: deals.length,             productsArray: productsArray,             queryName: queryName,             widgetTypeName: widgetTypeName         });      }      // 1. Setup Shadow DOM Sandbox      const currentScript = document.currentScript;      let hostContainer = null;      let template = null;            if (currentScript) {        let prev = currentScript.previousElementSibling;        while (prev) {          if (prev.tagName === 'TEMPLATE' && prev.classList.contains('tg-df-widget-template')) {            template = prev;          } else if (prev.tagName === 'DIV' && prev.classList.contains('tg-df-widget-host') && !prev.hasAttribute('data-initialized')) {            hostContainer = prev;            break;          }          prev = prev.previousElementSibling;        }      }            // Fallbacks in case script is deferred      if (!hostContainer) {        const hosts = document.querySelectorAll('.tg-df-widget-host:not([data-initialized])');        if (hosts.length > 0) hostContainer = hosts[0];      }            // Safely embedded template for CMS environments      const rawTemplate = `  \x3Cstyle>    /* --- Shadow DOM Base Reset --- */    *, *::before, *::after {      box-sizing: border-box;    }    img, picture, svg, video {      max-width: 100%;      height: auto;      display: block;    }    /*       1. Scoped CSS for Tom's Guide Deals Widget       All classes are prefixed with \`tg-df-\` to prevent CMS style leakage.    */    .tg-df-container {      container-type: inline-size;      container-name: tg-df;      --tg-df-blue: #1F69FF;      --tg-df-blue-hover: #004d8c;      --tg-df-text: #222222;      --tg-df-text-muted: #555555;      --tg-df-bg: #ffffff;      --tg-df-bg-secondary: #f4f4f4;      --tg-df-border: #e2e8f0;      font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;      color: var(--tg-df-text);      background-color: transparent;       width: 100%;      max-width: 1200px;      margin: 0 auto;      padding-bottom: 24px;    }    .tg-df-container *, .tg-df-container *::before, .tg-df-container *::after {      margin: 0;      padding: 0;      box-sizing: border-box;    }    .tg-df-container img {      border: none;      margin: 0;      padding: 0;    }    .tg-df-container a {      text-decoration: none;      color: inherit;    }    /*       2. Search & Filter Bar    */    .tg-df-controls {      display: flex;      flex-direction: column;      align-items: center;      gap: 20px;      margin-bottom: 32px;      width: 100%;      position: relative;      z-index: 20;    }    .tg-df-top-bar {      display: flex;      width: 100%;      max-width: 760px;      gap: 12px;      margin: 0 auto;      align-items: center;    }    .tg-df-search-wrapper {      position: relative;      flex: 1;      width: 100%;      box-shadow: 0 8px 24px rgba(0,0,0,0.06);      border-radius: 40px;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      z-index: 100;    }    .tg-df-autocomplete-dropdown {      position: absolute;      top: calc(100% + 4px);      left: 0;      right: 0;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 12px;      box-shadow: 0 8px 32px rgba(0,0,0,0.12);      max-height: 300px;      overflow-y: auto;      z-index: 200;      display: none;    }    .tg-df-autocomplete-dropdown.active {      display: block;    }    .tg-df-autocomplete-item {      padding: 12px 24px;      cursor: pointer;      font-size: 14px;      color: var(--tg-df-text);      transition: background 0.1s ease;    }    .tg-df-autocomplete-item:hover {      background: var(--tg-df-bg-secondary);    }    .tg-df-search-input {      width: 100%;      padding: 16px 64px 16px 24px;      font-size: 16px;      border: 2px solid transparent;      border-radius: 40px;      outline: none;      transition: border-color 0.2s ease, box-shadow 0.2s ease;      color: var(--tg-df-text);      background: transparent;    }    .tg-df-search-input:focus {      border-color: transparent;      box-shadow: 0 0 0 3px rgba(0, 108, 196, 0.15);    }    .tg-df-search-input::placeholder {      color: #999999;    }        .tg-df-search-btn {      position: absolute;      right: 8px;      top: 50%;      transform: translateY(-50%);      width: 40px;      height: 40px;      border-radius: 50%;      background: #222;      border: none;      display: flex;      align-items: center;      justify-content: center;      cursor: pointer;      transition: background 0.2s ease;    }        .tg-df-search-btn:hover {      background: #000;    }    .tg-df-search-icon {      width: 16px;      height: 16px;      fill: #fff;    }    .tg-df-settings-wrapper {      position: relative;    }        .tg-df-settings-btn {      width: 48px;      height: 48px;      border-radius: 50%;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      box-shadow: 0 4px 12px rgba(0,0,0,0.04);      display: flex;      align-items: center;      justify-content: center;      cursor: pointer;      transition: all 0.2s ease;      color: var(--tg-df-text-muted);      flex-shrink: 0;    }    .tg-df-settings-btn:hover {      background: var(--tg-df-bg-secondary);      border-color: #0000ff;      color: var(--tg-df-text);    }    .tg-df-settings-btn svg {      width: 24px;      height: 24px;      fill: currentColor;    }    .tg-df-settings-dropdown {      position: absolute;      top: calc(100% + 8px);      right: 0;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 12px;      box-shadow: 0 8px 32px rgba(0,0,0,0.12);      width: 280px;      padding: 20px;      display: none;      z-index: 100;      flex-direction: column;      gap: 20px;    }    .tg-df-settings-dropdown.active {      display: flex;    }        .tg-df-settings-dropdown-backdrop {      display: none;      position: fixed;      inset: 0;      z-index: 99;    }        .tg-df-settings-dropdown-backdrop.active {      display: block;    }    .tg-df-setting-item {      display: flex;      flex-direction: column;      gap: 10px;    }    .tg-df-setting-label {      font-size: 11px;      font-weight: 700;      color: var(--tg-df-text-muted);      text-transform: uppercase;      letter-spacing: 0.5px;    }        .tg-df-region-select {        padding: 10px 12px;        border-radius: 8px;        border: 1px solid var(--tg-df-border);        font-size: 15px;        outline: none;        background: var(--tg-df-bg-secondary);        color: var(--tg-df-text);        cursor: pointer;        width: 100%;    }    .tg-df-toggle {        position: relative;        display: inline-block;        width: 44px;        height: 24px;        flex-shrink: 0;    }    .tg-df-toggle input {        opacity: 0;        width: 0;        height: 0;    }    .tg-df-slider {        position: absolute;        cursor: pointer;        top: 0; left: 0; right: 0; bottom: 0;        background-color: #ccc;        transition: .2s;        border-radius: 24px;    }    .tg-df-slider:before {        position: absolute;        content: "";        height: 18px;        width: 18px;        left: 3px;        bottom: 3px;        background-color: white;        transition: .2s;        border-radius: 50%;    }    .tg-df-toggle input:checked + .tg-df-slider {        background-color: #1F69FF;    }    .tg-df-toggle input:checked + .tg-df-slider:before {        transform: translateX(20px);    }    .tg-df-dl-row {        flex-direction: row;        align-items: center;        justify-content: space-between;    }    .tg-df-dl-row-text {        font-size: 14px;        font-weight: 600;        color: var(--tg-df-text);    }    .tg-df-dl-row-subtext {        font-size: 12px;        font-weight: 400;        line-height: 1.3;        color: var(--tg-df-text-muted);        margin-top: 4px;        display: block;    }    .tg-df-filters-container {      position: relative;      width: 100%;      max-width: 800px;    }    .tg-df-scroll-btn {      display: none;      position: absolute;      top: 50%;      transform: translateY(-50%);      width: 32px;      height: 32px;      background: white;      border: 1px solid var(--tg-df-border);      border-radius: 50%;      align-items: center;      justify-content: center;      cursor: pointer;      z-index: 10;      box-shadow: 0 2px 8px rgba(0,0,0,0.1);      color: var(--tg-df-text-primary);      padding: 0;    }    .tg-df-scroll-btn svg {      width: 16px;      height: 16px;    }    .tg-df-scroll-btn:hover {      background: #f4f4f4;    }    .tg-df-scroll-btn.left {      left: 0px;    }    .tg-df-scroll-btn.right {      right: 0px;    }    @container tg-df (max-width: 768px) {      .tg-df-scroll-btn {        display: flex;        top: 22px; /* vertically center within the 44px high filter buttons */      }    }    .tg-df-filters {      display: grid;      width: 100%;      grid-template-columns: repeat(4, 1fr);      gap: 12px;      margin: 0 auto;      max-width: 800px;    }                 .tg-df-sort-wrapper {      position: relative;      display: flex;      align-items: center;      width: 100%;    }        .tg-df-sort-icon {      position: absolute;      left: 14px;      width: 14px;      height: 14px;      fill: var(--tg-df-text-muted);      pointer-events: none;    }    .tg-df-sort-select, .tg-df-filter-select {      width: 100%;      padding: 10px 36px 10px 38px;      font-size: 14px;      border: 1px solid var(--tg-df-border);      border-radius: 100px;      outline: none;      appearance: none;      background-color: var(--tg-df-bg-secondary);      background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 12 12'%3E%3Cpath fill='%23555555' d='M6 8L1 3h10z'/%3E%3C/svg%3E");      background-repeat: no-repeat;      background-position: right 14px center;      color: var(--tg-df-text);      cursor: pointer;      font-weight: 500;      transition: all 0.2s ease;    }        .tg-df-price-input::-webkit-outer-spin-button,    .tg-df-price-input::-webkit-inner-spin-button {      -webkit-appearance: none;      margin: 0;    }    .tg-df-price-input {      -moz-appearance: textfield;    }    .tg-df-sort-select:hover, .tg-df-filter-select:hover {      background-color: #e2e8f0;    }    .tg-df-multiselect-container {      position: relative;    }    @container tg-df (max-width: 768px) {      .tg-df-filters-container {      position: relative;      width: 100%;      max-width: 800px;    }    .tg-df-scroll-btn {      display: none;      position: absolute;      top: 50%;      transform: translateY(-50%);      width: 32px;      height: 32px;      background: white;      border: 1px solid var(--tg-df-border);      border-radius: 50%;      align-items: center;      justify-content: center;      cursor: pointer;      z-index: 10;      box-shadow: 0 2px 8px rgba(0,0,0,0.1);      color: var(--tg-df-text-primary);      padding: 0;    }    .tg-df-scroll-btn svg {      width: 16px;      height: 16px;    }    .tg-df-scroll-btn:hover {      background: #f4f4f4;    }    .tg-df-scroll-btn.left {      left: 0px;    }    .tg-df-scroll-btn.right {      right: 0px;    }    @container tg-df (max-width: 768px) {      .tg-df-scroll-btn {        display: flex;        top: 22px; /* vertically center within the 44px high filter buttons */      }    }    .tg-df-filters {        width: 100%;        margin: 0;        margin-bottom: -320px;        padding: 0 16px 320px 16px;        display: flex;        flex-wrap: nowrap;        gap: 8px;        overflow-x: auto;        overflow-y: hidden;        pointer-events: none;        scrollbar-width: none;        -webkit-overflow-scrolling: touch;      }      .tg-df-filters::-webkit-scrollbar {        display: none;      }      .tg-df-sort-wrapper {        pointer-events: auto;        flex: 0 0 auto;        width: 175px;        min-width: 175px;      }    }        .tg-df-multiselect-trigger {      display: block;      background: #fff;      user-select: none;      width: 100%;      overflow: hidden;      white-space: nowrap;      text-overflow: ellipsis;    }        .tg-df-multiselect-dropdown {      display: none;      position: absolute;      top: calc(100% + 4px);      left: 0;      width: 100%;      min-width: 220px;      max-height: 300px;      overflow-y: auto;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 8px;      box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);      z-index: 100;      padding: 8px 0;    }    .tg-df-multiselect-dropdown.active {      display: block;    }    .tg-df-ms-option {      padding: 8px 16px;      display: flex;      align-items: center;      gap: 8px;      cursor: pointer;      font-size: 14px;    }    .tg-df-ms-option:hover {      background-color: var(--tg-df-bg-secondary);    }        .tg-df-ms-option input {      cursor: pointer;      accent-color: #1f69ff;    }    .tg-df-sort-select:focus, .tg-df-filter-select:focus {      border-color: #0000ff;      box-shadow: 0 0 0 3px rgba(0, 0, 255, 0.2);      background-color: var(--tg-df-bg);    }    /*       3. Deal Grid Layout    */    .tg-df-grid.tg-df-grid-auto {      padding-top: 24px;    }    .tg-df-grid, .tg-df-grid.layout-grid {      display: grid;      grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));      gap: 10px;    }    .tg-df-grid.layout-row {      grid-template-columns: 1fr;      gap: 16px;    }        .tg-df-grid.layout-row .tg-df-card {      flex-direction: row;      align-items: stretch;      height: auto;      box-shadow: none;      border-bottom: 1px solid var(--tg-df-border);    }    .tg-df-grid.layout-row .tg-df-card:hover {      box-shadow: none;    }    .tg-df-grid.layout-row .tg-df-card-image-box {      width: 140px;      min-width: 140px;      aspect-ratio: 3/4;      border-right: none;      padding: 16px 16px 16px 32px;    }    .tg-df-grid.layout-row .tg-df-card-body {      padding: 16px;      justify-content: space-between;    }    .tg-df-grid.layout-row .tg-df-card-title {      font-size: 15px;      margin-bottom: 16px;    }    .tg-df-grid.layout-row .tg-df-card-stars { margin-bottom: 8px; }    .tg-df-grid.layout-row .tg-df-card-footer {      flex-direction: column;      align-items: flex-start;      gap: 0;    }    .tg-df-grid.layout-row .tg-df-card-merchant-pill {      margin-bottom: 4px;    }    .tg-df-grid.layout-row .tg-df-card-price-group {      margin-bottom: 8px;    }    .tg-df-grid.layout-row .tg-df-price-group {      width: auto;    }    .tg-df-grid.layout-row .tg-df-card-cta {      width: 100%;      max-width: 200px;      padding: 10px 24px;      font-size: 13px;      flex-shrink: 0;      text-align: center;      justify-content: center;    }    /*       4. Deal Card Design    */    .tg-df-card {      position: relative;      display: flex;      flex-direction: column;      background-color: #ffffff;      border-radius: 0;      overflow: hidden;      transition: transform 0.2s ease, box-shadow 0.2s ease;      text-decoration: none;      color: inherit;      height: 100%;      box-shadow: 0 0 16px rgba(0, 0, 0, 0.08);      border: 1px solid var(--tg-df-border);    }    .tg-df-card:hover {      box-shadow: 0 0 24px rgba(0, 0, 0, 0.12);    }    .tg-df-card-image-box {      width: 100%;      aspect-ratio: 3/4;      background-color: #f8f8f8;      display: flex;      align-items: center;      justify-content: center;      position: relative;      overflow: hidden;      padding: 32px;      flex: 0 0 auto;    }    .tg-df-card-image {      max-width: 100%;      max-height: 100%;      width: auto;      height: auto;      object-fit: contain;      mix-blend-mode: multiply; /* Helps white background images blend into secondary bg */      transition: transform 0.3s ease;    }    .tg-df-card:hover .tg-df-card-image {      transform: scale(1.05); /* Zoom in on hover */    }    .tg-df-card-discount-badge {      position: absolute;      top: 12px;      left: 12px;      background: #dc2626; /* Red */      color: #ffffff;      padding: 6px 8px;      font-size: 11px;      font-weight: 500;      text-transform: uppercase;      letter-spacing: 0.5px;      border-radius: 0;      z-index: 10;    }        .tg-df-card-merchant-pill {      display: block;      padding: 0;      font-size: 11px;      font-weight: 600;      text-transform: uppercase;      letter-spacing: 0.5px;      border-radius: 0;      color: var(--tg-df-text-muted);      margin-bottom: 8px;      white-space: nowrap;      overflow: hidden;      text-overflow: ellipsis;    }    .tg-df-card-body {      padding: 16px;      display: flex;      flex-direction: column;      flex-grow: 1;      min-width: 0;    }    .tg-df-card-badges {      display: flex;      flex-wrap: wrap;      gap: 6px;      margin-bottom: 8px;    }    .tg-df-tag {      display: inline-flex;      align-items: center;      padding: 4px 6px;      font-size: 11px;      font-weight: 700;      text-transform: uppercase;      border-radius: 4px;      gap: 4px;    }    .tg-df-tag-prime {      background-color: #00A8E1;      color: #fff;    }    .tg-df-tag-coupons {      background-color: #f1f5f9;      color: #334155;      border: 1px solid #cbd5e1;      cursor: pointer;      transition: background-color 0.2s;    }    .tg-df-tag-coupons:hover {      background-color: #e2e8f0;    }        .tg-df-tag-outline {      background-color: #f1f5f9;      color: #334155;      border: 1px solid #cbd5e1;      cursor: pointer;      transition: background-color 0.2s;    }    .tg-df-tag-outline:hover {      background-color: #e2e8f0;    }        @keyframes tg-df-spin {      0% { transform: rotate(0deg); }      100% { transform: rotate(360deg); }    }    .tg-df-coupon-spinner {      border: 2px solid #e2e8f0;      border-top: 2px solid #3b82f6;      border-radius: 50%;      width: 14px;      height: 14px;      animation: tg-df-spin 1s linear infinite;      margin: 4px 8px;      display: inline-block;    }        /* Vouchers Modal */    .tg-df-modal-backdrop {      position: fixed;      top: 0; left: 0; right: 0; bottom: 0;      background: rgba(0,0,0,0.5);      z-index: 10000;      display: flex;      align-items: center;      justify-content: center;      opacity: 0;      pointer-events: none;      transition: opacity 0.3s;    }    .tg-df-modal-backdrop.active {      opacity: 1;      pointer-events: auto;    }    .tg-df-modal {      background: #fff;      border-radius: 12px;      width: 90%;      max-width: 400px;      max-height: 80vh;      display: flex;      flex-direction: column;      box-shadow: 0 10px 40px rgba(0,0,0,0.2);      transform: translateY(20px);      transition: transform 0.3s;    }    .tg-df-modal-backdrop.active .tg-df-modal {      transform: translateY(0);    }    .tg-df-modal-header {      padding: 16px;      border-bottom: 1px solid #e2e8f0;      display: flex;      align-items: center;      justify-content: space-between;    }    .tg-df-modal-title {      font-size: 16px;      font-weight: 600;      margin: 0;    }    .tg-df-modal-close {      background: none;      border: none;      cursor: pointer;      padding: 4px;      color: #64748b;    }    .tg-df-modal-body {      padding: 16px;      overflow-y: auto;    }    .tg-df-voucher-item {      padding: 12px;      border: 1px dashed #cbd5e1;      border-radius: 8px;      margin-bottom: 10px;      background: #f8fafc;      display: flex;      align-items: center;      gap: 12px;      text-decoration: none;      color: inherit;      transition: background-color 0.2s, border-color 0.2s;    }    .tg-df-voucher-item:hover {      background: #f1f5f9;      border-color: #94a3b8;    }    .tg-df-voucher-item:last-child {      margin-bottom: 0;    }    .tg-df-voucher-logo {      width: 48px;      height: 48px;      object-fit: contain;      border-radius: 4px;      background: #fff;      border: 1px solid #e2e8f0;      flex-shrink: 0;    }    .tg-df-voucher-content {      flex: 1;      min-width: 0;    }    .tg-df-voucher-title {      font-size: 14px;      font-weight: 600;      margin: 0 0 4px 0;      line-height: 1.3;      color: #0f172a;    }    .tg-df-voucher-expiry {      font-size: 12px;      color: #64748b;      display: flex;      align-items: center;      gap: 4px;      margin-top: 6px;    }    .tg-df-voucher-code {      display: inline-flex;      align-items: center;      background: #f1f5f9;      border: 1px dashed #cbd5e1;      padding: 6px 10px;      font-family: monospace;      font-weight: 700;      font-size: 14px;      color: #0f172a;      border-radius: 4px;      margin-top: 8px;      cursor: pointer;      transition: all 0.2s ease;    }    .tg-df-voucher-code:hover {      background: #e2e8f0;      border-color: #94a3b8;    }    .tg-df-voucher-code.copied {      background: #ecfdf5;      border-color: #10b981;      color: #10b981;    }    .tg-df-voucher-cta {      display: inline-block;      margin-top: 8px;      font-size: 13px;      font-weight: 600;      color: #2563eb;      text-decoration: none;    }    .tg-df-card-title {      font-size: 15px;      font-weight: 400;      line-height: 1.4;      margin: 0 0 12px 0;      color: var(--tg-df-text);    }    .tg-df-card-footer {      margin-top: auto;      display: flex;      flex-direction: column;      width: 100%;    }    .tg-df-card-price-group {      display: flex;      flex-direction: row;      align-items: center;      gap: 8px;      margin-bottom: 12px;    }    .tg-df-card-price {      font-size: 16px;      font-weight: 700;      color: #dc2626; /* Red price */      line-height: 1;    }        .tg-df-card-msrp {      font-size: 13px;      color: var(--tg-df-text-muted);      text-decoration: line-through;    }    .tg-df-container .tg-df-card-cta {      display: flex;      align-items: center;      justify-content: center;      width: 100%;      box-sizing: border-box;      background-color: #1f69ff;      color: #ffffff;      font-size: 12px;      font-weight: 700;      text-transform: uppercase;      letter-spacing: 0.5px;      padding: 12px 16px;      border-radius: 0;      border: none;      cursor: pointer;      transition: background-color 0.2s ease;    }    .tg-df-card:hover .tg-df-card-cta,    .tg-df-card-cta:hover {      background-color: #1555cc;    }    /*       5. State & Skeleton Styles    */    .tg-df-message {      grid-column: 1 / -1;      text-align: center;      padding: 48px 24px;      color: var(--tg-df-text-muted);      font-size: 16px;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 8px;    }    @keyframes tg-df-shimmer {      0% { background-position: -200% 0; }      100% { background-position: 200% 0; }    }    .tg-df-skeleton {      background: linear-gradient(90deg, var(--tg-df-bg-secondary) 25%, #e2e8f0 50%, var(--tg-df-bg-secondary) 75%);      background-size: 200% 100%;      animation: tg-df-shimmer 1.5s infinite;      border-radius: 4px;    }    .tg-df-skeleton-img {      width: 100%;      height: 100%;      position: absolute;      top: 0; left: 0;    }        .tg-df-skeleton-text {      height: 16px;      margin-bottom: 8px;      width: 100%;    }    .tg-df-skeleton-text.short { width: 40%; }    .tg-df-skeleton-text.title { height: 20px; margin-bottom: 16px; }    /* Editor Floating Bar & Elements */    .tg-df-editor-bar {      position: sticky;      top: 120px;      z-index: 1000;      background: #111827;      color: #fff;      padding: 12px 16px;      border-radius: 8px;      margin-bottom: 16px;      display: flex;      align-items: center;      justify-content: space-between;      box-shadow: 0 4px 12px rgba(0,0,0,0.15);    }    .tg-df-editor-bar-text {      font-weight: 600;      font-size: 14px;    }    .tg-df-editor-copy-btn {      background: #10b981;      color: #fff;      padding: 6px 16px;      border: none;      border-radius: 4px;      font-weight: 600;      cursor: pointer;      display: flex;      align-items: center;      font-size: 13px;    }    .tg-df-editor-copy-btn:hover { background: #059669; }        .tg-df-deal-checkbox {      position: absolute;      top: 12px;      right: 12px;      z-index: 10;      width: 20px;      height: 20px;      cursor: pointer;      pointer-events: auto;    }    /*       6. Mobile List View (Stacks into a cleaner horizontal row/list)    */    @container tg-df (max-width: 599px) {      .tg-df-controls {        padding: 16px 16px 8px;      }            .tg-df-top-bar {        width: 100%;      }            .tg-df-settings-dropdown {        position: fixed;        top: auto;        bottom: 0;        left: 0;        right: 0;        width: 100%;        border-radius: 20px 20px 0 0;        padding: 24px;        box-shadow: 0 -8px 32px rgba(0,0,0,0.15);        z-index: 1000;        border: none;        border-top: 1px solid var(--tg-df-border);      }            .tg-df-settings-dropdown-backdrop.active {        background: rgba(0,0,0,0.4);      }            .tg-df-search-wrapper {        box-shadow: 0 0 16px rgba(0,0,0,0.08);      }                  .tg-df-sort-wrapper.tg-df-price-range-wrapper {        flex: 0 0 auto;        min-width: max-content;        width: auto;      }            .tg-df-sort-select, .tg-df-filter-select {        width: 100%;        text-align: left;        padding: 10px 24px 10px 32px;        background-position: right 8px center;        text-overflow: ellipsis;        white-space: nowrap;        overflow: hidden;      }      .tg-df-sort-icon {        left: 10px;      }      .tg-df-grid:not(.layout-grid):not(.layout-row),      .tg-df-grid.layout-row {        grid-template-columns: 1fr;        gap: 16px;      }            .tg-df-grid.tg-df-grid-auto {        padding-top: 24px;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card,      .tg-df-grid.layout-row .tg-df-card {        flex-direction: row;        align-items: stretch;        height: auto;        box-shadow: none; /* simple line on mobile if preferred, or keep */        border-bottom: 1px solid var(--tg-df-border);      }      .tg-df-grid.tg-df-grid-auto .tg-df-card:hover,      .tg-df-grid.layout-row .tg-df-card:hover {        box-shadow: none;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-image-box,      .tg-df-grid.layout-row .tg-df-card-image-box {        width: 120px;        min-width: 120px;        aspect-ratio: 3/4;        border-right: none;        padding: 12px;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-body,      .tg-df-grid.layout-row .tg-df-card-body {        padding: 12px;        justify-content: space-between;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-title,      .tg-df-grid.layout-row .tg-df-card-title {        font-size: 14px;        margin-bottom: 12px;      }      /* Single column mobile grid override */      .tg-df-grid.layout-grid {        grid-template-columns: 1fr;        gap: 16px;      }      .tg-df-grid.layout-grid .tg-df-card-image-box {        padding: 12px;      }      .tg-df-grid.layout-grid .tg-df-card-body {        padding: 10px;      }      .tg-df-grid.layout-grid .tg-df-card-title {        font-size: 13px;        margin-bottom: 8px;      }      .tg-df-grid.layout-grid .tg-df-card-price {        font-size: 14px;      }            .tg-df-card-footer {        flex-direction: column;        align-items: stretch;        gap: 0;        width: 100%;        min-width: 0;      }      .tg-df-card-merchant-pill {        margin-bottom: 4px;      }      .tg-df-card-price-group {        flex: 1 1 auto;        margin-bottom: 8px;      }      .tg-df-card-price {        font-size: 16px;      }      .tg-df-card-msrp {        display: block;       }      .tg-df-grid.layout-row .tg-df-card-cta,      .tg-df-container .tg-df-card-cta {        width: 100%;        max-width: none;        min-width: 0;        box-sizing: border-box;        padding: 8px 16px;        font-size: 12px;        flex: 0 0 auto;        text-align: center;        white-space: normal;        line-height: 1.2;      }    }    .tg-df-container.is-carousel {      min-height: 760px;      background-color: #E7F0FF;      padding: 0 0 24px 0;      border-radius: 24px;      width: 100vw;      max-width: 1200px;      position: relative;      left: 50%;      transform: translateX(-50%);    }    .tg-df-container.is-carousel.hide-header-details {      min-height: 480px;    }    /*       7. Carousel View Mode    */    .tg-df-container .tg-df-carousel-host {      /* Layout is now handled by container wrapper */    }    .tg-df-container .tg-df-carousel-eyebrow {      color: #1F69FF;      font-weight: 700;      font-size: 14px;      text-transform: uppercase;      letter-spacing: 1px;      padding: 24px 16px 0 16px;      display: none;    }    .tg-df-container .tg-df-carousel-query-title {      color: #011535;      font-size: 28px;      font-weight: 600;      padding: 0 16px 24px 16px;      line-height: 1.2;      display: none;    }    .tg-df-container .tg-df-carousel-blue-box {      background-color: transparent;      border-radius: 0;      padding: 24px 24px 0 24px;      margin: 0;      color: #1F69FF;          position: relative;      overflow: hidden;    }    .tg-df-container .tg-df-carousel-bg-circle-1 {      display: none;    }    .tg-df-container .tg-df-carousel-bg-circle-2 {      display: none;    }    .tg-df-container .tg-df-carousel-bg-circle-3 {      display: none;    }    .tg-df-container .tg-df-carousel-box-content {      position: relative;      z-index: 10;    }    .tg-df-container .tg-df-carousel-box-eyebrow {      background-color: transparent;      color: #1F69FF;      font-weight: 700;      font-size: 14px;      text-transform: uppercase;      letter-spacing: 1px;      display: inline-block;      padding: 0;      border-radius: 0;    }    .tg-df-container .tg-df-carousel-box-title {      font-size: 28px;      font-weight: 600;      line-height: 1.2;      margin-top: 8px;      color: #1e293b;    }    .tg-df-container .tg-df-countdown-wrapper {      position: absolute;      top: 0;      right: 0;      display: flex;      flex-direction: column;      align-items: flex-end;      gap: 12px;      transform: scale(0.67);      transform-origin: top right;    }    .tg-df-container .tg-df-countdown-title {      font-size: 14px;      font-weight: 600;      color: #011535;      margin: 0;    }    .tg-df-container .tg-df-countdown-blocks {      display: flex;      gap: 16px;    }    .tg-df-container .tg-df-countdown-item {      display: flex;      flex-direction: column;      align-items: center;      gap: 4px;    }    .tg-df-container .tg-df-countdown-box {      width: 59px;      height: 59px;      background: #03FE9E;      border-radius: 15px;      display: flex;      align-items: center;      justify-content: center;    }    .tg-df-container .tg-df-countdown-num {      font-family: 'Inter', sans-serif;      font-weight: 700;      font-size: 20px;      line-height: normal;      color: #011535;    }    .tg-df-container .tg-df-countdown-label {      font-family: 'Inter', sans-serif;      font-weight: 500;      font-size: 16px;      line-height: normal;      color: #1e293b;      text-transform: uppercase;    }    .tg-df-container .tg-df-carousel-box-subtitle {      font-size: 16px;      margin-top: 8px;      font-weight: 300;      color: #1e293b;      line-height: 24px;    }    .tg-df-container .tg-df-carousel-roundels-wrapper {      position: relative;      margin-top: 24px;      margin-left: -24px;      margin-right: -24px;    }    .tg-df-container .tg-df-carousel-roundels {      display: flex;      gap: 16px;      overflow-x: auto;            scrollbar-width: none;      padding-top: 12px;      padding-bottom: 24px;      padding-left: 24px;      padding-right: 24px;      margin-left: 0;      margin-right: 0;    }        .tg-df-container .tg-df-carousel-scroll-left,    .tg-df-container .tg-df-carousel-scroll-right {      position: absolute;      top: 50%;      transform: translateY(-50%);      height: 36px;      width: 36px;      display: flex;      align-items: center;      justify-content: center;      border-radius: 50%;      background-color: #ffffff;      border: 1px solid #e2e8f0;      box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);      color: #1F69FF;      cursor: pointer;      transition: all 0.2s;      margin-top: -4px;      z-index: 20;    }    .tg-df-container .tg-df-carousel-scroll-left { left: 8px; }    .tg-df-container .tg-df-carousel-scroll-right { right: 8px; }    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-left { left: 0px; }    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-right { right: 0px; }    .tg-df-carousel-filters-outer { margin-left: -24px; margin-right: -24px; padding-left: 24px; padding-right: 24px; }    .tg-df-grid-wrapper { position: relative; }    @container tg-df (max-width: 599px) { .tg-df-carousel-filters-outer { margin-left: -16px; margin-right: -16px; padding-left: 16px; padding-right: 16px; } }        .tg-df-container .tg-df-carousel-scroll-left:hover,    .tg-df-container .tg-df-carousel-scroll-right:hover {      background-color: rgba(255, 255, 255, 0.6);    }    .tg-df-container .tg-df-carousel-roundels::-webkit-scrollbar {      display: none;    }    .tg-df-container .tg-df-roundel {      display: flex;      flex-direction: column;      align-items: center;      gap: 8px;      cursor: pointer;      min-width: 120px;      flex-shrink: 0;    }    .tg-df-container .tg-df-roundel-img-box {      width: 120px;      height: 120px;      border-radius: 50%;      background: white;      display: flex;      align-items: center;      justify-content: center;      overflow: hidden;      box-shadow: 0px 3px 14px 0px rgba(30, 41, 59, 0.08);      transition: box-shadow 0.2s;    }    .tg-df-container .tg-df-roundel:hover .tg-df-roundel-img-box {      box-shadow: 0 0 0 2px #E7F0FF, 0 0 0 4px #1F69FF;    }    .tg-df-container .tg-df-roundel.active .tg-df-roundel-img-box {      box-shadow: 0 0 0 2px #E7F0FF, 0 0 0 4px #1F69FF;    }    .tg-df-container .tg-df-roundel:hover .tg-df-roundel-img-box img {      transform: scale(1.08);    }    .tg-df-container .tg-df-roundel-img-box img {      width: 100%;      height: 100%;      object-fit: contain;      padding: 10px;      box-sizing: border-box;      transition: transform 0.3s ease;    }    .tg-df-container .tg-df-roundel-label {      font-size: 13px;      font-weight: 400;      color: #1e293b;      text-align: center;    }    .tg-df-container .tg-df-carousel-filters-label {      font-size: 16px;      font-weight: 400;      color: #1e293b;      white-space: nowrap;      margin-right: 4px;    }    .tg-df-container .tg-df-carousel-filters-wrap {      display: flex;      align-items: center;      flex-wrap: nowrap;      gap: 8px;      margin-top: 8px;      overflow-x: auto;      scrollbar-width: none;      -webkit-overflow-scrolling: touch;      padding-bottom: 8px;      margin-left: -24px;      margin-right: -24px;      padding-left: 24px;      padding-right: 24px;    }    .tg-df-container .tg-df-carousel-filters-wrap::-webkit-scrollbar {      display: none;    }        .tg-df-container .tg-df-carousel-filter-btn img,    .tg-df-container .tg-df-carousel-filter-btn picture {      height: 20px;      width: 20px;      object-fit: contain;      object-position: center;      display: inline-flex;      align-items: center;      justify-content: center;      margin-right: 6px;    }    .tg-df-container .tg-df-carousel-filter-btn picture img {      margin-right: 0;      height: 100%;      width: 100%;    }    .tg-df-container .tg-df-carousel-filter-btn img.active-img,    .tg-df-container .tg-df-carousel-filter-btn picture:has(.active-img) {      display: none;    }    .tg-df-container .tg-df-carousel-filter-btn:hover img.inactive-img,    .tg-df-container .tg-df-carousel-filter-btn.active img.inactive-img,    .tg-df-container .tg-df-carousel-filter-btn:hover picture:has(.inactive-img),    .tg-df-container .tg-df-carousel-filter-btn.active picture:has(.inactive-img) {      display: none;    }    .tg-df-container .tg-df-carousel-filter-btn:hover img.active-img,    .tg-df-container .tg-df-carousel-filter-btn.active img.active-img,    .tg-df-container .tg-df-carousel-filter-btn:hover picture:has(.active-img),    .tg-df-container .tg-df-carousel-filter-btn.active picture:has(.active-img) {      display: inline-flex;    }    .tg-df-container .tg-df-carousel-filter-btn {      background: #ffffff;      border: 2px solid #1e293b;      color: #1e293b;      border-radius: 24px;      padding: 6px 16px;      font-size: 14px;      font-weight: 600;      cursor: pointer;      transition: all 0.2s;      flex-shrink: 0;      white-space: nowrap;    }    .tg-df-container .tg-df-carousel-filter-btn svg {      margin-right: 6px;    }    .tg-df-container .tg-df-carousel-filter-btn {      display: inline-flex;      align-items: center;    }    .tg-df-container .tg-df-carousel-filter-btn:hover {      background: #1e293b;      color: white;      border-color: #1e293b;    }    .tg-df-container .tg-df-carousel-filter-btn.active {      background: #1e293b;      color: white;      border-color: #1e293b;    }        .tg-df-grid.carousel-compact {      display: flex;      flex-wrap: nowrap;      overflow-x: auto;      gap: 16px;      padding: 16px 24px;      align-items: stretch;      scrollbar-width: none;    }    .tg-df-grid.carousel-compact::-webkit-scrollbar {      display: none;    }    .tg-df-grid.carousel-compact .tg-df-card {      flex: 0 0 auto;      width: 200px;      min-height: auto;      height: auto;      display: flex;      flex-direction: column;      border-radius: 15px;      border: none;      box-shadow: 0 0 16px rgba(0,0,0,0.08);      overflow: visible;    }    .tg-df-grid.carousel-compact .tg-df-card-image-box {      padding: 12px;      background-color: transparent;      border-radius: 15px 15px 0 0;      height: 130px;    }    .tg-df-grid.carousel-compact .tg-df-card-image {      mix-blend-mode: normal;    }    .tg-df-grid.carousel-compact .tg-df-card-discount-badge {      border-radius: 0;      top: 0px;      left: 0px;      padding: 4px 8px;      font-size: 11px;    }    .tg-df-grid.carousel-compact .tg-df-card-body {      padding: 8px 12px 12px 12px;    }    .tg-df-grid.carousel-compact .tg-df-card-title {      font-size: 14px;      font-weight: 400;      margin-bottom: 8px;      color: #011535;    }    .tg-df-grid.carousel-compact .tg-df-card-body:not(:has(.tg-df-card-stars)):not(:has(.tg-df-tag-prime)):not(:has(.tg-df-coupon-wrapper:not([style*="none"]))) > .tg-df-card-title,    .tg-df-grid.carousel-compact .tg-df-card-body:not(:has(.tg-df-card-stars)):has(> .tg-df-card-title:first-child) > .tg-df-card-title {    }    .tg-df-grid.carousel-compact .tg-df-card-cta {      border-radius: 5px;      padding: 8px 10px;      margin-top: 4px;      background-color: #1F69FF;    }    .tg-df-grid.carousel-compact .tg-df-card-price-group {      margin-bottom: 2px;    }    .tg-df-grid.carousel-compact .tg-df-card-merchant-pill {      margin-bottom: 2px;    }    @container tg-df (max-width: 599px) {      .tg-df-container .tg-df-carousel-blue-box-title {        font-size: 24px;      }      .tg-df-container .tg-df-countdown-title {        display: none;      }      .tg-df-container .tg-df-countdown-wrapper {        position: absolute;        top: 0;        right: 0;        align-items: flex-end;        transform: scale(0.40);        transform-origin: top right;      }      .tg-df-container .tg-df-roundel {        min-width: 88px;      }      .tg-df-container .tg-df-roundel-img-box {        width: 88px;        height: 88px;      }    }    /* REPLICA BLOCK STYLES */    .tg-df-grid.layout-replica-2 { grid-template-columns: repeat(2, 1fr) !important; gap: 20px; }    .tg-df-grid.layout-replica-1 { grid-template-columns: 1fr !important; gap: 20px; }        .tg-df-container .hawk-deal-widget-container { border-bottom: 1px solid #e5e7eb; display: flex; flex-direction: column; margin: 0; padding: 20px 0; box-sizing: border-box; font-family: inherit; }    .tg-df-container .hawk-deal-widget-wrap { display: flex; flex-direction: row; align-items: flex-start; width: 100%; gap: 24px; }    .tg-df-container .hawk-deal-widget-image-container { display: flex; flex-shrink: 0; justify-content: center; width: 160px; height: 160px; align-items: center; background: white; margin-bottom: 0px; }    .tg-df-container .hawk-deal-widget-title-product-title { color: #111827; font-size: 18px; font-weight: 700; line-height: 1.4; display: inline; }    .tg-df-container .hawk-deal-widget-title-price { font-size: 18px; font-weight: 700; line-height: 1.4; white-space: nowrap; color: #2563eb; }    .tg-df-container .hawk-deal-widget-title-price-now { font-weight: 700; }    .tg-df-container .hawk-deal-widget-title-retailer-price:hover { text-decoration: underline; }    .tg-df-container .hawk-deal-widget-title-retailer { font-size: 18px; font-weight: 700; line-height: 1.4; color: #2563eb; }    .tg-df-container .hawk-deal-widget-title-was-price { color: #dc2626; font-size: 16px; font-weight: 500; line-height: 1.4; text-decoration: line-through; white-space: nowrap; margin-left: 8px; margin-right: 8px; }    .tg-df-container .hawk-deal-widget-text-body-container { position: relative; width: 100%; box-sizing: border-box; }    .tg-df-container .hawk-deal-widget-text-body-main { font-size: 16px; width: 100%; margin-bottom: 12px; }    .tg-df-container .hawk-deal-widget-text-body-description { display: block; font-size: 15px; margin-top: 12px; color: #4b5563; line-height: 1.6; }    .tg-df-container .hawk-deal-widget-text-body-description p { margin: 0; line-height: 1.6; }    .tg-df-container .hawk-deal-widget-text-cta-container { display: flex; flex-direction: column; gap: 12px; width: 100%; flex: 1; min-width: 0; box-sizing: border-box; }    .tg-df-container .hawk-deal-widget-footer { display: flex; justify-content: flex-end; width: 100%; margin-top: auto; }    .tg-df-container .hawk-deal-widget-button-wrapper { display: flex; flex-direction: column; align-items: flex-end; justify-content: flex-end; width: 100%; }    .tg-df-container .hawk-deal-widget-preferred-partner-wrapper { display: flex; flex-direction: row; }        @container tg-df (min-width: 600px) {      .tg-df-mobile-only { display: none !important; }    }    @container tg-df (max-width: 599px) {      .tg-df-desktop-only { display: none !important; }      .tg-df-grid.layout-replica-2 { grid-template-columns: 1fr !important; }      .tg-df-grid.savings-squad-cards { grid-template-columns: 1fr !important; display: flex; flex-direction: column; }    }    .tg-df-grid.savings-squad-cards .tg-df-card-title {      -webkit-line-clamp: unset !important;      display: block !important;      overflow: visible !important;    }    @container tg-df (max-width: 500px) {      .tg-df-container .hawk-deal-widget-wrap { display: block; }      .tg-df-container .hawk-deal-widget-image-container { display: block; float: left; margin: 0 16px 8px 0; width: 120px; max-width: 120px; height: auto; align-items: normal; justify-content: normal; }      .tg-df-container .hawk-deal-widget-text-cta-container { display: block; text-align: left; }      .tg-df-container .hawk-deal-widget-footer { display: block; margin-top: 16px; clear: both; width: 100%; }      .tg-df-container .hawk-deal-widget-button-wrapper { display: block; width: 100%; }      .tg-df-container .hawk-deal-widget-button-wrapper .hawk-deal-widget-preferred-partner-wrapper { display: block; width: 100%; }      .tg-df-container .hawk-affiliate-link-deal-button { box-sizing: border-box !important; display: flex !important; max-width: none !important; width: 100% !important; margin: 0 !important; }    }        .tg-df-container .hawk-affiliate-link-deal-button {       align-items: center; background-color: #1f69ff; box-sizing: border-box; color: #ffffff !important; display: flex; font-size: 14px; font-weight: 700; justify-content: center; letter-spacing: 0.5px; line-height: 1; min-width: 160px; padding: 14px 24px; text-align: center; text-decoration: none; text-transform: uppercase; width: 100%; word-break: normal; border-radius: 4px; border: 0; transition: background-color 0.2s;     }    .tg-df-container .hawk-affiliate-link-deal-button:hover { background-color: #0056e0; text-decoration: none; }    .tg-df-container .hawk-lazy-image-deal-widget { display: block; height: auto; margin: auto; max-height: 160px; max-width: 100%; mix-blend-mode: multiply; object-fit: contain; }    .tg-df-container .hawk-deal-widget-text-cta-container a { color: #2563eb; text-decoration: none; display: inline; }    .tg-df-container .hawk-deal-widget-text-cta-container a:hover { text-decoration: underline; }    .tg-df-container .hawk-deal-widget-text-cta-container a:has(.hawk-deal-widget-title-product-title) { color: #111827; }    .tg-df-container .hawk-deal-widget-text-cta-container a:hover .hawk-deal-widget-title-product-title,    .tg-df-container .hawk-deal-widget-text-cta-container a:hover .hawk-deal-widget-title-retailer-price { text-decoration: underline; }    .tg-df-savings-squad-header { margin-bottom: 24px; text-align: center; display: none; }    .tg-df-banner-img-desktop { display: block; width: 100%; height: auto; margin-bottom: 32px; }    .tg-df-banner-img-mobile { display: none; width: 100%; height: auto; margin-bottom: 32px; }    @container tg-df (max-width: 600px) {      .tg-df-banner-img-desktop { display: none; }      .tg-df-banner-img-mobile { display: block; }    }    .tg-df-header-title { font-size: 28px; font-weight: 700; color: var(--tg-df-text); margin: 32px 0 12px 0; line-height: 1.3; }    .tg-df-header-subtitle { font-size: 16px; color: var(--tg-df-text-muted); margin: 0 0 32px 0; line-height: 1.5; }  \x3C/style>  \x3C!-- Widget Container --\x3E  \x3Cdiv class="tg-df-container" id="signal-deals-finder-root">    \x3Cdiv class="tg-df-savings-squad-header" id="tg-df-savings-squad-header">      \x3Cpicture>        \x3Cimg src="https://cdn.mos.cms.futurecdn.net/flexiimages/xkh2og7m3d1778189998.png" alt="Deals Banner" class="tg-df-banner-img-desktop" />        \x3Cimg src="https://cdn.mos.cms.futurecdn.net/flexiimages/gmak6rtdf41778245089.png" alt="Deals Banner Mobile" class="tg-df-banner-img-mobile" />      \x3C/picture>      \x3Cdiv class="tg-df-header-text">        \x3Ch2 class="tg-df-header-title" id="tg-df-header-title">Editor's Choice Deals\x3C/h2>        \x3Cp class="tg-df-header-subtitle" id="tg-df-header-subtitle">Discover the best discounts currently available, curated daily by the Tom's Guide Savings Squad.\x3C/p>      \x3C/div>    \x3C/div>    \x3C!-- Editor Floating Bar --\x3E    \x3Cdiv class="tg-df-editor-bar" id="tg-df-editor-bar" style="display:none;">      \x3Cdiv class="tg-df-editor-bar-text" style="display: flex; align-items: center;">        \x3Cspan id="tg-df-selected-count">0\x3C/span>\x26nbsp;Deals Selected        \x3Cbutton class="tg-df-editor-clear-btn" id="tg-df-editor-clear" type="button" style="margin-left: 12px; font-size: 13px; color: #9ca3af; background: none; border: none; cursor: pointer; text-decoration: underline;">Clear All\x3C/button>      \x3C/div>      \x3Cbutton class="tg-df-editor-copy-btn" id="tg-df-editor-copy" type="button">        \x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2">\x3C/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1">\x3C/path>\x3C/svg>        Copy to CMS      \x3C/button>    \x3C/div>    \x3Cdiv class="tg-df-carousel-host" id="tg-df-carousel-host" style="display: none;">      \x3Cdiv class="tg-df-carousel-eyebrow">DEAL FINDER\x3C/div>      \x3Cdiv class="tg-df-carousel-query-title" id="tg-df-carousel-title-label">Best Deals\x3C/div>            \x3Cdiv class="tg-df-carousel-blue-box">        \x3Cdiv class="tg-df-carousel-bg-circle-1" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-bg-circle-2" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-bg-circle-3" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-box-content">          \x3Cdiv class="tg-df-countdown-wrapper" id="tg-df-countdown-wrapper" style="display:none;">            \x3Cdiv class="tg-df-countdown-title" id="tg-df-countdown-title">Prime Day starts in\x3C/div>            \x3Cdiv class="tg-df-countdown-blocks">              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-days">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">DAYS\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-hrs">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">HRS\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-min">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">MIN\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-sec">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">SEC\x3C/div>\x3C/div>            \x3C/div>          \x3C/div>          \x3Cdiv class="tg-df-carousel-box-eyebrow">DEAL FINDER\x3C/div>          \x3Cdiv class="tg-df-carousel-box-title">Find Deals Fast\x3C/div>          \x3Cdiv class="tg-df-carousel-box-subtitle">The latest deals from the biggest retailers, all in one place\x3C/div>                    \x3Cdiv class="tg-df-carousel-roundels-wrapper">          \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-roundels').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>          \x3Cdiv class="tg-df-carousel-roundels">                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Televisions" data-pr="all">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/wcMxTsHgqu3roMbAx7RLnT-132-100.png" alt="TVs" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">TVs\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Phones" data-pr="over50">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/G3KGaRGzj24F6PUsw4bWpT-132-100.png" alt="Phones" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Phones\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Computing" data-pr="all">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/znNvsLzx8NEgNkD9HSFSnT-132-100.png" alt="Computing" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Computing\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Gaming" data-pr="all">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/Pgew8yaRQeZFHqHjTzvBnT-132-100.png" alt="Gaming" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Gaming\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Mattresses" data-pr="over500">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/cW7xsaLyesxkHFVSiC4kmT-132-100.png" alt="Mattresses" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Mattresses\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Audio" data-pr="over30">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/pCvBVHuhaQVjKt3VgCjbqT-132-100.png" alt="Audio" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Audio\x3C/span>            \x3C/div>                  \x3C/div>        \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" onclick="this.parentElement.querySelector('.tg-df-carousel-roundels').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>        \x3C/div>        \x3C/div>        \x3Cdiv class="tg-df-carousel-filters-outer" style="position: relative;">          \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-filters-wrap').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>          \x3Cdiv class="tg-df-carousel-filters-wrap">                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="0">All\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-ot="amazon_lightning">              \x3Cimg src="https://cdn.mos.cms.futurecdn.net/HqAui7w97ft2NPqBtQ5r38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/yWPQ5yyQRhUwVKzGwYbh38-600-100.png" class="active-img" alt="" /> Lightning deals\x3C/button>            \x3Cbutton class="tg-df-carousel-filter-btn" data-ot="amazon_prime">              \x3Cimg src="https://cdn.mos.cms.futurecdn.net/fwoVXvL79turN3Ph535m38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/u75QjVpt3w2EsMimJiRo38-600-100.png" class="active-img" alt="" /> Prime deals\x3C/button>            \x3Cbutton class="tg-df-carousel-filter-btn" data-d="10">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 10% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="15">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 15% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="25">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 25% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-pr="under50">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-badge-dollar-sign">\x3Cpath d="M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z">\x3C/path>\x3Cpath d="M16 8h-6a2 2 0 1 0 0 4h4a2 2 0 1 1 0 4H8">\x3C/path>\x3Cpath d="M12 18V6">\x3C/path>\x3C/svg>            Under $50\x3C/button>        \x3C/div>        \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-filters-wrap').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>      \x3C/div>    \x3C/div>    \x3C/div>      \x3C!-- Search & Filter Controls --\x3E      \x3Cdiv class="tg-df-top-bar" id="tg-df-top-bar" style="position: relative; z-index: 100; margin: 0 auto 20px;">        \x3Cdiv class="tg-df-search-wrapper">          \x3Cinput type="text" class="tg-df-search-input" placeholder="Search for deals, products, or brands...">          \x3Cbutton type="button" class="tg-df-search-btn" aria-label="Search">              \x3Csvg class="tg-df-search-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">                \x3Cpath d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/>              \x3C/svg>          \x3C/button>          \x3Cdiv class="tg-df-autocomplete-dropdown" id="tg-df-autocomplete">\x3C/div>        \x3C/div>      \x3C/div>    \x3Cdiv class="tg-df-controls" id="tg-df-controls" style="display:flex;">              \x3Cdiv class="tg-df-filters-container" style="position: relative; width: 100%; max-width: 800px; margin: 0 auto;">          \x3Cbutton class="tg-df-scroll-btn left" style="display: none;" onclick="this.parentElement.querySelector('.tg-df-filters').scrollBy({left: -200, behavior: 'smooth'})">            \x3Csvg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\x3Cpath d="M15 18l-6-6 6-6"/>\x3C/svg>          \x3C/button>          \x3Cbutton class="tg-df-scroll-btn right" style="display: none;" onclick="this.parentElement.querySelector('.tg-df-filters').scrollBy({left: 200, behavior: 'smooth'})">            \x3Csvg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\x3Cpath d="M9 18l6-6-6-6"/>\x3C/svg>          \x3C/button>          \x3Cdiv class="tg-df-filters">          \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-category-filter-wrapper" style="display: none;">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-category-filter" aria-label="Category">            \x3Coption value="all">All Categories\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper tg-df-multiselect-container" id="tg-df-brand-filter-wrapper" style="display:none;">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M4.25 5.61C6.27 8.2 10 13 10 13v6c0 .55.45 1 1 1h2c.55 0 1-.45 1-1v-6s3.72-4.8 5.74-7.39A.998.998 0 0 0 18.95 4H5.04c-.83 0-1.3.95-.79 1.61z"/>          \x3C/svg>          \x3Cdiv class="tg-df-filter-select tg-df-multiselect-trigger" id="tg-df-brand-trigger" tabindex="0">            Any Brand          \x3C/div>          \x3Cdiv class="tg-df-multiselect-dropdown" id="tg-df-brand-dropdown">            \x3C!-- Populated via script --\x3E          \x3C/div>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper tg-df-price-range-wrapper" id="tg-df-custom-price-wrapper" style="display: flex; align-items:center; justify-content:center; padding: 10px 20px; gap: 8px; border: 1px solid var(--tg-df-border); border-radius: 100px; background-color: var(--tg-df-bg);">          \x3Cspan style="font-size:14px; font-weight:500; color:var(--tg-df-text-primary);">Price\x3C/span>          \x3Cinput type="number" class="tg-df-price-input" id="tg-df-custom-price-min" placeholder="Min" style="width: 48px; background: transparent; border: none; color: var(--tg-df-text-primary); outline: none; font-size: 14px; text-align: center; padding: 0;">          \x3Cspan style="color:var(--tg-df-text-muted)">-\x3C/span>          \x3Cinput type="number" class="tg-df-price-input" id="tg-df-custom-price-max" placeholder="Max" style="width: 48px; background: transparent; border: none; color: var(--tg-df-text-primary); outline: none; font-size: 14px; text-align: center; padding: 0;">        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-legacy-price-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58.55 0 1.05-.22 1.41-.59l7-7c.37-.36.59-.86.59-1.41 0-.55-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-price-filter" aria-label="Filter Prices">            \x3Coption value="all">All Prices\x3C/option>            \x3Coption value="under50">Under $50\x3C/option>            \x3Coption value="50_100">$50 - $100\x3C/option>            \x3Coption value="100_200">$100 - $200\x3C/option>            \x3Coption value="200_500">$200 - $500\x3C/option>            \x3Coption value="over500">Over $500\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-discount-filter-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">            \x3Cpath d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58.55 0 1.05-.22 1.41-.59l7-7c.37-.36.59-.86.59-1.41 0-.55-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-discount-filter" aria-label="Discount Amount">            \x3Coption value="all">Any discount\x3C/option>            \x3Coption value="5">Min 5%\x3C/option>            \x3Coption value="10">Min 10%\x3C/option>            \x3Coption value="15">Min 15%\x3C/option>            \x3Coption value="20">Min 20%\x3C/option>            \x3Coption value="25">Min 25%\x3C/option>            \x3Coption value="30">Min 30%\x3C/option>            \x3Coption value="40">Min 40%\x3C/option>            \x3Coption value="50">Min 50%\x3C/option>            \x3Coption value="60">Min 60%\x3C/option>            \x3Coption value="70">Min 70%\x3C/option>          \x3C/select>          \x3C/div>        \x3C/div>        \x3C/div>      \x3C/div>    \x3C!-- Deals Grid Wrapper --\x3E    \x3Cdiv class="tg-df-grid-wrapper tg-df-carousel-cards-wrapper" id="tg-df-grid-wrapper">      \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('#tg-df-grid').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>      \x3Cdiv class="tg-df-grid" id="tg-df-grid">        \x3C!-- Content populated by JavaScript --\x3E      \x3C/div>      \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" style="display:none;" onclick="this.parentElement.querySelector('#tg-df-grid').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>    \x3C/div>        \x3C!-- Vouchers Modal --\x3E    \x3Cdiv class="tg-df-modal-backdrop" id="tg-df-vouchers-modal">      \x3Cdiv class="tg-df-modal">        \x3Cdiv class="tg-df-modal-header">          \x3Ch3 class="tg-df-modal-title" id="tg-df-vouchers-title">Available Coupons & Deals\x3C/h3>          \x3Cbutton class="tg-df-modal-close" id="tg-df-vouchers-close">            \x3Csvg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">              \x3Cline x1="18" y1="6" x2="6" y2="18">\x3C/line>              \x3Cline x1="6" y1="6" x2="18" y2="18">\x3C/line>            \x3C/svg>          \x3C/button>        \x3C/div>        \x3Cdiv class="tg-df-modal-body" id="tg-df-vouchers-content">          \x3C!-- Vouchers injected here --\x3E        \x3C/div>      \x3C/div>    \x3C/div>  \x3C/div>`;      if (!template) {        template = document.createElement('template');        template.innerHTML = rawTemplate;      }      let shadowRoot = null;      if (hostContainer && template) {        hostContainer.setAttribute('data-initialized', 'true');        shadowRoot = hostContainer.attachShadow({ mode: 'open' });        shadowRoot.appendChild(template.content.cloneNode(true));      }      class DealsFinderWidget {        constructor(config) {          this.rootNode = config.rootNode || document;          this.hostContainer = config.hostContainer || null;          this.rootId = config.rootId || 'signal-deals-finder-root';          this.root = this.rootNode.querySelector('#' + this.rootId);          if (!this.root) return;          this.widgetId = (window.crypto && window.crypto.randomUUID) ? window.crypto.randomUUID() : 'widget-' + Date.now() + '-' + Math.random().toString(36).slice(2);          this.grid = this.root.querySelector('#tg-df-grid');          this.tagsContainer = this.root.querySelector('#tg-df-tags-container');          this.categoryFilter = this.root.querySelector('#tg-df-category-filter');          this.categoryFilterWrapper = this.root.querySelector('#tg-df-category-filter-wrapper');          this.searchInput = this.root.querySelector('.tg-df-search-input');          this.autocompleteDropdown = this.root.querySelector('#tg-df-autocomplete');          this.sortSelect = this.root.querySelector('.tg-df-sort-select');          this.searchBtn = this.root.querySelector('.tg-df-search-btn');                    this.settingsToggle = this.root.querySelector('#tg-df-settings-toggle');          this.settingsPanel = this.root.querySelector('#tg-df-settings-panel');          this.settingsBackdrop = this.root.querySelector('#tg-df-settings-backdrop');          this.regionSelect = this.root.querySelector('#tg-df-region-select');          this.retailerSelect = this.root.querySelector('#tg-df-retailer-select');          this.offerTypeSelect = this.root.querySelector('#tg-df-offer-type-select');          this.viewModeSelect = this.root.querySelector('#tg-df-view-mode-select');          this.rowsSelect = this.root.querySelector('#tg-df-rows-select');          this.dealModeToggle = this.root.querySelector('#tg-df-deal-mode');          this.editorModeToggle = this.root.querySelector('#tg-df-editor-mode');          this.priceFilter = this.root.querySelector('#tg-df-price-filter');          this.discountFilter = this.root.querySelector('#tg-df-discount-filter');                    this.editorBar = this.root.querySelector('#tg-df-editor-bar');          this.editorSelectedCount = this.root.querySelector('#tg-df-selected-count');          this.editorCopyBtn = this.root.querySelector('#tg-df-editor-copy');          this.editorClearBtn = this.root.querySelector('#tg-df-editor-clear');                    this.apiUrl = 'https://search-api.fie.future.net.uk/widget.php';          this.deals = [];          this.displayLimit = 12;          this.airedaleArticles = null;          this.airedaleTags = [];          this.airedaleTagCounts = {};          this.activeDealTag = null;          this.selectedBrands = [];          this.currentQuery = '';          this.editorMode = this.hostContainer ? this.hostContainer.hasAttribute('data-editor-mode') : false;          this.viewModeOverride = this.hostContainer ? this.hostContainer.getAttribute('data-view-mode') : null;          this.selectedDeals = new Map();                    this.brandFilterWrapper = this.root.querySelector('#tg-df-brand-filter-wrapper');          this.brandTrigger = this.root.querySelector('#tg-df-brand-trigger');          this.brandDropdown = this.root.querySelector('#tg-df-brand-dropdown');                    this.customPriceWrapper = this.root.querySelector('#tg-df-custom-price-wrapper');          this.customPriceMin = this.root.querySelector('#tg-df-custom-price-min');          this.customPriceMax = this.root.querySelector('#tg-df-custom-price-max');          this.legacyPriceWrapper = this.root.querySelector('#tg-df-legacy-price-wrapper');          this.discountFilterWrapper = this.root.querySelector('#tg-df-discount-filter-wrapper');          this.initResizeObserver();          this.init();        }        getViewMode() {          console.log("DEBUG getViewMode -> override:", this.viewModeOverride, "editorMode:", this.editorMode);          if (this.viewModeOverride && (!this.editorMode || !this.viewModeSelect)) {            return this.viewModeOverride;          }          return (this.viewModeSelect && this.viewModeSelect.value) ? this.viewModeSelect.value : (this.viewModeOverride || 'auto');        }        applyLayoutMode() {          if (!this.grid) return;          const mode = this.getViewMode();          console.log("[DEBUG] applyLayoutMode CALLED! mode=", mode);          this.grid.classList.remove('layout-row', 'layout-grid', 'tg-df-grid-auto', 'carousel-compact', 'layout-replica-1', 'layout-replica-2');                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          const showHeaderDetails = params.get('show_header_details') !== 'false';          const carouselHost = this.root.querySelector('#tg-df-carousel-host');          const controlsDiv = this.root.querySelector('#tg-df-controls');          const topBarDiv = this.root.querySelector('#tg-df-top-bar');          const headerElement = this.root.querySelector('#tg-df-savings-squad-header');          if (headerElement) {             headerElement.style.display = (mode === 'savings_squad' && showHeaderDetails) ? 'block' : 'none';          }          if (mode === 'carousel') {             this.grid.classList.add('carousel-compact');             if (carouselHost) carouselHost.style.display = 'block';             if (controlsDiv) controlsDiv.style.display = 'none';             if (topBarDiv) topBarDiv.style.display = 'none';             if (this.root.classList.contains('tg-df-container')) {               this.root.classList.add('is-carousel');             }          } else {             if (carouselHost) carouselHost.style.display = 'none';             if (controlsDiv) controlsDiv.style.display = 'flex';             if (topBarDiv) topBarDiv.style.display = 'block';             if (this.root.classList.contains('tg-df-container')) {               this.root.classList.remove('is-carousel');             }          }          if (mode === 'grid') {            this.grid.classList.add('layout-grid');          } else if (mode === 'row') {            this.grid.classList.add('layout-row');          } else if (mode === 'savings_squad') {            this.grid.classList.add('tg-df-grid-auto', 'savings-squad-cards');          } else if (mode !== 'carousel') {            this.grid.classList.add('tg-df-grid-auto');          }                    const settingsWrapper = this.root.querySelector('.tg-df-settings-wrapper');          if (settingsWrapper) {            settingsWrapper.style.display = mode === 'auto' ? 'none' : 'block';          }          if (this.customPriceWrapper) {             this.customPriceWrapper.style.display = mode === 'auto' ? 'flex' : 'none';          }          if (this.legacyPriceWrapper) {             this.legacyPriceWrapper.style.display = mode === 'auto' ? 'none' : 'flex';          }          if (this.discountFilterWrapper) {             this.discountFilterWrapper.style.display = mode === 'auto' ? 'none' : 'flex';          }        }        initResizeObserver() {          try {            if (window.parent === window) return;          } catch (e) {            // cross origin frame check threw          }          const emitHeight = () => {            try {              const height = document.documentElement.scrollHeight || document.body.scrollHeight;              const msg = { type: 'embed-size', height: height };              if (window.parent && window.parent !== window) {                window.parent.postMessage(msg, '*');                window.parent.postMessage(JSON.stringify({ ...msg, sentinel: 'amp' }), '*');              }            } catch (e) {}          };                    if (window.ResizeObserver) {            try {              const ro = new ResizeObserver(() => emitHeight());              ro.observe(document.body);              if (this.root) ro.observe(this.root);            } catch(e){ console.warn(e); }          }          window.addEventListener('resize', emitHeight);          setTimeout(emitHeight, 300);        }        initCountdown() {          this.cdWrapper = this.root.querySelector('#tg-df-countdown-wrapper');                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          this.showCountdown = params.get('show_countdown') === 'true';          const showHeaderDetails = params.get('show_header_details') !== 'false';          const eyebrow = this.root.querySelector('.tg-df-carousel-box-eyebrow');          const title = this.root.querySelector('.tg-df-carousel-box-title');          const subtitle = this.root.querySelector('.tg-df-carousel-box-subtitle');          if (!showHeaderDetails) {            let containerElement = this.root.classList.contains('tg-df-container') ? this.root : this.root.querySelector('.tg-df-container');            if (containerElement) containerElement.classList.add('hide-header-details');            if (eyebrow) eyebrow.style.display = 'none';            if (title) title.style.display = 'none';            if (subtitle) subtitle.style.display = 'none';          }          if (!this.cdWrapper) return;          this.cdTitle = this.root.querySelector('#tg-df-countdown-title');          this.cdDays = this.root.querySelector('#tg-df-cd-days');          this.cdHrs = this.root.querySelector('#tg-df-cd-hrs');          this.cdMin = this.root.querySelector('#tg-df-cd-min');          this.cdSec = this.root.querySelector('#tg-df-cd-sec');          this.updateCountdown();          this.cdInterval = setInterval(() => this.updateCountdown(), 1000);        }        updateCountdown() {          if (!this.cdWrapper) return;          if (!this.showCountdown) {            this.cdWrapper.style.display = 'none';            return;          }          const area = this.getAreaCode();          let offset = '-04:00';          if (['DE', 'FR', 'IT', 'ES', 'NL'].includes(area)) {             offset = '+02:00';          } else if (['GB', 'IE', 'UK'].includes(area)) {             offset = '+01:00';          }          const startTime = new Date('2026-06-23T00:00:00' + offset).getTime();          const endTime = new Date('2026-06-26T00:00:00' + offset).getTime();          const now = Date.now();          let targetTime = 0;          if (now < startTime) {             targetTime = startTime;             if (this.cdTitle) this.cdTitle.textContent = 'Prime Day starts in';             this.cdWrapper.style.display = 'flex';          } else if (now < endTime) {             targetTime = endTime;             if (this.cdTitle) this.cdTitle.textContent = 'Prime Day ends in';             this.cdWrapper.style.display = 'flex';          } else {             this.cdWrapper.style.display = 'none';             if (this.cdInterval) clearInterval(this.cdInterval);             return;          }          const diff = Math.max(0, targetTime - now);          const d = Math.floor(diff / (1000 * 60 * 60 * 24));          const h = Math.floor((diff / (1000 * 60 * 60)) % 24);          const m = Math.floor((diff / 1000 / 60) % 60);          const s = Math.floor((diff / 1000) % 60);          if (this.cdDays) this.cdDays.textContent = d;          if (this.cdHrs) this.cdHrs.textContent = h;          if (this.cdMin) this.cdMin.textContent = m;          if (this.cdSec) this.cdSec.textContent = s;        }        init() {          this.initCountdown();          try {            initAnalytics();          } catch (e) {            console.warn('Deals Widget Analytics Error:', e);          }                    this.bindEvents();                    let initialQuery = '';                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          let initialViewMode = params.get('view_mode');          if (!this.viewModeOverride && initialViewMode) {            this.viewModeOverride = initialViewMode;          }          if (!params.has('search') && !params.has('q') && !params.has('query') && initialViewMode !== 'savings_squad') {             initialQuery = 'Gaming laptops';          }          const website = params.get('website') || 'tomsguide';          this.website = website;          if (website === 'techradar') {            const squadHeader = this.root.querySelector('.tg-df-savings-squad-header');            if (squadHeader) {               const pic = squadHeader.querySelector('picture');               if (pic) pic.style.display = 'none';            }            const style = document.createElement('style');            style.innerHTML = `              .tg-df-container .hawk-affiliate-link-deal-button, .tg-df-container .tg-df-card-cta { background-color: #5DAF08 !important; }              .tg-df-container .hawk-affiliate-link-deal-button:hover, .tg-df-container .tg-df-card-cta:hover { background-color: #4a8c06 !important; }            `;            this.root.appendChild(style);          }                    if (this.regionSelect) {            this.regionSelect.value = params.get('region') || 'auto';            this.updatePriceDropdownCurrency();          }                    if (this.retailerSelect && params.has('retailer')) {            this.retailerSelect.value = params.get('retailer');          }                    if (params.has('brands')) {            const b = params.get('brands');            if (b) {              this.selectedBrands = b.split(',');            }          }                    if (this.offerTypeSelect && params.has('offer_type')) {            this.offerTypeSelect.value = params.get('offer_type');          }          if (this.viewModeSelect && params.has('view_mode')) {            this.viewModeSelect.value = params.get('view_mode');          }          if (this.rowsSelect && params.has('rows')) {            this.rowsSelect.value = params.get('rows');          }          if (params.has('price')) {            const priceVal = params.get('price');            if (this.priceFilter) {               // Try assigning it directly to select. If it's not present implicitly ignores               this.priceFilter.value = priceVal;            }            if (priceVal.includes('_')) {               const parts = priceVal.split('_');               if (this.customPriceMin && parts[0]) this.customPriceMin.value = parts[0];               if (this.customPriceMax && parts[1]) this.customPriceMax.value = parts[1];            }          }          if (this.discountFilter && params.has('min_discount_ratio')) {            // Need to convert back from ratio (e.g. 0.8) to select value (e.g. "20")            const ratioStr = params.get('min_discount_ratio');            const ratioFloat = parseFloat(ratioStr);            if (!isNaN(ratioFloat)) {               const percentage = Math.round((1 - ratioFloat) * 100);               this.discountFilter.value = percentage.toString();            }          }          if (this.sortSelect) {            this.sortSelect.value = params.get('sort') || 'date_desc';          }          if (this.dealModeToggle && params.has('deal_mode')) {            this.dealModeToggle.checked = params.get('deal_mode') === 'true' || params.get('deal_mode') === '1';          }          const headerTitleEl = this.root.querySelector('#tg-df-header-title');          const headerSubtitleEl = this.root.querySelector('#tg-df-header-subtitle');          if (params.has('widget_title') && headerTitleEl) {             headerTitleEl.textContent = params.get('widget_title');          }          if (params.has('widget_subtitle') && headerSubtitleEl) {             headerSubtitleEl.textContent = params.get('widget_subtitle');          }                    // Re-apply layout after params have updated control values          this.applyLayoutMode();                    if (params.get('search')) {            initialQuery = params.get('search');          } else if (params.get('q')) {            initialQuery = params.get('q');          } else if (params.get('query')) {            initialQuery = params.get('query');          }                    this.currentQuery = initialQuery;          if (this.searchInput) {            if (this.getViewMode() === 'savings_squad') {              this.searchInput.value = '';            } else {              this.searchInput.value = this.currentQuery;            }          }                    if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {            this.fetchDeals(this.currentQuery);          } else {            this.render();          }        }        updatePriceDropdownCurrency() {          if (!this.priceFilter || !this.regionSelect) return;          const currencySymbols = {            'US': '$',            'GB': '£',            'CA': '$CA',            'AU': '$AU',            'DE': '€',            'FR': '€',            'IT': '€',          };          const area = this.getAreaCode();          const cur = currencySymbols[area || 'US'] || '$';                    const options = this.priceFilter.options;          for (let i = 0; i < options.length; i++) {            const opt = options[i];            if (opt.value === 'all') {              opt.innerText = 'All Prices';            } else if (opt.value === 'under50') {              opt.innerText = `Under ${cur}50`;            } else if (opt.value === '50_100') {              opt.innerText = `${cur}50 - ${cur}100`;            } else if (opt.value === '100_200') {              opt.innerText = `${cur}100 - ${cur}200`;            } else if (opt.value === '200_500') {              opt.innerText = `${cur}200 - ${cur}500`;            } else if (opt.value === 'over500') {              opt.innerText = `Over ${cur}500`;            }          }        }        populateBrandDropdown(values) {          if (!this.brandDropdown || !this.brandFilterWrapper) return;          this.brandFilterWrapper.style.display = 'flex'; // show the wrapper                    let html = '';          const allChecked = this.selectedBrands.length === 0 ? 'checked' : '';          const _div = '<' + '/div>';          const _span = '<' + '/span>';          html += `\x3Cdiv class="tg-df-ms-option">\x3Cinput type="checkbox" value="" ${allChecked} class="tg-df-brand-chk"> Any Brand${_div}`;                    values.forEach(v => {             if (!v.formatted_value || v.formatted_value === 'Any Brand') return;             const isChecked = this.selectedBrands.includes(v.formatted_value) ? 'checked' : '';             html += `\x3Cdiv class="tg-df-ms-option">\x3Cinput type="checkbox" value="${this.escapeHTML(v.formatted_value)}" ${isChecked} class="tg-df-brand-chk"> ${this.escapeHTML(v.formatted_value)} \x3Cspan style="color:var(--tg-df-text-muted);font-size:12px">(${v.count || 0})${_span}${_div}`;          });                    this.brandDropdown.innerHTML = html;                    // Re-bind listeners          const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');          chks.forEach(chk => {            chk.addEventListener('change', (e) => {              const val = e.target.value;              if (val === '') {                this.selectedBrands = [];              } else {                if (e.target.checked) {                   if (!this.selectedBrands.includes(val)) this.selectedBrands.push(val);                } else {                   this.selectedBrands = this.selectedBrands.filter(b => b !== val);                }              }                            if (this.selectedBrands.length === 0) {                 this.brandTrigger.innerText = 'Any Brand';              } else if (this.selectedBrands.length === 1) {                 this.brandTrigger.innerText = this.selectedBrands[0];              } else {                 this.brandTrigger.innerText = `${this.selectedBrands.length} Brands selected`;              }                            // Only call API if changed from UI interactions              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                 this.updateURLParams();                 this.fetchDeals(this.currentQuery);              }            });          });                    // Update button text on load          if (this.selectedBrands.length === 0) {             this.brandTrigger.innerText = 'Any Brand';          } else if (this.selectedBrands.length === 1) {             this.brandTrigger.innerText = this.selectedBrands[0];          } else {             this.brandTrigger.innerText = `${this.selectedBrands.length} Brands selected`;          }        }        updateURLParams() {          const url = new URL(window.location);          if (this.currentQuery && this.currentQuery !== 'Gaming laptops') {            url.searchParams.set('q', this.currentQuery);          } else {            url.searchParams.delete('q');            url.searchParams.delete('search');            url.searchParams.delete('query');          }                    if (this.regionSelect && this.regionSelect.value !== 'auto') {            url.searchParams.set('region', this.regionSelect.value);          } else {            url.searchParams.delete('region');          }                    if (this.retailerSelect && this.retailerSelect.value) {            url.searchParams.set('retailer', this.retailerSelect.value);          } else {            url.searchParams.delete('retailer');          }                    if (this.selectedBrands && this.selectedBrands.length > 0) {            url.searchParams.set('brands', this.selectedBrands.join(','));          } else {            url.searchParams.delete('brands');          }                    if (this.offerTypeSelect && this.offerTypeSelect.value) {            url.searchParams.set('offer_type', this.offerTypeSelect.value);          } else {            url.searchParams.delete('offer_type');          }                    if (this.viewModeSelect && this.viewModeSelect.value !== 'auto') {            url.searchParams.set('view_mode', this.viewModeSelect.value);          } else {            url.searchParams.delete('view_mode');          }                    if (this.rowsSelect && this.rowsSelect.value !== '12') {            url.searchParams.set('rows', this.rowsSelect.value);          } else {            url.searchParams.delete('rows');          }                    const min = this.customPriceMin ? this.customPriceMin.value : '';          const max = this.customPriceMax ? this.customPriceMax.value : '';          if (min || max) {             url.searchParams.set('price', `${min}_${max}`);          } else if (this.priceFilter && this.priceFilter.value !== 'all') {            url.searchParams.set('price', this.priceFilter.value);          } else {            url.searchParams.delete('price');          }                    if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {            const v = parseInt(this.discountFilter.value);            if (!isNaN(v) && v > 0) {               const ratio = (100 - v) / 100;               url.searchParams.set('min_discount_ratio', ratio.toString());            }          } else {            url.searchParams.delete('min_discount_ratio');          }                    if (this.sortSelect && this.sortSelect.value !== 'date_desc') {            url.searchParams.set('sort', this.sortSelect.value);          } else {            url.searchParams.delete('sort');          }                    if (this.dealModeToggle && this.dealModeToggle.checked) {            url.searchParams.set('deal_mode', 'true');          } else {            url.searchParams.delete('deal_mode');          }                    window.history.replaceState({}, '', url);        }        bindEvents() {          const handleFiltersScroll = () => {            const filters = this.root.querySelector('.tg-df-filters');            const leftBtn = this.root.querySelector('.tg-df-scroll-btn.left');            const rightBtn = this.root.querySelector('.tg-df-scroll-btn.right');            if (filters && leftBtn && rightBtn) {              const { scrollLeft, scrollWidth, clientWidth } = filters;              leftBtn.style.display = scrollLeft > 0 ? 'flex' : 'none';              rightBtn.style.display = Math.ceil(scrollLeft + clientWidth) < scrollWidth - 5 ? 'flex' : 'none';            }          };          const filters = this.root.querySelector('.tg-df-filters');          if (filters) {            filters.addEventListener('scroll', handleFiltersScroll);            window.addEventListener('resize', handleFiltersScroll);            setTimeout(handleFiltersScroll, 100);                        // Also call after rendering dropdowns            const origRenderCategories = this.renderCategories;            if (origRenderCategories) {               this.renderCategories = (...args) => {                 origRenderCategories.apply(this, args);                 setTimeout(handleFiltersScroll, 50);               };            }          }                const roundels = this.root.querySelectorAll('.tg-df-carousel-cat');          roundels.forEach(r => {             r.addEventListener('click', () => {                const q = r.getAttribute('data-query');                const pr = r.getAttribute('data-pr');                if (typeof trackHawkEvent !== 'undefined') {                     trackHawkEvent({                         clickType: "CC",                         widgetId: this.widgetId,                         productCategoryName: "deals",                         zeroBasedProductIndexOrNull: null,                         totalDealsOrProducts: null,                         areaClicked: "Category Roundel",                         revenueId: this.revenueId,                         isoCurrencyCode: typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD',                         queryName: q,                         widgetTypeName: this.widgetTypeName                     });                 }                this.currentQuery = q;                const label = this.root.querySelector('#tg-df-carousel-title-label');                if (label) label.textContent = 'Best ' + q;                if (this.priceFilter) this.priceFilter.value = pr || 'all';                if (this.discountFilter) this.discountFilter.value = '5';                if (this.searchInput) this.searchInput.value = q;                                roundels.forEach(ro => ro.classList.remove('active'));                r.classList.add('active');                this.fetchDeals(this.currentQuery);             });          });          const discBtns = this.root.querySelectorAll('.tg-df-carousel-filter-btn');          discBtns.forEach(b => {             b.addEventListener('click', () => {                const d = b.getAttribute('data-d');                const pr = b.getAttribute('data-pr');                const ot = b.getAttribute('data-ot');                let label = b.innerText ? b.innerText.trim() : '';                let filterType = 'unknown';                let filterVal = 'unknown';                if (d !== null) { filterType = 'discount'; filterVal = d; }                else if (pr !== null) { filterType = 'price'; filterVal = pr; }                else if (ot !== null) { filterType = 'offertype'; filterVal = ot; }                if (typeof trackElementInteraction === 'function') trackElementInteraction({ id: `filter-${filterType}-${filterVal}`, name: 'Filter Button', label: label });                                if (d !== null) {                   if (this.discountFilter) this.discountFilter.value = this.discountFilter.value === d ? '0' : d;                } else if (pr !== null) {                   if (this.priceFilter) this.priceFilter.value = this.priceFilter.value === pr ? 'all' : pr;                } else if (ot !== null) {                   if (this.offerTypeSelect) this.offerTypeSelect.value = this.offerTypeSelect.value === ot ? 'all' : ot;                } else {                   if (this.discountFilter) this.discountFilter.value = '0';                   if (this.priceFilter) this.priceFilter.value = 'all';                   if (this.offerTypeSelect) this.offerTypeSelect.value = 'all';                }                if (d === null && pr === null && ot === null && b.getAttribute("data-type") !== "custom") {                   discBtns.forEach(ro => ro.classList.remove('active'));                   b.classList.add('active');                } else if (b.getAttribute("data-type") !== "custom") {                   // Only operate on hardcoded buttons (those without data-type)                   discBtns.forEach(ro => {                      if (!ro.getAttribute('data-d') && !ro.getAttribute('data-pr') && !ro.getAttribute('data-ot') && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active');                   });                                      let makeActive = true;                   if (d !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-d') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   } else if (pr !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-pr') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   } else if (ot !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-ot') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   }                                      if (makeActive) b.classList.add('active');                                      // Check if anything is active, if not activate "All"                   let anyActive = false;                   discBtns.forEach(ro => { if (ro.classList.contains('active') && ro.getAttribute('data-type') !== 'custom') anyActive = true; });                   if (!anyActive) {                       discBtns.forEach(ro => { if (!ro.getAttribute('data-d') && !ro.getAttribute('data-pr') && !ro.getAttribute('data-ot') && ro.getAttribute('data-type') !== 'custom') ro.classList.add('active'); });                   }                }                                this.fetchDeals(this.currentQuery);             });          });          if (this.brandTrigger && this.brandDropdown) {            this.brandTrigger.addEventListener('click', () => {              this.brandDropdown.classList.toggle('active');            });            document.addEventListener('click', (e) => {              if (this.brandFilterWrapper && !e.composedPath().includes(this.brandFilterWrapper)) {                this.brandDropdown.classList.remove('active');              }            });          }          const showAutocomplete = () => {             if (this.getViewMode() !== 'savings_squad' || !this.autocompleteDropdown || !this.airedaleTags) return;                          let terms = this.airedaleTags;             if (this.airedaleBrands) {                terms = terms.concat(this.airedaleBrands.map(b => b.formatted_value));             }             terms = [...new Set(terms)];                          const query = this.searchInput.value.trim();             let matches = [];             if (query.length > 0) {                 matches = terms.filter(t => t.toLowerCase().includes(query.toLowerCase()) && t.toLowerCase() !== query.toLowerCase());             } else {                 matches = terms;             }                          if (matches.length > 0) {                 this.autocompleteDropdown.innerHTML = matches.map(m => `\x3Cdiv class="tg-df-autocomplete-item" data-tag="${this.escapeHTML(m)}">${this.escapeHTML(m)}<` + `/div>`).join('');                 this.autocompleteDropdown.classList.add('active');             } else {                 this.autocompleteDropdown.classList.remove('active');             }          };          let debounceTimer;          if(this.searchInput) {            this.searchInput.addEventListener('focus', showAutocomplete);            this.searchInput.addEventListener('input', (e) => {              clearTimeout(debounceTimer);              const query = e.target.value.trim();              this.currentQuery = query;              showAutocomplete();              debounceTimer = setTimeout(() => {                this.updateURLParams();                if (query.length > 2) {                  this.fetchDeals(query);                } else if (query.length === 0) {                  if (this.getViewMode() === 'savings_squad') {                    this.activeDealTag = null;                    this.currentQuery = '';                    if (this.categoryFilter) this.categoryFilter.value = 'all';                    this.fetchDeals('');                  } else {                    this.deals = [];                    this.render();                  }                }              }, 400);            });            this.searchInput.addEventListener('keypress', (e) => {              if (e.key === 'Enter') {                if (this.autocompleteDropdown) this.autocompleteDropdown.classList.remove('active');                clearTimeout(debounceTimer);                const query = e.target.value.trim();                this.currentQuery = query;                                let isTag = false;                if (this.airedaleTags && this.airedaleTags.includes(query)) isTag = true;                if (this.airedaleBrands && this.airedaleBrands.some(b => b.formatted_value === query)) isTag = true;                this.activeDealTag = isTag ? query : null;                                trackElementInteraction({ id: 'search-submit', name: 'Ask', label: 'Ask (main search)', text: query });                this.updateURLParams();                if (query.length > 2 || (this.getViewMode() === 'savings_squad')) {                   if (query.length === 0 && this.getViewMode() === 'savings_squad') {                       if (this.categoryFilter) this.categoryFilter.value = 'all';                   }                   this.fetchDeals(query);                }              }            });          }          if (this.autocompleteDropdown) {             this.autocompleteDropdown.addEventListener('click', (e) => {                const item = e.target.closest('.tg-df-autocomplete-item');                if (item) {                   const tag = item.getAttribute('data-tag');                   this.currentQuery = tag;                   if (this.searchInput) this.searchInput.value = tag;                   this.activeDealTag = tag;                   if (this.categoryFilter && this.airedaleTags.includes(tag)) {                       this.categoryFilter.value = tag;                   }                   this.autocompleteDropdown.classList.remove('active');                   this.updateURLParams();                   this.fetchDeals(tag);                }             });             document.addEventListener('click', (e) => {               if (this.autocompleteDropdown && this.searchInput && !e.composedPath().includes(this.searchInput) && !e.composedPath().includes(this.autocompleteDropdown)) {                 this.autocompleteDropdown.classList.remove('active');               }             });          }          if (this.searchBtn) {            this.searchBtn.addEventListener('click', () => {              if (this.autocompleteDropdown) this.autocompleteDropdown.classList.remove('active');              clearTimeout(debounceTimer);              const query = this.searchInput.value.trim();              trackElementInteraction({ id: 'search-submit', name: 'Ask', label: 'Ask (main search)', text: query });                            let isTag = false;              if (this.airedaleTags && this.airedaleTags.includes(query)) isTag = true;              if (this.airedaleBrands && this.airedaleBrands.some(b => b.formatted_value === query)) isTag = true;              this.activeDealTag = isTag ? query : null;                            this.currentQuery = query;              this.updateURLParams();              if (query.length > 2 || (this.getViewMode() === 'savings_squad')) {                 if (query.length === 0 && this.getViewMode() === 'savings_squad') {                     if (this.categoryFilter) this.categoryFilter.value = 'all';                 }                 this.fetchDeals(query);              }            });          }          if(this.sortSelect && this.sortSelect.querySelector('option[value="date_desc"]') === null) {              const option = document.createElement('option');              option.value = "date_desc";              option.text = "Newest First";              this.sortSelect.insertBefore(option, this.sortSelect.firstChild);          }          if(this.sortSelect) this.sortSelect.addEventListener('change', () => {            trackElementInteraction({ id: `sort-option-${this.sortSelect.value}`, name: 'Sort', label: `Sort: ${this.sortSelect.options[this.sortSelect.selectedIndex].text}` });            this.updateURLParams();            if (this.deals.length > 0) {              this.sortData();              this.render();            }          });                    const priceFilter = this.root.querySelector('#tg-df-price-filter');          if (priceFilter) {            this.priceFilter = priceFilter;            this.priceFilter.addEventListener('change', () => {              trackElementInteraction({ id: `filter-price-${this.priceFilter.value}`, name: 'Price', label: this.priceFilter.options[this.priceFilter.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }            });          }          const updateCustomPrice = () => {             this.updateURLParams();             if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);             } else {                this.render();             }          };          if (this.customPriceMin) {             this.customPriceMin.addEventListener('change', updateCustomPrice);             this.customPriceMin.addEventListener('keypress', (e) => {                if (e.key === 'Enter') updateCustomPrice();             });          }          if (this.customPriceMax) {             this.customPriceMax.addEventListener('change', updateCustomPrice);             this.customPriceMax.addEventListener('keypress', (e) => {                if (e.key === 'Enter') updateCustomPrice();             });          }          const discountFilter = this.root.querySelector('#tg-df-discount-filter');          if (discountFilter) {            this.discountFilter = discountFilter;            this.discountFilter.addEventListener('change', () => {              trackElementInteraction({ id: `filter-discount-${this.discountFilter.value}`, name: 'Discount', label: this.discountFilter.options[this.discountFilter.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }            });          }          if (this.categoryFilter) {            this.categoryFilter.addEventListener('change', (e) => {               const val = e.target.value === 'all' ? null : e.target.value;               this.activeDealTag = val;               if (val) {                 this.currentQuery = val;               } else {                 if (this.searchInput && this.currentQuery === document.querySelector('#tg-df-brand-trigger')?.getAttribute('data-active-brand')) {                     // don't clear current query if a brand is selected                 } else if (this.searchInput) {                     this.currentQuery = '';                     this.searchInput.value = '';                 }               }               this.fetchSavingsSquad();            });          }                    if (this.settingsToggle) {            this.settingsToggle.addEventListener('click', () => {              const o = this.settingsPanel.classList.toggle('active');              this.settingsBackdrop.classList.toggle('active');              if (o) trackElementInteraction({ id: 'filter-open', name: 'Filters', label: 'Open filters' });            });          }                    if (this.settingsBackdrop) {            this.settingsBackdrop.addEventListener('click', () => {              this.settingsPanel.classList.remove('active');              this.settingsBackdrop.classList.remove('active');            });          }                    if (this.regionSelect) {            this.regionSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-region-${this.regionSelect.value}`, name: 'Region', label: this.regionSelect.options[this.regionSelect.selectedIndex].text });              this.updateURLParams();              this.updatePriceDropdownCurrency();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.retailerSelect) {            this.retailerSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-merchant-${this.retailerSelect.value}`, name: 'Retailer', label: this.retailerSelect.options[this.retailerSelect.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.offerTypeSelect) {            this.offerTypeSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-offertype-${this.offerTypeSelect.value}`, name: 'Offer Type', label: this.offerTypeSelect.options[this.offerTypeSelect.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.viewModeSelect) {            this._prevViewMode = this.viewModeSelect.value;            this.viewModeSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-viewmode-${this.viewModeSelect.value}`, name: 'View Mode', label: this.viewModeSelect.options[this.viewModeSelect.selectedIndex].text });                            // Reset all active toggles and filters to prevent config carry-over              this.selectedBrands = [];              if (this.brandTrigger) this.brandTrigger.innerText = 'Select Brands';              if (this.brandDropdown) {                const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                chks.forEach(chk => { chk.checked = false; });              }              if (this.priceFilter) this.priceFilter.value = 'all';              if (this.customPriceMin) this.customPriceMin.value = '';              if (this.customPriceMax) this.customPriceMax.value = '';              if (this.sortSelect) this.sortSelect.value = 'date_desc';              if (this.discountFilter) this.discountFilter.value = '0';              if (this.retailerSelect) this.retailerSelect.value = '';              if (this.offerTypeSelect) this.offerTypeSelect.value = '';              if (this.rowsSelect) this.rowsSelect.value = '12';              if (this.categoryFilter) this.categoryFilter.value = 'all';              this.activeDealTag = null;              this.updateURLParams();              this.applyLayoutMode();                            if (this.getViewMode() === 'savings_squad' || this._prevViewMode === 'savings_squad') {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }              this._prevViewMode = this.viewModeSelect.value;            });          }                    if (this.rowsSelect) {            this.rowsSelect.addEventListener('change', () => {              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.dealModeToggle) {            this.dealModeToggle.addEventListener('change', () => {              this.updateURLParams();              this.render();            });          }          if (this.editorModeToggle) {             this.editorModeToggle.addEventListener('change', (e) => {                this.editorMode = e.target.checked;                this.render();                this.updateFloatingCopyBar();             });          }          if (this.editorCopyBtn) {             this.editorCopyBtn.addEventListener('click', () => {                this.copySelectedDealsToCMS();             });          }          if (this.editorClearBtn) {             this.editorClearBtn.addEventListener('click', () => {                this.selectedDeals.clear();                this.render();                this.updateFloatingCopyBar();             });          }          if (this.grid) {            this.grid.addEventListener('change', (e) => {               if (e.target.classList.contains('tg-df-deal-checkbox')) {                  const dealId = e.target.getAttribute('data-id');                  if (e.target.checked) {                     const dealObj = this.deals.find(d => d.id === dealId);                     if (dealObj) this.selectedDeals.set(dealId, dealObj);                  } else {                     this.selectedDeals.delete(dealId);                  }                  this.updateFloatingCopyBar();               }            });            this.grid.addEventListener('click', (e) => {              const dealCard = e.target.closest('[data-action="deal-click"]');              const similarCard = e.target.closest('[data-action="view-similar-click"]');              const cardLink = dealCard || similarCard;              if (cardLink) {                const productName = cardLink.getAttribute('data-product-name');                const merchantName = cardLink.getAttribute('data-merchant-name');                const productId = cardLink.getAttribute('data-analytics-id');                const price = parseFloat(cardLink.getAttribute('data-price')) || null;                const prevPriceStr = cardLink.getAttribute('data-previous-price');                const previousPrice = prevPriceStr ? parseFloat(prevPriceStr) : null;                const originalLink = cardLink.getAttribute('data-original-link');                const rewrittenLink = cardLink.getAttribute('href');                const revenueId = cardLink.getAttribute('data-revenue-id');                const index = parseInt(cardLink.getAttribute('data-index'), 10) || 0;                const inStock = cardLink.getAttribute('data-in-stock') === 'true';                const totalText = cardLink.getAttribute('data-total');                const totalDeals = parseInt(totalText, 10) || 0;                const productCategoryName = 'deals';                const trackingParams = {                  widgetId: this.widgetId,                  productCategoryName: productCategoryName,                  product: {                    modelId: cardLink.getAttribute('data-model-id') || null,                    matchId: cardLink.getAttribute('data-match-id') || null,                    brand: cardLink.getAttribute('data-model-brand') || null,                    parent: cardLink.getAttribute('data-model-parent') || null,                    name: productName,                    price: price,                    previousPrice: previousPrice,                    link: rewrittenLink,                    originalLink: originalLink,                    inStock: inStock                  },                  zeroBasedProductIndexOrNull: index,                  totalDealsOrProducts: totalDeals,                   merchant: {                    id: cardLink.getAttribute('data-merchant-id') || null,                    network: cardLink.getAttribute('data-merchant-network') || null,                    url: cardLink.getAttribute('data-merchant-url') || null,                    name: merchantName                  },                  revenueId: revenueId,                  widgetTypeName: this.widgetTypeName,                  isoCurrencyCode: normalizeCurrency(this.escapeHTML(cardLink.getAttribute('data-currency') || '$'))                };                if (dealCard) {                  trackDealClick(trackingParams);                } else {                  trackViewSimilarClick(trackingParams);                }              }              const couponsBtn = e.target.closest('[data-action="coupons-click"]');              if (couponsBtn) {                trackElementInteraction({                  id: 'product-card-show-coupons',                  name: 'Coupons',                  label: `Product card coupons: ${couponsBtn.getAttribute('data-merchant')}`                });              }            });          }          this.setupScrollListeners();        }        setupScrollListeners() {          const containers = [             this.root.querySelector('.tg-df-carousel-roundels'),             this.root.querySelector('.tg-df-carousel-filters-wrap'),             this.root.querySelector('#tg-df-grid')          ];                    containers.forEach(container => {             if (!container) return;                          const checkScroll = () => {                if (!container.parentElement) return;                const leftBtn = container.parentElement.querySelector('.tg-df-carousel-scroll-left');                const rightBtn = container.parentElement.querySelector('.tg-df-carousel-scroll-right');                                if (leftBtn) {                   if (container.scrollLeft <= 5) leftBtn.style.display = 'none';                   else leftBtn.style.display = 'flex';                }                                if (rightBtn) {                   if (container.scrollWidth <= container.clientWidth) {                       rightBtn.style.display = 'none';                   } else if (container.scrollLeft >= container.scrollWidth - container.clientWidth - 5) {                       rightBtn.style.display = 'none';                   } else {                       rightBtn.style.display = 'flex';                   }                }             };                          container.addEventListener('scroll', checkScroll);             checkScroll();                          window.addEventListener('resize', checkScroll);                          const observer = new MutationObserver(checkScroll);             observer.observe(container, { childList: true, subtree: true, characterData: false });          });        }        get widgetTypeName() {          const mode = this.viewModeSelect ? this.viewModeSelect.value : (this.viewModeOverride || 'auto');          switch(mode) {              case 'carousel': return 'Carousel';              case 'savings_squad': return 'Savings Squad';              case 'grid': return 'Grid';              case 'row': return 'Row';              default: return 'Auto Collection';          }        }        getRowsLimit() {          if (this.rowsSelect && this.rowsSelect.value) return parseInt(this.rowsSelect.value, 10);          let configSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {             configSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {             configSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(configSource);          if (params.has('rows')) return parseInt(params.get('rows'), 10) || 12;          return 12;        }        getAreaCode() {          if (this.regionSelect && this.regionSelect.value) {            if (this.regionSelect.value === 'auto') return null;            return this.regionSelect.value;          }          let area = null;          try {            const locale = window.navigator.language || window.navigator.userLanguage;            if (locale && locale.includes('-')) {              area = locale.split('-')[1].toUpperCase();            } else if (locale && locale.length === 2) {              if (locale.toUpperCase() === 'EN') { area = 'US'; }              else { area = locale.toUpperCase(); }            }          } catch (e) { /* Ignore */ }                    // Map to known valid options or fallback to US          const valid = ['US', 'GB', 'CA', 'AU', 'DE', 'FR', 'IT'];          if (area === 'UK') area = 'GB';          if (valid.includes(area)) {             return area;          }          return 'US';        }        async fetchDeals(query) {          this.showLoading();          this.deals = [];          this.displayLimit = this.getRowsLimit();                    try {            console.log("getViewMode returns:", this.getViewMode());            if (this.getViewMode() === 'savings_squad') {               await this.fetchSavingsSquad();            } else {               if (this.isBroadQuery(query)) {                 await this.fetchAdviserDeals(query);               } else {                 await this.fetchHawkDeals(query);                 if (this.deals.length === 0) {                   await this.fetchAdviserDeals(query);                 }               }            }          } catch (error) {            console.warn("[Tom's Guide Widget] Fetch error:", error);            this.showError();          }        }        async fetchSavingsSquad() {          let topArticles = this.airedaleArticles;          if (!topArticles) {            const siteParam = this.website || 'tomsguide';            const airedaleUrl = `https://airedale.futurecdn.net/feeds/feed_1781000519267.json?site=${siteParam}&articleType=deals&limit=50`;            let res;            try {               res = await fetch(airedaleUrl);            } catch(e) {               try { res = await fetch(`https://airedale.futurecdn.net/feeds/feed_1776420579726.json?site=${siteParam}&articleType=deals&limit=50`); } catch (err) { console.warn("Fallback fetch failed", err); return; }            }            if (!res.ok) throw new Error('Airedale API Error');            const articles = await res.json();            topArticles = Array.isArray(articles) ? articles.slice(0, 50) : ((articles.data && Array.isArray(articles.data)) ? articles.data.slice(0, 50) : []);            this.airedaleArticles = topArticles;                        let tagCounts = {};            topArticles.forEach((a) => {              let articleTags = new Set();              if (a.articlecategory && Array.isArray(a.articlecategory)) {                 a.articlecategory.forEach((t) => articleTags.add(t));              }              articleTags.forEach(t => {                 tagCounts[t] = (tagCounts[t] || 0) + 1;              });            });                        this.airedaleTags = Object.keys(tagCounts).sort((a, b) => tagCounts[b] - tagCounts[a]);            this.airedaleTagCounts = tagCounts;          }                    let targetArticles = topArticles;          if (!this.activeDealTag && this.currentQuery) {             const tagMatch = this.airedaleTags.find(t => t.toLowerCase() === this.currentQuery.toLowerCase());             if (tagMatch) {                this.activeDealTag = tagMatch;             }          }          if (this.activeDealTag) {             const cleanTag = this.activeDealTag.toLowerCase().replace(/&/g, '').replace(/[^a-z0-9]+/g, '-').replace(/-+/g, '-').replace(/^-|-$/g, '');             const encodedTag = encodeURIComponent(cleanTag);             const siteParam = this.website || 'tomsguide';             const url = `https://airedale.futurecdn.net/feeds/feed_1781000519267.json?site=${siteParam}&articleType=deals&limit=50&articleCategoryHandle=${encodedTag}`;             try {                const res = await fetch(url);                if (res.ok) {                   const articles = await res.json();                   targetArticles = Array.isArray(articles) ? articles.slice(0, 50) : ((articles.data && Array.isArray(articles.data)) ? articles.data.slice(0, 50) : []);                }             } catch(e) {                console.warn("Failed to fetch by activeDealTag", e);             }          }          let extractedDeals = [];          let seenUrls = new Set();                    let overallBrandsCounts = {};                    // First pass: extract ALL brands from topArticles so the dropdown has all options          topArticles.forEach((article) => {             if (!article.articlepage) return;             let pageData = [];             try { pageData = JSON.parse(article.articlepage[0]); } catch(e){ console.warn(e); }             const savingsSquad = pageData.filter((p) => p.type === 'deal' || p.type === 'featured-product');             savingsSquad.forEach((block) => {                const data = block.data || {};                if (data.brand) {                   const cleanBrand = data.brand.replace(/^\d+\.\s*/, '').trim();                   overallBrandsCounts[cleanBrand] = (overallBrandsCounts[cleanBrand] || 0) + 1;                }             });          });          targetArticles.forEach((article) => {             if (!article.articlepage) return;                          let pageData = [];             try {                pageData = JSON.parse(article.articlepage[0]);             } catch(e){ console.warn(e); }                          const savingsSquad = pageData.filter((p) => p.type === 'deal' || p.type === 'featured-product');                          savingsSquad.forEach((block, idx) => {                const data = block.data || {};                const isFeatured = block.type === 'featured-product';                                const link = data.link || {};                const priceObj = data.price || {};                const image = data.image || {};                                if (data.brand) {                   data.brand = data.brand.replace(/^\d+\.\s*/, '').trim();                }                const externalUrl = isFeatured ? data.url : (link.href || null);                let summaryTitle = isFeatured ? (data.name || data.brand) : (data.productName || link.label || article.articlename);                let description = isFeatured ? (data.strapline || '') : (data.text || '');                                if (!isFeatured && !data.productName && data.text) {                   const brSplit = data.text.split(new RegExp('\x3Cbr\\s*\\/?\\x3E', 'i'));                   if (brSplit.length > 1) {                     summaryTitle = brSplit[0].replace(/<[^>]+>/g, '').trim();                     description = brSplit.slice(1).join(' ').replace(/<br\s*\/?>/gi, ' ').replace(/<\/?(p|div)[^>]*>/gi, ' ').replace(/<[^>]+>/g, '').replace(/\s+/g, ' ').trim();                   } else {                     const match = data.text.match(/\x3Cstrong>(.*?)<\/strong>/);                     if (match) {                       summaryTitle = match[1].replace(/<[^>]+>/g, '').trim();                       if (summaryTitle.endsWith(':')) summaryTitle = summaryTitle.slice(0, -1);                     }                   }                }                                let imageUrl = isFeatured ? image.mos : (image.src || null);                if (imageUrl && imageUrl.startsWith('//')) imageUrl = 'https:' + imageUrl;                                description = description.replace(/<br\s*\/?>/gi, ' ').replace(/<\/?(p|div)[^>]*>/gi, ' ').replace(/<[^>]+>/g, '').replace(/\s+/g, ' ').replace(/View Deal$/i, '').trim();                                let merchantName = data.retailer || '';                if (!merchantName && externalUrl) {                   try {                     merchantName = new URL(externalUrl).hostname.replace('www.', '').split('.')[0];                     merchantName = merchantName.charAt(0).toUpperCase() + merchantName.slice(1);                   }catch(e){ console.warn(e); }                }                if (!merchantName) merchantName = 'Retailer';                const q = (this.currentQuery || '').toLowerCase();                const activeTagLogic = (this.activeDealTag || '').toLowerCase();                if (q.length > 2 && q !== activeTagLogic) {                   const searchTarget = `${summaryTitle || ''} ${description || ''}`.toLowerCase();                   if (!searchTarget.includes(q)) return;                }                let rawPrice = 0;                let rawMsrp = 0;                let currencyStr = '$';                if (isFeatured) {                   rawPrice = typeof data.salePrice === 'number' && data.salePrice > 0 ? data.salePrice : (typeof data.price === 'number' ? data.price : 0);                   rawMsrp = typeof data.salePrice === 'number' && typeof data.price === 'number' && data.price > data.salePrice ? data.price : 0;                   currencyStr = data.currency === 'GBP' ? '£' : '$';                } else {                   rawPrice = priceObj.amount ? parseFloat(priceObj.amount) : 0;                   rawMsrp = priceObj.amountWas ? parseFloat(priceObj.amountWas) : 0;                   currencyStr = priceObj.currency === 'GBP' ? '£' : '$';                }                                let savingAmt = 0;                let savingLabel = '';                if (rawPrice > 0 && rawMsrp > rawPrice) {                   savingAmt = parseFloat((rawMsrp - rawPrice).toFixed(2));                   savingLabel = `Save ${currencyStr}${savingAmt}`;                }                                // Apply Brand filter                if (this.selectedBrands && this.selectedBrands.length > 0) {                   const itemBrand = (data.brand || '').toLowerCase();                   const hasMatch = this.selectedBrands.some(sb => sb.toLowerCase() === itemBrand);                   if (!hasMatch) return;                }                // Apply Price filter                let priceFilterVal = null;                const min = this.customPriceMin ? this.customPriceMin.value : '';                const max = this.customPriceMax ? this.customPriceMax.value : '';                if (min || max) {                   priceFilterVal = `${min}_${max}`;                } else if (this.priceFilter && this.priceFilter.value !== 'all') {                   priceFilterVal = this.priceFilter.value;                }                if (priceFilterVal && rawPrice > 0) {                   if (priceFilterVal === 'under50' && rawPrice >= 50) return;                   if (priceFilterVal === 'over50' && rawPrice <= 50) return;                   if (priceFilterVal === 'over30' && rawPrice <= 30) return;                   if (priceFilterVal === 'over500' && rawPrice <= 500) return;                   if (priceFilterVal.includes('_')) {                      const parts = priceFilterVal.split('_');                      const min = parseFloat(parts[0]);                      const max = parseFloat(parts[1]);                      if (!isNaN(min) && rawPrice < min) return;                      if (!isNaN(max) && rawPrice > max) return;                   }                }                // Apply Discount filter                if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {                   const requiredDiscount = parseInt(this.discountFilter.value);                   if (!isNaN(requiredDiscount) && requiredDiscount > 0) {                      if (!rawMsrp || rawMsrp <= rawPrice) return;                      const ratio = Math.round((1 - (rawPrice / rawMsrp)) * 100);                      if (ratio < requiredDiscount) return;                   }                }                                if (externalUrl) {                   if (seenUrls.has(externalUrl)) return;                  seenUrls.add(externalUrl);                }                                extractedDeals.push({                   id: `airedale-${article.id || Math.random()}-${idx}`,                   url: externalUrl,                   image: imageUrl,                   fallbackImage: imageUrl,                   title: summaryTitle,                   brand: data.brand || '',                   productName: data.productName || '',                   merchant: merchantName,                   rawPrice: rawPrice,                   rawMsrp: rawMsrp,                   price: rawPrice > 0 ? rawPrice.toString() : '',                   msrp: rawMsrp > 0 ? rawMsrp.toString() : '',                   currency: currencyStr,                   isCheckPrice: !rawPrice,                   savingLabel: savingLabel,                   savingType: rawMsrp > rawPrice ? 'amount' : 'none',                   isPrime: false,                   starRating: null,                   description: description,                   text: data.text || '',                   authorName: article.articleauthortext ? article.articleauthortext[0] : (article.articleauthor ? article.articleauthor[0] : ''),                   authorRole: article.articleauthorrole ? article.articleauthorrole[0] : '',                   authorImage: article.articleauthormedia ? article.articleauthormedia[0] : '',                   documentUrl: article.documenturl ? article.documenturl[0] : '',                   modifiedDate: article.contentmodifieddate || article.modifieddate || ''                });             });          });                    const airedaleBrandsList = Object.keys(overallBrandsCounts).map(b => ({              formatted_value: b,              count: overallBrandsCounts[b]          })).sort((a,b) => b.count - a.count);                    if (this.getViewMode() === 'savings_squad') {             this.populateBrandDropdown(airedaleBrandsList.slice(0, 15));             if (this.brandFilterWrapper) {                if (airedaleBrandsList.length === 0) {                    this.brandFilterWrapper.style.display = 'none';                } else {                    this.brandFilterWrapper.style.display = 'flex';                }             }          }                    this.deals = extractedDeals;          this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        isBroadQuery(query) {          const q = query.toLowerCase();          const intentModifiers = ['deals', 'best', 'sale', 'under', 'cheap', 'offers', 'discount'];          return intentModifiers.some(term => q.includes(term));        }        async fetchHawkDeals(query) {          const url = new URL(this.apiUrl);          url.searchParams.append('model_name', query);          const areaCode = this.getAreaCode();          if (areaCode) {            url.searchParams.append('area', areaCode);          }                    if (this.retailerSelect && this.retailerSelect.value) {            url.searchParams.append('filter_merchant_name', this.retailerSelect.value);          }                    if (this.selectedBrands && this.selectedBrands.length > 0) {            url.searchParams.append('filter_label[text_brand]', this.selectedBrands.join(','));          }                    let priceVal = null;          const min = this.customPriceMin ? this.customPriceMin.value : '';          const max = this.customPriceMax ? this.customPriceMax.value : '';          if (min || max) {             priceVal = `${min}_${max}`;          } else if (this.priceFilter && this.priceFilter.value !== 'all') {             priceVal = this.priceFilter.value;          }          if (priceVal) {            if (priceVal === 'under50') {              url.searchParams.append('filter_max_price', '50');            } else if (priceVal === 'over50') {              url.searchParams.append('filter_min_price', '50');            } else if (priceVal === 'over30') {              url.searchParams.append('filter_min_price', '30');            } else if (priceVal === 'over500') {              url.searchParams.append('filter_min_price', '500');            } else if (priceVal.includes('_')) {              const parts = priceVal.split('_');              if (parts[0]) url.searchParams.append('filter_min_price', parts[0]);              if (parts[1]) url.searchParams.append('filter_max_price', parts[1]);            }          }                    if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {            const v = parseInt(this.discountFilter.value);            if (!isNaN(v) && v > 0) {              const ratio = (100 - v) / 100;              url.searchParams.append('min_discount_ratio', ratio.toString());            }          }                    if (this.offerTypeSelect && this.offerTypeSelect.value) {            url.searchParams.append('offer', this.offerTypeSelect.value);          }                    url.searchParams.append('filter_product_types', 'deals');                    url.searchParams.append('rows', this.getRowsLimit().toString());          let response;          try {             response = await fetch(url.toString());          } catch(e) {             if (window.location.protocol === 'file:') {                console.warn("[Tom's Guide Widget] fetch from file:// blocked by local CORS policy, falling back to Adviser mock.");                await this.fetchAdviserDeals(query);                return;             }             console.warn("Hawk fetch failed", e);             this.deals = [];             this.render();             return;          }          if (!response.ok) {            throw new Error('Hawk API Response Error');          }          const rawData = await response.json();          // Safely locate data array from potentially wrapped response          let offers = [];          let modelInfoArray = [];                    let brandFilterData = null;          if (rawData && rawData.widget && rawData.widget.data && Array.isArray(rawData.widget.data.filters)) {             brandFilterData = rawData.widget.data.filters.find(f => f.type === 'label_text_brand');          } else if (rawData && rawData.data && Array.isArray(rawData.data.filters)) {             brandFilterData = rawData.data.filters.find(f => f.type === 'label_text_brand');          }          if (brandFilterData && Array.isArray(brandFilterData.values) && brandFilterData.values.length > 0) {             this.populateBrandDropdown(brandFilterData.values);          } else {             if (this.brandFilterWrapper && this.selectedBrands.length === 0) {                this.brandFilterWrapper.style.display = 'none';             }          }                    if (rawData && rawData.widget && rawData.widget.data) {            if (Array.isArray(rawData.widget.data.offers)) offers = rawData.widget.data.offers;            if (rawData.widget.data.model_info && typeof rawData.widget.data.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.widget.data.model_info) ? rawData.widget.data.model_info : Object.values(rawData.widget.data.model_info);            }          } else if (rawData && rawData.data) {            if (Array.isArray(rawData.data.offers)) offers = rawData.data.offers;            if (rawData.data.model_info && typeof rawData.data.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.data.model_info) ? rawData.data.model_info : Object.values(rawData.data.model_info);            }          } else {            if (Array.isArray(rawData)) offers = rawData;            else if (rawData && Array.isArray(rawData.offers)) offers = rawData.offers;            else if (rawData && rawData.offers && Array.isArray(rawData.offers.offer)) offers = rawData.offers.offer;            else if (rawData && rawData.offers) offers = [].concat(rawData.offers);                        if (rawData && rawData.model_info && typeof rawData.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.model_info) ? rawData.model_info : Object.values(rawData.model_info);            }          }          let modelDetails = {};          modelInfoArray.forEach(m => {            const mId = m.model_id || m.id;            if (mId) {              modelDetails[mId] = {                score: m.score != null ? parseFloat(m.score) : null,                brand: m.brand || null,                parent: (m.parents && Array.isArray(m.parents) && m.parents.length > 0) ? m.parents[0].name : null              };            }          });          offers.forEach(item => {            let data = { ...item };            const mId = data.model_id;            if (mId && modelDetails[mId]) {              data.review_score = modelDetails[mId].score;              data.model_brand = modelDetails[mId].brand;              data.model_parent = modelDetails[mId].parent;            } else {              data.review_score = null;            }                        let itemOffers = [];            if (Array.isArray(item.offers)) itemOffers = item.offers;            else if (Array.isArray(item.offer)) itemOffers = item.offer;            else if (item.offers && typeof item.offers === 'object') itemOffers = [item.offers];            else if (item.offer && typeof item.offer === 'object') itemOffers = [item.offer];            if (itemOffers.length > 0) {              itemOffers.forEach(subItem => {                let subData = { ...item, ...subItem };                const subId = subData.model_id;                if (subId && modelDetails[subId]) {                  subData.review_score = modelDetails[subId].score;                  subData.model_brand = modelDetails[subId].brand;                  subData.model_parent = modelDetails[subId].parent;                } else if (data.review_score != null) {                  subData.review_score = data.review_score;                }                if (subData.merchant && typeof subData.merchant === 'object') {                  subData.merchant_name = subData.merchant.name;                }                this.deals.push(this.extractDealData(subData));              });              return;            }                        if (item.merchant && typeof item.merchant === 'object') {              data.merchant_name = item.merchant.name;            }                        this.deals.push(this.extractDealData(data));          });                    this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        async fetchAdviserDeals(query) {          // ======================================================================          // TODO: ADVISER API REPLACEMENT          // The code below simulates the Adviser API response using mock data.          // Once the real endpoint is ready, remove getAdviserMockData() and           // perform an actual fetch() request similar to fetchHawkDeals().          // Example:          // const area = this.getAreaCode();          // let apiUrl = `https://your-adviser-api.com/search?q=${query}&area=${area}`;          // if (this.priceFilter && this.priceFilter.value !== 'all') {          //   const val = this.priceFilter.value;          //   if (val === 'under50') apiUrl += '&filter_max_price=50';          //   else if (val === '50_100') apiUrl += '&filter_max_price=100';          //   else if (val === '100_200') apiUrl += '&filter_max_price=200';          //   else if (val === '200_500') apiUrl += '&filter_max_price=500';          // }          // const res = await fetch(apiUrl);          // const rawData = await res.json();          // ======================================================================          // Simulating network latency          await new Promise(resolve => setTimeout(resolve, 400));                    const rawData = this.getAdviserMockData();          let offers = [];                    if (rawData && rawData.data && rawData.data.Get && Array.isArray(rawData.data.Get.Deal)) {            offers = rawData.data.Get.Deal;          }                    // Basic client-side filtering for the mock if we want it to react to the query          const q = query.toLowerCase();          const selectedRetailer = (this.retailerSelect && this.retailerSelect.value) ? this.retailerSelect.value.toLowerCase() : null;                    offers.forEach(item => {            const dataObj = item;                        // Apply retailer filter            const itemRetailer = (dataObj.dataRetailer || '').toLowerCase();            if (selectedRetailer && itemRetailer !== selectedRetailer && !itemRetailer.includes(selectedRetailer)) {              return;            }                        // Apply mock price filter            let price = dataObj.dataDiscountedPrice || 0;            if (typeof price === 'string') {              price = parseFloat(price.replace(/[^0-9.]/g, ''));            }            let priceVal = null;            const min = this.customPriceMin ? this.customPriceMin.value : '';            const max = this.customPriceMax ? this.customPriceMax.value : '';            if (min || max) {               priceVal = `${min}_${max}`;            } else if (this.priceFilter && this.priceFilter.value !== 'all') {               priceVal = this.priceFilter.value;            }            if (priceVal) {              if (priceVal === 'under50' && price >= 50) return;              if (priceVal === 'over50' && price <= 50) return;              if (priceVal === 'over30' && price <= 30) return;              if (priceVal === 'over500' && price <= 500) return;              if (priceVal.includes('_')) {                 const parts = priceVal.split('_');                 if (parts[0] && price < parseFloat(parts[0])) return;                 if (parts[1] && price > parseFloat(parts[1])) return;              }            }                        // Map Adviser schema to our widget's expected schema            const mappedData = {              url: dataObj.linkHREF || dataObj.dataLink || '#',              image: dataObj.imageURL || (dataObj.image && dataObj.image.src) || '',              title: dataObj.dataProduct || (dataObj.product && dataObj.product.name) || 'Product Deal',              merchant: dataObj.dataRetailer || 'Retailer',              price: dataObj.dataDiscountedPrice || 0,              currency: dataObj.dataCurrency === 'USD' ? '$' : (dataObj.dataCurrency || '$'),              msrp: dataObj.dataOriginalPrice || null            };                        const titleLow = mappedData.title.toLowerCase();            const merchLow = mappedData.merchant.toLowerCase();                        // Smarter mock filtering            let isMatch = false;            if (q === '' || this.isBroadQuery(q)) {              isMatch = true;            } else if (titleLow.includes(q) || merchLow.includes(q)) {              isMatch = true;            } else if ((q.includes('laptop') || q.includes('mac') || q.includes('pc')) && (titleLow.includes('macbook') || titleLow.includes('laptop'))) {              isMatch = true;            } else if ((q.includes('tv') || q.includes('television')) && (titleLow.includes('tv') || titleLow.includes('oled') || titleLow.includes('qled'))) {              isMatch = true;            } else if ((q.includes('phone') || q.includes('smartphone')) && (titleLow.includes('galaxy') || titleLow.includes('phone'))) {              isMatch = true;            } else if ((q.match(/watch|fitness|run|shoe/)) && (titleLow.includes('forerunner') || titleLow.includes('saucony') || titleLow.includes('watch'))) {              isMatch = true;            }                        if (isMatch) {               this.deals.push(this.extractDealData(mappedData));            }          });                    let rowLimit = this.getRowsLimit();          // Intentionally omitting the slice here to allow "Load More" to work if the API returns more                    this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        getAdviserMockData() {          return {            "data": {              "Get": {                "Deal": [                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 300,                    "dataOriginalPrice": 399,                    "dataProduct": "Samsung Galaxy A36",                    "dataRetailer": "Samsung",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/MqDYsukV3JBG54te6dEs7j.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 14,                    "dataOriginalPrice": 24,                    "dataProduct": "Blink Mini",                    "dataRetailer": "Amazon",                    "imageURL": "http://cdn.mos.cms.futurecdn.net/3JurmAjHsDa5tPdaHAwEV8.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 59,                    "dataOriginalPrice": 99,                    "dataProduct": "Ring Video Doorbell",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/rAh4uR7AsAsALCCLTXnLNJ.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 10,                    "dataOriginalPrice": 599,                    "dataProduct": "MacBook Neo",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/Lg4Dvg68j9SbB5CPNrTEpH.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 749,                    "dataOriginalPrice": 849,                    "dataProduct": "65\\\" Fire TV Omni 4K QLED TV",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/SG34ZWodUkLTxJvMTbjPYR.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 71,                    "dataOriginalPrice": 160,                    "dataProduct": "Saucony Hurricane 24",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/vxf7UD5T2Am7guVzFoFcZ4.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 649,                    "dataOriginalPrice": 749,                    "dataProduct": "Garmin Forerunner 970",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/3GKnEu7CdhtxPMfnPCMCiA.png"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 1049,                    "dataOriginalPrice": 1499,                    "dataProduct": "LG 48\\\" C4 4K OLED TV",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/imvwZV9zoMD6fn9Afuge35.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 1499,                    "dataOriginalPrice": 2199,                    "dataProduct": "Samsung 49\\\" Odyssey Neo G9 4K Gaming Monitor",                    "dataRetailer": "Amazon",                    "imageURL": "http://cdn.mos.cms.futurecdn.net/XWDEJ5dUAE2nhK8k3Jk7k7.png"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 299,                    "dataOriginalPrice": 699,                    "dataProduct": "EGOHOME Black Memory Foam Mattress (queen)",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/hMUemtAejNETLVYxNrktzm.jpg"                  }                ]              }            }          };        }        decodeHTML(html) {          if (!html) return '';          const txt = document.createElement("textarea");          txt.innerHTML = String(html);          return txt.value;        }        extractDealData(item) {          const priceRawStr = String(item.price || item.current_price || '0');          const msrpRawStr = String(item.was_price || item.msrp || item.original_price || '0');          const rawPrice = parseFloat(priceRawStr.replace(/[^\d.]/g, '')) || 0;          const rawMsrp = parseFloat(msrpRawStr.replace(/[^\d.]/g, '')) || 0;          const isCheckPrice = rawPrice === 0 || priceRawStr === '0.00' || priceRawStr === '0';                    let originalImageUrl = item.image || item.image_url || item.product_image || '';          let imageUrl = originalImageUrl;          if ((!imageUrl || isCheckPrice) && item.model_image_url) {             imageUrl = item.model_image_url;             originalImageUrl = imageUrl;          } else if ((!imageUrl || isCheckPrice) && item.model_image) {             imageUrl = item.model_image;             originalImageUrl = imageUrl;          }                    if (imageUrl) {            imageUrl = imageUrl.replace(/-(\d+)-(\d+)(\.[a-z.]+)$/i, '$3');          }                    let fallbackImage = '';          if (originalImageUrl && originalImageUrl !== imageUrl) {             fallbackImage = originalImageUrl;          } else if (item.model_image && item.model_image !== imageUrl) {             fallbackImage = item.model_image;          } else if (item.model_image_url && item.model_image_url !== imageUrl) {             fallbackImage = item.model_image_url;          }                    const rawCurrency = item.currency || item.currency_symbol || '$';                    let savingLabel = item.percentage_saving_label || '';          if (!savingLabel && rawMsrp > rawPrice && rawPrice > 0) {            const pct = Math.round(((rawMsrp - rawPrice) / rawMsrp) * 100);            if (pct > 0) {              savingLabel = `${pct}% OFF`;            }          }                    const isPrime = item.shipping && item.shipping.prime === true;                    let scoreRaw = (item.review_score !== undefined && item.review_score !== null && item.review_score > 0) ? parseFloat(item.review_score) : null;          let starRating = 0;          if (scoreRaw !== null) {            starRating = Math.round((scoreRaw > 10 ? scoreRaw / 20 : scoreRaw / 2) * 2) / 2;          }                    return {            id: item.offer_id || item.link || item.url || item.offer_link || Math.random().toString(),            url: item.link || item.url || item.offer_link || '#',            image: imageUrl,            fallbackImage: fallbackImage,            title: item.name || item.title || item.model_name || item.product_name || 'Unknown Product',            brand: item.brand || '',            productName: item.model_name || item.product_name || item.name || '',            merchant: item.merchant_name || item.merchant || item.retailer || 'Retailer',            price: item.price !== undefined ? String(item.price) : '0.00',            currency: this.decodeHTML(rawCurrency),            msrp: item.was_price || item.msrp || item.original_price || null,            rawPrice: rawPrice,            rawMsrp: rawMsrp,            hasWasPrice: (item.was_price !== undefined && item.was_price !== null),            isCheckPrice: isCheckPrice,            savingLabel: savingLabel,            isPrime: isPrime,            starRating: starRating > 0 ? starRating : null,            modelId: item.model_id || '',            productKey: item.product_key || '',            merchantId: (item.merchant && typeof item.merchant === 'object') ? item.merchant.id || '' : '',            matchId: item.match_id || '',            merchantNetwork: (item.merchant && typeof item.merchant === 'object') ? item.merchant.an || '' : '',            merchantUrl: (item.merchant && typeof item.merchant === 'object') ? item.merchant.url || '' : '',            modelBrand: item.model_brand || item.brand || '',            modelParent: item.model_parent || ''          };        }        sortData() {          const sortVal = this.sortSelect ? this.sortSelect.value : 'date_desc';          if (sortVal === 'price_asc') {            this.deals.sort((a, b) => a.rawPrice - b.rawPrice);          } else if (sortVal === 'price_desc') {            this.deals.sort((a, b) => b.rawPrice - a.rawPrice);          } else if (sortVal === 'discount_desc') {            this.deals.sort((a, b) => {              const aDiscount = a.rawMsrp > a.rawPrice ? (a.rawMsrp - a.rawPrice) : 0;              const bDiscount = b.rawMsrp > b.rawPrice ? (b.rawMsrp - b.rawPrice) : 0;              return bDiscount - aDiscount;            });          } else if (sortVal === 'date_desc') {             this.deals.sort((a, b) => {                let dateA = 0;                let dateB = 0;                if (a && a.modifiedDate) {                   const valA = Array.isArray(a.modifiedDate) ? a.modifiedDate[0] : a.modifiedDate;                   dateA = new Date(valA).getTime();                   if (isNaN(dateA)) dateA = 0;                }                if (b && b.modifiedDate) {                   const valB = Array.isArray(b.modifiedDate) ? b.modifiedDate[0] : b.modifiedDate;                   dateB = new Date(valB).getTime();                   if (isNaN(dateB)) dateB = 0;                }                return dateB - dateA;             });          }        }        getFilteredDeals() {          let filteredDeals = [...this.deals];                    if (this.dealModeToggle && this.dealModeToggle.checked) {            filteredDeals = filteredDeals.filter(d => d.hasWasPrice || (d.msrp && d.rawMsrp > d.rawPrice));          }                    return filteredDeals;        }        showLoading() {          const _div = '<' + '/div>';          const skeletonCardHtml = `            \x3Cdiv class="tg-df-card">              \x3Cdiv class="tg-df-card-image-box">                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-img">${_div}              ${_div}              \x3Cdiv class="tg-df-card-body">                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short">${_div}                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text title">${_div}                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text title">${_div}                \x3Cdiv class="tg-df-card-footer mt-auto">                  \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="height:24px;">${_div}                ${_div}              ${_div}              \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text" style="height:44px; margin:0; border-radius:0;">${_div}            ${_div}`;          this.grid.innerHTML = Array(4).fill(skeletonCardHtml).join('');        }        showError() {          const _div = '<' + '/div>';          this.grid.innerHTML = `\x3Cdiv class="tg-df-message">            An error occurred while finding deals. Please check your connection and try again.          ${_div}`;        }        escapeHTML(str) {          if (!str) return '';          return String(str).replace(/[&<>'"]/g, tag => ({              '&': '&', '<': '<', '>': '>', "'": ''', '"': '"'          }[tag] || tag));        }                bindCouponButtons() {          const btns = this.root.querySelectorAll('.tg-df-tag-coupons');          btns.forEach(btn => {            btn.addEventListener('click', (e) => {              e.preventDefault();              e.stopPropagation();              const merchant = btn.getAttribute('data-merchant');              this.openVouchersModal(merchant);            });          });                    const closeBtn = this.root.querySelector('#tg-df-vouchers-close');          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          if (closeBtn) {            closeBtn.onclick = () => this.closeVouchersModal();          }          if (backdrop) {            backdrop.onclick = (e) => {              if (e.target === backdrop) this.closeVouchersModal();            };          }        }                closeVouchersModal() {          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          if (backdrop) backdrop.classList.remove('active');        }                async checkMerchantsCouponsBulk(merchants) {          if (!merchants || merchants.length === 0) return {};          const controller = new AbortController();          const timeoutId = setTimeout(() => controller.abort(), 4000);          try {            const area = this.getAreaCode();            const url = new URL('https://search-api.fie.future.net.uk/widget.php');            url.searchParams.append('model_name', 'Everything');            url.searchParams.append('language', 'en-GB');            if (area) url.searchParams.append('area', area);            url.searchParams.append('combine_product_types', '1');            url.searchParams.append('filter_merchant_name', merchants.join(','));            url.searchParams.append('all_filters', 'false');            url.searchParams.append('exclude_unlabelled', 'false');            url.searchParams.append('include_specs', 'false');            url.searchParams.append('sort', 'voucher');            url.searchParams.append('distinct_merchants', 'natural');            url.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');            url.searchParams.append('rows', '120');            url.searchParams.append('origin', 'widgets-clientside');                        let res; try { res = await fetch(url.toString(), { signal: controller.signal }); } catch (e) { return {}; }            clearTimeout(timeoutId);            if (!res.ok) return {};            const data = await res.json();                        let offers = [];            if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {              offers = data.widget.data.offers;            } else if (data && data.data && Array.isArray(data.data.offers)) {              offers = data.data.offers;            } else if (Array.isArray(data)) {              offers = data;            } else if (data && Array.isArray(data.offers)) {              offers = data.offers;            } else if (data && data.offers && Array.isArray(data.offers.offer)) {              offers = data.offers.offer;            } else if (data && Array.isArray(data.data)) {              offers = data.data;            }                        const foundMerchants = new Set();            offers.forEach(o => {              let mName = o.merchant_name || o.merchant || o.retailer;              if (mName && typeof mName === 'object') mName = mName.name;              if (mName) foundMerchants.add(String(mName).toLowerCase());            });            const resultMap = {};            merchants.forEach(m => {              if (m) resultMap[m] = foundMerchants.has(String(m).toLowerCase());            });            return resultMap;          } catch (e) {            return {};          }        }                async openVouchersModal(merchantName) {          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          const title = this.root.querySelector('#tg-df-vouchers-title');          const content = this.root.querySelector('#tg-df-vouchers-content');                    if (!backdrop || !content) return;                    // HACK: Hide closing tags          const _div = '<' + '/div>';          const _span = '<' + '/span>';          const _a = '<' + '/a>';          const _h4 = '<' + '/h4>';          const _svg = '<' + '/svg>';          const _circle = '<' + '/circle>';          const _polyline = '<' + '/polyline>';          const _rect = '<' + '/rect>';          const _path = '<' + '/path>';                    title.innerText = `${merchantName} Coupons & Deals`;          content.innerHTML = `\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text">${_div}                               \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text">${_div}`;          backdrop.classList.add('active');                    try {            const area = this.getAreaCode();            const url = new URL('https://search-api.fie.future.net.uk/widget.php');            url.searchParams.append('model_name', 'Everything');            url.searchParams.append('language', 'en-GB');            if (area) url.searchParams.append('area', area);            url.searchParams.append('combine_product_types', '1');            url.searchParams.append('filter_merchant_name', merchantName);            url.searchParams.append('all_filters', 'false');            url.searchParams.append('exclude_unlabelled', 'false');            url.searchParams.append('include_specs', 'false');            url.searchParams.append('sort', 'voucher');            url.searchParams.append('distinct_merchants', 'natural');            url.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');            url.searchParams.append('rows', '50');            url.searchParams.append('origin', 'widgets-clientside');                        const res = await fetch(url.toString());            if (!res.ok) throw new Error('API Error');            const data = await res.json();                        let offers = [];            if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {              offers = data.widget.data.offers;            } else if (data && data.data && Array.isArray(data.data.offers)) {              offers = data.data.offers;            } else if (Array.isArray(data)) {              offers = data;            } else if (data && Array.isArray(data.offers)) {              offers = data.offers;            } else if (data && data.offers && Array.isArray(data.offers.offer)) {              offers = data.offers.offer;            } else if (data && Array.isArray(data.data)) {              offers = data.data;            }                        if (offers.length === 0) {              content.innerHTML = `\x3Cdiv class="tg-df-message">No vouchers currently available for ${this.escapeHTML(merchantName)}.${_div}`;              return;            }                        content.innerHTML = offers.map((v, idx) => {              let offerObj = v;              if (v.offers && v.offers.offer) {                offerObj = Array.isArray(v.offers.offer) ? v.offers.offer[0] : v.offers.offer;              } else if (v.offer) {                offerObj = Array.isArray(v.offer) ? v.offer[0] : v.offer;              }              let logoUrl = v.logo_url || offerObj.logo_url || '';              if (!logoUrl && v.merchant) {                if (Array.isArray(v.merchant) && v.merchant.length > 0) logoUrl = v.merchant[0].logo_url || '';                else logoUrl = v.merchant.logo_url || '';              }                            const offerName = offerObj.name || offerObj.title || v.name || v.title || 'Special Offer';              const endTime = offerObj.end_time || v.end_time || '';              const linkUrl = offerObj.link || offerObj.url || v.link || v.url || '#';                            let foundVoucherCode = '';              const findVoucherCode = (obj) => {                if (!obj || typeof obj !== 'object') return;                if (obj.type === 'voucher_code' && obj.display_value) {                  foundVoucherCode = obj.display_value;                  return;                }                if (Array.isArray(obj)) {                  for (const item of obj) {                    findVoucherCode(item);                    if (foundVoucherCode) return;                  }                } else {                  for (const k in obj) {                    if (Object.prototype.hasOwnProperty.call(obj, k)) {                      findVoucherCode(obj[k]);                      if (foundVoucherCode) return;                    }                  }                }              };              findVoucherCode(offerObj);              if (!foundVoucherCode) findVoucherCode(v);                            const voucherCode = foundVoucherCode || offerObj.voucher_code || v.voucher_code || '';              const codeHtml = voucherCode ? `\x3Cspan class="tg-df-voucher-code" data-action="copy-code" data-code="${this.escapeHTML(voucherCode)}" title="Copy to clipboard">                \x3Cspan class="tg-df-voucher-code-text">${this.escapeHTML(voucherCode)}${_span}                \x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-left:6px;flex-shrink:0;" class="tg-df-voucher-copy-icon">                  \x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2">${_rect}                  \x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1">${_path}                ${_svg}              ${_span}` : '';                            const logoHtml = logoUrl                 ? `\x3Cimg src="${this.escapeHTML(logoUrl)}" alt="${this.escapeHTML(offerName)}" class="tg-df-voucher-logo" />`                 : `\x3Cdiv class="tg-df-voucher-logo" style="background:#e2e8f0;">${_div}`;                            let expiryHtml = '';              if (endTime) {                let dStr = endTime;                if (!isNaN(dStr) && String(dStr).length === 10) dStr = Number(dStr) * 1000;                const d = new Date(dStr);                if (!isNaN(d.getTime())) {                  const options = { year: 'numeric', month: 'short', day: 'numeric' };                  expiryHtml = `                    \x3Cdiv class="tg-df-voucher-expiry">                      \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">                        \x3Ccircle cx="12" cy="12" r="10">${_circle}                        \x3Cpolyline points="12 6 12 12 16 14">${_polyline}                      ${_svg}                      Expires ${d.toLocaleDateString(undefined, options)}                    ${_div}`;                }              }              const revenueIdVal = generateRevenueId(linkUrl, offerName, merchantName, null);              const rewrittenLinkUrl = rewriteAffiliateLink(linkUrl, area, revenueIdVal);              return `                \x3Ca href="${this.escapeHTML(rewrittenLinkUrl)}" target="_blank" rel="noopener nofollow" class="tg-df-voucher-item"                  data-action="voucher-click"                  data-product-name="${this.escapeHTML(offerName)}"                  data-merchant-name="${this.escapeHTML(merchantName)}"                  data-analytics-id="${this.escapeHTML(offerObj.offer_id || offerObj.id || v.id || '')}"                  data-price=""                  data-previous-price=""                  data-original-link="${this.escapeHTML(linkUrl)}"                  data-revenue-id="${revenueIdVal}"                  data-index="${idx}"                  data-total="${offers.length}"                  data-in-stock="true"                  data-currency="USD"                  data-model-id="${this.escapeHTML(offerObj.model_id || v.model_id || offerObj.id || v.id || '')}"                  data-merchant-id="${this.escapeHTML(offerObj.merchant_id || offerObj.merchant?.id || '')}"                >                  ${logoHtml}                  \x3Cdiv class="tg-df-voucher-content">                    \x3Ch4 class="tg-df-voucher-title">${this.escapeHTML(offerName)}${_h4}                    ${codeHtml}                    ${expiryHtml}                  ${_div}                ${_a}              `;            }).join('');                        // Attach copy functionality            const copyBtns = content.querySelectorAll('[data-action="copy-code"]');            copyBtns.forEach(btn => {              btn.addEventListener('click', async (e) => {                e.preventDefault();                e.stopPropagation();                                const code = btn.getAttribute('data-code');                if (!code) return;                                try {                  const copyToClipboard = async (text) => {                     if (window.navigator.clipboard && window.isSecureContext) {                        try { await window.navigator.clipboard.writeText(text); return; } catch (e) {}                     }                     const textArea = document.createElement("textarea");                     textArea.value = text;                     textArea.style.position = "fixed";                     document.body.appendChild(textArea);                     textArea.focus();                     textArea.select();                     document.execCommand('copy');                     textArea.remove();                  };                  await copyToClipboard(code);                                    // Visual feedback                  btn.classList.add('copied');                  const textSpan = btn.querySelector('.tg-df-voucher-code-text');                  const iconSvg = btn.querySelector('.tg-df-voucher-copy-icon');                                    const origText = textSpan.innerText;                  const origIcon = iconSvg.innerHTML;                                    textSpan.innerText = 'Copied!';                  iconSvg.innerHTML = `\x3Cpolyline points="20 6 9 17 4 12">${_polyline}`;                                    setTimeout(() => {                    if (btn) {                      btn.classList.remove('copied');                      if (textSpan) textSpan.innerText = origText;                      if (iconSvg) iconSvg.innerHTML = origIcon;                    }                  }, 2000);                                    trackElementInteraction({                    id: 'voucher-code-copy',                    name: 'Copy Voucher Code',                    label: `Copied ${code} for ${merchantName}`                  });                } catch (err) {                  console.warn('Failed to copy text: ', err);                }              });            });            // Attach voucher click tracking            const voucherBtns = content.querySelectorAll('[data-action="voucher-click"]');            voucherBtns.forEach(btn => {              btn.addEventListener('click', (e) => {                if (e.target.closest('[data-action="copy-code"]')) return;                                const productName = btn.getAttribute('data-product-name');                const merchantNameAttr = btn.getAttribute('data-merchant-name');                const productId = btn.getAttribute('data-analytics-id');                const price = parseFloat(btn.getAttribute('data-price')) || null;                const prevPriceStr = btn.getAttribute('data-previous-price');                const previousPrice = prevPriceStr ? parseFloat(prevPriceStr) : null;                const originalLink = btn.getAttribute('data-original-link');                const rewrittenLink = btn.getAttribute('href');                const revenueId = btn.getAttribute('data-revenue-id');                const index = parseInt(btn.getAttribute('data-index'), 10) || 0;                const inStock = btn.getAttribute('data-in-stock') === 'true';                const totalText = btn.getAttribute('data-total');                const totalDeals = parseInt(totalText, 10) || 0;                const productCategoryName = 'deals';                const trackingParams = {                  widgetId: this.widgetId,                  productCategoryName: productCategoryName,                  product: {                    modelId: btn.getAttribute('data-model-id') || null,                    matchId: btn.getAttribute('data-match-id') || null,                    brand: btn.getAttribute('data-model-brand') || null,                    parent: btn.getAttribute('data-model-parent') || null,                    name: productName,                    price: price,                    previousPrice: previousPrice,                    link: rewrittenLink,                    originalLink: originalLink,                    inStock: inStock                  },                  zeroBasedProductIndexOrNull: index,                  totalDealsOrProducts: totalDeals,                   merchant: {                    id: btn.getAttribute('data-merchant-id') || null,                    network: btn.getAttribute('data-merchant-network') || null,                    url: btn.getAttribute('data-merchant-url') || null,                    name: merchantNameAttr                  },                  revenueId: revenueId,                  widgetTypeName: this.widgetTypeName,                  isoCurrencyCode: btn.getAttribute('data-currency') || 'USD'                };                if (typeof trackDealClick === 'function') {                  trackDealClick(trackingParams);                }              });            });                                  } catch (e) {            console.warn(e);            content.innerHTML = `\x3Cdiv class="tg-df-message">Failed to load vouchers.${_div}`;          }        }        render() {          try {            if (this.getViewMode() === 'savings_squad' && this.airedaleTags.length > 0) {              if (this.categoryFilterWrapper) {                 this.categoryFilterWrapper.style.display = 'flex';              }              if (this.categoryFilter) {                 const _option = '<' + '/option>';                 let optionsHtml = `\x3Coption value="all">All Categories${_option}`;                 this.airedaleTags.forEach(tag => {                    const isSelected = this.activeDealTag === tag ? 'selected' : '';                    optionsHtml += `\x3Coption value="${this.escapeHTML(tag)}" ${isSelected}>${this.escapeHTML(tag)}${_option}`;                 });                 this.categoryFilter.innerHTML = optionsHtml;                 this.categoryFilter.value = this.activeDealTag || 'all';              }            } else {               if (this.categoryFilterWrapper) {                  this.categoryFilterWrapper.style.display = 'none';               }            }            const displayDeals = this.getFilteredDeals();          // HACK: Hide closing tags from the CMS HTML sanitizer so it doesn't strip them during in-page injection          const _div = '<' + '/div>';          const _span = '<' + '/span>';          const _a = '<' + '/a>';          const _h3 = '<' + '/h3>';          const _p = '<' + '/p>';          const _strong = '<' + '/strong>';          const _sup = '<' + '/sup>';          const _button = '<' + '/button>';          if (displayDeals.length === 0) {            if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {              if (this.deals.length > 0) {                 this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                  No deals match your selected filters.                ${_div}`;              } else if (this.getViewMode() === 'savings_squad' && this.currentQuery.length <= 2) {                 // Do not show "no exact matches" if query is empty for savings_squad                 this.grid.innerHTML = '';              } else {                 this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                  No exact matches found for "\x3Cstrong>${this.escapeHTML(this.currentQuery)}${_strong}". Try adjusting your search term.                ${_div}`;              }            } else {              this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                Search product or category names to discover the best deals from across the web.              ${_div}`;            }            return;          }          let dealsHtml = displayDeals.slice(0, this.displayLimit).map((deal, index) => {            try {               const currencySym = this.escapeHTML(deal.currency);               const isoCurrencyCode = normalizeCurrency(currencySym);               const escapedPrice = this.escapeHTML(deal.price);               const escapedMsrp = this.escapeHTML(deal.msrp);               const areaCode = this.getAreaCode();                              const revenueId = generateRevenueId(deal.url, deal.title, deal.merchant, null);               const originalLink = deal.url;               const rewrittenLink = rewriteAffiliateLink(deal.url, areaCode, revenueId);                        const productCategoryName = 'deals';            const dataAttr = `              data-action="${deal.isCheckPrice ? 'view-similar-click' : 'deal-click'}"              data-analytics-id="${this.escapeHTML(deal.externalProductId || deal.id || '')}"              data-product-name="${this.escapeHTML(deal.title)}"              data-merchant-name="${this.escapeHTML(deal.merchant)}"              data-price="${deal.rawPrice || ''}"              data-previous-price="${deal.rawMsrp || ''}"              data-original-link="${this.escapeHTML(originalLink)}"              data-revenue-id="${revenueId}"              data-index="${index}"              data-total="${displayDeals.length}"              data-in-stock="${deal.inStock !== false}"              data-currency="${this.escapeHTML(isoCurrencyCode)}"              data-model-id="${this.escapeHTML(deal.modelId || '')}"              data-product-key="${this.escapeHTML(deal.productKey || '')}"              data-merchant-id="${this.escapeHTML(deal.merchantId || '')}"            `;                        let priceGroupHtml = '';            let isSavingsSquadMode = this.getViewMode() === 'savings_squad';            let ctaText = 'View Deal';            let formattedPrice = '';            let msrpHtml = '';                        if (deal.isCheckPrice) {              ctaText = 'View Deal';              if (isSavingsSquadMode) {                priceGroupHtml = ``;              } else {                priceGroupHtml = `                  \x3Cdiv class="tg-df-card-price-group">                    \x3Cspan class="tg-df-card-price" style="font-size: 15px; font-weight: 500; font-style: italic;">See price at retailer${_span}                  ${_div}                `;              }            } else {              // Format Price              formattedPrice = escapedPrice.includes(currencySym)                 ? escapedPrice                 : `${currencySym}${escapedPrice}`;                              // Format MSRP              msrpHtml = deal.msrp && deal.rawMsrp > deal.rawPrice                ? `\x3Cspan class="tg-df-card-msrp">${escapedMsrp.includes(currencySym) ? escapedMsrp : currencySym + escapedMsrp}${_span}`                : '';                              priceGroupHtml = isSavingsSquadMode ? `` : `                \x3Cdiv class="tg-df-card-price-group">                  \x3Cspan class="tg-df-card-price">${formattedPrice}${_span}                  ${msrpHtml}                ${_div}              `;            }                        const discountBadgeHtml = deal.savingLabel && !deal.isCheckPrice              ? `\x3Cspan class="tg-df-card-discount-badge">${this.escapeHTML(deal.savingLabel)}${_span}`              : '';                          // HACK for CMS            const _button = '<' + '/button>';            const _svg = '<' + '/svg>';            const _path = '<' + '/path>';            const _rect = '<' + '/rect>';            const _circle = '<' + '/circle>';            const _polyline = '<' + '/polyline>';            const _line = '<' + '/line>';                        let badgesHtml = '';            const primeBadge = deal.isPrime ? `              \x3Cspan class="tg-df-tag tg-df-tag-prime">                \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="currentColor">                  \x3Cpath d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z">${_path}                ${_svg} Prime              ${_span}            ` : '';                        const couponsBadge = deal.merchant && deal.merchant.toLowerCase().includes('amazon') ? '' : `              \x3Cdiv class="tg-df-coupon-wrapper" data-merchant="${this.escapeHTML(deal.merchant)}" style="display:inline-flex; align-items:center;">                \x3Cdiv class="tg-df-coupon-spinner">${_div}                \x3Cbutton type="button" class="tg-df-tag tg-df-tag-coupons" data-action="coupons-click" data-merchant="${this.escapeHTML(deal.merchant)}" style="display:none;">                  \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">                    \x3Cpath d="M20.59 13.41l-7.17 7.17a2 2 0 0 1-2.83 0L2 12V2h10l8.59 8.59a2 2 0 0 1 0 2.82z">${_path}                    \x3Cline x1="7" y1="7" x2="7.01" y2="7">${_line}                  ${_svg} Coupons                ${_button}              ${_div}            `;                        // Note: We always add coupons badge if there's a chance, but to allow 3-line titles we check wrapper display state            badgesHtml = `              \x3Cdiv class="tg-df-card-badges">                ${primeBadge}                ${couponsBadge}              ${_div}            `;            const _linearGradient = '<' + '/linearGradient>';            const _polygon = '<' + '/polygon>';            const _stop = '<' + '/stop>';            const _defs = '<' + '/defs>';                        let starHtml = '';            if (deal.starRating) {              let rating = deal.starRating;                            if (rating > 0) {                const fullStars = Math.floor(rating);                const halfStar = (rating - fullStars) >= 0.5 ? 1 : 0;                const emptyStars = Math.max(0, 5 - fullStars - halfStar);                const blue = '#1f69ff'; // Tom's guide brand color from VIEW DEAL button                const gray = '#cbd5e1';                                const starSvgFull = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="${blue}" stroke="${blue}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26">${_polygon}${_svg}`;                                const gradId = 'half_grad_' + Math.floor(Math.random()*1000000);                const starSvgHalf = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" stroke="${blue}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cdefs>\x3ClinearGradient id="${gradId}" x1="0" x2="1" y1="0" y2="0">\x3Cstop offset="50%" stop-color="${blue}">${_stop}\x3Cstop offset="50%" stop-color="transparent">${_stop}${_linearGradient}${_defs}                  \x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26" fill="url(#${gradId})">${_polygon}${_svg}`;                                  const starSvgEmpty = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="${gray}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26">${_polygon}${_svg}`;                                let stars = [];                for (let i=0; i<fullStars; i++) stars.push(starSvgFull);                if (halfStar) stars.push(starSvgHalf);                for (let i=0; i<emptyStars; i++) stars.push(starSvgEmpty);                                starHtml = `\x3Cdiv class="tg-df-card-stars" style="display:flex;align-items:center;margin-bottom:8px;font-size:13px;font-weight:600;color:var(--tg-df-text-muted);">                  \x3Cspan style="margin-right:6px;">Tom's Guide:${_span}                  \x3Cdiv style="display:flex;gap:2px;">                    ${stars.join('')}                  ${_div}                ${_div}`;              }            }            let htmlOutput = '';            if (isSavingsSquadMode) {              htmlOutput += `              \x3Cdiv class="hawk-deal-widget-container tg-df-mobile-only" data-collapsible="true">                ${this.editorMode ? `\x3Cinput type="checkbox" class="tg-df-deal-checkbox" data-id="${this.escapeHTML(deal.id)}" ${this.selectedDeals.has(deal.id) ? 'checked' : ''} style="margin-bottom: 10px;">` : ''}                \x3Cdiv class="hawk-deal-widget-wrap">                  \x3Cdiv class="hawk-deal-widget-image-container">                    \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" rel="sponsored noopener" target="_blank" class="hawk-affiliate-link-deal-widget" ${dataAttr}>                      \x3Cimg ${deal.image ? `src="${this.escapeHTML(deal.image)}"` : ''} alt="${this.escapeHTML(deal.title)}" class="hawk-lazy-image-deal-widget" loading="lazy" width="140" height="160" onerror="${deal.fallbackImage ? `if(!this.dataset.fb) { this.dataset.fb='1'; this.src='${this.escapeHTML(deal.fallbackImage)}'; } else { this.style.opacity='0'; }` : `this.style.opacity='0';`}">                    ${_a}                  ${_div}                  \x3Cdiv class="hawk-deal-widget-text-cta-container">                    \x3Cdiv class="hawk-deal-widget-text-body-container">                      \x3Cdiv class="hawk-deal-widget-text-body-main">                        \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                          ${deal.isCheckPrice ? `                            \x3Cspan class="hawk-deal-widget-title-product-title">${this.escapeHTML(deal.title)}${_span}                          ` : `                            \x3Cspan class="hawk-deal-widget-title-product-title">${deal.brand ? this.escapeHTML(deal.brand) + ' ' : ''}${this.escapeHTML(deal.productName || deal.title || '')}:${_span}                          `}                        ${_a}                        ${!deal.isCheckPrice && deal.rawMsrp && deal.rawMsrp > deal.rawPrice ? `                          \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                            \x3Cspan class="hawk-deal-widget-title-was-price">was ${currencySym}${escapedMsrp}${_span}                          ${_a}                        ` : ''}                        \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                          \x3Cspan class="hawk-deal-widget-title-retailer-price">                            ${!deal.isCheckPrice ? `                              \x3Cspan class="hawk-deal-widget-title-price">now ${formattedPrice}${_span}                              \x3Cspan class="hawk-deal-widget-title-retailer"> at ${this.escapeHTML(deal.merchant)}${_span}                            ` : `                              \x3Cspan class="hawk-deal-widget-title-price">See price at ${this.escapeHTML(deal.merchant)}${_span}                            `}                          ${_span}                        ${_a}                        ${deal.description ? `\x3Cdiv class="hawk-deal-widget-text-body-description tg-df-card-desc-container" style="margin-bottom: 12px; position: relative;">                          \x3Cp class="tg-df-card-desc-content" style="font-size: 13px; color: var(--tg-df-text-muted); margin-bottom: 0; line-height: 1.4; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;">${this.escapeHTML(deal.description)}${_p}                          \x3Cbutton type="button" class="tg-df-card-desc-btn" style="display: none; appearance: none; border: none; color: #000000; font-size: 11px; font-weight: 700; text-transform: uppercase; cursor: pointer; font-family: inherit; position: absolute; bottom: 2px; right: 0; background: linear-gradient(to right, transparent, #fff 20%, #fff); padding: 0 0 0 16px;" onclick="                            var c = this.parentNode;                            if (this.dataset.expanded === 'true') {                              var pd = (c.tagName === 'P') ? c : this.previousElementSibling;                              if (c.tagName === 'P') { c.parentNode.appendChild(this); pd = c; }                              pd.style.display = '-webkit-box';                              pd.style.webkitLineClamp = '3';                              this.textContent = 'READ MORE';                              this.style.position = 'absolute';                              this.style.background = 'linear-gradient(to right, transparent, #fff 20%, #fff)';                              this.style.paddingLeft = '16px';                              this.dataset.expanded = 'false';                            } else {                              var pd = this.previousElementSibling;                              pd.style.display = 'inline';                              pd.style.webkitLineClamp = 'unset';                              this.textContent = 'READ LESS';                              this.style.position = 'static';                              this.style.background = 'transparent';                              this.style.paddingLeft = '4px';                              this.dataset.expanded = 'true';                              pd.appendChild(this);                            }                          ">READ MORE${_button}                        \x3C/div>` : ''}                      ${_div}                    ${_div}                    ${deal.authorName ? `                      \x3Cdiv class="tg-df-author-line-mobile" style="padding: 0 0 12px 0; background: transparent;">                         \x3Cdiv style="display: flex; align-items: center; gap: 12px;">                            ${deal.authorImage ? `\x3Cimg src="${this.escapeHTML(deal.authorImage)}" alt="${this.escapeHTML(deal.authorName)}" class="tg-df-author-img" width="40" height="40" style="border-radius: 50%; object-fit: cover; flex-shrink: 0; aspect-ratio: 1 / 1; min-width: 40px; min-height: 40px;">` : ''}                            \x3Cdiv style="display: flex; flex-direction: column;">                               \x3Cdiv style="font-size: 10px; color: var(--tg-df-text-muted); text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 2px; font-weight: 600;">\x3Cspan style="color: #FF6600;">${this.escapeHTML(deal.merchant)}${_span} deal recommended by:${_div}                               \x3Cdiv style="font-size: 11px; color: var(--tg-df-text); line-height: 1.3;">                                  \x3Cstrong>\x3Ca href="https://www.tomsguide.com/${this.escapeHTML(deal.documentUrl || '').replace(/^\/+/, '')}" target="_blank" rel="noopener nofollow" style="text-decoration: none; color: inherit; border-bottom: 1px dotted var(--tg-df-text-muted);">${this.escapeHTML(deal.authorName)}${_a}${_strong}                                  ${deal.authorRole && !['null', 'nul', 'undefined'].includes(String(deal.authorRole).toLowerCase()) ? ` • ${this.escapeHTML(deal.authorRole)}` : ''}                                  ${deal.modifiedDate ? `\x3Cdiv style="color: var(--tg-df-text-muted); margin-top: 2px;">${getTimeAgo(deal.modifiedDate)}${_div}` : ''}                               ${_div}                            ${_div}                         ${_div}                      ${_div}                    ` : ''}                    \x3Cdiv class="hawk-deal-widget-footer">                      \x3Cdiv class="hawk-deal-widget-button-wrapper">                        \x3Cdiv class="hawk-deal-widget-preferred-partner-wrapper">                          \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-deal-button" rel="sponsored noopener" target="_blank" ${dataAttr}>                            \x3Cspan>View Deal${_span}                          ${_a}                        ${_div}                      ${_div}                    ${_div}                  ${_div}                ${_div}              ${_div}              `;            }            htmlOutput += `              \x3Cdiv class="tg-df-card ${isSavingsSquadMode ? 'tg-df-desktop-only' : ''}">                ${this.editorMode ? `\x3Cinput type="checkbox" class="tg-df-deal-checkbox" data-id="${this.escapeHTML(deal.id)}" ${this.selectedDeals.has(deal.id) ? 'checked' : ''}>` : ''}                \x3Cdiv class="tg-df-card-image-box">                  ${discountBadgeHtml}                  \x3Ca href="${this.escapeHTML(rewrittenLink)}" ${dataAttr} target="_blank" rel="noopener nofollow" style="display: flex; align-items: center; justify-content: center; width: 100%; height: 100%;">                    \x3Cimg ${deal.image ? `src="${this.escapeHTML(deal.image)}"` : ''} alt="${this.escapeHTML(deal.title)}" class="tg-df-card-image" loading="lazy" onerror="${deal.fallbackImage ? `if(!this.dataset.fb) { this.dataset.fb='1'; this.src='${this.escapeHTML(deal.fallbackImage)}'; } else { this.style.opacity='0'; }` : `this.style.opacity='0';`}">                  ${_a}                  \x3Cdiv class="tg-df-card-merchant-wrapper" style="position: absolute; bottom: 0; right: 0; background: transparent; padding: 8px 12px; z-index: 10;">                     \x3Cspan class="tg-df-card-merchant-pill" style="text-align: right; margin-bottom: 0;" title="${this.escapeHTML(deal.merchant)}">${this.escapeHTML(deal.merchant)}${_span}                  ${_div}                ${_div}                \x3Cdiv class="tg-df-card-body">                  ${starHtml}                  ${badgesHtml}                  \x3Ch3 class="tg-df-card-title tg-df-custom-savings-squad-title" title="${this.escapeHTML(deal.title)}">                    \x3Ca href="${this.escapeHTML(rewrittenLink)}" disable-tracking="true" target="_blank" rel="noopener nofollow" style="text-decoration: none; color: inherit;">                      ${isSavingsSquadMode                         ? (deal.isCheckPrice                             ? (deal.title && deal.title.includes(':')                                 ? `\x3Cstrong>${this.escapeHTML(deal.title.substring(0, deal.title.indexOf(':') + 1))}${_strong}\x3Cspan style="color: #1f69ff; font-weight: normal;">${this.escapeHTML(deal.title.substring(deal.title.indexOf(':') + 1))}${_span}`                                : this.escapeHTML(deal.title)                              )                             : `\x3Cstrong>${deal.brand ? this.escapeHTML(deal.brand) + ' ' : ''}${this.escapeHTML(deal.productName || deal.title || '')}:${_strong} ${deal.rawMsrp && deal.rawMsrp > deal.rawPrice ? `\x3Cspan style="color: #d0021b; text-decoration: line-through; font-weight: normal; margin-right: 4px;">was ${currencySym}${escapedMsrp}${_span} ` : ''}\x3Cspan style="color: #1f69ff; font-weight: normal;">now ${formattedPrice} at ${this.escapeHTML(deal.merchant)}${_span}`                          )                        : this.escapeHTML(deal.title)                      }                    ${_a}                  ${_h3}                  ${deal.description ? `\x3Cdiv class="tg-df-card-desc-container" style="margin-bottom: 12px; position: relative;">                    \x3Cp class="tg-df-card-desc-content" style="font-size: 13px; color: var(--tg-df-text-muted); margin-bottom: 0; line-height: 1.4; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;">${this.escapeHTML(deal.description)}${_p}                    \x3Cbutton type="button" class="tg-df-card-desc-btn" style="display: none; appearance: none; border: none; color: #000000; font-size: 11px; font-weight: 700; text-transform: uppercase; cursor: pointer; font-family: inherit; position: absolute; bottom: 2px; right: 0; background: linear-gradient(to right, transparent, #fff 20%, #fff); padding: 0 0 0 16px;" onclick="                      var c = this.parentNode;                      if (this.dataset.expanded === 'true') {                        var pd = (c.tagName === 'P') ? c : this.previousElementSibling;                        if (c.tagName === 'P') { c.parentNode.appendChild(this); pd = c; }                        pd.style.display = '-webkit-box';                        pd.style.webkitLineClamp = '3';                        this.textContent = 'READ MORE';                        this.style.position = 'absolute';                        this.style.background = 'linear-gradient(to right, transparent, #fff 20%, #fff)';                        this.style.paddingLeft = '16px';                        this.dataset.expanded = 'false';                      } else {                        var pd = this.previousElementSibling;                        pd.style.display = 'inline';                        pd.style.webkitLineClamp = 'unset';                        this.textContent = 'READ LESS';                        this.style.position = 'static';                        this.style.background = 'transparent';                        this.style.paddingLeft = '4px';                        this.dataset.expanded = 'true';                        pd.appendChild(this);                      }                    ">READ MORE${_button}                  \x3C/div>` : ''}                  \x3Cdiv class="tg-df-card-footer">                    ${deal.authorName ? `                    \x3Cdiv class="tg-df-author-line-desktop" style="padding: 0 0 ${isSavingsSquadMode ? 0 : 12}px 0;">                       \x3Cdiv style="display: flex; align-items: center; gap: 10px;">                          ${deal.authorImage ? `\x3Cimg src="${this.escapeHTML(deal.authorImage)}" alt="${this.escapeHTML(deal.authorName)}" class="tg-df-author-img" width="36" height="36" style="border-radius: 50%; object-fit: cover; flex-shrink: 0; aspect-ratio: 1 / 1; min-width: 36px; min-height: 36px;">` : ''}                          \x3Cdiv style="display: flex; flex-direction: column;">                             \x3Cdiv style="font-size: 10px; color: var(--tg-df-text-muted); text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 2px; font-weight: 600;">Recommended by:${_div}                             \x3Cdiv style="font-size: 11px; color: var(--tg-df-text); line-height: 1.2;">                                \x3Cstrong>\x3Ca href="https://www.tomsguide.com/${this.escapeHTML(deal.documentUrl || '').replace(/^\/+/, '')}" target="_blank" rel="noopener nofollow" style="text-decoration: none; color: inherit; border-bottom: 1px dotted var(--tg-df-text-muted);">${this.escapeHTML(deal.authorName)}${_a}${_strong}                                ${deal.authorRole && !['null', 'nul', 'undefined'].includes(String(deal.authorRole).toLowerCase()) ? ` • ${this.escapeHTML(deal.authorRole)}` : ''}                                ${deal.modifiedDate ? `\x3Cspan style="color: var(--tg-df-text-muted);"> • ${getTimeAgo(deal.modifiedDate)}${_span}` : ''}                             ${_div}                          ${_div}                       ${_div}                    ${_div}                    ` : ''}                    ${priceGroupHtml}                  ${_div}                ${_div}                \x3Ca href="${this.escapeHTML(rewrittenLink)}" ${dataAttr} target="_blank" rel="noopener nofollow" class="tg-df-card-cta" style="text-decoration: none; border-radius: 0;">${ctaText}${_a}              ${_div}            `;                        return htmlOutput;            } catch (e) {               console.log("Error rendering deal in map for index", index, typeof deal === 'object' ? JSON.stringify(deal) : deal, "MSG:", e.message);               return '';            }          }).join('');                    if (displayDeals.length > this.displayLimit) {            dealsHtml += `              \x3Cdiv style="width: 100%; display: flex; justify-content: center; margin-top: 16px; grid-column: 1 / -1;">                \x3Cbutton type="button" class="tg-df-tag-outline tg-df-load-more" style="padding: 8px 24px; border-radius: 100px; font-weight: 600; font-size: 14px; cursor: pointer;">Load More${_button}              ${_div}            `;          }                    this.grid.innerHTML = dealsHtml;          // Inject JSON-LD          try {            let targetNode = this.hostContainer || document.head;            let jsonLdScript = targetNode.querySelector('#tg-df-json-ld-' + this.widgetId);            if (!jsonLdScript) {                jsonLdScript = document.createElement('script');                jsonLdScript.type = 'application/ld+json';                jsonLdScript.id = 'tg-df-json-ld-' + this.widgetId;                targetNode.appendChild(jsonLdScript);            }            const jsonLdData = {              "@context": "https://schema.org",              "@type": "ItemList",              "itemListElement": displayDeals.slice(0, this.displayLimit).map((deal, index) => {                 let isoCurrency = "USD";                 if (deal.currency === '£') isoCurrency = "GBP";                 else if (deal.currency === '€') isoCurrency = "EUR";                 else if (deal.currency === 'A$') isoCurrency = "AUD";                 else if (deal.currency === 'CA$') isoCurrency = "CAD";                 const areaCode = typeof this.getAreaCode === 'function' ? this.getAreaCode() : 'US';                 const revenueId = typeof generateRevenueId === 'function' ? generateRevenueId(deal.url, deal.title, deal.merchant, null) : '';                 const rewrittenLink = typeof rewriteAffiliateLink === 'function' ? rewriteAffiliateLink(deal.url, areaCode, revenueId) : deal.url;                 return {                   "@type": "ListItem",                   "position": index + 1,                   "item": {                     "@type": "Product",                     "name": deal.title,                     "image": deal.image || "",                     "description": deal.description || "",                     "brand": {                       "@type": "Brand",                       "name": deal.brand || ""                     },                     "offers": {                       "@type": "Offer",                       "priceCurrency": isoCurrency,                       "price": deal.rawPrice || 0,                       "url": rewrittenLink,                       "seller": {                         "@type": "Organization",                         "name": deal.merchant || ""                       }                     }                   }                 };              }).filter(item => item.item.name)            };            jsonLdScript.textContent = JSON.stringify(jsonLdData);          } catch(e) { console.warn("JSON-LD generation failed", e); }          setTimeout(() => {            const contents = this.root.querySelectorAll('.tg-df-card-desc-content');            contents.forEach(p => {              if (p.scrollHeight > p.clientHeight || p.scrollHeight > 60) {                if (p.nextElementSibling) {                  p.nextElementSibling.style.display = 'block';                }              }            });                        // Allow hawklinks.js to discover and rewrite our widget links             // by appending the .article-body class and manually triggering processArticle.            let container = this.root.classList.contains('tg-df-container') ? this.root : this.root.querySelector('.tg-df-container');            if (container && !container.classList.contains('article-body')) {               container.classList.add('article-body');            }            if (this.grid && !this.grid.classList.contains('article-body')) this.grid.classList.add('article-body');            document.dispatchEvent(new CustomEvent('processArticle', { detail: { element: this.root } }));          }, 50);          const loadMoreBtn = this.grid.querySelector('.tg-df-load-more');          if (loadMoreBtn) {            loadMoreBtn.addEventListener('click', () => {              if (typeof trackElementInteraction === 'function') {                trackElementInteraction({ id: 'load-more', name: 'Load more', label: 'Load More Results' });              }              this.displayLimit += this.getRowsLimit();              this.render();            });          }                      this.bindCouponButtons();            this.checkAndUpdateCoupons();          } catch(e) {            console.warn("Widget render error", e);          }        }                async checkAndUpdateCoupons() {          const wrappers = Array.from(this.root.querySelectorAll('.tg-df-coupon-wrapper'));          if (wrappers.length === 0) return;                    const merchants = [...new Set(wrappers.map(w => w.getAttribute('data-merchant')).filter(Boolean))];          if (merchants.length === 0) return;          const couponResultsMap = await this.checkMerchantsCouponsBulk(merchants);                    for (const merchant of merchants) {            const hasCoupons = !!couponResultsMap[merchant];            const merchantWrappers = wrappers.filter(w => w.getAttribute('data-merchant') === merchant);            merchantWrappers.forEach(wrapper => {              const spinner = wrapper.querySelector('.tg-df-coupon-spinner');              const btn = wrapper.querySelector('.tg-df-tag-coupons');                            if (spinner) spinner.style.display = 'none';                            if (hasCoupons && btn) {                btn.style.display = 'inline-flex';              } else if (!hasCoupons) {                wrapper.style.display = 'none';              }            });          }        }        updateFloatingCopyBar() {          if (!this.editorBar || !this.editorSelectedCount) return;          if (this.editorMode && this.selectedDeals.size > 0) {            this.editorBar.style.display = 'flex';            this.editorSelectedCount.innerText = this.selectedDeals.size;          } else {            this.editorBar.style.display = 'none';          }        }        async copySelectedDealsToCMS() {           function htmlToSlate(htmlString) {              if (!htmlString) return [{ type: 'paragraph', children: [{ text: '' }] }];              let doc;              if (typeof window !== 'undefined' && window.DOMParser) {                 doc = new DOMParser().parseFromString(htmlString, 'text/html');              } else {                 doc = document.implementation.createHTMLDocument('');                 doc.body.innerHTML = htmlString;              }                            function parseNode(node, marks = {}) {                  if (node.nodeType === 3) {                      const text = node.textContent;                      if (!text) return null;                      return { text: text, ...marks };                  }                  if (node.nodeType === 1) {                      const tagName = node.tagName.toLowerCase();                      if (tagName === 'br') {                          return { type: 'line-break', children: [{ text: '' }] };                      }                      if (tagName === 'p') {                          let children = Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                          if (children.length === 0) children.push({ text: "" });                          return { type: 'paragraph', children };                      }                      if (tagName === 'strong' || tagName === 'b') {                          const newMarks = { ...marks, bold: true };                          return Array.from(node.childNodes).map(child => parseNode(child, newMarks)).flat().filter(Boolean);                      }                      if (tagName === 'em' || tagName === 'i') {                          const newMarks = { ...marks, italic: true };                          return Array.from(node.childNodes).map(child => parseNode(child, newMarks)).flat().filter(Boolean);                      }                      if (tagName === 'a') {                          const href = node.getAttribute('href') || '';                          let children = Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                          if (children.length === 0) children.push({ text: "" });                          return {                              type: 'link',                              url: href,                              isNoFollow: (node.getAttribute('rel') || '').includes('nofollow'),                              isSponsored: (node.getAttribute('rel') || '').includes('sponsored'),                              isOpenNewTab: node.getAttribute('target') === '_blank',                              isPreventDataRewrite: false,                              children: children                          };                      }                      return Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                  }                  return null;              }                            let blocksArray = [];              let currentParagraphChildren = [];              function flushParagraph() {                  if (currentParagraphChildren.length > 0) {                      blocksArray.push({ type: 'paragraph', children: currentParagraphChildren });                      currentParagraphChildren = [];                  }              }              Array.from(doc.body.childNodes).forEach(node => {                  const parsed = parseNode(node, {});                  const parsedItems = Array.isArray(parsed) ? parsed : (parsed ? [parsed] : []);                  parsedItems.forEach(item => {                      if (item.type === 'paragraph') {                          flushParagraph();                          blocksArray.push(item);                      } else {                          currentParagraphChildren.push(item);                      }                  });              });              flushParagraph();              if (blocksArray.length === 0) {                  blocksArray = [{ type: 'paragraph', children: [{ text: '' }] }];              }              return blocksArray;           }           const blocks = [];                      this.editorCopyBtn.innerHTML = '\x3Cspan class="tg-df-coupon-spinner" style="display:inline-block; margin-right:8px; border-top-color:#fff;">' + '<' + '/span> Copying...';           for (const deal of Array.from(this.selectedDeals.values())) {              const url = deal.url;              const merchant = deal.merchant;              const title = deal.title;              const image = deal.image;              const currentPrice = deal.currency + deal.rawPrice;              const wasPrice = deal.hasWasPrice && deal.rawMsrp > deal.rawPrice ? deal.currency + deal.rawMsrp : '';                            let couponsChildren = [];              try {                  const area = this.getAreaCode();                  const apiUrl = new URL('https://search-api.fie.future.net.uk/widget.php');                  apiUrl.searchParams.append('model_name', 'Everything');                  apiUrl.searchParams.append('language', 'en-GB');                  apiUrl.searchParams.append('area', area);                  apiUrl.searchParams.append('combine_product_types', '1');                  apiUrl.searchParams.append('filter_merchant_name', merchant);                  apiUrl.searchParams.append('all_filters', 'false');                  apiUrl.searchParams.append('exclude_unlabelled', 'false');                  apiUrl.searchParams.append('include_specs', 'false');                  apiUrl.searchParams.append('sort', 'voucher');                  apiUrl.searchParams.append('distinct_merchants', 'natural');                  apiUrl.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');                  apiUrl.searchParams.append('rows', '3');                  apiUrl.searchParams.append('origin', 'widgets-clientside');                                    let res; try { res = await fetch(apiUrl.toString()); } catch (e) { return; }                  if (res.ok) {                      const data = await res.json();                      let offers = [];                      if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {                        offers = data.widget.data.offers;                      } else if (data && data.data && Array.isArray(data.data.offers)) {                        offers = data.data.offers;                      }                                            if (offers.length > 0) {                          couponsChildren.push({ text: "Also check out these coupons: ", bold: true });                          offers.slice(0, 3).forEach((offer, idx) => {                              const actualOffer = offer.offer || offer;                              const offerName = actualOffer.name || actualOffer.title || offer.model_name || offer.title || offer.name || 'Coupon';                              const linkUrl = actualOffer.link || actualOffer.url || actualOffer.offer_link || '#';                              couponsChildren.push({ type: "line-break", children: [{ text: "" }] });                              couponsChildren.push({ text: "🎟️ " });                              couponsChildren.push({                                  type: "link",                                  url: linkUrl,                                  isNoFollow: true,                                  isSponsored: false,                                  isOpenNewTab: true,                                  isPreventDataRewrite: false,                                  children: [{ text: offerName, bold: true }]                              });                          });                      }                  }              } catch (err) {                  console.warn('Failed to fetch coupons for', merchant, err);              }              let descriptionValue = [];              if (deal.text) {                 descriptionValue = htmlToSlate(deal.text);              } else {                 const dealDescriptions = [                   `Don't miss out on this fantastic deal for the ${title}. It is currently available at ${merchant} for a highly competitive price.`,                   `We've spotted an excellent price drop on the ${title}. Grab it now at ${merchant} before it's gone.`,                   `The ${title} is currently seeing a generous discount over at ${merchant}. This is a perfect time to buy if you've been holding out.`,                   `If you're in the market for the ${title}, ${merchant} has just the deal for you.`,                   `Score the ${title} for less at ${merchant} right now. This is a rare chance to save big.`,                   `Upgrade your setup with the ${title}, now available at a stellar price via ${merchant}.`                 ];                 const randomDescription = dealDescriptions[Math.floor(Math.random() * dealDescriptions.length)];                 descriptionValue = [                    { type: "paragraph", children: [{ text: randomDescription }] }                 ];              }                            if (couponsChildren.length > 0) {                 let lastBlock = descriptionValue[descriptionValue.length - 1];                 if (lastBlock && lastBlock.type === 'paragraph') {                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children.push({ text: "Also check out these coupons: ", bold: true });                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children = lastBlock.children.concat(couponsChildren);                 } else {                     descriptionValue.push({                         type: "paragraph",                         children: [                             { type: "line-break", children: [{ text: "" }] },                             { type: "line-break", children: [{ text: "" }] },                             { text: "Also check out these coupons: ", bold: true },                             { type: "line-break", children: [{ text: "" }] },                             ...couponsChildren                         ]                     });                 }              }              function normalizeCurrencyToISO(symbol) {                const map = { '£': 'GBP', '$': 'USD', 'A$': 'AUD', 'CA$': 'CAD', '€': 'EUR' };                return map[symbol] || symbol;              }              const isoCurrency = normalizeCurrencyToISO(deal.currency);              blocks.push({                 id: (window.crypto && window.crypto.randomUUID) ? window.crypto.randomUUID() : 'cms-' + Date.now() + Math.random(),                 blockTypeName: "deal",                 excludeFrom: [],                 collapsible: false,                 props: {                    description: {                       value: descriptionValue,                       touched: false,                       validationMessage: ""                    },                    image: {                       value: {                          credit: [{ type: "paragraph", children: [{ text: merchant }] }],                          dateCreated: Date.now(),                          dateModified: Date.now(),                          distribution: [],                          fileSize: 0,                          height: 1000,                          id: deal.id,                          imageRights: "",                          src: image,                          name: title + ".jpg",                          tags: [],                          width: 1000                       },                       touched: false,                       validationMessage: ""                    },                    showDealButton: { value: true, touched: false, validationMessage: "" },                    isPreferredPartner: { value: false, touched: false, validationMessage: "" },                    linkHref: { value: url, touched: false, validationMessage: "" },                    linkLabel: { value: "", touched: false, validationMessage: "" },                    linkIsNoFollow: { value: true, touched: false, validationMessage: "" },                    linkIsSponsored: { value: false, touched: false, validationMessage: "" },                    linkIsOpenNewWindow: { value: true, touched: false, validationMessage: "" },                    customPromoFlags: { value: [], touched: false, validationMessage: "" },                    showStarDeal: { value: false, touched: false, validationMessage: "" },                    savingType: { value: "none", touched: false, validationMessage: "" },                    starDealPromoFlag: { value: "", touched: false, validationMessage: "" },                    showEditorsChoice: { value: false, touched: false, validationMessage: "" },                    editorsChoiceTitle: { value: "", touched: false, validationMessage: "" },                    hawkPriceCurrency: { value: { value: isoCurrency, label: isoCurrency }, touched: false, validationMessage: "" },                    hawkPrice: { value: deal.hasWasPrice ? String(deal.rawMsrp) : String(deal.rawPrice), touched: false, validationMessage: "" },                    hawkSalePrice: { value: String(deal.rawPrice), touched: false, validationMessage: "" },                    lastCheckedPriceDate: { value: "", touched: false, validationMessage: "" },                    hawkModel: { touched: false, validationMessage: "" },                    productId: { value: "", touched: false, validationMessage: "" },                    voucherId: { value: "", touched: false, validationMessage: "" },                    brand: { value: deal.brand || merchant, touched: false, validationMessage: "" },                    productName: { value: title, touched: false, validationMessage: "" },                    label: { value: "", touched: false, validationMessage: "" },                    retailer: { value: merchant, touched: false, validationMessage: "" },                    priceCheckError: false                 },                 failedFetchError: ""              });           }           const payload = {              type: "articleBuilderPages",              data: blocks           };           const jsonStr = JSON.stringify(payload);                      if (navigator.clipboard && navigator.clipboard.writeText) {              navigator.clipboard.writeText(jsonStr).then(() => {                 this.editorCopyBtn.innerHTML = 'Copied!';                 setTimeout(() => {                    this.editorCopyBtn.innerHTML = '\x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2"><' + '/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"><' + '/path><' + '/svg> Copy to CMS';                 }, 2000);              }).catch(err => {                 console.warn('Failed to copy text: ', err);                 alert('Failed to copy deals to clipboard. See console.');              });           } else {              // Fallback              const textArea = document.createElement("textarea");              textArea.value = jsonStr;              document.body.appendChild(textArea);              textArea.focus();              textArea.select();              try {                 document.execCommand('copy');                 this.editorCopyBtn.innerHTML = 'Copied!';                 setTimeout(() => {                    this.editorCopyBtn.innerHTML = '\x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2"><' + '/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"><' + '/path><' + '/svg> Copy to CMS';                 }, 2000);              } catch (err) {                 console.warn('Fallback: Oops, unable to copy', err);                 alert('Fallback: Failed to copy deals to clipboard.');              }              document.body.removeChild(textArea);           }        }      }      // Initialize the Widget      if (document.readyState === 'loading') {        document.addEventListener('DOMContentLoaded', () => new DealsFinderWidget({ rootId: 'signal-deals-finder-root', rootNode: shadowRoot, hostContainer: hostContainer }));      } else {        new DealsFinderWidget({ rootId: 'signal-deals-finder-root', rootNode: shadowRoot, hostContainer: hostContainer });      }    })();  </script></div>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ I tested De'Longhi's most expensive superautomatic espresso machine —and it's even got an app ]]></title>
                                                                                                <dc:content><![CDATA[ <p>The De’Longhi PrimaDonna Aromatic is an ambitious superautomatic coffee machine. It can make 38 drinks and is even app-compatible, so you can control it from your phone (in theory). Is this enough to make it one of the <a href="https://www.tomsguide.com/home/coffee-makers/best-espresso-machines">best espresso machines</a>?</p><p>Yes and no. The PrimaDonna Aromatic is extremely pricey, at a whopping $2,500, and I’m… not really sure why. You can get 80% of the same performance with the $1,500 De’Longhi Rivelia and — checks notes — 99.9% of the same performance with the $2,000 De’Longhi Eletta Explore. I’m not saying <em>don’t</em> get the PrimaDonna Aromatic — I’m saying you might be able to save your money without sacrificing quality here. </p><p>But, I digress. The PrimaDonna Aromatic is a fun, consistent, and functional coffee machine. Want to find out more? Keep reading this De’Longhi PrimaDonna Aromatic review. </p><h2 class="article-body__section" id="section-de-longhi-primadonna-aromatic-review-specs"><span>De'Longhi PrimaDonna Aromatic review: Specs</span></h2><div ><table><tbody><tr><td class="firstcol " ><p><strong>Price</strong></p></td><td  ><p><a href="https://www.delonghi.com/en-us/p/primadonna-aromatic-primadonna-aromatic-automatic-coffee-maker-ecam63075tm/ECAM63075TM.html" target="_blank" rel="nofollow">$2,499</a> / <a href="https://www.currys.co.uk/products/delonghi-prima-donna-aromatic-ecam630.75.tsm-smart-bean-to-cup-coffee-machine-silver-10283595.html" target="_blank" rel="nofollow">£1,549</a></p></td></tr><tr><td class="firstcol " ><p><strong>Weight</strong></p></td><td  ><p>27.7 pounds</p></td></tr><tr><td class="firstcol " ><p><strong>Dimensions</strong></p></td><td  ><p>18.2 x 10.3 x 16 inches</p></td></tr><tr><td class="firstcol " ><p><strong>Grinder</strong></p></td><td  ><p>Yes</p></td></tr><tr><td class="firstcol " ><p><strong>Heating system </strong></p></td><td  ><p>Not known</p></td></tr><tr><td class="firstcol " ><p><strong>Pressure </strong></p></td><td  ><p>19 bar</p></td></tr><tr><td class="firstcol " ><p><strong>Water tank capacity</strong></p></td><td  ><p>60.9 ounces</p></td></tr><tr><td class="firstcol " ><p><strong>Accessories</strong></p></td><td  ><p>Hot & cold milk frother, cleaning accessories, descaler, ice cube tray</p></td></tr></tbody></table></div><h2 class="article-body__section" id="section-de-longhi-primadonna-aromatic-review-price-availability"><span>De'Longhi PrimaDonna Aromatic review: Price & availability</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="9GWT4i7ZzeeHm5iacbMoXE" name="Delonghi_05.JPG" alt="the de'longhi primadonna aromatic photographed against the blue tom's guide background" src="https://cdn.mos.cms.futurecdn.net/9GWT4i7ZzeeHm5iacbMoXE.jpg" mos="" align="middle" fullscreen="" width="1920" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The De’Longhi PrimaDonna Aromatic is objectively expensive. You’ll find it for <a href="https://www.delonghi.com/en-us/p/primadonna-aromatic-primadonna-aromatic-automatic-coffee-maker-ecam63075tm/ECAM63075TM.html" target="_blank" rel="nofollow">$2,499 from De’Longhi U.S.</a> and <a href="https://www.currys.co.uk/products/delonghi-prima-donna-aromatic-ecam630.75.tsm-smart-bean-to-cup-coffee-machine-silver-10283595.html" target="_blank" rel="nofollow">£1,549 from Currys in the U.K.</a> </p><p>If you’re wincing, you’re not alone. $2,499 makes the PrimaDonna Aromatic the most expensive fully automatic coffee machine made by De’Longhi. Yes, <em>the most expensive. </em>As you might already be able to guess, this is markedly more expensive than the <a href="https://www.tomsguide.com/home/home-appliances/delonghi-rivelia-review">De’Longhi Rivelia</a> ($1,499/£749), De’Longhi Magnifica Duo ($999). </p><p>However, it’s only (<em>only, </em>she types, while wincing) $499 more expensive than the <a href="https://www.tomsguide.com/home/home-appliances/kitchenaid-KF8-espresso-machine">KitchenAid KF8</a>, which I reviewed a couple of years ago and loved. </p><p>If you’re familiar with the world of superautomatic coffee machines, you might’ve come across Jura — its fully automatic models can go up to $5,499. I’ve tested the $2,699 <a href="https://www.tomsguide.com/home/coffee-makers/jura-e8-review">Jura E8</a>, and let me tell you — the PrimaDonna Aromatic is much better.</p><h2 class="article-body__section" id="section-de-longhi-primadonna-aromatic-review-design"><span>De'Longhi PrimaDonna Aromatic review: Design </span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="WaEdz7Fjciq34AMf5ruxXE" name="Delonghi_03.JPG" alt="the de'longhi primadonna aromatic photographed against the blue tom's guide background" src="https://cdn.mos.cms.futurecdn.net/WaEdz7Fjciq34AMf5ruxXE.jpg" mos="" align="middle" fullscreen="" width="1920" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>Like other automatic De’Longhi machines, the PrimaDonna Aromatic is a somewhat narrow but incredibly deep machine. It stretches a whopping 18 inches deep, so you’ll need to check your kitchen countertops can fit this behemoth before purchasing. </p><p>Even so, the 10-inch width is pretty good, even with the water tank on the side. You shouldn’t need to clear too much space if your counters are deep already. </p><p>And the PrimaDonna Aromatic also <em>looks</em> like other De’Longhi superautomatics. If I didn’t read the name, I could believe it was the Magnifica Duo or the Dinamica or the Eletta. All these machines are effectively big shiny squares. They’re not massively gorgeous, but they’re functional, unobtrusive, and get the job done. It obviously works, because De’Longhi machines are everywhere. </p><p>There’s also a bright LCD screen on the machine. Here, you can select your desired beverage — 38 recipes, some of which I’d never heard of — and customize your intensity and volume. Two buttons on either side of the machine configure hot and cold, so you can view only cold or only hot drinks. </p><h2 id="app">App</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="kNnqn9LTFBaZfbYGTKSkWE" name="Delonghi_10.JPG" alt="the de'longhi primadonna aromatic photographed against the blue tom's guide background" src="https://cdn.mos.cms.futurecdn.net/kNnqn9LTFBaZfbYGTKSkWE.jpg" mos="" align="middle" fullscreen="" width="1920" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>I like apps when they’re actually useful. I like the Fellow app. I like the Acaia Brewmaster app. I like the apps for all the earbuds I test. But I do not like the De’Longhi My Coffee Lounge app. </p><p>I was prompted to complete a “coffee taste profile”, which told me I should get fruity coffee with notes of citrus, forest berry, and florals. I already knew this, though. It’s why I buy the same Ethiopian beans every time. </p><p>I suppose this is helpful for complete newbies — but I wouldn’t recommend complete newbies spend $2,500 on a coffee machine.</p><p>The app was also riddled with connectivity issues: There’s a Spotify-Wrapped-esque “Statistics” setting. This never loaded for me. You’re also supposed to be able to make your own recipes, but, again, these never loaded for me. The app just said “Couldn’t load any drink”. Hm, maybe because you won’t let me make any recipes? </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1600px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="AYrE7GJfptpdNyQ5iSL8pT" name="delongghi primadonna aromatic" alt="three screenshots from the delonghi my coffee lounge app" src="https://cdn.mos.cms.futurecdn.net/AYrE7GJfptpdNyQ5iSL8pT.png" mos="" align="middle" fullscreen="" width="1600" height="900" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: De'Longhi / Tom's Guide)</span></figcaption></figure><p>I like two parts of the My Coffee Lounge app: One, the “Health status” setting. Here you can see how many uses you have until you need to descale, how empty your water tank is, and how full your grounds drawer is. I love this. This is great for newbies. And “experts”. Everyone, actually.</p><p>And two: Suggested recipes. I got some super cool, super unique offerings here: Iced orange coffee, Iced raspberry tonic espresso, Iced espresso Mojito. Yes, please! I want more of this and fewer connectivity issues, thank you!</p><h2 class="article-body__section" id="section-de-longhi-primadonna-aromatic-review-espresso"><span>De'Longhi PrimaDonna Aromatic review: Espresso</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="9gr6LjvVNo4yZcfiPHNqWE" name="Delonghi_04.JPG" alt="the de'longhi primadonna aromatic photographed against the blue tom's guide background" src="https://cdn.mos.cms.futurecdn.net/9gr6LjvVNo4yZcfiPHNqWE.jpg" mos="" align="middle" fullscreen="" width="1920" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The De’Longhi PrimaDonna Aromatic espresso tastes like an automatic coffee machine’s espresso. That’s neither a good nor a bad thing depending on your preference. If you know you dislike automatic coffee, this wouldn’t be for you. If you know you like it, then great! </p><p>Here’s a photo of a shot of double espresso. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:3681px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="uvPTHC9UVoNUAebxECBtk3" name="delonghi primadonna aromatic espresso" alt="coffee made on the de'longhi primadonna aromatic" src="https://cdn.mos.cms.futurecdn.net/uvPTHC9UVoNUAebxECBtk3.png" mos="" align="middle" fullscreen="" width="3681" height="2071" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Erin Bashford)</span></figcaption></figure><p>As you can see, the coffee has a lovely bright caramelly color, and there’s a layer of fluffy crema. Did it taste like the most nuanced, complex, scintillating coffee in the world? No. It was a little weak, but it had enough of a coffee flavor to be devoured by straightforward coffee fans. I would not recommend this machine for coffee snobs or espresso lovers, but if you’re a general coffee drinker who prioritizes ease-of-use over messing around with doses and flow rates, this would get the job done. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:4382px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="xkCivcjxwMjQuuZGm7qhr3" name="delonghi primadonna aromaticcold brew" alt="coffee made on the de'longhi primadonna aromatic" src="https://cdn.mos.cms.futurecdn.net/xkCivcjxwMjQuuZGm7qhr3.png" mos="" align="middle" fullscreen="" width="4382" height="2465" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Erin Bashford)</span></figcaption></figure><p>I also made a cold brew, which was, in all honesty, pretty nasty.  I wouldn’t recommend this for cold brew aficionados. The coffee was actually hot as it extracted, which means it’s also not “cold brew”. It’s more like an iced Americano. </p><h2 class="article-body__section" id="section-de-longhi-primadonna-aromatic-review-milk"><span>De'Longhi PrimaDonna Aromatic review: Milk</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="5aPdZe973RRZAZkNWrtUXE" name="Delonghi_07.JPG" alt="the de'longhi primadonna aromatic photographed against the blue tom's guide background" src="https://cdn.mos.cms.futurecdn.net/5aPdZe973RRZAZkNWrtUXE.jpg" mos="" align="middle" fullscreen="" width="1920" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>Milk performance is what (mostly) separates the PrimaDonna Aromatic from other De’Longhi models. The PrimaDonna Aromatic comes with both a hot and cold milk frother, so you can have hot microfoam or cold foam. </p><p>The <a href="https://www.delonghi.com/en-us/p/eletta-explore-eletta-explore-espresso-machine/ECAM45086S+EX%3A4.html?pid=0132250196">De’Longhi Eletta Explore</a> ($1,999) also has this capability, so it might be worth checking out that model if you want to save some $$$. However, the Eletta Explore has a smaller water tank capacity. Again, not sure that’s worth an extra $500, but some food for thought. </p><p>Here’s a photo of a drink. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:5117px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="JYsUS54wYBpHdSGecLjiu3" name="delonghi primadonna aromatic milk" alt="coffee made on the de'longhi primadonna aromatic" src="https://cdn.mos.cms.futurecdn.net/JYsUS54wYBpHdSGecLjiu3.png" mos="" align="middle" fullscreen="" width="5117" height="2879" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Erin Bashford)</span></figcaption></figure><p>As you can see, the milk is smooth and evenly textured. Hot foam tends to deflate quite rapidly, so I’d recommend not leaving your cappuccinos around before drinking. Get ‘em while they’re hot! </p><p>This milk texture is around the same quality as the De’Longhi Rivelia, but that model doesn’t come with cold and hot — you’d have to buy the <a href="https://www.delonghi.com/en-us/p/automatic-milk-jugs-dlsc032-lattecrema-cool-upgrade-set/DLSC032.html?pid=AS00006309">cool version separately</a> ($129).</p><p>I really like the milk function on the PrimaDonna Aromatic. It has great texture, it’s easy to clean, and it comes with all the necessary accessories (unlike Jura). </p><h2 class="article-body__section" id="section-de-longhi-primadonna-aromatic-review-storage-maintenance"><span>De'Longhi PrimaDonna Aromatic review: Storage & maintenance</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="rsBEzxYgsJESzWfDtDJXXE" name="Delonghi_09.JPG" alt="the de'longhi primadonna aromatic photographed against the blue tom's guide background" src="https://cdn.mos.cms.futurecdn.net/rsBEzxYgsJESzWfDtDJXXE.jpg" mos="" align="middle" fullscreen="" width="1920" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The PrimaDonna Aromatic is easy to clean. The app tells you exactly when to clean, and I would recommend cleaning out the drip tray every day at a minimum. </p><p>My only major qualm is that you have to empty the grounds drawer more often than you think. I emptied it after around 3-4 drinks each time, and the drawer was full of ground beans each time. I don’t think this machine is particularly economical in terms of coffee and water usage, but that’s true of almost all automatic machines. </p><p>In terms of longevity, you get a 2-year warranty as standard, which goes up to 3 years with registration. Comparatively, Breville offers a 2-year warranty, as does Ninja.</p><h2 class="article-body__section" id="section-de-longhi-primadonna-aromatic-review-verdict"><span>De'Longhi PrimaDonna Aromatic review: Verdict</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="8TB4KShMnijxRDsgGe7rqD" name="Delonghi_08.JPG" alt="the de'longhi primadonna aromatic photographed against the blue tom's guide background" src="https://cdn.mos.cms.futurecdn.net/8TB4KShMnijxRDsgGe7rqD.jpg" mos="" align="middle" fullscreen="" width="1920" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The PrimaDonna Aromatic prioritizes simplicity and speed over coffee snobbery. It’s perfect for automatic machine users who want coffee and want it now. Would I buy it? Probably not. Would I recommend it for people who love Starbucks and Dunkin’ coffee and want to make drinks easily at home? 100%.</p><p>However, I’m still not totally sure what separates it from De’Longhi’s $1,999 Eletta Explore — it has Bean Adapt, De’Longhi’s My Coffee Lounge app connectivity, and 50 recipes compared to the PrimaDonna Aromatic’s 38. I think I’d recommend saving your $500 and getting the Eletta Explore — or save $1,000 and get the De’Longhi Rivelia. </p><p>But if you have $2,500 to spend, by all means, go for it. The PrimaDonna Aromatic is a great machine capable of making consistent espresso over and over. It’s just <em>very </em>expensive. </p> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/home/coffee-makers/delonghi-primadonna-aromatic-review</link>
                                                                            <description>
                            <![CDATA[ The new De'Longhi PrimaDonna Aromatic can make iced and hot drinks in seconds, has a range of recipes in the app, and looks super sleek. It's just... pricey. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">pCpVtkPjHVoWk8kHvFWBJG</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/PHMqX3gMv3WkGXzsqV6icD-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Fri, 31 Jul 2026 13:58:07 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Coffee Makers]]></category>
                                                    <category><![CDATA[Home]]></category>
                                                    <category><![CDATA[Home Appliances]]></category>
                                                    <category><![CDATA[Kitchen & Dining]]></category>
                                                                                                <author><![CDATA[ erin.bashford@futurenet.com (Erin Bashford) ]]></author>                    <dc:creator><![CDATA[ Erin Bashford ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/rLvJvJVZx43hEzSsJy3BpL.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Erin Bashford is a senior reviews writer at Tom’s Guide. She has a Master’s in Broadcast and Digital Journalism from the University of East Anglia and 7 years of experience reviewing music and events for various publications. She has edited publications such as Outline Magazine’s Guide to Norwich, and she has written for a number of music magazines and websites such as Clash Magazine, Outline Magazine and Dork Magazine. She has a strong interest in audio gear and the music world. &lt;/p&gt;&lt;p&gt;As an ex-barista, Erin is passionate about coffee tech. She also loves finding the best cooking hacks and kitchen appliances, including her beloved Instant Pot. &lt;/p&gt;&lt;p&gt;In her spare time, you can find her reading, practising yoga, hiking, writing fantasy novels, or stressing over NYT Games.&lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/PHMqX3gMv3WkGXzsqV6icD-1280-80.jpg">
                                                            <media:credit><![CDATA[Tom&#039;s Guide]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[the de&#039;longhi primadonna aromatic photographed against the blue tom&#039;s guide background]]></media:description>                                                            <media:text><![CDATA[the de&#039;longhi primadonna aromatic photographed against the blue tom&#039;s guide background]]></media:text>
                                <media:title type="plain"><![CDATA[the de&#039;longhi primadonna aromatic photographed against the blue tom&#039;s guide background]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/PHMqX3gMv3WkGXzsqV6icD-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>The De’Longhi PrimaDonna Aromatic is an ambitious superautomatic coffee machine. It can make 38 drinks and is even app-compatible, so you can control it from your phone (in theory). Is this enough to make it one of the <a href="https://www.tomsguide.com/home/coffee-makers/best-espresso-machines">best espresso machines</a>?</p><p>Yes and no. The PrimaDonna Aromatic is extremely pricey, at a whopping $2,500, and I’m… not really sure why. You can get 80% of the same performance with the $1,500 De’Longhi Rivelia and — checks notes — 99.9% of the same performance with the $2,000 De’Longhi Eletta Explore. I’m not saying <em>don’t</em> get the PrimaDonna Aromatic — I’m saying you might be able to save your money without sacrificing quality here. </p><p>But, I digress. The PrimaDonna Aromatic is a fun, consistent, and functional coffee machine. Want to find out more? Keep reading this De’Longhi PrimaDonna Aromatic review. </p><h2 class="article-body__section" id="section-de-longhi-primadonna-aromatic-review-specs"><span>De'Longhi PrimaDonna Aromatic review: Specs</span></h2><div ><table><tbody><tr><td class="firstcol " ><p><strong>Price</strong></p></td><td  ><p><a href="https://www.delonghi.com/en-us/p/primadonna-aromatic-primadonna-aromatic-automatic-coffee-maker-ecam63075tm/ECAM63075TM.html" target="_blank" rel="nofollow">$2,499</a> / <a href="https://www.currys.co.uk/products/delonghi-prima-donna-aromatic-ecam630.75.tsm-smart-bean-to-cup-coffee-machine-silver-10283595.html" target="_blank" rel="nofollow">£1,549</a></p></td></tr><tr><td class="firstcol " ><p><strong>Weight</strong></p></td><td  ><p>27.7 pounds</p></td></tr><tr><td class="firstcol " ><p><strong>Dimensions</strong></p></td><td  ><p>18.2 x 10.3 x 16 inches</p></td></tr><tr><td class="firstcol " ><p><strong>Grinder</strong></p></td><td  ><p>Yes</p></td></tr><tr><td class="firstcol " ><p><strong>Heating system </strong></p></td><td  ><p>Not known</p></td></tr><tr><td class="firstcol " ><p><strong>Pressure </strong></p></td><td  ><p>19 bar</p></td></tr><tr><td class="firstcol " ><p><strong>Water tank capacity</strong></p></td><td  ><p>60.9 ounces</p></td></tr><tr><td class="firstcol " ><p><strong>Accessories</strong></p></td><td  ><p>Hot & cold milk frother, cleaning accessories, descaler, ice cube tray</p></td></tr></tbody></table></div><h2 class="article-body__section" id="section-de-longhi-primadonna-aromatic-review-price-availability"><span>De'Longhi PrimaDonna Aromatic review: Price & availability</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="9GWT4i7ZzeeHm5iacbMoXE" name="Delonghi_05.JPG" alt="the de'longhi primadonna aromatic photographed against the blue tom's guide background" src="https://cdn.mos.cms.futurecdn.net/9GWT4i7ZzeeHm5iacbMoXE.jpg" mos="" align="middle" fullscreen="" width="1920" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The De’Longhi PrimaDonna Aromatic is objectively expensive. You’ll find it for <a href="https://www.delonghi.com/en-us/p/primadonna-aromatic-primadonna-aromatic-automatic-coffee-maker-ecam63075tm/ECAM63075TM.html" target="_blank" rel="nofollow">$2,499 from De’Longhi U.S.</a> and <a href="https://www.currys.co.uk/products/delonghi-prima-donna-aromatic-ecam630.75.tsm-smart-bean-to-cup-coffee-machine-silver-10283595.html" target="_blank" rel="nofollow">£1,549 from Currys in the U.K.</a> </p><p>If you’re wincing, you’re not alone. $2,499 makes the PrimaDonna Aromatic the most expensive fully automatic coffee machine made by De’Longhi. Yes, <em>the most expensive. </em>As you might already be able to guess, this is markedly more expensive than the <a href="https://www.tomsguide.com/home/home-appliances/delonghi-rivelia-review">De’Longhi Rivelia</a> ($1,499/£749), De’Longhi Magnifica Duo ($999). </p><p>However, it’s only (<em>only, </em>she types, while wincing) $499 more expensive than the <a href="https://www.tomsguide.com/home/home-appliances/kitchenaid-KF8-espresso-machine">KitchenAid KF8</a>, which I reviewed a couple of years ago and loved. </p><p>If you’re familiar with the world of superautomatic coffee machines, you might’ve come across Jura — its fully automatic models can go up to $5,499. I’ve tested the $2,699 <a href="https://www.tomsguide.com/home/coffee-makers/jura-e8-review">Jura E8</a>, and let me tell you — the PrimaDonna Aromatic is much better.</p><h2 class="article-body__section" id="section-de-longhi-primadonna-aromatic-review-design"><span>De'Longhi PrimaDonna Aromatic review: Design </span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="WaEdz7Fjciq34AMf5ruxXE" name="Delonghi_03.JPG" alt="the de'longhi primadonna aromatic photographed against the blue tom's guide background" src="https://cdn.mos.cms.futurecdn.net/WaEdz7Fjciq34AMf5ruxXE.jpg" mos="" align="middle" fullscreen="" width="1920" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>Like other automatic De’Longhi machines, the PrimaDonna Aromatic is a somewhat narrow but incredibly deep machine. It stretches a whopping 18 inches deep, so you’ll need to check your kitchen countertops can fit this behemoth before purchasing. </p><p>Even so, the 10-inch width is pretty good, even with the water tank on the side. You shouldn’t need to clear too much space if your counters are deep already. </p><p>And the PrimaDonna Aromatic also <em>looks</em> like other De’Longhi superautomatics. If I didn’t read the name, I could believe it was the Magnifica Duo or the Dinamica or the Eletta. All these machines are effectively big shiny squares. They’re not massively gorgeous, but they’re functional, unobtrusive, and get the job done. It obviously works, because De’Longhi machines are everywhere. </p><p>There’s also a bright LCD screen on the machine. Here, you can select your desired beverage — 38 recipes, some of which I’d never heard of — and customize your intensity and volume. Two buttons on either side of the machine configure hot and cold, so you can view only cold or only hot drinks. </p><h2 id="app">App</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="kNnqn9LTFBaZfbYGTKSkWE" name="Delonghi_10.JPG" alt="the de'longhi primadonna aromatic photographed against the blue tom's guide background" src="https://cdn.mos.cms.futurecdn.net/kNnqn9LTFBaZfbYGTKSkWE.jpg" mos="" align="middle" fullscreen="" width="1920" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>I like apps when they’re actually useful. I like the Fellow app. I like the Acaia Brewmaster app. I like the apps for all the earbuds I test. But I do not like the De’Longhi My Coffee Lounge app. </p><p>I was prompted to complete a “coffee taste profile”, which told me I should get fruity coffee with notes of citrus, forest berry, and florals. I already knew this, though. It’s why I buy the same Ethiopian beans every time. </p><p>I suppose this is helpful for complete newbies — but I wouldn’t recommend complete newbies spend $2,500 on a coffee machine.</p><p>The app was also riddled with connectivity issues: There’s a Spotify-Wrapped-esque “Statistics” setting. This never loaded for me. You’re also supposed to be able to make your own recipes, but, again, these never loaded for me. The app just said “Couldn’t load any drink”. Hm, maybe because you won’t let me make any recipes? </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1600px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="AYrE7GJfptpdNyQ5iSL8pT" name="delongghi primadonna aromatic" alt="three screenshots from the delonghi my coffee lounge app" src="https://cdn.mos.cms.futurecdn.net/AYrE7GJfptpdNyQ5iSL8pT.png" mos="" align="middle" fullscreen="" width="1600" height="900" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: De'Longhi / Tom's Guide)</span></figcaption></figure><p>I like two parts of the My Coffee Lounge app: One, the “Health status” setting. Here you can see how many uses you have until you need to descale, how empty your water tank is, and how full your grounds drawer is. I love this. This is great for newbies. And “experts”. Everyone, actually.</p><p>And two: Suggested recipes. I got some super cool, super unique offerings here: Iced orange coffee, Iced raspberry tonic espresso, Iced espresso Mojito. Yes, please! I want more of this and fewer connectivity issues, thank you!</p><h2 class="article-body__section" id="section-de-longhi-primadonna-aromatic-review-espresso"><span>De'Longhi PrimaDonna Aromatic review: Espresso</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="9gr6LjvVNo4yZcfiPHNqWE" name="Delonghi_04.JPG" alt="the de'longhi primadonna aromatic photographed against the blue tom's guide background" src="https://cdn.mos.cms.futurecdn.net/9gr6LjvVNo4yZcfiPHNqWE.jpg" mos="" align="middle" fullscreen="" width="1920" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The De’Longhi PrimaDonna Aromatic espresso tastes like an automatic coffee machine’s espresso. That’s neither a good nor a bad thing depending on your preference. If you know you dislike automatic coffee, this wouldn’t be for you. If you know you like it, then great! </p><p>Here’s a photo of a shot of double espresso. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:3681px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="uvPTHC9UVoNUAebxECBtk3" name="delonghi primadonna aromatic espresso" alt="coffee made on the de'longhi primadonna aromatic" src="https://cdn.mos.cms.futurecdn.net/uvPTHC9UVoNUAebxECBtk3.png" mos="" align="middle" fullscreen="" width="3681" height="2071" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Erin Bashford)</span></figcaption></figure><p>As you can see, the coffee has a lovely bright caramelly color, and there’s a layer of fluffy crema. Did it taste like the most nuanced, complex, scintillating coffee in the world? No. It was a little weak, but it had enough of a coffee flavor to be devoured by straightforward coffee fans. I would not recommend this machine for coffee snobs or espresso lovers, but if you’re a general coffee drinker who prioritizes ease-of-use over messing around with doses and flow rates, this would get the job done. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:4382px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="xkCivcjxwMjQuuZGm7qhr3" name="delonghi primadonna aromaticcold brew" alt="coffee made on the de'longhi primadonna aromatic" src="https://cdn.mos.cms.futurecdn.net/xkCivcjxwMjQuuZGm7qhr3.png" mos="" align="middle" fullscreen="" width="4382" height="2465" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Erin Bashford)</span></figcaption></figure><p>I also made a cold brew, which was, in all honesty, pretty nasty.  I wouldn’t recommend this for cold brew aficionados. The coffee was actually hot as it extracted, which means it’s also not “cold brew”. It’s more like an iced Americano. </p><h2 class="article-body__section" id="section-de-longhi-primadonna-aromatic-review-milk"><span>De'Longhi PrimaDonna Aromatic review: Milk</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="5aPdZe973RRZAZkNWrtUXE" name="Delonghi_07.JPG" alt="the de'longhi primadonna aromatic photographed against the blue tom's guide background" src="https://cdn.mos.cms.futurecdn.net/5aPdZe973RRZAZkNWrtUXE.jpg" mos="" align="middle" fullscreen="" width="1920" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>Milk performance is what (mostly) separates the PrimaDonna Aromatic from other De’Longhi models. The PrimaDonna Aromatic comes with both a hot and cold milk frother, so you can have hot microfoam or cold foam. </p><p>The <a href="https://www.delonghi.com/en-us/p/eletta-explore-eletta-explore-espresso-machine/ECAM45086S+EX%3A4.html?pid=0132250196">De’Longhi Eletta Explore</a> ($1,999) also has this capability, so it might be worth checking out that model if you want to save some $$$. However, the Eletta Explore has a smaller water tank capacity. Again, not sure that’s worth an extra $500, but some food for thought. </p><p>Here’s a photo of a drink. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:5117px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="JYsUS54wYBpHdSGecLjiu3" name="delonghi primadonna aromatic milk" alt="coffee made on the de'longhi primadonna aromatic" src="https://cdn.mos.cms.futurecdn.net/JYsUS54wYBpHdSGecLjiu3.png" mos="" align="middle" fullscreen="" width="5117" height="2879" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Erin Bashford)</span></figcaption></figure><p>As you can see, the milk is smooth and evenly textured. Hot foam tends to deflate quite rapidly, so I’d recommend not leaving your cappuccinos around before drinking. Get ‘em while they’re hot! </p><p>This milk texture is around the same quality as the De’Longhi Rivelia, but that model doesn’t come with cold and hot — you’d have to buy the <a href="https://www.delonghi.com/en-us/p/automatic-milk-jugs-dlsc032-lattecrema-cool-upgrade-set/DLSC032.html?pid=AS00006309">cool version separately</a> ($129).</p><p>I really like the milk function on the PrimaDonna Aromatic. It has great texture, it’s easy to clean, and it comes with all the necessary accessories (unlike Jura). </p><h2 class="article-body__section" id="section-de-longhi-primadonna-aromatic-review-storage-maintenance"><span>De'Longhi PrimaDonna Aromatic review: Storage & maintenance</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="rsBEzxYgsJESzWfDtDJXXE" name="Delonghi_09.JPG" alt="the de'longhi primadonna aromatic photographed against the blue tom's guide background" src="https://cdn.mos.cms.futurecdn.net/rsBEzxYgsJESzWfDtDJXXE.jpg" mos="" align="middle" fullscreen="" width="1920" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The PrimaDonna Aromatic is easy to clean. The app tells you exactly when to clean, and I would recommend cleaning out the drip tray every day at a minimum. </p><p>My only major qualm is that you have to empty the grounds drawer more often than you think. I emptied it after around 3-4 drinks each time, and the drawer was full of ground beans each time. I don’t think this machine is particularly economical in terms of coffee and water usage, but that’s true of almost all automatic machines. </p><p>In terms of longevity, you get a 2-year warranty as standard, which goes up to 3 years with registration. Comparatively, Breville offers a 2-year warranty, as does Ninja.</p><h2 class="article-body__section" id="section-de-longhi-primadonna-aromatic-review-verdict"><span>De'Longhi PrimaDonna Aromatic review: Verdict</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="8TB4KShMnijxRDsgGe7rqD" name="Delonghi_08.JPG" alt="the de'longhi primadonna aromatic photographed against the blue tom's guide background" src="https://cdn.mos.cms.futurecdn.net/8TB4KShMnijxRDsgGe7rqD.jpg" mos="" align="middle" fullscreen="" width="1920" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The PrimaDonna Aromatic prioritizes simplicity and speed over coffee snobbery. It’s perfect for automatic machine users who want coffee and want it now. Would I buy it? Probably not. Would I recommend it for people who love Starbucks and Dunkin’ coffee and want to make drinks easily at home? 100%.</p><p>However, I’m still not totally sure what separates it from De’Longhi’s $1,999 Eletta Explore — it has Bean Adapt, De’Longhi’s My Coffee Lounge app connectivity, and 50 recipes compared to the PrimaDonna Aromatic’s 38. I think I’d recommend saving your $500 and getting the Eletta Explore — or save $1,000 and get the De’Longhi Rivelia. </p><p>But if you have $2,500 to spend, by all means, go for it. The PrimaDonna Aromatic is a great machine capable of making consistent espresso over and over. It’s just <em>very </em>expensive. </p>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ I put a battery-powered induction stove to the test — here’s what surprised me ]]></title>
                                                                                                <dc:content><![CDATA[ <p>The oil sizzled as I placed the scallops in the pan. On the counter next to me sat a tray of just-baked chocolate chip cookies, their aroma wafting through the air. In the oven, a tray of chicken thighs was slowly baking atop a mixture of Chinese vegetables, their juices infusing with the cabbage and boy choy beneath.</p><p>I was cooking it all on the Copper Charlie, an innovative induction stove that doesn’t require any special installation, thanks to a massive battery. And while it's an early adopter in the world of early adopters, it could represent the future of home appliances. </p><h2 id="renovation-is-the-mother-of-necessity">Renovation is the mother of necessity</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="5CZATxc8HsbQamB9K4HAUe" name="Copper Charlie cooktop" alt="Copper Charlie cooktop" src="https://cdn.mos.cms.futurecdn.net/5CZATxc8HsbQamB9K4HAUe.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>I tested out the range in the Brooklyn apartment of Ted Booth, who switched from a traditional gas oven to the Copper about a year ago. At the time, his building was facing a million-dollar renovation bill to upgrade the ancient gas pipes leading into, and threading through, the entire 33-unit building.</p><p>Rather than forcing the entire building to front the cost of fixing each unit’s gas line, the condo board gave each owner an option to switch to an induction stove. However, most induction stoves require a 220-volt electric line — which would have meant an equally expensive bill. </p><p>But there was an alternative: the Copper induction stove. This range has a large battery in the bottom, where the warming tray would sit. Not only does this provide a steady source of energy, even when the power goes out, but it also allows the stove to use a regular 110-volt outlet, so you can plug it in almost anywhere. </p><p>“To me, it was an opportunity to get off gas,” Booth said. “And, you can call me a bit of an early adopter, so it appealed to me that way.”</p><h3 class="article-body__section" id="section-modern-but-retro"><span>Modern but retro</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="4NxvG2P32duYnS62Mc5dFJ" name="Copper Charlie knobs" alt="Copper Charlie knobs" src="https://cdn.mos.cms.futurecdn.net/4NxvG2P32duYnS62Mc5dFJ.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><div><blockquote><p>"It's the most analog experience I've had with a tech product"</p><p>— Ted Booth</p></blockquote></div><p>While the Charlie uses a very new type of technology, and has Wi-Fi and can be updated over the internet, it’s surprisingly low on connected features. </p><p>“I like how simple it is,” Booth said. “It's connected to the Wi-Fi, it has a battery, but it's the most analog experience I've had with a tech product. You have the little light indicator on the side, and the screen shows you what it's doing — it's 350 degrees. That's all you need to know. It's great.  And then the two little switches for the light and convection.”</p><h3 class="article-body__section" id="section-the-cost-of-upgrading"><span>The cost of upgrading</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:4032px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="YtFxSHTSXqXwf62mnYZtBP" name="Copper Charlie oven open" alt="Copper Charlie oven open" src="https://cdn.mos.cms.futurecdn.net/YtFxSHTSXqXwf62mnYZtBP.jpg" mos="" align="middle" fullscreen="" width="4032" height="2268" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>The Copper Charlie isn’t cheap. The <a href="https://copperhome.com/products/charlie?variant=42413374079069" target="_blank">base model, with black plastic knobs, costs $6,000</a>, while the model with black walnut knobs is $6,300. That’s more than twice as expensive as some popular models from <a href="https://www.bestbuy.com/product/lg-30-in-wide-6-3-cu-ft-slide-in-electric-induction-true-convect-range-with-5-elements-instaview-and-flex-control-knobs-stainless-steel/J7G5658LSF"><u>LG</u></a> and GE — though it should be noted the GE Cafe series can get up to $5,000. </p><p>The Charlie is not Energy Star-certified, so you can’t get any government rebates from that program, but there are several other local clean energy tax credits that can help ease the cost.</p><p>However, it did get the seal of approval from the New York City Housing Authority, which is installing <a href="https://www.nytimes.com/2026/01/16/nyregion/induction-stoves-housing-authority.html"><u>100 Copper Charlie stoves in apartments</u></a> throughout the city as a pilot program for lower-income residents, as all city-owned apartment buildings get converted from gas to electric.</p><p>“There are so many families that haven't had the ability to cook for years because they had their utility to get the gas shut off,” said Lisa Pickney, a professional chef who created the Official Dessert of the 1996 Atlanta Olympics, served on the Obama White House culinary team, and now works for Copper. </p><p>“And so they just gave them a hot plate and a rice cooker and a teapot. And it's just not right. They can't make a Thanksgiving turkey. So that kind of broke my heart. And now they'll be able to have Thanksgiving and do proper cooking now.” </p><p>The Copper Charlie isn’t the only induction stove of its kind; a rival company, the <a href="https://www.tomsguide.com/home/home-appliances/i-tried-out-an-induction-stove-that-works-even-when-the-power-goes-out"><u>Electra Induction Stove</u></a>, works in much the same way. Rather than the lithium ion batteries you might find in your phone or electric scooter, these stoves use a lithium phosphate battery, which is more stable, and more suited for how it’s used with the stoves. </p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-OqREmX"></div>                            </div>                            <script src="https://kwizly.com/embed/OqREmX.js" async></script><h3 class="article-body__section" id="section-now-we-re-cooking"><span>Now we're cooking</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="Cv4aYBK8AB99GeMZm3MFmU" name="Copper Charlie scallops" alt="searing scallops on the Copper Charlie" src="https://cdn.mos.cms.futurecdn.net/Cv4aYBK8AB99GeMZm3MFmU.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>As I (well, mostly Lisa) were cooking, I was impressed with how fast the oven heated up. While I didn’t time it, the Copper Charlie seemed far shorter than my oven at home. Similarly, its cooktop element warmed up the pan in no time, and put a sear on the scallops as good as I’ve ever done on any range, gas or electric.</p><p>Booth said that his cooking game has improved since getting the Charlie. “I like to make a Spanish potato omelet,” he said. “I like it because you can get a really nice, low temperature, so it doesn't brown too quickly. With the gas, I could get a low flame, but then the heat doesn't distribute quite as well, and so it's like cooking more in one spot and less on the edges.” </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:57.65%;"><img id="7in93fN4mpP8rnadB7BmuY" name="Copper Charlie chicken" alt="Chicken baked in the Copper Charlie" src="https://cdn.mos.cms.futurecdn.net/7in93fN4mpP8rnadB7BmuY.jpg" mos="" align="middle" fullscreen="" width="2000" height="1153" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>Booth said he could no longer do the <a href="https://bittmanproject.com/recipe/seared-steak/" target="_blank">Mark Bittman trick of cooking a steak</a> by placing a pan on the very bottom of the oven, but the Charlie proved its worth when the outlet behind the stove stopped working. </p><p>“At first, I was like, what are we gonna do?” he said. “It's gonna take a while to get an electrician to come, and then I was like, oh, no, wait, it's fine. We have an outlet behind that cluster of little appliances in the corner is a four-prong outlet with a GFCI. So I just plugged it into that.”</p><p>“That to me really proved to me how much power this draws, because we've got an Instapot, we've got a kettle, we've got an espresso machine.  And we never had an issue, it never popped the GFCI.”</p><h3 class="article-body__section" id="section-how-it-s-working-out"><span>How it's working out</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="js4rQ6VnrMbiGjMoaYsBZ4" name="Copper Charlie induction range" alt="Copper Charlie induction range" src="https://cdn.mos.cms.futurecdn.net/js4rQ6VnrMbiGjMoaYsBZ4.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>Ultimately, eleven owners in Booth’s building ended up getting a Copper Charlie. It proved to be more expensive than those who merely opted to replace their gas line, but Booth said it was worth the expense.</p><p>“We're gonna spend all this money for these pipes in the wall, and all I get is to get a blue flame?” he asks. ”I want something better than that.”</p><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h3><ul><li><a href="https://www.tomsguide.com/home/I-tried-an-induction-cooktop-3-things-i-learned">I used an induction cooktop for the first time — here are 3 things I learned</a></li><li><a href="https://www.tomsguide.com/home/home-appliances/mistakes-i-made-when-i-switched-to-an-induction-cooktop-and-how-to-avoid-them">5 mistakes I made when I switched to an induction cooktop</a></li><li><a href="https://www.tomsguide.com/home/home-appliances/we-tested-3-portable-induction-cooktops-at-wildly-different-prices-heres-our-verdict">We tested 3 portable induction cooktops from $50 to $1,500 </a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/home/kitchen-dining/i-put-a-battery-powered-induction-stove-to-the-test-heres-what-surprised-me</link>
                                                                            <description>
                            <![CDATA[ I tested the Copper Charlie, an induction range with a built-in battery, which makes it far easier to install — and even works when the power is out. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">DdYjBJKiUFNpyXNePiyb4A</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/g8TQNn5XqY4EknpbYVuy3n-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Fri, 31 Jul 2026 09:45:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Kitchen & Dining]]></category>
                                                    <category><![CDATA[Home]]></category>
                                                    <category><![CDATA[Home Appliances]]></category>
                                                                                                <author><![CDATA[ mike.prospero@futurenet.com (Mike Prospero) ]]></author>                    <dc:creator><![CDATA[ Mike Prospero ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/xeJFBrJwXQzCqXLZXBFBKQ.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Michael A. Prospero is the U.S. Editor-in-Chief for Tom’s Guide.  In his spare time, he also tests out the latest drones, electric scooters, and smart home gadgets, such as video doorbells. Before his tenure at Tom&#039;s Guide, he was the Reviews Editor for Laptop Magazine, a reporter at Fast Company, the Times of Trenton, and, many eons back, an intern at George magazine. He received his undergraduate degree from Boston College, where he worked on the campus newspaper The Heights, and then attended the Columbia University school of Journalism. When he’s not testing out the latest running watch, electric scooter, or skiing or training for a marathon, he’s probably using the latest sous vide machine, smoker, or pizza oven, to the delight — or chagrin — of his family.&lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/g8TQNn5XqY4EknpbYVuy3n-1280-80.jpg">
                                                            <media:credit><![CDATA[Future]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Copper Charlie induction range]]></media:description>                                                            <media:text><![CDATA[Copper Charlie induction range]]></media:text>
                                <media:title type="plain"><![CDATA[Copper Charlie induction range]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/g8TQNn5XqY4EknpbYVuy3n-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>The oil sizzled as I placed the scallops in the pan. On the counter next to me sat a tray of just-baked chocolate chip cookies, their aroma wafting through the air. In the oven, a tray of chicken thighs was slowly baking atop a mixture of Chinese vegetables, their juices infusing with the cabbage and boy choy beneath.</p><p>I was cooking it all on the Copper Charlie, an innovative induction stove that doesn’t require any special installation, thanks to a massive battery. And while it's an early adopter in the world of early adopters, it could represent the future of home appliances. </p><h2 id="renovation-is-the-mother-of-necessity">Renovation is the mother of necessity</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="5CZATxc8HsbQamB9K4HAUe" name="Copper Charlie cooktop" alt="Copper Charlie cooktop" src="https://cdn.mos.cms.futurecdn.net/5CZATxc8HsbQamB9K4HAUe.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>I tested out the range in the Brooklyn apartment of Ted Booth, who switched from a traditional gas oven to the Copper about a year ago. At the time, his building was facing a million-dollar renovation bill to upgrade the ancient gas pipes leading into, and threading through, the entire 33-unit building.</p><p>Rather than forcing the entire building to front the cost of fixing each unit’s gas line, the condo board gave each owner an option to switch to an induction stove. However, most induction stoves require a 220-volt electric line — which would have meant an equally expensive bill. </p><p>But there was an alternative: the Copper induction stove. This range has a large battery in the bottom, where the warming tray would sit. Not only does this provide a steady source of energy, even when the power goes out, but it also allows the stove to use a regular 110-volt outlet, so you can plug it in almost anywhere. </p><p>“To me, it was an opportunity to get off gas,” Booth said. “And, you can call me a bit of an early adopter, so it appealed to me that way.”</p><h3 class="article-body__section" id="section-modern-but-retro"><span>Modern but retro</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="4NxvG2P32duYnS62Mc5dFJ" name="Copper Charlie knobs" alt="Copper Charlie knobs" src="https://cdn.mos.cms.futurecdn.net/4NxvG2P32duYnS62Mc5dFJ.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><div><blockquote><p>"It's the most analog experience I've had with a tech product"</p><p>— Ted Booth</p></blockquote></div><p>While the Charlie uses a very new type of technology, and has Wi-Fi and can be updated over the internet, it’s surprisingly low on connected features. </p><p>“I like how simple it is,” Booth said. “It's connected to the Wi-Fi, it has a battery, but it's the most analog experience I've had with a tech product. You have the little light indicator on the side, and the screen shows you what it's doing — it's 350 degrees. That's all you need to know. It's great.  And then the two little switches for the light and convection.”</p><h3 class="article-body__section" id="section-the-cost-of-upgrading"><span>The cost of upgrading</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:4032px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="YtFxSHTSXqXwf62mnYZtBP" name="Copper Charlie oven open" alt="Copper Charlie oven open" src="https://cdn.mos.cms.futurecdn.net/YtFxSHTSXqXwf62mnYZtBP.jpg" mos="" align="middle" fullscreen="" width="4032" height="2268" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>The Copper Charlie isn’t cheap. The <a href="https://copperhome.com/products/charlie?variant=42413374079069" target="_blank">base model, with black plastic knobs, costs $6,000</a>, while the model with black walnut knobs is $6,300. That’s more than twice as expensive as some popular models from <a href="https://www.bestbuy.com/product/lg-30-in-wide-6-3-cu-ft-slide-in-electric-induction-true-convect-range-with-5-elements-instaview-and-flex-control-knobs-stainless-steel/J7G5658LSF"><u>LG</u></a> and GE — though it should be noted the GE Cafe series can get up to $5,000. </p><p>The Charlie is not Energy Star-certified, so you can’t get any government rebates from that program, but there are several other local clean energy tax credits that can help ease the cost.</p><p>However, it did get the seal of approval from the New York City Housing Authority, which is installing <a href="https://www.nytimes.com/2026/01/16/nyregion/induction-stoves-housing-authority.html"><u>100 Copper Charlie stoves in apartments</u></a> throughout the city as a pilot program for lower-income residents, as all city-owned apartment buildings get converted from gas to electric.</p><p>“There are so many families that haven't had the ability to cook for years because they had their utility to get the gas shut off,” said Lisa Pickney, a professional chef who created the Official Dessert of the 1996 Atlanta Olympics, served on the Obama White House culinary team, and now works for Copper. </p><p>“And so they just gave them a hot plate and a rice cooker and a teapot. And it's just not right. They can't make a Thanksgiving turkey. So that kind of broke my heart. And now they'll be able to have Thanksgiving and do proper cooking now.” </p><p>The Copper Charlie isn’t the only induction stove of its kind; a rival company, the <a href="https://www.tomsguide.com/home/home-appliances/i-tried-out-an-induction-stove-that-works-even-when-the-power-goes-out"><u>Electra Induction Stove</u></a>, works in much the same way. Rather than the lithium ion batteries you might find in your phone or electric scooter, these stoves use a lithium phosphate battery, which is more stable, and more suited for how it’s used with the stoves. </p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-OqREmX"></div>                            </div>                            <script src="https://kwizly.com/embed/OqREmX.js" async></script><h3 class="article-body__section" id="section-now-we-re-cooking"><span>Now we're cooking</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="Cv4aYBK8AB99GeMZm3MFmU" name="Copper Charlie scallops" alt="searing scallops on the Copper Charlie" src="https://cdn.mos.cms.futurecdn.net/Cv4aYBK8AB99GeMZm3MFmU.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>As I (well, mostly Lisa) were cooking, I was impressed with how fast the oven heated up. While I didn’t time it, the Copper Charlie seemed far shorter than my oven at home. Similarly, its cooktop element warmed up the pan in no time, and put a sear on the scallops as good as I’ve ever done on any range, gas or electric.</p><p>Booth said that his cooking game has improved since getting the Charlie. “I like to make a Spanish potato omelet,” he said. “I like it because you can get a really nice, low temperature, so it doesn't brown too quickly. With the gas, I could get a low flame, but then the heat doesn't distribute quite as well, and so it's like cooking more in one spot and less on the edges.” </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:57.65%;"><img id="7in93fN4mpP8rnadB7BmuY" name="Copper Charlie chicken" alt="Chicken baked in the Copper Charlie" src="https://cdn.mos.cms.futurecdn.net/7in93fN4mpP8rnadB7BmuY.jpg" mos="" align="middle" fullscreen="" width="2000" height="1153" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>Booth said he could no longer do the <a href="https://bittmanproject.com/recipe/seared-steak/" target="_blank">Mark Bittman trick of cooking a steak</a> by placing a pan on the very bottom of the oven, but the Charlie proved its worth when the outlet behind the stove stopped working. </p><p>“At first, I was like, what are we gonna do?” he said. “It's gonna take a while to get an electrician to come, and then I was like, oh, no, wait, it's fine. We have an outlet behind that cluster of little appliances in the corner is a four-prong outlet with a GFCI. So I just plugged it into that.”</p><p>“That to me really proved to me how much power this draws, because we've got an Instapot, we've got a kettle, we've got an espresso machine.  And we never had an issue, it never popped the GFCI.”</p><h3 class="article-body__section" id="section-how-it-s-working-out"><span>How it's working out</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="js4rQ6VnrMbiGjMoaYsBZ4" name="Copper Charlie induction range" alt="Copper Charlie induction range" src="https://cdn.mos.cms.futurecdn.net/js4rQ6VnrMbiGjMoaYsBZ4.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>Ultimately, eleven owners in Booth’s building ended up getting a Copper Charlie. It proved to be more expensive than those who merely opted to replace their gas line, but Booth said it was worth the expense.</p><p>“We're gonna spend all this money for these pipes in the wall, and all I get is to get a blue flame?” he asks. ”I want something better than that.”</p><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h3><ul><li><a href="https://www.tomsguide.com/home/I-tried-an-induction-cooktop-3-things-i-learned">I used an induction cooktop for the first time — here are 3 things I learned</a></li><li><a href="https://www.tomsguide.com/home/home-appliances/mistakes-i-made-when-i-switched-to-an-induction-cooktop-and-how-to-avoid-them">5 mistakes I made when I switched to an induction cooktop</a></li><li><a href="https://www.tomsguide.com/home/home-appliances/we-tested-3-portable-induction-cooktops-at-wildly-different-prices-heres-our-verdict">We tested 3 portable induction cooktops from $50 to $1,500 </a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ I'm an ex-Starbucks barista — you can make the Iced Brown Sugar Oatmilk Shaken Espresso at home for a fraction of the cost ]]></title>
                                                                                                <dc:content><![CDATA[ <div  class="fancy-box"><div class="fancy_box-title">The Coffee Lab</div><div class="fancy_box_body"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' ><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="UwFdgr6xkNzHUWjapZThcN" name="smeg edited2" caption="" alt="the smeg emc02 mini pro manual espresso machine in jade green" src="https://cdn.mos.cms.futurecdn.net/UwFdgr6xkNzHUWjapZThcN.jpg" mos="" link="" align="" fullscreen="" width="" height="" attribution="" endorsement="" class="pinterest-pin-exclude"></p></div></div><figcaption itemprop="caption description" class=""><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p class="fancy-box__body-text">I'm Erin, and welcome to the eighteenth episode of <a data-analytics-id="inline-link" href="https://www.tomsguide.com/tag/the-coffee-lab">The Coffee Lab</a>, the series where we forget coffee snobbery. The Coffee Lab is all about making coffee fun. Join me as I help you kickstart your coffee journey!</p></div></div><p>Starbucks is expensive. There's no getting around that. Some drinks can cost as much as $10 in certain states these days, which is simply ridiculous. If I were to order a <a href="https://www.starbucks.com/menu" target="_blank" rel="nofollow">Grande Iced Brown Sugar Oatmilk Shaken Espresso at the Starbucks closest to Tom's Guide's Manhattan office</a>, it would cost me $7.57. Yes, almost 8 bucks.  </p><p>Fortunately, you can make it yourself, for far less. </p><p>I was a Starbucks barista for years, and learned how to make the delicious Starbucks Iced Brown Sugar Oatmilk Shaken Espresso at home. I've even done some coffee math down below to show you how much better this version is for your wallet (and your health, if you use homemade syrup). </p><p>You only need three ingredients (four if you count ice as an ingredient, and five if you include the optional cinnamon) to make a delicious iced espresso at home. And the best part? It takes about two minutes. Here's my step-by-step guide to making the Starbucks Iced Brown Sugar Oatmilk Shaken Espresso at home, using the <a href="https://www.tomsguide.com/home/coffee-makers/nespresso-vertuo-up-review">Nespresso Vertuo Up</a>, Oatly Barista oat milk, homemade brown sugar syrup, ice, and cinnamon.</p><section class="howto-block">                    <h3>Step 1: Make your brown sugar syrup</h3>                    <figure>                            <p class="bordeaux-image-check">                                <img    src="https://cdn.mos.cms.futurecdn.net/LcZBZmCGRqRiaXyzQ9iQHi.png"                                        alt="a photo of a copycat starbucks iced brown sugar oatmilk shaken espresso"                                        onerror="this.parentNode.replaceChild(window.missingImage(),this)"                                        data-pin-media="https://cdn.mos.cms.futurecdn.net/LcZBZmCGRqRiaXyzQ9iQHi.png"                                        class="expandable van-old-layout-image">                            </p><div class="credit">(Image: © Erin Bashford)</div></figure>                    <p><p>I opted to make my own syrup for two reasons. One: brown sugar syrup isn't readily available where I live, and two: I know the exact ingredients, so no surprises here. </p><p>Simply add your desired amount of sugar and a tiny drop of hot water to melt the sugar. If you have a sweet tooth, this might be 10g. I used one teaspoon, so 5g. </p></p>                </section><section class="howto-block">                    <h3>Step 2: Make your espresso</h3>                    <figure>                            <p class="bordeaux-image-check">                                <img    src="https://cdn.mos.cms.futurecdn.net/4MKv3iawqik6msXULAPCJi.png"                                        alt="a photo of a copycat starbucks iced brown sugar oatmilk shaken espresso"                                        onerror="this.parentNode.replaceChild(window.missingImage(),this)"                                        data-pin-media="https://cdn.mos.cms.futurecdn.net/4MKv3iawqik6msXULAPCJi.png"                                        class="expandable van-old-layout-image">                            </p><div class="credit">(Image: © Erin Bashford)</div></figure>                    <p><p>Starbucks uses Blonde roast for the Iced Brown Sugar Oatmilk Shaken Espresso, so I'd recommend using a light or medium roast coffee with notes like citrus, cherry, caramel, or fruit to achieve a similar result. </p><p>Of course, you could simply buy Blonde roast from your local Starbucks. </p><p>I'd recommend a double shot here, so use around 18g of finely ground coffee for 36g espresso. I used the Oatly Nespresso pods for this video using my Nespresso Vertuo Up.</p></p>                </section><section class="howto-block">                    <h3>Step 3: Combine your ingredients in a shaker</h3>                    <figure>                            <p class="bordeaux-image-check">                                <img    src="https://cdn.mos.cms.futurecdn.net/fXSWB3dSTwhQ4VEZrWuNbi.png"                                        alt="a photo of a copycat starbucks iced brown sugar oatmilk shaken espresso"                                        onerror="this.parentNode.replaceChild(window.missingImage(),this)"                                        data-pin-media="https://cdn.mos.cms.futurecdn.net/fXSWB3dSTwhQ4VEZrWuNbi.png"                                        class="expandable van-old-layout-image">                            </p><div class="credit">(Image: © Erin Bashford)</div></figure>                    <p><p>If you don't have a shaker, you could use a water bottle or even a leakproof Tupperware. </p><p>Add your espresso, syrup, ice, a splash of oat milk, and optional cinnamon if you like it a little warming. </p><p>Shake, pour, and you're done!</p></p>                </section>                    <div class= "tiktok-wrapper" style="min-height: 750px;"><blockquote class="tiktok-embed" cite="https://www.tiktok.com/@tomsguide/video/7668471634939874573" data-video-id="7668471634939874573" style="max-width: 605px; min-width: 325px;">                        <section>                            <a target="_blank" title="@tomsguide" href="https://www.tiktok.com/@tomsguide">@tomsguide</a>                            <p></p><a target="_blank" title="♬ electric piano bossa nova jazz(1392318) - Kenta Fukuoka" href="https://www.tiktok.com/music/electric-piano-bossa-nova-jazz-1392318-7211216288398444546">♬ electric piano bossa nova jazz(1392318) - Kenta Fukuoka</a></section>                    </blockquote></div>                <h2 id="the-coffee-math">The coffee math</h2><p>I hate math, but I love coffee math. Let's see if making your own Starbucks Iced Brown Sugar Oatmilk Shaken Espresso actually is cheaper — and how many times you have to make it yourself to break even.</p><h2 class="article-body__section" id="section-with-a-nespresso-machine"><span>With a Nespresso machine</span></h2><ol start="1"><li><strong>Nespresso Vertuo Pop+:</strong><a href="https://www.amazon.com/Nespresso-Espresso-Machine-DeLonghi-Liquorice/dp/B0DVD67F76" target="_blank" rel="nofollow"> $130 from Amazon</a></li><li><strong>Oat milk:</strong> <a href="https://www.walmart.com/ip/Planet-Oat-Oat-Milk-Velvety-Smooth-Barista-Lovers-52-fl-oz/5040429010" target="_blank" rel="nofollow">$3.32/52 fluid ounces from Walmart | 0.19 per drink</a></li><li><strong>Brown sugar:</strong> <a href="https://www.walmart.com/ip/Great-Value-Light-Brown-Sugar-32-oz/10315012" target="_blank" rel="nofollow">$2.02/32 ounces from Walmart | 0.01 per drink</a></li><li><strong>Coffee: </strong><a href="https://www.walmart.com/ip/Starbucks-By-Nespresso-Vertuo-Line-Starbucks-Blonde-Espresso-Roast-Nespresso-Pods-10-ct/348136846" target="_blank" rel="nofollow">Starbucks Blonde Nespresso Vertuo pods: $12.97 for 10 | 1.30 per pod</a></li></ol><p>So that's <strong>$1.50</strong> for the ingredients, $130 for the machine. </p><p>You’d need to drink 22 drinks to start making a profit. After that, it’s <strong>$6.07</strong> in savings per drink.</p><h2 class="article-body__section" id="section-with-an-espresso-machine-grinder"><span>With an espresso machine + grinder</span></h2><ol start="1"><li><strong>Breville Bambino:</strong><a href="https://www.amazon.com/Breville-Bambino-Espresso-Machine-Stainless/dp/B0B1JPPG2L" target="_blank" rel="nofollow"><strong> </strong>$299 from Amazon </a></li><li><strong>Baratza Encore ESP:</strong><a href="https://www.amazon.com/Baratza-Encore-Electric-Coffee-Grinder/dp/B0BW272XCV" target="_blank" rel="nofollow"> $199 from Amazon</a></li><li><strong>Starbucks Blonde whole bean coffee:</strong><a href="https://www.walmart.com/ip/Starbucks-Whole-Bean-Blonde-Espresso-Roast-Coffee-18-oz/17845554263" target="_blank" rel="nofollow"><strong> </strong>$17.13/18 ounces | $0.57 per drink</a></li><li><strong>Oat milk:</strong> <a href="https://www.walmart.com/ip/Planet-Oat-Oat-Milk-Velvety-Smooth-Barista-Lovers-52-fl-oz/5040429010" target="_blank" rel="nofollow">$3.32/52 fluid ounces from Walmart | 0.19 per drink</a></li><li><strong>Brown sugar:</strong> <a href="https://www.walmart.com/ip/Great-Value-Light-Brown-Sugar-32-oz/10315012" target="_blank" rel="nofollow">$2.02/32 ounces from Walmart | 0.01 per drink</a></li></ol><p>This version has a higher initial cost but cheaper overall ingredients: <strong>$0.77</strong> for the ingredients, $498 for the machines.</p><p>You'd need to drink 74 drinks to start making a profit. After that, it’s <strong>$6.80</strong> of pure savings each time.</p><p>If you already have an espresso machine, you're saving almost <strong>90%</strong> on every drink. </p><p>So, are you going to skip Starbucks and try making the Iced Brown Sugar Oatmilk Shaken Espresso at home? I only ever make it myself — I haven't been into a Starbucks in years. </p><p>Are there any other Starbucks drinks you'd like me to simplify? Perhaps the Pumpkin Spiced Latte in September? Or the Eggnog latte in December? Let me know in the comments!</p><p>I post new episodes of The Coffee Lab every Friday, so be sure to check back next week.</p><figure class="inline-layout"><div style="min-height: 400px;"><fw-embed-feed channel="toms_guide" playlist="ojE0pK" mode="row" player_placement="bottom-right"></fw-embed-feed></div></figure><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h3><ul><li><a href="https://www.tomsguide.com/home/coffee-makers/i-tried-the-new-nespresso-summer-flavors-heres-my-favorite"><strong>I tried the new Nespresso summer flavors — here's my favorite</strong></a></li><li><a href="https://www.tomsguide.com/home/coffee-makers/non-plastic-coffee-makers-are-trending-and-this-low-plastic-ratio-model-is-my-favorite-for-coffee-snobs"><strong>Non-plastic coffee makers are trending — and this low-plastic Ratio model is my favorite for coffee snobs</strong></a></li><li><a href="https://www.tomsguide.com/home/coffee-makers/i-tried-lelits-brand-new-entry-level-espresso-machine-and-i-wish-i-had-usd2-000-so-i-could-buy-it"><strong>I tried Lelit's brand-new 'entry-level' espresso machine — and I wish I had $2,000 so I could buy it</strong></a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/home/coffee-makers/im-an-ex-starbucks-barista-you-can-make-the-iced-brown-sugar-oatmilk-shaken-espresso-at-home-for-a-fraction-of-the-cost</link>
                                                                            <description>
                            <![CDATA[ For the eighteenth episode of The Coffee Lab, I let you in on a little Starbucks secret and show you how to make one of my favorite summer drinks. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">hr5zsoC8LGSQvyLoVz7YiX</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/d9pDVVLQk5w4wu2EegDg49-1280-80.png" type="image/png" length="0"></enclosure>
                                                                        <pubDate>Fri, 31 Jul 2026 08:00:00 +0000</pubDate>                                                                                                                                <updated>Fri, 31 Jul 2026 14:53:28 +0000</updated>
                                                                                                                                            <category><![CDATA[Coffee Makers]]></category>
                                                    <category><![CDATA[Home]]></category>
                                                    <category><![CDATA[Home Appliances]]></category>
                                                    <category><![CDATA[Kitchen & Dining]]></category>
                                                                                                <author><![CDATA[ erin.bashford@futurenet.com (Erin Bashford) ]]></author>                    <dc:creator><![CDATA[ Erin Bashford ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/rLvJvJVZx43hEzSsJy3BpL.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Erin Bashford is a senior reviews writer at Tom’s Guide. She has a Master’s in Broadcast and Digital Journalism from the University of East Anglia and 7 years of experience reviewing music and events for various publications. She has edited publications such as Outline Magazine’s Guide to Norwich, and she has written for a number of music magazines and websites such as Clash Magazine, Outline Magazine and Dork Magazine. She has a strong interest in audio gear and the music world. &lt;/p&gt;&lt;p&gt;As an ex-barista, Erin is passionate about coffee tech. She also loves finding the best cooking hacks and kitchen appliances, including her beloved Instant Pot. &lt;/p&gt;&lt;p&gt;In her spare time, you can find her reading, practising yoga, hiking, writing fantasy novels, or stressing over NYT Games.&lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                <media:content type="image/png" url="https://cdn.mos.cms.futurecdn.net/d9pDVVLQk5w4wu2EegDg49-1280-80.png">
                                                            <media:credit><![CDATA[Erin Bashford]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[ingredients for the starbucks iced brown sugar oat milk espresso ]]></media:description>                                                            <media:text><![CDATA[ingredients for the starbucks iced brown sugar oat milk espresso ]]></media:text>
                                <media:title type="plain"><![CDATA[ingredients for the starbucks iced brown sugar oat milk espresso ]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/d9pDVVLQk5w4wu2EegDg49-1280-80.png" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <div  class="fancy-box"><div class="fancy_box-title">The Coffee Lab</div><div class="fancy_box_body"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' ><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="UwFdgr6xkNzHUWjapZThcN" name="smeg edited2" caption="" alt="the smeg emc02 mini pro manual espresso machine in jade green" src="https://cdn.mos.cms.futurecdn.net/UwFdgr6xkNzHUWjapZThcN.jpg" mos="" link="" align="" fullscreen="" width="" height="" attribution="" endorsement="" class="pinterest-pin-exclude"></p></div></div><figcaption itemprop="caption description" class=""><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p class="fancy-box__body-text">I'm Erin, and welcome to the eighteenth episode of <a data-analytics-id="inline-link" href="https://www.tomsguide.com/tag/the-coffee-lab">The Coffee Lab</a>, the series where we forget coffee snobbery. The Coffee Lab is all about making coffee fun. Join me as I help you kickstart your coffee journey!</p></div></div><p>Starbucks is expensive. There's no getting around that. Some drinks can cost as much as $10 in certain states these days, which is simply ridiculous. If I were to order a <a href="https://www.starbucks.com/menu" target="_blank" rel="nofollow">Grande Iced Brown Sugar Oatmilk Shaken Espresso at the Starbucks closest to Tom's Guide's Manhattan office</a>, it would cost me $7.57. Yes, almost 8 bucks.  </p><p>Fortunately, you can make it yourself, for far less. </p><p>I was a Starbucks barista for years, and learned how to make the delicious Starbucks Iced Brown Sugar Oatmilk Shaken Espresso at home. I've even done some coffee math down below to show you how much better this version is for your wallet (and your health, if you use homemade syrup). </p><p>You only need three ingredients (four if you count ice as an ingredient, and five if you include the optional cinnamon) to make a delicious iced espresso at home. And the best part? It takes about two minutes. Here's my step-by-step guide to making the Starbucks Iced Brown Sugar Oatmilk Shaken Espresso at home, using the <a href="https://www.tomsguide.com/home/coffee-makers/nespresso-vertuo-up-review">Nespresso Vertuo Up</a>, Oatly Barista oat milk, homemade brown sugar syrup, ice, and cinnamon.</p><section class="howto-block">                    <h3>Step 1: Make your brown sugar syrup</h3>                    <figure>                            <p class="bordeaux-image-check">                                <img    src="https://cdn.mos.cms.futurecdn.net/LcZBZmCGRqRiaXyzQ9iQHi.png"                                        alt="a photo of a copycat starbucks iced brown sugar oatmilk shaken espresso"                                        onerror="this.parentNode.replaceChild(window.missingImage(),this)"                                        data-pin-media="https://cdn.mos.cms.futurecdn.net/LcZBZmCGRqRiaXyzQ9iQHi.png"                                        class="expandable van-old-layout-image">                            </p><div class="credit">(Image: © Erin Bashford)</div></figure>                    <p><p>I opted to make my own syrup for two reasons. One: brown sugar syrup isn't readily available where I live, and two: I know the exact ingredients, so no surprises here. </p><p>Simply add your desired amount of sugar and a tiny drop of hot water to melt the sugar. If you have a sweet tooth, this might be 10g. I used one teaspoon, so 5g. </p></p>                </section><section class="howto-block">                    <h3>Step 2: Make your espresso</h3>                    <figure>                            <p class="bordeaux-image-check">                                <img    src="https://cdn.mos.cms.futurecdn.net/4MKv3iawqik6msXULAPCJi.png"                                        alt="a photo of a copycat starbucks iced brown sugar oatmilk shaken espresso"                                        onerror="this.parentNode.replaceChild(window.missingImage(),this)"                                        data-pin-media="https://cdn.mos.cms.futurecdn.net/4MKv3iawqik6msXULAPCJi.png"                                        class="expandable van-old-layout-image">                            </p><div class="credit">(Image: © Erin Bashford)</div></figure>                    <p><p>Starbucks uses Blonde roast for the Iced Brown Sugar Oatmilk Shaken Espresso, so I'd recommend using a light or medium roast coffee with notes like citrus, cherry, caramel, or fruit to achieve a similar result. </p><p>Of course, you could simply buy Blonde roast from your local Starbucks. </p><p>I'd recommend a double shot here, so use around 18g of finely ground coffee for 36g espresso. I used the Oatly Nespresso pods for this video using my Nespresso Vertuo Up.</p></p>                </section><section class="howto-block">                    <h3>Step 3: Combine your ingredients in a shaker</h3>                    <figure>                            <p class="bordeaux-image-check">                                <img    src="https://cdn.mos.cms.futurecdn.net/fXSWB3dSTwhQ4VEZrWuNbi.png"                                        alt="a photo of a copycat starbucks iced brown sugar oatmilk shaken espresso"                                        onerror="this.parentNode.replaceChild(window.missingImage(),this)"                                        data-pin-media="https://cdn.mos.cms.futurecdn.net/fXSWB3dSTwhQ4VEZrWuNbi.png"                                        class="expandable van-old-layout-image">                            </p><div class="credit">(Image: © Erin Bashford)</div></figure>                    <p><p>If you don't have a shaker, you could use a water bottle or even a leakproof Tupperware. </p><p>Add your espresso, syrup, ice, a splash of oat milk, and optional cinnamon if you like it a little warming. </p><p>Shake, pour, and you're done!</p></p>                </section>                    <div class= "tiktok-wrapper" style="min-height: 750px;"><blockquote class="tiktok-embed" cite="https://www.tiktok.com/@tomsguide/video/7668471634939874573" data-video-id="7668471634939874573" style="max-width: 605px; min-width: 325px;">                        <section>                            <a target="_blank" title="@tomsguide" href="https://www.tiktok.com/@tomsguide">@tomsguide</a>                            <p></p><a target="_blank" title="♬ electric piano bossa nova jazz(1392318) - Kenta Fukuoka" href="https://www.tiktok.com/music/electric-piano-bossa-nova-jazz-1392318-7211216288398444546">♬ electric piano bossa nova jazz(1392318) - Kenta Fukuoka</a></section>                    </blockquote></div>                <h2 id="the-coffee-math">The coffee math</h2><p>I hate math, but I love coffee math. Let's see if making your own Starbucks Iced Brown Sugar Oatmilk Shaken Espresso actually is cheaper — and how many times you have to make it yourself to break even.</p><h2 class="article-body__section" id="section-with-a-nespresso-machine"><span>With a Nespresso machine</span></h2><ol start="1"><li><strong>Nespresso Vertuo Pop+:</strong><a href="https://www.amazon.com/Nespresso-Espresso-Machine-DeLonghi-Liquorice/dp/B0DVD67F76" target="_blank" rel="nofollow"> $130 from Amazon</a></li><li><strong>Oat milk:</strong> <a href="https://www.walmart.com/ip/Planet-Oat-Oat-Milk-Velvety-Smooth-Barista-Lovers-52-fl-oz/5040429010" target="_blank" rel="nofollow">$3.32/52 fluid ounces from Walmart | 0.19 per drink</a></li><li><strong>Brown sugar:</strong> <a href="https://www.walmart.com/ip/Great-Value-Light-Brown-Sugar-32-oz/10315012" target="_blank" rel="nofollow">$2.02/32 ounces from Walmart | 0.01 per drink</a></li><li><strong>Coffee: </strong><a href="https://www.walmart.com/ip/Starbucks-By-Nespresso-Vertuo-Line-Starbucks-Blonde-Espresso-Roast-Nespresso-Pods-10-ct/348136846" target="_blank" rel="nofollow">Starbucks Blonde Nespresso Vertuo pods: $12.97 for 10 | 1.30 per pod</a></li></ol><p>So that's <strong>$1.50</strong> for the ingredients, $130 for the machine. </p><p>You’d need to drink 22 drinks to start making a profit. After that, it’s <strong>$6.07</strong> in savings per drink.</p><h2 class="article-body__section" id="section-with-an-espresso-machine-grinder"><span>With an espresso machine + grinder</span></h2><ol start="1"><li><strong>Breville Bambino:</strong><a href="https://www.amazon.com/Breville-Bambino-Espresso-Machine-Stainless/dp/B0B1JPPG2L" target="_blank" rel="nofollow"><strong> </strong>$299 from Amazon </a></li><li><strong>Baratza Encore ESP:</strong><a href="https://www.amazon.com/Baratza-Encore-Electric-Coffee-Grinder/dp/B0BW272XCV" target="_blank" rel="nofollow"> $199 from Amazon</a></li><li><strong>Starbucks Blonde whole bean coffee:</strong><a href="https://www.walmart.com/ip/Starbucks-Whole-Bean-Blonde-Espresso-Roast-Coffee-18-oz/17845554263" target="_blank" rel="nofollow"><strong> </strong>$17.13/18 ounces | $0.57 per drink</a></li><li><strong>Oat milk:</strong> <a href="https://www.walmart.com/ip/Planet-Oat-Oat-Milk-Velvety-Smooth-Barista-Lovers-52-fl-oz/5040429010" target="_blank" rel="nofollow">$3.32/52 fluid ounces from Walmart | 0.19 per drink</a></li><li><strong>Brown sugar:</strong> <a href="https://www.walmart.com/ip/Great-Value-Light-Brown-Sugar-32-oz/10315012" target="_blank" rel="nofollow">$2.02/32 ounces from Walmart | 0.01 per drink</a></li></ol><p>This version has a higher initial cost but cheaper overall ingredients: <strong>$0.77</strong> for the ingredients, $498 for the machines.</p><p>You'd need to drink 74 drinks to start making a profit. After that, it’s <strong>$6.80</strong> of pure savings each time.</p><p>If you already have an espresso machine, you're saving almost <strong>90%</strong> on every drink. </p><p>So, are you going to skip Starbucks and try making the Iced Brown Sugar Oatmilk Shaken Espresso at home? I only ever make it myself — I haven't been into a Starbucks in years. </p><p>Are there any other Starbucks drinks you'd like me to simplify? Perhaps the Pumpkin Spiced Latte in September? Or the Eggnog latte in December? Let me know in the comments!</p><p>I post new episodes of The Coffee Lab every Friday, so be sure to check back next week.</p><figure class="inline-layout"><div style="min-height: 400px;"><fw-embed-feed channel="toms_guide" playlist="ojE0pK" mode="row" player_placement="bottom-right"></fw-embed-feed></div></figure><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h3><ul><li><a href="https://www.tomsguide.com/home/coffee-makers/i-tried-the-new-nespresso-summer-flavors-heres-my-favorite"><strong>I tried the new Nespresso summer flavors — here's my favorite</strong></a></li><li><a href="https://www.tomsguide.com/home/coffee-makers/non-plastic-coffee-makers-are-trending-and-this-low-plastic-ratio-model-is-my-favorite-for-coffee-snobs"><strong>Non-plastic coffee makers are trending — and this low-plastic Ratio model is my favorite for coffee snobs</strong></a></li><li><a href="https://www.tomsguide.com/home/coffee-makers/i-tried-lelits-brand-new-entry-level-espresso-machine-and-i-wish-i-had-usd2-000-so-i-could-buy-it"><strong>I tried Lelit's brand-new 'entry-level' espresso machine — and I wish I had $2,000 so I could buy it</strong></a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ HelloFresh Australia review: flexible, fuss-free meal options, but not always the best bang for your buck ]]></title>
                                                                                                <dc:content><![CDATA[ <p>As much as I consider myself a whiz in the kitchen, for me, there's nothing worse than having to think about what's for dinner every night. I'm frequently indecisive, can't commit to meal prep for fear of taste bud boredom, and I would much rather scroll through DoorDash than try to piece together a meal from ingredients in my pantry. </p><p>When the opportunity arose to try out HelloFresh Australia for a month, I was ecstatic. I'm no stranger to HelloFresh (and its subsidiaries, YouFoodz and EveryPlate), as it consistently ranks as one of the best meal kit delivery services globally. It takes the hassle out of dinnertime by menu planning and food shopping for you. The service handpicks ingredients, organises timely deliveries and offers you meals from an expansive catalogue of weekly recipes. </p><p>To put HelloFresh to the test, I whipped out my chef hat, dusted off my somewhat dormant cooking skills and selected a variety of recipes for my two-person household. Do note, though, HelloFresh expects that subscribers have some culinary staples and cooking experience in the kitchen to get the most out of it. That said, if you've cut a carrot or minced some garlic before, you've surely got enough skill for this beginner-friendly meal kit. </p><p>I'll stop with the waffling now — here's how I fared during my monthlong review of HelloFresh AU. </p><h3 class="article-body__section" id="section-hellofresh-australia-review-price-and-availability"><span>HelloFresh Australia review: price and availability </span></h3><p>Much like other meal-kit providers, prices for HelloFresh will differ depending on how many meals per week you order and how many people you need to feed. The total per-serve cost typically goes down when you opt for more meals. </p><p>HelloFresh offers meal kit subscriptions for two to six people, with options of two to six recipes. I purchased six meals for two people to get the most out of HelloFresh's huge weekly menu. It cost AU$136.50 plus shipping per week, which worked out to AU$11.37 per person per serve. </p><p>You can add bonus meals to your plan for an additional out-of-pocket cost. For example, one week, I opted to include another meal on top of our six recipe plan. It worked out to AU$157.68 or AU$11.26 per person, per serve. It's not the biggest saving — 11 cents per serve — but if you had more mouths to feed, the cost per serving would be significantly less. As per HelloFresh, the cost per serve for a four-person, six-meal week is AU$9.29 (or AU$223 total) and the cost per serve for a six-person, six-meal week is AU$8.83 (or AU$318 total). </p><p>You can also add one-off desserts, sides, snacks and family-style catering meals to your plan for an additional fee. HelloFresh owns YouFoodz, a convenience-based meal subscription service, so there were a few ready meal options to choose from in the weekly menu as well. </p><p>When compared to the cost of groceries, HelloFresh costs slightly less than our usual AU$200 two-person weekly shop, and it is definitely cheaper per serve than getting our local Chinese takeaway, which is AU$35 for our order. We still had some change leftover to nab our weekly essentials, lunch and snacks. </p><p>That said, larger families might get more bang for their buck by heading to the supermarket, as there are more meals than dinner to consider. According to Finder, the <a href="https://www.finder.com.au/budgeting/average-grocery-bill#average-cost-of-groceries-by-household-size" target="_blank" rel="nofollow">average cost of groceries for a family of four is AU$274 per week</a>, so the AU$223 HelloFresh box cost that only covers dinnertime meals might not provide the best value for money. </p><p>It is also worth noting that HelloFresh frequently provides discount codes and free delivery for new subscribers. These discounts usually knock off savings over the course of four deliveries, making prices more affordable to try out for a short period.</p><h3 class="article-body__section" id="section-hellofresh-australia-review-delivery-and-customer-service"><span>HelloFresh Australia review: Delivery and customer service</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:4097px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="7MMivnCL5gTnPvaUvNKWok" name="hellofresh-1" alt="HelloFresh Box" src="https://cdn.mos.cms.futurecdn.net/7MMivnCL5gTnPvaUvNKWok.jpg" mos="" align="middle" fullscreen="" width="4097" height="2305" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Lucy Scotting)</span></figcaption></figure><p>Delivery for HelloFresh is a rather seamless process. Deliveries can occur on any given day during the week, depending on your area, and are conducted via a third-party service. You also don't need to be home to accept the delivery, as the service will leave your box in a safe location. HelloFresh delivers to most metro, regional and rural suburbs around mainland Australia, but it doesn't currently offer delivery to Tasmania. </p><p>In my case, I could organise delivery for either Wednesday or Sunday, during two timeframes of either early morning (between 12am and 4am) or during the day (between 8am and 12pm). For greater context, my colleague in a neighbouring suburb could only select the early morning timeslot on a Sunday, so I’d highly recommend researching delivery days and times available in your area before you commit to HelloFresh. Additionally, I paid AU$11.99 on top of my boxes for delivery. The fee was initially waived for my first two boxes, as part of a free delivery promotion. </p><p>Subscribers can also adjust or skip weekly orders any time up until five days before the expected delivery date. This is particularly useful if you’re away from home for any period of time and simply want to hit pause on your HelloFresh subscription.</p><p>In the highly unlikely event that anything happens to your subscription box — such as it arrives with out-of-date ingredients or missing items — you can contact HelloFresh's customer support team. It is worth noting that you won't necessarily receive a replacement box or ingredient; however, the team will likely give you a credit or refund should anything go awry. </p><h3 class="article-body__section" id="section-hellofresh-australia-review-meals"><span>HelloFresh Australia review: Meals</span></h3><p>HelloFresh Australia offers over 45 fresh recipes to choose from in its weekly menu and it varies week to week. Meals fall into different menu categories to cater to dietary needs and preferences. These include: Classic, Vegetarian, Family-friendly, Calorie Smart, Quick & Easy, Carb Smart, Flexitarian and Protein Rich. You can also opt for air-fryer-friendly options or dinners that will take 30 minutes or less to prepare for the ultimate convenience factor. </p><p>I selected meals from the Carb Smart and Calorie Smart menus, which feature a variety of cuisines and cater to those who want more balanced dinners with lower carbohydrates and calories. I also selected some heat-and-eat options (more on that below) for late nights when I craved a lazy, decision-free dinner. </p><a href="https://www.hellofresh.com.au/"><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:3054px;"><p class="vanilla-image-block" style="padding-top:49.18%;"><img id="hZCNBgndG962v7wBhFP8za" name="Screenshot 2026-05-11 at 12.43.10 pm" alt="Screenshot of HelloFresh AU menu" src="https://cdn.mos.cms.futurecdn.net/hZCNBgndG962v7wBhFP8za.png" mos="" align="middle" fullscreen="" width="3054" height="1502" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="caption-text">An example of my preselected meals during my HelloFresh review </span><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Lucy Scotting)</span></figcaption></figure></a><p>Your menu each week is automatically populated with preselected meals that HelloFresh recommends according to your chosen menu and previous orders. However, you have free rein to chop and change meals as you see fit by unselecting them and choosing another option from the recipes on offer. </p><p>You shouldn’t expect an entirely fresh menu each week, as HelloFresh will reuse the same dishes week to week. For example, there were some repeat preselected meals in the final week of my subscription, but I simply opted not to include them. For the most part, there were few, if any, duplicate recipes each week, which was ideal for my foodie taste buds. </p><p>I gravitated towards Asian-inspired dishes, quick dinners and easy, but delicious protein-based recipes throughout my review. Out of the 26 recipes I made, my favourites included Chermoula Honey Roast Lamb, Salt'n'Pepper Salmon and Lemony Greens, Homestyle Chicken Schnitzel and Mustard Mayo and Singaporean Prawn and Noodle Stir Fry. </p><p>It’s also worth mentioning that HelloFresh does an excellent job with clearly listing allergen information for its recipes, with details on its website and app for each recipe. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:3222px;"><p class="vanilla-image-block" style="padding-top:53.63%;"><img id="4xkEDSNZGripqCcFgn8njZ" name="Screenshot 2026-05-11 at 12.43.32 pm" alt="Screenshot of HelloFresh AU menu" src="https://cdn.mos.cms.futurecdn.net/4xkEDSNZGripqCcFgn8njZ.png" mos="" align="middle" fullscreen="" width="3222" height="1728" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Lucy Scotting)</span></figcaption></figure><p>On the subject of allergens, when you browse the menu on either the website or app, not only can you filter dishes by cuisine, but you can select ingredient types to not include. The only slight issue I found with this is that nuts, for example, is listed as a singular category. If you’re allergic to peanuts, say, but can eat cashews and almonds, you can’t filter to such a granular level.</p><p>You can also swap out the default protein in the meals for something else, if you'd prefer. For our chosen menu, our preselected options usually included chicken, so we opted to swap for pork or salmon a few times. You can also swap chicken thigh for chicken tenderloins or breast, for example, if you prefer white meat. </p><h3 class="article-body__section" id="section-hellofresh-australia-review-recipes-and-ingredients"><span>HelloFresh Australia review: Recipes and ingredients</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:5210px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="apFd732QqyUzzChJW5ZMzm" name="hellofresh-5" alt="Hellofresh box with recipe cards" src="https://cdn.mos.cms.futurecdn.net/apFd732QqyUzzChJW5ZMzm.jpg" mos="" align="middle" fullscreen="" width="5210" height="2931" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Lucy Scotting)</span></figcaption></figure><p>Inside the box, HelloFresh ingredients are packaged in brown paper bags with a corresponding number for each recipe card. The cold ingredients — i.e. meat and dairy products — are stored separately in an insulated cold bag with ice packs. This bag isn’t sealed, which I found a little disappointing, because if you’re able to receive the box for some time and it’s left outside, it could be more susceptible to warming up. The box also includes some discount codes for friends and family, as well as discounts for other businesses supported by HelloFresh. All the ingredients I received came fresh with no issues and didn't go to waste. </p><p>Each bag provides most — but not all — ingredients for the recipe. You'll need to have some basic kitchen staples on hand, like butter, oil, salt and pepper. You'll also need utensils, like sharp knives, pots, pans and cooking utensils to make each dish. For most recipes, I had everything I needed, but I had to purchase white wine vinegar before making two meals. You can also check the recipes online to make sure you have any extra ingredients ready to go. </p><p>The recipe cards are pretty straightforward and easy to follow, with some even offering handy kitchen tips. There's a handy picture guide that walks you through step-by-step, and there's even a QR code so you can read the recipe online if you'd prefer. And, while it didn’t apply to my household, I appreciated HelloFresh offering tips aimed at children who may want to get involved with the cooking process.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:3432px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="umKajccZk7gxbQAqH393Wk" name="hellofresh-7" alt="Hellofresh salad" src="https://cdn.mos.cms.futurecdn.net/umKajccZk7gxbQAqH393Wk.jpg" mos="" align="middle" fullscreen="" width="3432" height="1930" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Lucy Scotting)</span></figcaption></figure><p>Throughout my review, I found estimated prep times to be accurate, but you might need to budget more time if you're new to cooking or specific techniques. There was only one instance where I felt it was a bit off. For example, when roasting lamb for the Chermoula Honey Roast Lamb recipe, I was instructed to sear the lamb rump for 12 minutes in a pan before transferring it to the oven for an additional 25 minutes. </p><p>At the time, I had not roasted or seared lamb before, so I had little experience of what it should look like. It took me a while longer — around 16 minutes to full sear — pushing out the prep time to around 57 minutes, instead of the budgeted 40 minutes. Despite this minor hiccup, the meal turned out perfectly. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:3006px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="CwLF555Q3oveEmNivhwe8k" name="hellofresh-6" alt="HelloFresh meal preparation" src="https://cdn.mos.cms.futurecdn.net/CwLF555Q3oveEmNivhwe8k.jpg" mos="" align="middle" fullscreen="" width="3006" height="1691" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Lucy Scotting)</span></figcaption></figure><p>Another meal we particularly enjoyed was the Crumbed Mexi-Spiced Chicken & Corn Tacos, which came with a small bottle of Cholula hot sauce. This meal was made easy by using an air fryer to cook the chicken, and came with a can of sweet corn for ease. If you don't own an air fryer, the recipe also provides details on how to pan-fry the chicken. </p><p>The recipe gave me great advice on how to crumb the chicken without making too much of a mess — by separating the crumbs, spices and egg into separate bowls — and how to chargrill the corn with a pan without burning it. This recipe budgeted 25 minutes from start to finish, and it was pretty accurate. </p><figure role="gallery"><figure><img src="https://cdn.mos.cms.futurecdn.net/4Cp74LdyduMHCbcQ9Dhj5m.jpg" alt="Hand holding Hellofresh meal" /><figcaption>An example of HelloFresh AU's ready meal selection<small role="credit">Future / Lucy Scotting</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/L2kVTUPyatyXj4VQtvZrJn.jpg" alt="Hellofresh ready meal plated" /><figcaption>HelloFresh's ready meal plated<small role="credit">Future / Lucy Scotting</small></figcaption></figure></figure><p>Further, I did opt to include some ready meal pasta dishes to our weekly boxes and it was very interesting to say the least. As someone who had tried YouFoodz before, I was familiar with some of the recipes, and the options that HelloFresh had to offer were very much in line with the previous YouFoodz I've had. I did use these for a lazy dinner on a few evenings, and the instructions were as simple as expected — peel back the lid and pop it in the microwave for 3 minutes on high. Flavour-wise, the meals were pretty good and satisfied my hunger, but they definitely weren't Michelin-rated. </p><p>The only real gripe we had was flavour and portion sizes. We're self-proclaimed foodies, and love trying new dishes, so we were thrilled to have such a range of cuisines to choose from. However, we found we need to add more than just the provided spice mixes to enhance dishes. The flavour depth was slightly lacking, which might disappoint those who prefer bold, heavy seasoning. </p><p>The other niggle we had was portion sizes. As you can imagine, being foodies means we like to eat and some of our protein portions didn't quite sustain us. In some cases, we ended up making two meals and eating them family style to feel fulfilled. Now, HelloFresh suggests opting for a larger meal kit size if you're worried about this, but you can always upgrade or downgrade your plan at any time. There are some recipes that come with 'premium' protein ingredients for an additional fee, too, with larger meat/protein allocations, but we didn't feel the need to pay for these recipes. </p><h3 class="article-body__section" id="section-hellofresh-australia-review-verdict"><span>HelloFresh Australia review: Verdict</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:3389px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="N3SiNJESmjapAnSDPEd9Lk" name="hellofresh-8" alt="HelloFresh meals on plates" src="https://cdn.mos.cms.futurecdn.net/N3SiNJESmjapAnSDPEd9Lk.jpg" mos="" align="middle" fullscreen="" width="3389" height="1906" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Lucy Scotting)</span></figcaption></figure><p>HelloFresh does exactly what you expect — takes the stress out of figuring out weekly dinners and offers the convenience of handpicked ingredients. I still had plenty of choice in what meals we got in every week, but it took immense pressure off hitting the shops after a long workday. Plus, with constant coupons offering savings for new subscribers, you could spend less than you would on takeaway every week. </p><p>Aside from that, the delivery was pretty seamless and I had no issue with editing meals or my order at any time in the lead-up to my next box. That said, I did spend some extra time prepping than allocated in some recipe cards, and portion sizes felt small, but overall, HelloFresh's meal kits didn't disappoint. And now with a more expanded range that includes air fryer-friendly meals and heat-and-eat dinners, there's much more accessibility on offer with HelloFresh's service. </p><p>So if you're looking for a simple and easy alternative to indecisive dinners, HelloFresh is a subscription box to consider.</p> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/homes/hellofresh-australia-review</link>
                                                                            <description>
                            <![CDATA[ Is HelloFresh Australia worth it in 2026? I put the meal kit subscription service to the test for value, variety and prep time. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">MxLqFrQts68YNtPazRBsN7</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/sEosoxQQmBfBczP4hYRRfj-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Fri, 31 Jul 2026 02:14:37 +0000</pubDate>                                                                                                                                <updated>Fri, 31 Jul 2026 02:16:36 +0000</updated>
                                                                                                                                            <category><![CDATA[Kitchen & Dining]]></category>
                                                    <category><![CDATA[Home]]></category>
                                                    <category><![CDATA[Home Appliances]]></category>
                                                                                                <author><![CDATA[ lucy.scotting@futurenet.com (Lucy Scotting) ]]></author>                    <dc:creator><![CDATA[ Lucy Scotting ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/UC9ncAYxkmJ5ipHEyX44ri.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Lucy Scotting is a staff writer for Tom’s Guide Australia, primarily covering lifestyle, streaming and internet-related news. Lucy started her career writing for HR and staffing industry publications, with articles covering emerging tech, business and finance.&lt;/p&gt;&lt;p&gt;In her spare time, Lucy can be found watching sci-fi movies, working on her dystopian fiction novel (in progress since 2017) or hanging out with her dog, Fletcher. If she’s not found doing any of the above, she’s likely on her next adventure to a new city, country, or continent. &lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/sEosoxQQmBfBczP4hYRRfj-1280-80.jpg">
                                                            <media:credit><![CDATA[HelloFresh]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Hellofresh box with vegetables]]></media:description>                                                            <media:text><![CDATA[Hellofresh box with vegetables]]></media:text>
                                <media:title type="plain"><![CDATA[Hellofresh box with vegetables]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/sEosoxQQmBfBczP4hYRRfj-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>As much as I consider myself a whiz in the kitchen, for me, there's nothing worse than having to think about what's for dinner every night. I'm frequently indecisive, can't commit to meal prep for fear of taste bud boredom, and I would much rather scroll through DoorDash than try to piece together a meal from ingredients in my pantry. </p><p>When the opportunity arose to try out HelloFresh Australia for a month, I was ecstatic. I'm no stranger to HelloFresh (and its subsidiaries, YouFoodz and EveryPlate), as it consistently ranks as one of the best meal kit delivery services globally. It takes the hassle out of dinnertime by menu planning and food shopping for you. The service handpicks ingredients, organises timely deliveries and offers you meals from an expansive catalogue of weekly recipes. </p><p>To put HelloFresh to the test, I whipped out my chef hat, dusted off my somewhat dormant cooking skills and selected a variety of recipes for my two-person household. Do note, though, HelloFresh expects that subscribers have some culinary staples and cooking experience in the kitchen to get the most out of it. That said, if you've cut a carrot or minced some garlic before, you've surely got enough skill for this beginner-friendly meal kit. </p><p>I'll stop with the waffling now — here's how I fared during my monthlong review of HelloFresh AU. </p><h3 class="article-body__section" id="section-hellofresh-australia-review-price-and-availability"><span>HelloFresh Australia review: price and availability </span></h3><p>Much like other meal-kit providers, prices for HelloFresh will differ depending on how many meals per week you order and how many people you need to feed. The total per-serve cost typically goes down when you opt for more meals. </p><p>HelloFresh offers meal kit subscriptions for two to six people, with options of two to six recipes. I purchased six meals for two people to get the most out of HelloFresh's huge weekly menu. It cost AU$136.50 plus shipping per week, which worked out to AU$11.37 per person per serve. </p><p>You can add bonus meals to your plan for an additional out-of-pocket cost. For example, one week, I opted to include another meal on top of our six recipe plan. It worked out to AU$157.68 or AU$11.26 per person, per serve. It's not the biggest saving — 11 cents per serve — but if you had more mouths to feed, the cost per serving would be significantly less. As per HelloFresh, the cost per serve for a four-person, six-meal week is AU$9.29 (or AU$223 total) and the cost per serve for a six-person, six-meal week is AU$8.83 (or AU$318 total). </p><p>You can also add one-off desserts, sides, snacks and family-style catering meals to your plan for an additional fee. HelloFresh owns YouFoodz, a convenience-based meal subscription service, so there were a few ready meal options to choose from in the weekly menu as well. </p><p>When compared to the cost of groceries, HelloFresh costs slightly less than our usual AU$200 two-person weekly shop, and it is definitely cheaper per serve than getting our local Chinese takeaway, which is AU$35 for our order. We still had some change leftover to nab our weekly essentials, lunch and snacks. </p><p>That said, larger families might get more bang for their buck by heading to the supermarket, as there are more meals than dinner to consider. According to Finder, the <a href="https://www.finder.com.au/budgeting/average-grocery-bill#average-cost-of-groceries-by-household-size" target="_blank" rel="nofollow">average cost of groceries for a family of four is AU$274 per week</a>, so the AU$223 HelloFresh box cost that only covers dinnertime meals might not provide the best value for money. </p><p>It is also worth noting that HelloFresh frequently provides discount codes and free delivery for new subscribers. These discounts usually knock off savings over the course of four deliveries, making prices more affordable to try out for a short period.</p><h3 class="article-body__section" id="section-hellofresh-australia-review-delivery-and-customer-service"><span>HelloFresh Australia review: Delivery and customer service</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:4097px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="7MMivnCL5gTnPvaUvNKWok" name="hellofresh-1" alt="HelloFresh Box" src="https://cdn.mos.cms.futurecdn.net/7MMivnCL5gTnPvaUvNKWok.jpg" mos="" align="middle" fullscreen="" width="4097" height="2305" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Lucy Scotting)</span></figcaption></figure><p>Delivery for HelloFresh is a rather seamless process. Deliveries can occur on any given day during the week, depending on your area, and are conducted via a third-party service. You also don't need to be home to accept the delivery, as the service will leave your box in a safe location. HelloFresh delivers to most metro, regional and rural suburbs around mainland Australia, but it doesn't currently offer delivery to Tasmania. </p><p>In my case, I could organise delivery for either Wednesday or Sunday, during two timeframes of either early morning (between 12am and 4am) or during the day (between 8am and 12pm). For greater context, my colleague in a neighbouring suburb could only select the early morning timeslot on a Sunday, so I’d highly recommend researching delivery days and times available in your area before you commit to HelloFresh. Additionally, I paid AU$11.99 on top of my boxes for delivery. The fee was initially waived for my first two boxes, as part of a free delivery promotion. </p><p>Subscribers can also adjust or skip weekly orders any time up until five days before the expected delivery date. This is particularly useful if you’re away from home for any period of time and simply want to hit pause on your HelloFresh subscription.</p><p>In the highly unlikely event that anything happens to your subscription box — such as it arrives with out-of-date ingredients or missing items — you can contact HelloFresh's customer support team. It is worth noting that you won't necessarily receive a replacement box or ingredient; however, the team will likely give you a credit or refund should anything go awry. </p><h3 class="article-body__section" id="section-hellofresh-australia-review-meals"><span>HelloFresh Australia review: Meals</span></h3><p>HelloFresh Australia offers over 45 fresh recipes to choose from in its weekly menu and it varies week to week. Meals fall into different menu categories to cater to dietary needs and preferences. These include: Classic, Vegetarian, Family-friendly, Calorie Smart, Quick & Easy, Carb Smart, Flexitarian and Protein Rich. You can also opt for air-fryer-friendly options or dinners that will take 30 minutes or less to prepare for the ultimate convenience factor. </p><p>I selected meals from the Carb Smart and Calorie Smart menus, which feature a variety of cuisines and cater to those who want more balanced dinners with lower carbohydrates and calories. I also selected some heat-and-eat options (more on that below) for late nights when I craved a lazy, decision-free dinner. </p><a href="https://www.hellofresh.com.au/"><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:3054px;"><p class="vanilla-image-block" style="padding-top:49.18%;"><img id="hZCNBgndG962v7wBhFP8za" name="Screenshot 2026-05-11 at 12.43.10 pm" alt="Screenshot of HelloFresh AU menu" src="https://cdn.mos.cms.futurecdn.net/hZCNBgndG962v7wBhFP8za.png" mos="" align="middle" fullscreen="" width="3054" height="1502" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="caption-text">An example of my preselected meals during my HelloFresh review </span><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Lucy Scotting)</span></figcaption></figure></a><p>Your menu each week is automatically populated with preselected meals that HelloFresh recommends according to your chosen menu and previous orders. However, you have free rein to chop and change meals as you see fit by unselecting them and choosing another option from the recipes on offer. </p><p>You shouldn’t expect an entirely fresh menu each week, as HelloFresh will reuse the same dishes week to week. For example, there were some repeat preselected meals in the final week of my subscription, but I simply opted not to include them. For the most part, there were few, if any, duplicate recipes each week, which was ideal for my foodie taste buds. </p><p>I gravitated towards Asian-inspired dishes, quick dinners and easy, but delicious protein-based recipes throughout my review. Out of the 26 recipes I made, my favourites included Chermoula Honey Roast Lamb, Salt'n'Pepper Salmon and Lemony Greens, Homestyle Chicken Schnitzel and Mustard Mayo and Singaporean Prawn and Noodle Stir Fry. </p><p>It’s also worth mentioning that HelloFresh does an excellent job with clearly listing allergen information for its recipes, with details on its website and app for each recipe. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:3222px;"><p class="vanilla-image-block" style="padding-top:53.63%;"><img id="4xkEDSNZGripqCcFgn8njZ" name="Screenshot 2026-05-11 at 12.43.32 pm" alt="Screenshot of HelloFresh AU menu" src="https://cdn.mos.cms.futurecdn.net/4xkEDSNZGripqCcFgn8njZ.png" mos="" align="middle" fullscreen="" width="3222" height="1728" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Lucy Scotting)</span></figcaption></figure><p>On the subject of allergens, when you browse the menu on either the website or app, not only can you filter dishes by cuisine, but you can select ingredient types to not include. The only slight issue I found with this is that nuts, for example, is listed as a singular category. If you’re allergic to peanuts, say, but can eat cashews and almonds, you can’t filter to such a granular level.</p><p>You can also swap out the default protein in the meals for something else, if you'd prefer. For our chosen menu, our preselected options usually included chicken, so we opted to swap for pork or salmon a few times. You can also swap chicken thigh for chicken tenderloins or breast, for example, if you prefer white meat. </p><h3 class="article-body__section" id="section-hellofresh-australia-review-recipes-and-ingredients"><span>HelloFresh Australia review: Recipes and ingredients</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:5210px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="apFd732QqyUzzChJW5ZMzm" name="hellofresh-5" alt="Hellofresh box with recipe cards" src="https://cdn.mos.cms.futurecdn.net/apFd732QqyUzzChJW5ZMzm.jpg" mos="" align="middle" fullscreen="" width="5210" height="2931" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Lucy Scotting)</span></figcaption></figure><p>Inside the box, HelloFresh ingredients are packaged in brown paper bags with a corresponding number for each recipe card. The cold ingredients — i.e. meat and dairy products — are stored separately in an insulated cold bag with ice packs. This bag isn’t sealed, which I found a little disappointing, because if you’re able to receive the box for some time and it’s left outside, it could be more susceptible to warming up. The box also includes some discount codes for friends and family, as well as discounts for other businesses supported by HelloFresh. All the ingredients I received came fresh with no issues and didn't go to waste. </p><p>Each bag provides most — but not all — ingredients for the recipe. You'll need to have some basic kitchen staples on hand, like butter, oil, salt and pepper. You'll also need utensils, like sharp knives, pots, pans and cooking utensils to make each dish. For most recipes, I had everything I needed, but I had to purchase white wine vinegar before making two meals. You can also check the recipes online to make sure you have any extra ingredients ready to go. </p><p>The recipe cards are pretty straightforward and easy to follow, with some even offering handy kitchen tips. There's a handy picture guide that walks you through step-by-step, and there's even a QR code so you can read the recipe online if you'd prefer. And, while it didn’t apply to my household, I appreciated HelloFresh offering tips aimed at children who may want to get involved with the cooking process.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:3432px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="umKajccZk7gxbQAqH393Wk" name="hellofresh-7" alt="Hellofresh salad" src="https://cdn.mos.cms.futurecdn.net/umKajccZk7gxbQAqH393Wk.jpg" mos="" align="middle" fullscreen="" width="3432" height="1930" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Lucy Scotting)</span></figcaption></figure><p>Throughout my review, I found estimated prep times to be accurate, but you might need to budget more time if you're new to cooking or specific techniques. There was only one instance where I felt it was a bit off. For example, when roasting lamb for the Chermoula Honey Roast Lamb recipe, I was instructed to sear the lamb rump for 12 minutes in a pan before transferring it to the oven for an additional 25 minutes. </p><p>At the time, I had not roasted or seared lamb before, so I had little experience of what it should look like. It took me a while longer — around 16 minutes to full sear — pushing out the prep time to around 57 minutes, instead of the budgeted 40 minutes. Despite this minor hiccup, the meal turned out perfectly. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:3006px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="CwLF555Q3oveEmNivhwe8k" name="hellofresh-6" alt="HelloFresh meal preparation" src="https://cdn.mos.cms.futurecdn.net/CwLF555Q3oveEmNivhwe8k.jpg" mos="" align="middle" fullscreen="" width="3006" height="1691" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Lucy Scotting)</span></figcaption></figure><p>Another meal we particularly enjoyed was the Crumbed Mexi-Spiced Chicken & Corn Tacos, which came with a small bottle of Cholula hot sauce. This meal was made easy by using an air fryer to cook the chicken, and came with a can of sweet corn for ease. If you don't own an air fryer, the recipe also provides details on how to pan-fry the chicken. </p><p>The recipe gave me great advice on how to crumb the chicken without making too much of a mess — by separating the crumbs, spices and egg into separate bowls — and how to chargrill the corn with a pan without burning it. This recipe budgeted 25 minutes from start to finish, and it was pretty accurate. </p><figure role="gallery"><figure><img src="https://cdn.mos.cms.futurecdn.net/4Cp74LdyduMHCbcQ9Dhj5m.jpg" alt="Hand holding Hellofresh meal" /><figcaption>An example of HelloFresh AU's ready meal selection<small role="credit">Future / Lucy Scotting</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/L2kVTUPyatyXj4VQtvZrJn.jpg" alt="Hellofresh ready meal plated" /><figcaption>HelloFresh's ready meal plated<small role="credit">Future / Lucy Scotting</small></figcaption></figure></figure><p>Further, I did opt to include some ready meal pasta dishes to our weekly boxes and it was very interesting to say the least. As someone who had tried YouFoodz before, I was familiar with some of the recipes, and the options that HelloFresh had to offer were very much in line with the previous YouFoodz I've had. I did use these for a lazy dinner on a few evenings, and the instructions were as simple as expected — peel back the lid and pop it in the microwave for 3 minutes on high. Flavour-wise, the meals were pretty good and satisfied my hunger, but they definitely weren't Michelin-rated. </p><p>The only real gripe we had was flavour and portion sizes. We're self-proclaimed foodies, and love trying new dishes, so we were thrilled to have such a range of cuisines to choose from. However, we found we need to add more than just the provided spice mixes to enhance dishes. The flavour depth was slightly lacking, which might disappoint those who prefer bold, heavy seasoning. </p><p>The other niggle we had was portion sizes. As you can imagine, being foodies means we like to eat and some of our protein portions didn't quite sustain us. In some cases, we ended up making two meals and eating them family style to feel fulfilled. Now, HelloFresh suggests opting for a larger meal kit size if you're worried about this, but you can always upgrade or downgrade your plan at any time. There are some recipes that come with 'premium' protein ingredients for an additional fee, too, with larger meat/protein allocations, but we didn't feel the need to pay for these recipes. </p><h3 class="article-body__section" id="section-hellofresh-australia-review-verdict"><span>HelloFresh Australia review: Verdict</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:3389px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="N3SiNJESmjapAnSDPEd9Lk" name="hellofresh-8" alt="HelloFresh meals on plates" src="https://cdn.mos.cms.futurecdn.net/N3SiNJESmjapAnSDPEd9Lk.jpg" mos="" align="middle" fullscreen="" width="3389" height="1906" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Lucy Scotting)</span></figcaption></figure><p>HelloFresh does exactly what you expect — takes the stress out of figuring out weekly dinners and offers the convenience of handpicked ingredients. I still had plenty of choice in what meals we got in every week, but it took immense pressure off hitting the shops after a long workday. Plus, with constant coupons offering savings for new subscribers, you could spend less than you would on takeaway every week. </p><p>Aside from that, the delivery was pretty seamless and I had no issue with editing meals or my order at any time in the lead-up to my next box. That said, I did spend some extra time prepping than allocated in some recipe cards, and portion sizes felt small, but overall, HelloFresh's meal kits didn't disappoint. And now with a more expanded range that includes air fryer-friendly meals and heat-and-eat dinners, there's much more accessibility on offer with HelloFresh's service. </p><p>So if you're looking for a simple and easy alternative to indecisive dinners, HelloFresh is a subscription box to consider.</p>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ I meal prep every Sunday — these are the 9 kitchen tools I can't live without ]]></title>
                                                                                                <dc:content><![CDATA[ <p>I enjoy cooking — but not every single night. That's why Sunday meal prep has become a must for setting myself up for the week ahead. I'm not <em>always</em> this organized, but when I am, it makes busy weekdays so much easier (and a lot more enjoyable). And of course, I couldn't do it without a few of my favorite kitchen tools.</p><p>From the best food storage containers and my favorite Cuisinart knives to functional vegetable dicers and the Ninja Flip air fryer that I love, I've rounded up my favorite kitchen tools and appliances that make Sunday meal prep a total breeze. Keep scrolling to check them out. </p>        <div class="featured_product_block featured_block_hero" data-id="4acfe432-8b5f-11f1-a290-a780ba8db859">            <a href="https://www.amazon.com/Pyrex-BPA-Free-Containers-Dishwasher-Microwave/dp/B0000BYCGF/" data-model-name="Simply Store (3-Pack) Glass Food Storage Containers Set" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:133.37%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/cm3mdXRQ5SKWa4Ag33NixN.jpg" alt="Meal Prep Deals"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Pyrex</div>                                        <div class="featured__title">Simply Store (3-Pack) Glass Food Storage Containers Set</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="4acfe4be-8b5f-11f1-81d0-f5f5344dfc4f">            <a href="https://www.amazon.com/INSETLAN-Glass-Overnight-Containers-6-Pack/dp/B0GLF86YR5/" data-model-name="Glass Overnight Oats Containers With Lids" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:133.37%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/ecVzzjzLwLtYJyzuRzmwzN.jpg" alt="Meal Prep Deals"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>INSETLAN</div>                                        <div class="featured__title">Glass Overnight Oats Containers With Lids</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="4acfe540-8b5f-11f1-a976-bd94d2366f3c">            <a href="https://www.amazon.com/Cuisinart-C55-01-12PCKS-Advantage-Collection-Multicolor/dp/B00FLQ4EE6/" data-model-name="12-Piece Knife Set" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:133.37%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/mu62AoZFJeQSuhZ33HpH4P.jpg" alt="Meal Prep Deals"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Cuisinart</div>                                        <div class="featured__title">12-Piece Knife Set</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="4acfe5b8-8b5f-11f1-97a4-3f8c8c261b17">            <a href="https://www.amazon.com/Fullstar-Vegetable-Chopper-Spiralizer-Container/dp/B0C1T6J3CS" data-model-name="Pro Original Vegetable Chopper Kitchen Prep Tool" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:133.37%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/is4KqTcSfgA8jVkVWk9JCP.jpg" alt="Meal Prep Deals"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>fullstar</div>                                        <div class="featured__title">Pro Original Vegetable Chopper Kitchen Prep Tool</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="4acfe630-8b5f-11f1-bc66-0f065d26b756">            <a href="https://www.amazon.com/COOK-COLOR-Mixing-Bowls-Lids/dp/B0CKTV5ZQK/" data-model-name="Mixing Bowls With Lids - 12 Piece Plastic Nesting Bowls Set" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:133.37%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/8Z8vLh3W26HXN6ZZNHUi6P.jpg" alt="Meal Prep Deals"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>COOK WITH COLOR</div>                                        <div class="featured__title">Mixing Bowls With Lids - 12 Piece Plastic Nesting Bowls Set</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="4acfe69e-8b5f-11f1-801d-5b46ee4754e4">            <a href="https://www.amazon.com/Rubbermaid-Brilliance-Containers-2-Compartment-Storage/dp/B08WR1P45C/" data-model-name="Brilliance Meal Prep Containers" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:133.37%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/wDtRr9BcJPFMwGrUfYoiJP.jpg" alt="Meal Prep Deals"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Rubbermaid</div>                                        <div class="featured__title">Brilliance Meal Prep Containers</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="4acfe70c-8b5f-11f1-9eb6-4f2824f70b11">            <a href="https://www.amazon.com/bamboo-cutting-board-plastic-board/dp/B08DHTN88H/" data-model-name="Bamboo Cutting Board Set" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:133.37%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/eLDiKewxKT2WLqHr5KFDFP.jpg" alt="Meal Prep Deals"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Cooler Kitchen</div>                                        <div class="featured__title">Bamboo Cutting Board Set</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="4acfe784-8b5f-11f1-b0e8-f3ef8d903f71">            <a href="https://www.amazon.com/Cuisinart-Small-Processor-Auto-Reversing-Smart/dp/B074MQFR55/" data-model-name="Small Food Processor" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:133.37%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/cM6yPs47QAESHfsbZPjPCP.jpg" alt="Meal Prep Deals"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Cuisinart</div>                                        <div class="featured__title">Small Food Processor</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="4acfe7f2-8b5f-11f1-a8a5-6d95df047824">            <a href="https://www.amazon.com/Ninja-Functionality-Capability-Removable-SP151/dp/B0D1CXL52G" data-model-name="Flip Toaster Oven & Air Fryer, 8-In-1" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:133.37%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/yiS54tocCJm3byMNGuReJP.jpg" alt="Meal Prep Deals"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Ninja</div>                                        <div class="featured__title">Flip Toaster Oven & Air Fryer, 8-In-1</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/home/kitchen-dining/i-meal-prep-every-sunday-these-are-the-9-kitchen-tools-i-cant-live-without</link>
                                                                            <description>
                            <![CDATA[ I'm rounding up the meal prep tools I use every Sunday. Here are my favorites from Cuisinart, Ninja and more. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">cyNGFXgEoSppfXViydjuKF</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/SAaXzA992K8hBi9oVKxSrk-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Wed, 29 Jul 2026 15:52:22 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Kitchen & Dining]]></category>
                                                    <category><![CDATA[Home]]></category>
                                                    <category><![CDATA[Home Appliances]]></category>
                                                                                                                    <dc:creator><![CDATA[ Olivia Halevy ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/YAg7Fmh9dGKbg3hULBMWiU.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Olivia is a Deals Writer at Tom’s Guide. She loves all things lifestyle, shopping and sourcing the best deals from some of the top brands, retailers and websites around. From fashion and beauty to smart home and tech, she has an eye for finding practical, stylish, and reasonably-priced items that help make life simpler (and a little more aesthetically-pleasing).&amp;nbsp;Olivia has over five years of experience writing lifestyle, commerce, and branded content for &lt;a href=&quot;http://patch.com/&quot;&gt;Patch.com&lt;/a&gt;. She&#039;s covered major shopping holidays like Amazon Prime Day, Black Friday and Cyber Monday. In her free time, she enjoys trying out new exercise classes, binge-watching the latest viral TV shows, cooking, spending time with family and taking long walks with her dog, Gus.&amp;nbsp;&lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/SAaXzA992K8hBi9oVKxSrk-1280-80.jpg">
                                                            <media:credit><![CDATA[Amazon]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Amazon deals]]></media:description>                                                            <media:text><![CDATA[Amazon deals]]></media:text>
                                <media:title type="plain"><![CDATA[Amazon deals]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/SAaXzA992K8hBi9oVKxSrk-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>I enjoy cooking — but not every single night. That's why Sunday meal prep has become a must for setting myself up for the week ahead. I'm not <em>always</em> this organized, but when I am, it makes busy weekdays so much easier (and a lot more enjoyable). And of course, I couldn't do it without a few of my favorite kitchen tools.</p><p>From the best food storage containers and my favorite Cuisinart knives to functional vegetable dicers and the Ninja Flip air fryer that I love, I've rounded up my favorite kitchen tools and appliances that make Sunday meal prep a total breeze. Keep scrolling to check them out. </p>        <div class="featured_product_block featured_block_hero" data-id="4acfe432-8b5f-11f1-a290-a780ba8db859">            <a href="https://www.amazon.com/Pyrex-BPA-Free-Containers-Dishwasher-Microwave/dp/B0000BYCGF/" data-model-name="Simply Store (3-Pack) Glass Food Storage Containers Set" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:133.37%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/cm3mdXRQ5SKWa4Ag33NixN.jpg" alt="Meal Prep Deals"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Pyrex</div>                                        <div class="featured__title">Simply Store (3-Pack) Glass Food Storage Containers Set</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="4acfe4be-8b5f-11f1-81d0-f5f5344dfc4f">            <a href="https://www.amazon.com/INSETLAN-Glass-Overnight-Containers-6-Pack/dp/B0GLF86YR5/" data-model-name="Glass Overnight Oats Containers With Lids" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:133.37%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/ecVzzjzLwLtYJyzuRzmwzN.jpg" alt="Meal Prep Deals"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>INSETLAN</div>                                        <div class="featured__title">Glass Overnight Oats Containers With Lids</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="4acfe540-8b5f-11f1-a976-bd94d2366f3c">            <a href="https://www.amazon.com/Cuisinart-C55-01-12PCKS-Advantage-Collection-Multicolor/dp/B00FLQ4EE6/" data-model-name="12-Piece Knife Set" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:133.37%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/mu62AoZFJeQSuhZ33HpH4P.jpg" alt="Meal Prep Deals"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Cuisinart</div>                                        <div class="featured__title">12-Piece Knife Set</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="4acfe5b8-8b5f-11f1-97a4-3f8c8c261b17">            <a href="https://www.amazon.com/Fullstar-Vegetable-Chopper-Spiralizer-Container/dp/B0C1T6J3CS" data-model-name="Pro Original Vegetable Chopper Kitchen Prep Tool" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:133.37%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/is4KqTcSfgA8jVkVWk9JCP.jpg" alt="Meal Prep Deals"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>fullstar</div>                                        <div class="featured__title">Pro Original Vegetable Chopper Kitchen Prep Tool</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="4acfe630-8b5f-11f1-bc66-0f065d26b756">            <a href="https://www.amazon.com/COOK-COLOR-Mixing-Bowls-Lids/dp/B0CKTV5ZQK/" data-model-name="Mixing Bowls With Lids - 12 Piece Plastic Nesting Bowls Set" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:133.37%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/8Z8vLh3W26HXN6ZZNHUi6P.jpg" alt="Meal Prep Deals"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>COOK WITH COLOR</div>                                        <div class="featured__title">Mixing Bowls With Lids - 12 Piece Plastic Nesting Bowls Set</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="4acfe69e-8b5f-11f1-801d-5b46ee4754e4">            <a href="https://www.amazon.com/Rubbermaid-Brilliance-Containers-2-Compartment-Storage/dp/B08WR1P45C/" data-model-name="Brilliance Meal Prep Containers" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:133.37%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/wDtRr9BcJPFMwGrUfYoiJP.jpg" alt="Meal Prep Deals"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Rubbermaid</div>                                        <div class="featured__title">Brilliance Meal Prep Containers</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="4acfe70c-8b5f-11f1-9eb6-4f2824f70b11">            <a href="https://www.amazon.com/bamboo-cutting-board-plastic-board/dp/B08DHTN88H/" data-model-name="Bamboo Cutting Board Set" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:133.37%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/eLDiKewxKT2WLqHr5KFDFP.jpg" alt="Meal Prep Deals"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Cooler Kitchen</div>                                        <div class="featured__title">Bamboo Cutting Board Set</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="4acfe784-8b5f-11f1-b0e8-f3ef8d903f71">            <a href="https://www.amazon.com/Cuisinart-Small-Processor-Auto-Reversing-Smart/dp/B074MQFR55/" data-model-name="Small Food Processor" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:133.37%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/cM6yPs47QAESHfsbZPjPCP.jpg" alt="Meal Prep Deals"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Cuisinart</div>                                        <div class="featured__title">Small Food Processor</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="4acfe7f2-8b5f-11f1-a8a5-6d95df047824">            <a href="https://www.amazon.com/Ninja-Functionality-Capability-Removable-SP151/dp/B0D1CXL52G" data-model-name="Flip Toaster Oven & Air Fryer, 8-In-1" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:133.37%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/yiS54tocCJm3byMNGuReJP.jpg" alt="Meal Prep Deals"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Ninja</div>                                        <div class="featured__title">Flip Toaster Oven & Air Fryer, 8-In-1</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ Deep clean on a budget: 9 unbeatable Dyson and Shark vacuum deals ]]></title>
                                                                                                <dc:content><![CDATA[ <p>When it comes to vacuum cleaners, arguably two brands rule the roost. At one end you have Dyson, which has a well-deserved reputation for its high end cordless vacuum cleaners where you get the quality that you pay for. At the other, you have Shark which is known for great value models that are especially good at tackling things like pet hair.</p><p>Both brands have their strengths and we're not here today to say which is better or right for your needs. What we are here to do, however, is present you with nine great deals for products from both brands. </p><p>There are corded and cordless models here, stick vacuums and more traditional cleaners. All of them have money off right now, meaning you can save up to 33% off the retail price. But hurry, these deals won't last forever...</p>        <div class="featured_product_block featured_block_hero" data-id="2a38bdf0-8b43-11f1-a780-7dd30d236918">            <a href="https://www.amazon.com/Shark-HV343AMZ-Self-Cleaning-Lightweight-Upholstery/dp/B08QW6RBBX/" data-model-name="Shark Rocket Corded Stick Vacuum " data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/YsnkrxKT7CV3xpzBxhufeh.jpg" alt="Shark Hv343amz Rocket Corded Stick Vacuum With Self-Cleaning Brushroll, Lightweight & Maneuverable, Perfect for Pet Hair Pickup, Converts to a Hand Vacuum, Crevice Upholstery Tools, Blue/silver"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Shark</div>                                        <div class="featured__title">Shark Rocket Corded Stick Vacuum </div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="2a38be68-8b43-11f1-ba1e-e7cab17f978f">            <a href="https://www.amazon.com/Shark-HV322-Headlights-Lightweight-Attachments/dp/B00NGVF4II/" data-model-name="Shark Rocket Pet Plus Corded Stick Vacuum" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/CnSAkqWHFj7pZDQny5i6jh.jpg" alt="Shark Rocket Pet Plus Corded Stick Vacuum, Xl Cup, Bordeaux/silver, Hv322"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Shark</div>                                        <div class="featured__title">Shark Rocket Pet Plus Corded Stick Vacuum</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="2a38bed6-8b43-11f1-93dc-79bce99e2612">            <a href="https://www.amazon.com/Shark-LA502-Lift-Away-PowerFins-Self-Cleaning/dp/B089TPNZQ5/" data-model-name="Shark Rotator Lift-Away Vacuum" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/mDLau86unLFYCLc9cJMo5i.jpg" alt="Shark Rotator Lift-Away Vacuum, Hepa Filter, No Hair Wrap, Silver, La502"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Shark</div>                                        <div class="featured__title">Shark Rotator Lift-Away Vacuum</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="2a38bf44-8b43-11f1-8d87-61b2724e14f2">            <a href="https://www.amazon.com/Dyson-626423-01-V8TM-Cordless-Vacuum/dp/B0GT2DG9SK/" data-model-name="Dyson V8 Cordless Vacuum" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/duKVVQ6akmE4wwcua9VgRi.jpg" alt="Dyson V8™ Cordless Vacuum"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Dyson</div>                                        <div class="featured__title">Dyson V8 Cordless Vacuum</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="2a38bfbc-8b43-11f1-ab5b-833e232890fd">            <a href="https://www.amazon.com/Shark-Lightweight-Rechargeable-Auto-Empty-BU3523/dp/B0D15LVBJB/" data-model-name="Shark Clean & Empty Cordless Vacuum" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/ryYDacnH9UKcwRxtxstKfi.jpg" alt="Shark Clean & Empty Cordless Stick Vacuum, Bu3523"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Shark</div>                                        <div class="featured__title">Shark Clean & Empty Cordless Vacuum</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="2a38c02a-8b43-11f1-913e-239473095f40">            <a href="https://www.amazon.com/Dyson-Ball-Animal-Corded-Vacuum/dp/B0GTBQQ9YK/" data-model-name="Dyson Ball Animal 2 Plus Vacuum" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/p3D6yJekrSVMwvMGTtvczi.jpg" alt="Dyson Ball Animal 2 Plus Corded Vacuum"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Dyson</div>                                        <div class="featured__title">Dyson Ball Animal 2 Plus Vacuum</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="2a38c08e-8b43-11f1-be09-43eab249535b">            <a href="https://www.amazon.com/Dyson-Cyclone-Origin-Cordless-Vacuum/dp/B0GT2D9ZCR/" data-model-name="Dyson Cyclone V10 Origin Cordless Vacuum" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/XDMsX8K5k8vcooiXJhjMLj.jpg" alt="Dyson Cyclone V10 Origin Cordless Vacuum"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Dyson</div>                                        <div class="featured__title">Dyson Cyclone V10 Origin Cordless Vacuum</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="2a38c0fc-8b43-11f1-834b-79358902004a">            <a href="https://www.amazon.com/Shark-PowerDetect-Auto-Empty-Filtration-IP3253/dp/B0DW237ZLB/" data-model-name="Shark Powerdetect Pet Plus Cordless Stick Vacuum" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/t5eAUzHnTso8etqeqrkfdj.jpg" alt="Shark Powerdetect Pet Plus Clean & Empty Cordless Stick Vacuum, Ip3253"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Shark</div>                                        <div class="featured__title">Shark Powerdetect Pet Plus Cordless Stick Vacuum</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="2a38c16a-8b43-11f1-bd16-7188e2032043">            <a href="https://www.amazon.com/Dyson-Detect-Cordless-Vacuum-Yellow/dp/B0CT97D9R2/" data-model-name="Dyson V15 Detect Plus Cordless Vacuum" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/DJbBscX6u7uzma9Fng8V5k.jpg" alt="Dyson V15 Detect Plus Cordless Vacuum, Illumination Reveals Dust, 240aw, 3 Power Modes, Up to 60 Minutes,² Deep Cleans Hard Floors and Carpets, Detangles Pet Hair, Converts to Handheld"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Dyson</div>                                        <div class="featured__title">Dyson V15 Detect Plus Cordless Vacuum</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/home/home-appliances/deep-clean-on-a-budget-9-unbeatable-dyson-and-shark-vacuum-deals</link>
                                                                            <description>
                            <![CDATA[ Dyson and Shark are two of the most trusted brands when it comes to vacuum cleaners. We've rounded up nine deals that offer big savings on some of the best models on the market right now. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">jYN28DA5as82JiefdMuLX9</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/A7GPukWVbyjrquS8ba7hTH-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Wed, 29 Jul 2026 15:32:53 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Home Appliances]]></category>
                                                    <category><![CDATA[Home]]></category>
                                                                                                                    <dc:creator><![CDATA[ Will Salmon ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/HpRWP7Mh9ErgRGoTvZBbBJ.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Will Salmon is Tom&#039;s Guide&#039;s Collections Editor, curating advice on the best products to spend your money on. Will has been writing about tech and entertainment for almost 20 years, including stints as GamesRadar+&#039;s Streaming Editor, editing comics website Newsarama, and writing for lots and lots of magazines.&lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/A7GPukWVbyjrquS8ba7hTH-1280-80.jpg">
                                                            <media:credit><![CDATA[Dyson, Shark / Edited by Gemini]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[A selection of Dyson and Shark vacuum cleaners.]]></media:description>                                                            <media:text><![CDATA[A selection of Dyson and Shark vacuum cleaners.]]></media:text>
                                <media:title type="plain"><![CDATA[A selection of Dyson and Shark vacuum cleaners.]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/A7GPukWVbyjrquS8ba7hTH-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>When it comes to vacuum cleaners, arguably two brands rule the roost. At one end you have Dyson, which has a well-deserved reputation for its high end cordless vacuum cleaners where you get the quality that you pay for. At the other, you have Shark which is known for great value models that are especially good at tackling things like pet hair.</p><p>Both brands have their strengths and we're not here today to say which is better or right for your needs. What we are here to do, however, is present you with nine great deals for products from both brands. </p><p>There are corded and cordless models here, stick vacuums and more traditional cleaners. All of them have money off right now, meaning you can save up to 33% off the retail price. But hurry, these deals won't last forever...</p>        <div class="featured_product_block featured_block_hero" data-id="2a38bdf0-8b43-11f1-a780-7dd30d236918">            <a href="https://www.amazon.com/Shark-HV343AMZ-Self-Cleaning-Lightweight-Upholstery/dp/B08QW6RBBX/" data-model-name="Shark Rocket Corded Stick Vacuum " data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/YsnkrxKT7CV3xpzBxhufeh.jpg" alt="Shark Hv343amz Rocket Corded Stick Vacuum With Self-Cleaning Brushroll, Lightweight & Maneuverable, Perfect for Pet Hair Pickup, Converts to a Hand Vacuum, Crevice Upholstery Tools, Blue/silver"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Shark</div>                                        <div class="featured__title">Shark Rocket Corded Stick Vacuum </div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="2a38be68-8b43-11f1-ba1e-e7cab17f978f">            <a href="https://www.amazon.com/Shark-HV322-Headlights-Lightweight-Attachments/dp/B00NGVF4II/" data-model-name="Shark Rocket Pet Plus Corded Stick Vacuum" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/CnSAkqWHFj7pZDQny5i6jh.jpg" alt="Shark Rocket Pet Plus Corded Stick Vacuum, Xl Cup, Bordeaux/silver, Hv322"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Shark</div>                                        <div class="featured__title">Shark Rocket Pet Plus Corded Stick Vacuum</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="2a38bed6-8b43-11f1-93dc-79bce99e2612">            <a href="https://www.amazon.com/Shark-LA502-Lift-Away-PowerFins-Self-Cleaning/dp/B089TPNZQ5/" data-model-name="Shark Rotator Lift-Away Vacuum" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/mDLau86unLFYCLc9cJMo5i.jpg" alt="Shark Rotator Lift-Away Vacuum, Hepa Filter, No Hair Wrap, Silver, La502"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Shark</div>                                        <div class="featured__title">Shark Rotator Lift-Away Vacuum</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="2a38bf44-8b43-11f1-8d87-61b2724e14f2">            <a href="https://www.amazon.com/Dyson-626423-01-V8TM-Cordless-Vacuum/dp/B0GT2DG9SK/" data-model-name="Dyson V8 Cordless Vacuum" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/duKVVQ6akmE4wwcua9VgRi.jpg" alt="Dyson V8™ Cordless Vacuum"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Dyson</div>                                        <div class="featured__title">Dyson V8 Cordless Vacuum</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="2a38bfbc-8b43-11f1-ab5b-833e232890fd">            <a href="https://www.amazon.com/Shark-Lightweight-Rechargeable-Auto-Empty-BU3523/dp/B0D15LVBJB/" data-model-name="Shark Clean & Empty Cordless Vacuum" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/ryYDacnH9UKcwRxtxstKfi.jpg" alt="Shark Clean & Empty Cordless Stick Vacuum, Bu3523"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Shark</div>                                        <div class="featured__title">Shark Clean & Empty Cordless Vacuum</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="2a38c02a-8b43-11f1-913e-239473095f40">            <a href="https://www.amazon.com/Dyson-Ball-Animal-Corded-Vacuum/dp/B0GTBQQ9YK/" data-model-name="Dyson Ball Animal 2 Plus Vacuum" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/p3D6yJekrSVMwvMGTtvczi.jpg" alt="Dyson Ball Animal 2 Plus Corded Vacuum"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Dyson</div>                                        <div class="featured__title">Dyson Ball Animal 2 Plus Vacuum</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="2a38c08e-8b43-11f1-be09-43eab249535b">            <a href="https://www.amazon.com/Dyson-Cyclone-Origin-Cordless-Vacuum/dp/B0GT2D9ZCR/" data-model-name="Dyson Cyclone V10 Origin Cordless Vacuum" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/XDMsX8K5k8vcooiXJhjMLj.jpg" alt="Dyson Cyclone V10 Origin Cordless Vacuum"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Dyson</div>                                        <div class="featured__title">Dyson Cyclone V10 Origin Cordless Vacuum</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="2a38c0fc-8b43-11f1-834b-79358902004a">            <a href="https://www.amazon.com/Shark-PowerDetect-Auto-Empty-Filtration-IP3253/dp/B0DW237ZLB/" data-model-name="Shark Powerdetect Pet Plus Cordless Stick Vacuum" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/t5eAUzHnTso8etqeqrkfdj.jpg" alt="Shark Powerdetect Pet Plus Clean & Empty Cordless Stick Vacuum, Ip3253"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Shark</div>                                        <div class="featured__title">Shark Powerdetect Pet Plus Cordless Stick Vacuum</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="2a38c16a-8b43-11f1-bd16-7188e2032043">            <a href="https://www.amazon.com/Dyson-Detect-Cordless-Vacuum-Yellow/dp/B0CT97D9R2/" data-model-name="Dyson V15 Detect Plus Cordless Vacuum" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/DJbBscX6u7uzma9Fng8V5k.jpg" alt="Dyson V15 Detect Plus Cordless Vacuum, Illumination Reveals Dust, 240aw, 3 Power Modes, Up to 60 Minutes,² Deep Cleans Hard Floors and Carpets, Detangles Pet Hair, Converts to Handheld"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Dyson</div>                                        <div class="featured__title">Dyson V15 Detect Plus Cordless Vacuum</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ I spent a month eating virtually nothing but pizza to test the Gozney Arc XL — here’s the outcome ]]></title>
                                                                                                <dc:content><![CDATA[ <p>The Gozney Arc XL is all the pizza oven most people will ever need. As you might’ve guessed from the name, it’s the larger variant of the <a href="https://www.tomsguide.com/home/kitchen-dining/gozney-arc-pizza-oven-review">Gozney Arc</a>, which we’ve also reviewed and loved.</p><p>The Arc XL sits below Gozney’s Dome / <a href="https://www.tomsguide.com/home/kitchen-dining/gozney-dome-xl-2-review">Dome XL (Gen 2)</a>, which are enormous and can fit multiple pizzas on their dual stones. The Arc XL is intended for those without the enormous amounts of space and cash it takes to get to a Dome. Nevertheless, the Arc XL should be plenty for most home pizzaioli, and even small-time commercial ventures.</p><p>Running on gas, it offers high heat and stable temperatures, plus it’s easy to use thanks to the digital display and simple controls. It’s beautifully styled and made, and will be a complement to any patio or pizza shelter. </p><p>It isn’t perfect. The elephant in the room is the Arc XL’s high price. Gozney also makes its stones quite tricky to remove versus Ooni, which is a problem if you get the front of the stone (which doesn’t get very hot) messy.</p><p>But could this be the <a href="https://www.tomsguide.com/best-picks/best-outdoor-pizza-ovens">best outdoor pizza oven</a> for you? Probably! Read my full Gozney Arc XL review to find out more.</p><h2 class="article-body__section" id="section-gozney-arc-xl-review-specs"><span>Gozney Arc XL review: Specs</span></h2><div ><table><tbody><tr><td class="firstcol " ><p><strong>Price</strong></p></td><td  ><p><a href="https://www.amazon.com/Gozney-Pizza-Fired-makes-pizza/dp/B0CY76J1NY/" target="_blank" rel="nofollow">$999</a> / <a href="https://www.gozney.com/products/arc-xl" target="_blank" rel="nofollow">£799</a></p></td></tr><tr><td class="firstcol " ><p><strong>Size</strong></p></td><td  ><p>20.9 x 24.8 x 13.5 inches (530 x 629x 342mm)</p></td></tr><tr><td class="firstcol " ><p><strong>Weight</strong></p></td><td  ><p>58.5lbs (26.5kg) </p></td></tr><tr><td class="firstcol " ><p><strong>Capacity</strong></p></td><td  ><p>1x 16-inch pizza</p></td></tr><tr><td class="firstcol " ><p><strong>Internal dimensions</strong></p></td><td  ><p>16.8 x 20.3 x 6.8 inches (427 x 517 x 173mm)</p></td></tr><tr><td class="firstcol " ><p><strong>Mouth opening</strong></p></td><td  ><p>16.8 x 3.6 inches (427 x 95mm)</p><p><br></p></td></tr><tr><td class="firstcol " ><p><strong>Stone</strong></p></td><td  ><p>0.8-inch/20mm cordierite</p></td></tr><tr><td class="firstcol " ><p><strong>Max temperature</strong></p></td><td  ><p>932F / 500C</p></td></tr><tr><td class="firstcol " ><p><strong>Fuel types</strong></p></td><td  ><p>Propane</p></td></tr></tbody></table></div><h2 class="article-body__section" id="section-gozney-arc-xl-review-price-availability"><span>Gozney Arc XL review: Price & availability</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="iRGEKpzFxPiWaA7PHzNNZg" name="Gozney Arc XL-11" alt="A photo of the Gozney Arc XL in a garden" src="https://cdn.mos.cms.futurecdn.net/iRGEKpzFxPiWaA7PHzNNZg.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Peter Wolinski / Future)</span></figcaption></figure><p>The Gozney Arc XL isn’t cheap, costing <a href="https://www.amazon.com/Gozney-Pizza-Fired-makes-pizza/dp/B0CY76J1NY/" target="_blank" rel="nofollow">$999</a> / <a href="https://www.gozney.com/products/arc-xl" target="_blank" rel="nofollow">£799</a>, which is a sizable $300 / £200 more than the 14-inch standard Arc. Other than the extra 2-inch capacity, the ovens are pretty much the same, so it’ll just depend on how much larger pizzas mean to you.</p><p>Personally, I love cooking larger pies. It’s trickier, so more of a challenge, but when you get it right you can feed more people easily, so the XL will be better if you plan on cooking for multiple guests regularly.</p><p>The Arc XL’s main rival is the <a href="https://www.tomsguide.com/reviews/ooni-koda-16">Ooni Koda 16</a>, which cooks 16-inch pizzas, runs on gas and undercuts the Gozney by a healthy margin, costing $599 / £499. The Koda is lighter, uses Ooni’s folding leg system for easier storage, and features an L-shaped burner for wider flame dispersion and less rotating required during cooking. We awarded the Koda 16 our full five stars, and you can probably now see why — for the money, it’s difficult to beat.</p><h2 class="article-body__section" id="section-gozney-arc-xl-review-design"><span>Gozney Arc XL review: Design</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="nUmSESdp7rcda2nZUq8cHj" name="Gozney Arc XL-4" alt="A photo of the Gozney Arc XL in a garden" src="https://cdn.mos.cms.futurecdn.net/nUmSESdp7rcda2nZUq8cHj.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Peter Wolinski / Future)</span></figcaption></figure><p>The Gozney Arc XL looks beautiful, employing Gozney’s typically slick, neo-retro aesthetic. It looks straight out of a trendy London pizzeria, which is the point. It’s beautifully made and finished, with a high level of attention to detail, and feels built to last. </p><p>I wouldn’t say it’s any better or worse than an Ooni in this respect, so which manufacturer you pick will depend on whether you want the more luxurious styling of Gozney, or the more futuristic look of Ooni. That is unless you’re a commercial user — if you’ve got a pizza van or small kitchen to kit out, I think the round shape and flat base of the Gozney is more versatile than the Ooni Karu 16, with its oblong shape and tall legs.</p><p>The Arc XL is a behemoth, though, measuring 20.9 x 24.8 x 13.5 inches and weighing nearly 60 pounds, so you’ll want a second person on hand to help you set up. My wife was on vacation so I had no choice but to set the Arc XL up on my own, and very nearly put my back out getting it unboxed and onto the stand. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.30%;"><img id="hf9vo6tiRYH8CFqHhXbo6h" name="Gozney Arc XL-10" alt="A photo of the Gozney Arc XL in a garden" src="https://cdn.mos.cms.futurecdn.net/hf9vo6tiRYH8CFqHhXbo6h.jpg" mos="" align="middle" fullscreen="" width="2000" height="1126" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Peter Wolinski / Future)</span></figcaption></figure><p>Colossal weight aside, setting the Arc XL up is very easy — you just remove the packaging and padding; pull the stone forward a fraction of an inch; put the metal flame guard in place; and put batteries (supplied) in the thermometer and digital dial. There’s a helpful quick start guide included to cover all this. </p><p>I was ready for the burn-in after about 10 minutes — burning in is something you must do with most pizza ovens before you can make pizza — although it actually took me around 5 days because I couldn't find any fuel in my area (it was peak summer).</p><h2 id="fuel">Fuel</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.30%;"><img id="3E7XXTr3qkrekwYi33Pb7h" name="Gozney Arc XL-9" alt="A photo of the Gozney Arc XL in a garden" src="https://cdn.mos.cms.futurecdn.net/3E7XXTr3qkrekwYi33Pb7h.jpg" mos="" align="middle" fullscreen="" width="2000" height="1126" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Peter Wolinski / Future)</span></figcaption></figure><p>The Arc XL runs on propane gas. You can theoretically use butane, too, although Gozney doesn’t recommend it, and butane is less likely to work in colder temperatures. My Arc XL was supplied with a clip-on regulator for the patio gas canisters we get here in the U.K.</p><p>Something I love about multi-fuel ovens is that, if you’re out of gas, you can simply use wood or charcoal. It’s worth considering a multi-fuel oven like the Gozney Dome or Ooni Karu 2 Pro if you’d rather have that extra flexibility.</p><p>The Arc XL is fairly fuel-efficient and Gozney says a 28lb / 13kg canister should last around 30 hours. You’ll need as much efficiency as you can get, as the only way to easily clean the Arc XL is by burning it for three hours, which sucks, as I’ll touch on later.</p><h2 class="article-body__section" id="section-gozney-arc-xl-review-accessories"><span>Gozney Arc XL review: Accessories</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.30%;"><img id="tA4CNWKTdRCrAk4xaz6TTj" name="Gozney Arc XL-14" alt="A photo of the Gozney Arc XL in a garden" src="https://cdn.mos.cms.futurecdn.net/tA4CNWKTdRCrAk4xaz6TTj.jpg" mos="" align="middle" fullscreen="" width="2000" height="1126" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Peter Wolinski / Future)</span></figcaption></figure><p>Something many don’t understand before they buy their first pizza oven is that you need accessories. You can’t make a pizza without at least a launching peel and a turning peel. I tested <a href="https://www.amazon.com/Gozney-Pro-Pizza-Placement-Peel/dp/B0FS2Y61RQ" target="_blank" rel="nofollow">Gozney’s 16-inch Pro Placement peel</a> ($109) and <a href="https://us.gozney.com/products/balance-turning-peel" target="_blank" rel="nofollow">Balance Turning peel</a> ($89) and would highly recommend them both. Although, if you’re just starting out or are on a tight budget, you can find cheaper alternatives at Amazon, which will work just fine.</p><p>I would also recommend you buy an infrared thermometer for measuring stone temperature (the temperature on the Arc XL only measures ambient temperature, which won’t tell you precisely when the stone is ready for cooking). The <a href="https://us.gozney.com/products/infrared-thermometer" target="_blank" rel="nofollow">Gozney infrared thermometer gun costs $49</a>, which is similar to Ooni’s pricing.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.30%;"><img id="PzLoS8iGREiCXx2jpUAGsh" name="Gozney Arc XL-15" alt="A photo of the Gozney Arc XL in a garden" src="https://cdn.mos.cms.futurecdn.net/PzLoS8iGREiCXx2jpUAGsh.jpg" mos="" align="middle" fullscreen="" width="2000" height="1126" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Peter Wolinski / Future)</span></figcaption></figure><p>Gozney also sells a variety of other accessories that I found exceptionally useful. Firstly, there’s the <a href="https://us.gozney.com/products/dough-tray" target="_blank" rel="nofollow">$49 dough tray</a>, which I absolutely love. This tray features a thermometer to show you which type of proof (cold, warm, etc) your ambient conditions will result in, allowing you to tailor proof times. It also shows you when conditions are too warm, and features a bulk fermenting tray and a silicone insert for six dough balls (for up to 14-inch pizzas).</p><p>I’m also a huge fan of the <a href="https://us.gozney.com/products/arc-xl-mantel" target="_blank" rel="nofollow">Arc XL mantel ($119)</a>, which gives you a couple of inches of surface outside the oven mouth — enough space to safely turn food or leave your pizza to rest for a moment without burning while you find a board for it. And <a href="https://us.gozney.com/products/heat-resistant-gloves" target="_blank" rel="nofollow">Gozney's $39 heat resistant gloves</a>, which can stand up to 950F / 500C heat.</p><p>I also tested the <a href="https://us.gozney.com/products/pizza-cutter" target="_blank" rel="nofollow">Gozney Pizza Cutter ($44)</a>. My wife hated pizza cutters and always refused to use our other ones (choosing a knife or scissors instead). The Gozney cutter has converted her — thanks to its weight and sharp blade, it's much more stable and effective than cheaper cutters.</p><h2 class="article-body__section" id="section-gozney-arc-xl-review-performance"><span>Gozney Arc XL review: Performance</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:5217px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="cT8UcMDUv9ZCLk6XCrsssn" name="Gozney Arc XL_Test shot-6" alt="A pizza cooking in the Gozney Arc XL" src="https://cdn.mos.cms.futurecdn.net/cT8UcMDUv9ZCLk6XCrsssn.jpg" mos="" align="middle" fullscreen="" width="5217" height="2935" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Peter Wolinski / Future)</span></figcaption></figure><p>The Gozney Arc XL performs like a professional pizza oven. The stone heats up to 750F / 400C in around 15-20 minutes, which is hot enough for Neapolitan-style pizza. Alternatively, you can cook other styles of pizza before then — low’n’slow pizzas like NY-style.</p><p>The thermometer gauge on the front of the oven is very useful to give you an idea of ambient temperatures, which dictate how quickly the upper sections of your pizza will cook (although the cooking of your toppings will also be affected by the size and intensity of the gas flame). </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.30%;"><img id="qo2R3dgpxboVzaiW4Xb8pg" name="Gozney Arc XL-13" alt="A photo of the Gozney Arc XL in a garden" src="https://cdn.mos.cms.futurecdn.net/qo2R3dgpxboVzaiW4Xb8pg.jpg" mos="" align="middle" fullscreen="" width="2000" height="1126" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Peter Wolinski / Future)</span></figcaption></figure><p>Annoyingly, the temperature gauge turns itself off after a while — on a few occasions I turned back to the gauge while cooking to check temperatures, only to find it switched off. I get that this is to save battery, but it’s really annoying.</p><p>The Arc XL is very predictable thanks to running on gas, and you have a high level of control over the flame size by twisting the control knob on the front.</p><p>You’ll need to cook a few pizzas and get used to the temperature of the oven, and to get a feel for how to adjust your flame while cooking. Once you’ve got it down, though, you can cook a Neapolitan pizza in just a minute or two.</p><figure role="gallery"><figure><img src="https://cdn.mos.cms.futurecdn.net/oWB4cCGpNUQVvcxoftMxhm.jpg" alt="A slice of pizza in hand, the pizza was cooked on the Gozney Arc XL" /><figcaption><small role="credit">Peter Wolinski / Future</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/EBQYdvgx7xoLoEySJVdxsn.jpg" alt="A pizza cooked on the Gozney Arc XL" /><figcaption><small role="credit">Peter Wolinski / Future</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/yMwi7zeD3wrkj7PrzjXqun.jpg" alt="A pizza cooked on the Gozney Arc XL" /><figcaption><small role="credit">Peter Wolinski / Future</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/ae59Fbbpv3Jk3hP3w9pNun.jpg" alt="A pizza cooked on the Gozney Arc XL" /><figcaption><small role="credit">Peter Wolinski / Future</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/LGHQdEdiGemfaSrK9D2jun.jpg" alt="A pizza cooked on the Gozney Arc XL" /><figcaption><small role="credit">Peter Wolinski / Future</small></figcaption></figure></figure><p>I cooked a variety of pizzas, from 12-inch through to 16-inch bases, in Neapolitan and NY styles. On several occasions, I cooked for groups of six. The Arc XL handled it all beautifully. Thanks to the large 16-inch stone, you can cook bigger pizzas to feed multiple people, so you don’t need to spend the entirety of a pizza party churning out 12-inch pies for each person.</p><p>It’s very easy to burn larger 16-inch pies, as they sit so close to the flame. This means that you’ll want to turn them early, which can cause rips in the dough and an awful mess. This happened on a few occasions for me — to avoid this, ensure the stone is at least 750F / 400C before launching, so pizza bases cook very quickly.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:4770px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="LkKuqvfb2h4c9TcEEg9Ctn" name="Gozney Arc XL_Test shot-4" alt="A garlic flatbread cooked on the Gozney Arc XL" src="https://cdn.mos.cms.futurecdn.net/LkKuqvfb2h4c9TcEEg9Ctn.jpg" mos="" align="middle" fullscreen="" width="4770" height="2683" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Peter Wolinski / Future)</span></figcaption></figure><p>I also cooked large garlic flatbreads, as well as sides like charred broccoli spears and caramelized roasted carrots. The stone also gets hot enough to sear steaks and meat, so it’s a highly versatile oven.</p><h2 class="article-body__section" id="section-gozney-arc-xl-review-storage-maintenance"><span>Gozney Arc XL review: Storage & maintenance</span></h2><p>My one major gripe with the Arc XL is how difficult the stone is to remove. Without buying a removal kit, you’ll need to tip the oven on its side and support the stone out — a two-person job, which also involves removing the oven from any stand or base you have it fastened to. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.30%;"><img id="cQ5L2r3DpjfDFQPvDFJF6h" name="Gozney Arc XL-6" alt="A photo of the Gozney Arc XL in a garden" src="https://cdn.mos.cms.futurecdn.net/cQ5L2r3DpjfDFQPvDFJF6h.jpg" mos="" align="middle" fullscreen="" width="2000" height="1126" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Peter Wolinski / Future)</span></figcaption></figure><p>This is infuriating if you make a mess. Gonzey’s advice is to burn the oven for 3 hours to clean it (wasting gas), which works, but only on the middle and rear of the stone. The front never gets hot enough to self-clean, so if you make a mess there when launching or removing a failed launch, you can’t clean it properly without a lot of hassle. You can scrape most mess off when cool, but not everything. And besides, food still gets stuck between the stone and the oven lip.</p><p>I love that Ooni’s stones are much easier to remove, so you can take them out and properly clean them up. As I mentioned before, this also means you don’t need to waste hours of gas just to clean. Gozney should include a stone removal kit with every oven.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.30%;"><img id="JovgEojWbc9cun2NkppDth" name="Gozney Arc XL-3" alt="A photo of the Gozney Arc XL in a garden" src="https://cdn.mos.cms.futurecdn.net/JovgEojWbc9cun2NkppDth.jpg" mos="" align="middle" fullscreen="" width="2000" height="1126" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Peter Wolinski / Future)</span></figcaption></figure><p>Gozney also recommends burning the oven for several hours to clean soot from the roof, which is just ridiculously wasteful. I just waited for it to cool and cleaned with a dry cloth. Maintenance is otherwise very simple — just wipe down the exterior parts when cool.</p><p>Storage is as you’d expect for such a huge cooker: you’ll need a fair bit of space. I’d recommend <a href="https://us.gozney.com/products/arc-arc-xl-stand" target="_blank" rel="nofollow">Gozney’s Arc + Arc XL stand</a> ($299), which features fold-away ledges, storage hooks, and wheels to move the oven to and from position. It’s also important to cover the oven and keep it safe from the elements — Gozney sells covers for this (including a <a href="https://us.gozney.com/products/arc-arc-xl-stand-cover" target="_blank" rel="nofollow">cover that goes over the whole stand</a>).</p><h2 class="article-body__section" id="section-gozney-arc-xl-review-verdict"><span>Gozney Arc XL review: Verdict</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="diNPFJT9L76PJjBZeYjrJh" name="Gozney Arc XL-2" alt="A photo of the Gozney Arc XL in a garden" src="https://cdn.mos.cms.futurecdn.net/diNPFJT9L76PJjBZeYjrJh.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Peter Wolinski / Future)</span></figcaption></figure><p>The Gozney Arc XL is a fantastic pizza oven. With its large 16-inch stone, you can cook big pizzas for multiple people and simplify your pizza parties. It’s easy to use, beautiful to behold and built to last. And most importantly, it makes fantastic pizza.</p><p>There are a couple of things to consider. First, it’s pricey — you can get the rival Ooni Karu 16 for much less money, which is better than the Arc XL in almost every way. Secondly, the stone is tricky to remove, which makes the Arc XL trickier to clean than Ooni ovens. </p><p>If you’re willing to overlook those flaws, though, as I have, then I’ve no hesitation in recommending the Arc XL to small commercial and home pizzaioli. </p> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/home/kitchen-dining/gozney-arc-xl-review</link>
                                                                            <description>
                            <![CDATA[ The Gozney Arc XL makes great pizza up to 16 inches, and is super easy to use. It’s a little pricey and tricky to clean though. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">feRsDk9CT9VPxhDGkm66Ld</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/oYsS42iYBUREEo4md89qj3-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Wed, 29 Jul 2026 15:10:02 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Kitchen & Dining]]></category>
                                                    <category><![CDATA[Home]]></category>
                                                    <category><![CDATA[Home Appliances]]></category>
                                                                                                <author><![CDATA[ peter.wolinski@futurenet.com (Peter Wolinski) ]]></author>                    <dc:creator><![CDATA[ Peter Wolinski ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/stgPfXWY7ukw8J8rfC7vjg.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Peter is a Senior Editor at Tom&#039;s Guide, heading up the site&#039;s Reviews team and Cameras section. Having built gaming PCs since he was 10 (that&#039;s a while ago now) he&#039;s a bit of a nerd about components and hardware. He&#039;s also been an iPhone user since the classic iPhone 4, and a Mac user for well over a decade. Experienced in using and testing all kinds of technology — from phones through to tablets, computers, games consoles, cameras and smart home tech — helping people find the best tech for them (at the best prices) is what Peter does best. A photographer since he bought his first camera (a Fujifilm) in 2015, Peter was previously an Editor for Canon-Europe.com. He then edited the Cameras and How To sections of Tom&#039;s Guide. When he&#039;s not crafting helpful, in-depth reviews, Peter can usually be found out and about honing his architectural photography skills, riding his motorcycle around Welsh mountain roads, telling everyone about his two greyhounds, squeezing a few extra FPS out of PC games or perfecting his espresso shots.&lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/oYsS42iYBUREEo4md89qj3-1280-80.jpg">
                                                            <media:credit><![CDATA[Peter Wolinski / Future]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[A split image showing a slice of pizza on the left and the Gozney Arc XL on the right]]></media:description>                                                            <media:text><![CDATA[A split image showing a slice of pizza on the left and the Gozney Arc XL on the right]]></media:text>
                                <media:title type="plain"><![CDATA[A split image showing a slice of pizza on the left and the Gozney Arc XL on the right]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/oYsS42iYBUREEo4md89qj3-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>The Gozney Arc XL is all the pizza oven most people will ever need. As you might’ve guessed from the name, it’s the larger variant of the <a href="https://www.tomsguide.com/home/kitchen-dining/gozney-arc-pizza-oven-review">Gozney Arc</a>, which we’ve also reviewed and loved.</p><p>The Arc XL sits below Gozney’s Dome / <a href="https://www.tomsguide.com/home/kitchen-dining/gozney-dome-xl-2-review">Dome XL (Gen 2)</a>, which are enormous and can fit multiple pizzas on their dual stones. The Arc XL is intended for those without the enormous amounts of space and cash it takes to get to a Dome. Nevertheless, the Arc XL should be plenty for most home pizzaioli, and even small-time commercial ventures.</p><p>Running on gas, it offers high heat and stable temperatures, plus it’s easy to use thanks to the digital display and simple controls. It’s beautifully styled and made, and will be a complement to any patio or pizza shelter. </p><p>It isn’t perfect. The elephant in the room is the Arc XL’s high price. Gozney also makes its stones quite tricky to remove versus Ooni, which is a problem if you get the front of the stone (which doesn’t get very hot) messy.</p><p>But could this be the <a href="https://www.tomsguide.com/best-picks/best-outdoor-pizza-ovens">best outdoor pizza oven</a> for you? Probably! Read my full Gozney Arc XL review to find out more.</p><h2 class="article-body__section" id="section-gozney-arc-xl-review-specs"><span>Gozney Arc XL review: Specs</span></h2><div ><table><tbody><tr><td class="firstcol " ><p><strong>Price</strong></p></td><td  ><p><a href="https://www.amazon.com/Gozney-Pizza-Fired-makes-pizza/dp/B0CY76J1NY/" target="_blank" rel="nofollow">$999</a> / <a href="https://www.gozney.com/products/arc-xl" target="_blank" rel="nofollow">£799</a></p></td></tr><tr><td class="firstcol " ><p><strong>Size</strong></p></td><td  ><p>20.9 x 24.8 x 13.5 inches (530 x 629x 342mm)</p></td></tr><tr><td class="firstcol " ><p><strong>Weight</strong></p></td><td  ><p>58.5lbs (26.5kg) </p></td></tr><tr><td class="firstcol " ><p><strong>Capacity</strong></p></td><td  ><p>1x 16-inch pizza</p></td></tr><tr><td class="firstcol " ><p><strong>Internal dimensions</strong></p></td><td  ><p>16.8 x 20.3 x 6.8 inches (427 x 517 x 173mm)</p></td></tr><tr><td class="firstcol " ><p><strong>Mouth opening</strong></p></td><td  ><p>16.8 x 3.6 inches (427 x 95mm)</p><p><br></p></td></tr><tr><td class="firstcol " ><p><strong>Stone</strong></p></td><td  ><p>0.8-inch/20mm cordierite</p></td></tr><tr><td class="firstcol " ><p><strong>Max temperature</strong></p></td><td  ><p>932F / 500C</p></td></tr><tr><td class="firstcol " ><p><strong>Fuel types</strong></p></td><td  ><p>Propane</p></td></tr></tbody></table></div><h2 class="article-body__section" id="section-gozney-arc-xl-review-price-availability"><span>Gozney Arc XL review: Price & availability</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="iRGEKpzFxPiWaA7PHzNNZg" name="Gozney Arc XL-11" alt="A photo of the Gozney Arc XL in a garden" src="https://cdn.mos.cms.futurecdn.net/iRGEKpzFxPiWaA7PHzNNZg.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Peter Wolinski / Future)</span></figcaption></figure><p>The Gozney Arc XL isn’t cheap, costing <a href="https://www.amazon.com/Gozney-Pizza-Fired-makes-pizza/dp/B0CY76J1NY/" target="_blank" rel="nofollow">$999</a> / <a href="https://www.gozney.com/products/arc-xl" target="_blank" rel="nofollow">£799</a>, which is a sizable $300 / £200 more than the 14-inch standard Arc. Other than the extra 2-inch capacity, the ovens are pretty much the same, so it’ll just depend on how much larger pizzas mean to you.</p><p>Personally, I love cooking larger pies. It’s trickier, so more of a challenge, but when you get it right you can feed more people easily, so the XL will be better if you plan on cooking for multiple guests regularly.</p><p>The Arc XL’s main rival is the <a href="https://www.tomsguide.com/reviews/ooni-koda-16">Ooni Koda 16</a>, which cooks 16-inch pizzas, runs on gas and undercuts the Gozney by a healthy margin, costing $599 / £499. The Koda is lighter, uses Ooni’s folding leg system for easier storage, and features an L-shaped burner for wider flame dispersion and less rotating required during cooking. We awarded the Koda 16 our full five stars, and you can probably now see why — for the money, it’s difficult to beat.</p><h2 class="article-body__section" id="section-gozney-arc-xl-review-design"><span>Gozney Arc XL review: Design</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="nUmSESdp7rcda2nZUq8cHj" name="Gozney Arc XL-4" alt="A photo of the Gozney Arc XL in a garden" src="https://cdn.mos.cms.futurecdn.net/nUmSESdp7rcda2nZUq8cHj.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Peter Wolinski / Future)</span></figcaption></figure><p>The Gozney Arc XL looks beautiful, employing Gozney’s typically slick, neo-retro aesthetic. It looks straight out of a trendy London pizzeria, which is the point. It’s beautifully made and finished, with a high level of attention to detail, and feels built to last. </p><p>I wouldn’t say it’s any better or worse than an Ooni in this respect, so which manufacturer you pick will depend on whether you want the more luxurious styling of Gozney, or the more futuristic look of Ooni. That is unless you’re a commercial user — if you’ve got a pizza van or small kitchen to kit out, I think the round shape and flat base of the Gozney is more versatile than the Ooni Karu 16, with its oblong shape and tall legs.</p><p>The Arc XL is a behemoth, though, measuring 20.9 x 24.8 x 13.5 inches and weighing nearly 60 pounds, so you’ll want a second person on hand to help you set up. My wife was on vacation so I had no choice but to set the Arc XL up on my own, and very nearly put my back out getting it unboxed and onto the stand. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.30%;"><img id="hf9vo6tiRYH8CFqHhXbo6h" name="Gozney Arc XL-10" alt="A photo of the Gozney Arc XL in a garden" src="https://cdn.mos.cms.futurecdn.net/hf9vo6tiRYH8CFqHhXbo6h.jpg" mos="" align="middle" fullscreen="" width="2000" height="1126" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Peter Wolinski / Future)</span></figcaption></figure><p>Colossal weight aside, setting the Arc XL up is very easy — you just remove the packaging and padding; pull the stone forward a fraction of an inch; put the metal flame guard in place; and put batteries (supplied) in the thermometer and digital dial. There’s a helpful quick start guide included to cover all this. </p><p>I was ready for the burn-in after about 10 minutes — burning in is something you must do with most pizza ovens before you can make pizza — although it actually took me around 5 days because I couldn't find any fuel in my area (it was peak summer).</p><h2 id="fuel">Fuel</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.30%;"><img id="3E7XXTr3qkrekwYi33Pb7h" name="Gozney Arc XL-9" alt="A photo of the Gozney Arc XL in a garden" src="https://cdn.mos.cms.futurecdn.net/3E7XXTr3qkrekwYi33Pb7h.jpg" mos="" align="middle" fullscreen="" width="2000" height="1126" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Peter Wolinski / Future)</span></figcaption></figure><p>The Arc XL runs on propane gas. You can theoretically use butane, too, although Gozney doesn’t recommend it, and butane is less likely to work in colder temperatures. My Arc XL was supplied with a clip-on regulator for the patio gas canisters we get here in the U.K.</p><p>Something I love about multi-fuel ovens is that, if you’re out of gas, you can simply use wood or charcoal. It’s worth considering a multi-fuel oven like the Gozney Dome or Ooni Karu 2 Pro if you’d rather have that extra flexibility.</p><p>The Arc XL is fairly fuel-efficient and Gozney says a 28lb / 13kg canister should last around 30 hours. You’ll need as much efficiency as you can get, as the only way to easily clean the Arc XL is by burning it for three hours, which sucks, as I’ll touch on later.</p><h2 class="article-body__section" id="section-gozney-arc-xl-review-accessories"><span>Gozney Arc XL review: Accessories</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.30%;"><img id="tA4CNWKTdRCrAk4xaz6TTj" name="Gozney Arc XL-14" alt="A photo of the Gozney Arc XL in a garden" src="https://cdn.mos.cms.futurecdn.net/tA4CNWKTdRCrAk4xaz6TTj.jpg" mos="" align="middle" fullscreen="" width="2000" height="1126" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Peter Wolinski / Future)</span></figcaption></figure><p>Something many don’t understand before they buy their first pizza oven is that you need accessories. You can’t make a pizza without at least a launching peel and a turning peel. I tested <a href="https://www.amazon.com/Gozney-Pro-Pizza-Placement-Peel/dp/B0FS2Y61RQ" target="_blank" rel="nofollow">Gozney’s 16-inch Pro Placement peel</a> ($109) and <a href="https://us.gozney.com/products/balance-turning-peel" target="_blank" rel="nofollow">Balance Turning peel</a> ($89) and would highly recommend them both. Although, if you’re just starting out or are on a tight budget, you can find cheaper alternatives at Amazon, which will work just fine.</p><p>I would also recommend you buy an infrared thermometer for measuring stone temperature (the temperature on the Arc XL only measures ambient temperature, which won’t tell you precisely when the stone is ready for cooking). The <a href="https://us.gozney.com/products/infrared-thermometer" target="_blank" rel="nofollow">Gozney infrared thermometer gun costs $49</a>, which is similar to Ooni’s pricing.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.30%;"><img id="PzLoS8iGREiCXx2jpUAGsh" name="Gozney Arc XL-15" alt="A photo of the Gozney Arc XL in a garden" src="https://cdn.mos.cms.futurecdn.net/PzLoS8iGREiCXx2jpUAGsh.jpg" mos="" align="middle" fullscreen="" width="2000" height="1126" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Peter Wolinski / Future)</span></figcaption></figure><p>Gozney also sells a variety of other accessories that I found exceptionally useful. Firstly, there’s the <a href="https://us.gozney.com/products/dough-tray" target="_blank" rel="nofollow">$49 dough tray</a>, which I absolutely love. This tray features a thermometer to show you which type of proof (cold, warm, etc) your ambient conditions will result in, allowing you to tailor proof times. It also shows you when conditions are too warm, and features a bulk fermenting tray and a silicone insert for six dough balls (for up to 14-inch pizzas).</p><p>I’m also a huge fan of the <a href="https://us.gozney.com/products/arc-xl-mantel" target="_blank" rel="nofollow">Arc XL mantel ($119)</a>, which gives you a couple of inches of surface outside the oven mouth — enough space to safely turn food or leave your pizza to rest for a moment without burning while you find a board for it. And <a href="https://us.gozney.com/products/heat-resistant-gloves" target="_blank" rel="nofollow">Gozney's $39 heat resistant gloves</a>, which can stand up to 950F / 500C heat.</p><p>I also tested the <a href="https://us.gozney.com/products/pizza-cutter" target="_blank" rel="nofollow">Gozney Pizza Cutter ($44)</a>. My wife hated pizza cutters and always refused to use our other ones (choosing a knife or scissors instead). The Gozney cutter has converted her — thanks to its weight and sharp blade, it's much more stable and effective than cheaper cutters.</p><h2 class="article-body__section" id="section-gozney-arc-xl-review-performance"><span>Gozney Arc XL review: Performance</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:5217px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="cT8UcMDUv9ZCLk6XCrsssn" name="Gozney Arc XL_Test shot-6" alt="A pizza cooking in the Gozney Arc XL" src="https://cdn.mos.cms.futurecdn.net/cT8UcMDUv9ZCLk6XCrsssn.jpg" mos="" align="middle" fullscreen="" width="5217" height="2935" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Peter Wolinski / Future)</span></figcaption></figure><p>The Gozney Arc XL performs like a professional pizza oven. The stone heats up to 750F / 400C in around 15-20 minutes, which is hot enough for Neapolitan-style pizza. Alternatively, you can cook other styles of pizza before then — low’n’slow pizzas like NY-style.</p><p>The thermometer gauge on the front of the oven is very useful to give you an idea of ambient temperatures, which dictate how quickly the upper sections of your pizza will cook (although the cooking of your toppings will also be affected by the size and intensity of the gas flame). </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.30%;"><img id="qo2R3dgpxboVzaiW4Xb8pg" name="Gozney Arc XL-13" alt="A photo of the Gozney Arc XL in a garden" src="https://cdn.mos.cms.futurecdn.net/qo2R3dgpxboVzaiW4Xb8pg.jpg" mos="" align="middle" fullscreen="" width="2000" height="1126" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Peter Wolinski / Future)</span></figcaption></figure><p>Annoyingly, the temperature gauge turns itself off after a while — on a few occasions I turned back to the gauge while cooking to check temperatures, only to find it switched off. I get that this is to save battery, but it’s really annoying.</p><p>The Arc XL is very predictable thanks to running on gas, and you have a high level of control over the flame size by twisting the control knob on the front.</p><p>You’ll need to cook a few pizzas and get used to the temperature of the oven, and to get a feel for how to adjust your flame while cooking. Once you’ve got it down, though, you can cook a Neapolitan pizza in just a minute or two.</p><figure role="gallery"><figure><img src="https://cdn.mos.cms.futurecdn.net/oWB4cCGpNUQVvcxoftMxhm.jpg" alt="A slice of pizza in hand, the pizza was cooked on the Gozney Arc XL" /><figcaption><small role="credit">Peter Wolinski / Future</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/EBQYdvgx7xoLoEySJVdxsn.jpg" alt="A pizza cooked on the Gozney Arc XL" /><figcaption><small role="credit">Peter Wolinski / Future</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/yMwi7zeD3wrkj7PrzjXqun.jpg" alt="A pizza cooked on the Gozney Arc XL" /><figcaption><small role="credit">Peter Wolinski / Future</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/ae59Fbbpv3Jk3hP3w9pNun.jpg" alt="A pizza cooked on the Gozney Arc XL" /><figcaption><small role="credit">Peter Wolinski / Future</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/LGHQdEdiGemfaSrK9D2jun.jpg" alt="A pizza cooked on the Gozney Arc XL" /><figcaption><small role="credit">Peter Wolinski / Future</small></figcaption></figure></figure><p>I cooked a variety of pizzas, from 12-inch through to 16-inch bases, in Neapolitan and NY styles. On several occasions, I cooked for groups of six. The Arc XL handled it all beautifully. Thanks to the large 16-inch stone, you can cook bigger pizzas to feed multiple people, so you don’t need to spend the entirety of a pizza party churning out 12-inch pies for each person.</p><p>It’s very easy to burn larger 16-inch pies, as they sit so close to the flame. This means that you’ll want to turn them early, which can cause rips in the dough and an awful mess. This happened on a few occasions for me — to avoid this, ensure the stone is at least 750F / 400C before launching, so pizza bases cook very quickly.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:4770px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="LkKuqvfb2h4c9TcEEg9Ctn" name="Gozney Arc XL_Test shot-4" alt="A garlic flatbread cooked on the Gozney Arc XL" src="https://cdn.mos.cms.futurecdn.net/LkKuqvfb2h4c9TcEEg9Ctn.jpg" mos="" align="middle" fullscreen="" width="4770" height="2683" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Peter Wolinski / Future)</span></figcaption></figure><p>I also cooked large garlic flatbreads, as well as sides like charred broccoli spears and caramelized roasted carrots. The stone also gets hot enough to sear steaks and meat, so it’s a highly versatile oven.</p><h2 class="article-body__section" id="section-gozney-arc-xl-review-storage-maintenance"><span>Gozney Arc XL review: Storage & maintenance</span></h2><p>My one major gripe with the Arc XL is how difficult the stone is to remove. Without buying a removal kit, you’ll need to tip the oven on its side and support the stone out — a two-person job, which also involves removing the oven from any stand or base you have it fastened to. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.30%;"><img id="cQ5L2r3DpjfDFQPvDFJF6h" name="Gozney Arc XL-6" alt="A photo of the Gozney Arc XL in a garden" src="https://cdn.mos.cms.futurecdn.net/cQ5L2r3DpjfDFQPvDFJF6h.jpg" mos="" align="middle" fullscreen="" width="2000" height="1126" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Peter Wolinski / Future)</span></figcaption></figure><p>This is infuriating if you make a mess. Gonzey’s advice is to burn the oven for 3 hours to clean it (wasting gas), which works, but only on the middle and rear of the stone. The front never gets hot enough to self-clean, so if you make a mess there when launching or removing a failed launch, you can’t clean it properly without a lot of hassle. You can scrape most mess off when cool, but not everything. And besides, food still gets stuck between the stone and the oven lip.</p><p>I love that Ooni’s stones are much easier to remove, so you can take them out and properly clean them up. As I mentioned before, this also means you don’t need to waste hours of gas just to clean. Gozney should include a stone removal kit with every oven.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.30%;"><img id="JovgEojWbc9cun2NkppDth" name="Gozney Arc XL-3" alt="A photo of the Gozney Arc XL in a garden" src="https://cdn.mos.cms.futurecdn.net/JovgEojWbc9cun2NkppDth.jpg" mos="" align="middle" fullscreen="" width="2000" height="1126" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Peter Wolinski / Future)</span></figcaption></figure><p>Gozney also recommends burning the oven for several hours to clean soot from the roof, which is just ridiculously wasteful. I just waited for it to cool and cleaned with a dry cloth. Maintenance is otherwise very simple — just wipe down the exterior parts when cool.</p><p>Storage is as you’d expect for such a huge cooker: you’ll need a fair bit of space. I’d recommend <a href="https://us.gozney.com/products/arc-arc-xl-stand" target="_blank" rel="nofollow">Gozney’s Arc + Arc XL stand</a> ($299), which features fold-away ledges, storage hooks, and wheels to move the oven to and from position. It’s also important to cover the oven and keep it safe from the elements — Gozney sells covers for this (including a <a href="https://us.gozney.com/products/arc-arc-xl-stand-cover" target="_blank" rel="nofollow">cover that goes over the whole stand</a>).</p><h2 class="article-body__section" id="section-gozney-arc-xl-review-verdict"><span>Gozney Arc XL review: Verdict</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="diNPFJT9L76PJjBZeYjrJh" name="Gozney Arc XL-2" alt="A photo of the Gozney Arc XL in a garden" src="https://cdn.mos.cms.futurecdn.net/diNPFJT9L76PJjBZeYjrJh.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Peter Wolinski / Future)</span></figcaption></figure><p>The Gozney Arc XL is a fantastic pizza oven. With its large 16-inch stone, you can cook big pizzas for multiple people and simplify your pizza parties. It’s easy to use, beautiful to behold and built to last. And most importantly, it makes fantastic pizza.</p><p>There are a couple of things to consider. First, it’s pricey — you can get the rival Ooni Karu 16 for much less money, which is better than the Arc XL in almost every way. Secondly, the stone is tricky to remove, which makes the Arc XL trickier to clean than Ooni ovens. </p><p>If you’re willing to overlook those flaws, though, as I have, then I’ve no hesitation in recommending the Arc XL to small commercial and home pizzaioli. </p>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ $300 vs $2,000 espresso machine — I ran a blind taste test to see if you need to spend $$$ for barista coffee at home ]]></title>
                                                                                                <dc:content><![CDATA[ <p>Very little comes close to the satisfaction I feel when I take my first sip of an expensive flat white from an equally expensive independent cafe. I love everything about frequenting coffeehouses: the adventure of actually going outside, deciding which of the plentiful bean varietals I fancy, then scrutinizing — ahem, <em>watching</em> — the barista as they make my oat milk flat white. </p><p>But patronizing cafes is costly, and I know I'm not the only one to say I don't have the money for it. But even if you want to make cafe-quality coffee at home, there's a catch. Many home espresso machines carry a staggering initial cost. Even the best-value stalwarts, like the <a href="https://www.tomsguide.com/home/coffee-makers/delonghi-la-specialista-arte-evo-review">De'Longhi La Specialista Arte Evo</a> ($699) and my personal machine, the <a href="https://www.tomsguide.com/home/home-appliances/breville-sage-bambino-plus-review">Breville Bambino Plus</a> ($499), are objectively expensive. And don't even get me started on grinders. </p><p>But could you get away with a cheaper espresso machine, and instead invest in a grinder and high-quality beans? To find out, I pitted two of my favorite espresso machines against one another in a blind taste test: the gorgeous prosumer <a href="https://www.tomsguide.com/home/coffee-makers/lelit-mara-x3-review">Lelit MaraX3</a> ($1,999) and the cheap <a href="https://www.tomsguide.com/home/coffee-makers/sage-breville-bambino-review">Breville Bambino</a> ($299). </p><p>So which machine won — and which machine should you buy?</p><h2 class="article-body__section" id="section-the-competitors"><span>The competitors</span></h2>        <div class="featured_product_block featured_block_versus" data-id="5495463a-8a95-11f1-8df2-3be1201f93a3">            <a href="https://www.amazon.com/Breville-Bambino-Espresso-Machine-Stainless/dp/B0B1JPPG2L" data-model-name="Sage Bambino" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/VFx8KQ3FReuyYgDviuN5hS.jpg" alt="the breville bambino espresso machine in silver with steam wand and drip tray visible"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                                            <div class='featured__brand'>Breville</div>                    <div class="featured__title">Bambino</div>                                    </div>                <div class="subtitle__description">                                                            <p><p>The Breville Bambino is, without a doubt, the best budget espresso machine you can buy. It has premium features like customizable pre-infusion and a PID controller for much cheaper than most of the competition.</p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_versus" data-id="549546b2-8a95-11f1-a176-878bfda703d5">            <a href="https://www.seattlecoffeegear.com/products/lelit-mara-x3-espresso-machine?variant=53213339648307" data-model-name="Lelit Mara X3" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/K72vsuo35nBPsGGzk4K8xU.webp" alt="Lelit, Mara X3"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                                            <div class='featured__brand'>Lelit</div>                    <div class="featured__title">MaraX3</div>                                    </div>                <div class="subtitle__description">                                                            <p><p>The Lelit MaraX3 is the newest entry-level prosumer model by the Australian manufacturer Breville, designed and manufactured in Italy, combining a dual-boiler system, customizable pressure paddle, a live manometer, and a 58mm portafilter. You've even got real wood finishes.</p></p>                </div>                            </div>        </div><h2 class="article-body__section" id="section-the-control"><span>The control</span></h2><p>I used the same beans — <a href="https://cartercoffee.uk/products/mendoza-peru-anaerobic-nat-copy" target="_blank" rel="nofollow">Carter Coffee's Two Trees Geisha</a>, £21 ($28) for 200g. With tasting notes of passion fruit, white peach, and an aromatic finish, I knew my espresso testers were in for a treat. When I first opened the bag, it made my brain light up like I was seeing my long-lost dog for the first time in thirty years. </p><p>I ground the beans using my <a href="https://www.tomsguide.com/home/coffee-makers/mazzer-philos-review">Mazzer Philos</a> ($1,500), the best grinder in the world. I'll acknowledge that this grinder is blindingly expensive, and not reasonable for most people at all. You do <em>not</em> need to buy this grinder to achieve similar results. I would recommend the <a href="https://www.tomsguide.com/home/home-appliances/baratza-encore-esp-review#section-baratza-encore-esp-review-performance">Baratza Encore ESP</a> ($199) or <a href="https://www.tomsguide.com/home/home-appliances/comandante-c40-mk4-review">Comandante C40 MK4</a> (usually around $300) for most people. </p><p>A brief disclaimer: I use the Mazzer Philos in all my espresso experiments, so if any issues arise, I <em>know</em> it wasn't the grinder.</p><p>Admittedly, I ground the beans to slightly different sizes: click 22 for the Lelit, and click 25 for the Breville. This is because anything under click 25 resulted in an overextracted shot on the Breville, and anything over click 22 resulted in an underextracted shot on the Lelit. I dialed in my beans for each machine before commencing.</p><h2 class="article-body__section" id="section-the-test"><span>The test</span></h2><p>I ran three blind taste tests: Black Americano, oat milk flat white, and pure espresso. </p><h2 id="black-americano">Black Americano</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:4574px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="bL9oJxo4z7fjCxHhFGNHPc" name="bambino vs mara x3" alt="a photo of a black americano made on the breville bambino and lelit mara x3" src="https://cdn.mos.cms.futurecdn.net/bL9oJxo4z7fjCxHhFGNHPc.png" mos="" align="middle" fullscreen="" width="4574" height="2573" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="caption-text">Can you guess which is which? (Coffee B on your left, and Coffee A on your right — confusing, I know. Sorry!) </span><span class="credit" itemprop="copyrightHolder">(Image credit: Erin Bashford)</span></figcaption></figure><p>I made the black Americanos identically: 18g of coffee for 36g out between 25-28 seconds. Topped up with 8 ounces of thirty-seconds-off-the-boil water.</p><p>For now, we'll call them <strong>Coffee A </strong>and <strong>Coffee B</strong>.<strong> </strong></p><p>My colleague Pete said <strong>Coffee A</strong> tasted "sour and bitter with less nuance, but still delicious." Lucy said <strong>A</strong> didn't have "much flavor," which was supported by James and Caspar, who said <strong>A</strong> tasted "a little thin" and "quite watery," respectively. </p><p>Josh was the only tester to prefer <strong>Coffee</strong> <strong>A</strong>: he reported it had a "richer aftertaste" and "more flavor in the afternotes" than <strong>Coffee B</strong>. </p><p>Lucy said <strong>Coffee B </strong>had a "more nuanced flavor than <strong>A,</strong>" which was supported by James: "tastes a lot fuller and stronger," and Caspar, who enjoyed <strong>B</strong>'s smoothness. Pete noticed the crema was thicker on <strong>Coffee B</strong>, which he thought meant it had a higher-quality group head. He preferred<strong> B </strong>overall due to the balanced bitter, caramel, and sour notes. </p><p>Josh was the only person to criticize <strong>B</strong>: he said it tasted "slightly more muted" and chose <strong>Coffee A</strong> as his favorite. </p><p>Can you guess which was which? </p><h2 id="oat-milk-flat-white">Oat milk flat white</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:4418px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="gfQQW7XvBvsedj6nZ4rpe7" name="bambino and mara flat white" alt="two flat whites made on the breville bambino and lelit mara x3" src="https://cdn.mos.cms.futurecdn.net/gfQQW7XvBvsedj6nZ4rpe7.png" mos="" align="middle" fullscreen="" width="4418" height="2485" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="caption-text">Can you guess which is which? Coffee B on your left, and Coffee A on your right. Confusing — sorry (again)! </span><span class="credit" itemprop="copyrightHolder">(Image credit: Erin Bashford)</span></figcaption></figure><p>The second test: oat milk flat white. I had a few fewer testers due to other responsibilities for this one. </p><p>Again, I made the coffees identically: 18g of coffee for 36g out within 25-28 seconds. I steamed milk using my usual barista-taught method (I am an ex-barista, after all). </p><p>Let's give them their names: <strong>Coffee A </strong>and <strong>Coffee B</strong>.</p><p>Pete preferred <strong>Coffee A</strong>, saying, "Milk is better textured on A. It's less aerated; smoother and silkier." He also preferred the coffee flavor on A. "Slight bit more flavor poking through. But very difficult to tell." </p><p>James said <strong>Coffee A </strong>was "really nice," but he liked the "darker, more intense flavor" on <strong>Coffee B </strong>more, so that was his favorite. Josh agreed with James, choosing <strong>Coffee B</strong> due to its "smoother" and "more coffee-like" flavor. </p><h2 id="espresso-2">Espresso</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2340px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="4S8Vvtr3M23SSgCY5jyxuY" name="bambino and mara x3 espresso" alt="two shots of espresso one made on lelit mara x3 one on the breville bambino" src="https://cdn.mos.cms.futurecdn.net/4S8Vvtr3M23SSgCY5jyxuY.png" mos="" align="middle" fullscreen="" width="2340" height="1316" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="caption-text">Can you tell which is which? Coffee A is on the right and Coffee B on the left (sorry — for the third and final time). </span><span class="credit" itemprop="copyrightHolder">(Image credit: Erin Bashford)</span></figcaption></figure><p>Now for the most important test: straight espresso. There's nowhere to hide here. </p><p>I actually made a single espresso for this one, using 12g of coffee for 24g of espresso out. I don't have two espresso glasses, so apologies for the unconventional container in the photographs above. </p><p>Again, I'll introduce the players: <strong>Coffee A </strong>and <strong>Coffee B</strong>. </p><p>Pete said <strong>Coffee A</strong> had a better crema and smelled "more potently of chocolate." When he took a sip, he said, "Oh, that's good." Not really much else for me to say, is there? Overall, he said <strong>Coffee A</strong> had "a lot of body and a bit of acidity." Spoiler alert, but after drinking <strong>Coffee B</strong>, he said <strong>Coffee A </strong>was, and I quote, "So much nicer."</p><p>James and Caspar also preferred <strong>Coffee A</strong>; James said it had "a lot more going on, with more levels to the coffee flavor."  </p><p>Josh mostly agreed — he said <strong>Coffee A</strong> had more fruit notes with a richer mouthfeel. I'll note here that Josh had the most sips out of anyone and mulled on his decision for much longer than anyone else, so his decision was almost too close to call.</p><p>Lucy was the only outlier, saying <strong>Coffee A</strong> had a "nice" espresso taste but not as rich as <strong>Coffee B</strong>, which had a more diverse flavor, with more dynamism in the sip. Interestingly, I also agreed — is this female vs male taste buds in action? (I'm joking — obviously there's no difference in female vs male taste buds).</p><p>What do you think? Ready for the results? </p><h2 class="article-body__section" id="section-the-results"><span>The results</span></h2><div ><table><thead><tr><th class="firstcol " ><p>Taster</p></th><th  ><p>Americano</p></th><th  ><p>Flat white</p></th><th  ><p>Espresso</p></th></tr></thead><tbody><tr><td class="firstcol " ><p>Pete</p></td><td  ><p>Coffee B - Bambino</p></td><td  ><p>Coffee A - Lelit</p></td><td  ><p>Coffee A - Bambino</p></td></tr><tr><td class="firstcol " ><p>Josh</p></td><td  ><p>Coffee A - Lelit</p></td><td  ><p>Coffee B - Bambino</p></td><td  ><p>Coffee A - Bambino</p></td></tr><tr><td class="firstcol " ><p>James</p></td><td  ><p>Coffee B - Bambino</p></td><td  ><p>Coffee B - Bambino</p></td><td  ><p>Coffee A - Bambino</p></td></tr><tr><td class="firstcol " ><p>Caspar</p></td><td  ><p>Coffee B - Bambino</p></td><td  ><p>-</p></td><td  ><p>Coffee A - Bambino</p></td></tr><tr><td class="firstcol " ><p>Lucy</p></td><td  ><p>Coffee B - Bambino</p></td><td  ><p>-</p></td><td  ><p>Coffee B - Lelit</p></td></tr><tr><td class="firstcol " ><p>Winner</p></td><td  ><p>Bambino</p></td><td  ><p>Bambino</p></td><td  ><p>Bambino</p></td></tr></tbody></table></div><p>And now I get to crown the $299 machine the winner! I didn't expect the Bambino to win — and neither did any of my testers. They were all shocked when I told them.</p><p>Of course, I tried all the drinks before I offered them to my taste-testers... and I preferred the Lelit MaraX3 every time. But is that because <em>I </em>knew it was the more expensive one, therefore I assumed it should have been tastier? Or because I personally prefer an acidic coffee, so this appealed to my unique taste buds?  </p><p>I suppose I'll never know. </p><h2 class="article-body__section" id="section-but-taste-isn-t-the-only-thing-you-should-consider"><span>But taste isn't the only thing you should consider</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="yRWDPrYTJUqnrzGTyAvGyZ" name="Sage_bambino_.JPG" alt="the breville bambino / sage bambino in silver photographed against a blue background with a wooden feature wall, showing the steam wand, group head, water tank, button controls, and espresso" src="https://cdn.mos.cms.futurecdn.net/yRWDPrYTJUqnrzGTyAvGyZ.jpg" mos="" align="middle" fullscreen="" width="1920" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>Although I love the Breville Bambino — it's my favorite budget espresso machine, and there's literally zero competition — winning the taste test doesn't mean it's the <a href="https://www.tomsguide.com/home/coffee-makers/im-an-ex-barista-heres-my-top-3-espresso-machines-for-every-budget">best espresso machine</a> in every situation. </p><p>The MaraX3 and Bambino are (mostly) intended for a different audience. You're not just paying $2,000 for coffee. You're paying $2,000 for a dual boiler, meaning you can steam milk and pull shots at the same time. You're paying $2,000 for the all-metal (+wood) construction, which might last longer than the Bambino's plastic. You're paying $2,000 for the steam, milk, and pressure configuration tools. </p><p>We're all thinking it, so I might as well say it: You're paying $2,000 for the Lelit branding and the Lelit design. </p><p>The MaraX3 is a work of art, and you should treat it like one. </p><p>If I had $2k, I know which machine I'd choose. The Lelit would already be in my kitchen.</p><p>Despite all of this, though, Lelit and Breville are part of the same company. Lelit is literally Breville's prosumer brand. The Baratza Encore ESP grinder I mentioned earlier? Also owned by Breville. </p><p>So, at the end of the day, your money's going to the same pocket. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1820px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="Unvedt68K7JGoD2qj6ro63" name="Lelit_Mara_X320.JPG" alt="the lelit mara x3 in white and walnut photographed against a blue tom's guide background" src="https://cdn.mos.cms.futurecdn.net/Unvedt68K7JGoD2qj6ro63.jpg" mos="" align="middle" fullscreen="" width="1820" height="1024" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>If you want more coffee content, don't fret. I've got bucketloads (cuploads?). Every week, I release new episodes of <a href="https://www.tomsguide.com/tag/the-coffee-lab">The Coffee Lab</a>, my series dedicated to forgetting coffee snobbery and figuring out what actually matters in your daily brew. </p><figure class="inline-layout"><div style="min-height: 400px;"><fw-embed-feed channel="toms_guide" playlist="ojE0pK" mode="row" player_placement="bottom-right"></fw-embed-feed></div></figure><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h3><ul><li><a href="https://www.tomsguide.com/home/coffee-makers/i-tried-the-new-nespresso-summer-flavors-heres-my-favorite"><strong>I tried the new Nespresso summer flavors — here's my favorite</strong></a></li><li><a href="https://www.tomsguide.com/home/coffee-makers/non-plastic-coffee-makers-are-trending-and-this-low-plastic-ratio-model-is-my-favorite-for-coffee-snobs"><strong>Non-plastic coffee makers are trending — and this low-plastic Ratio model is my favorite for coffee snobs</strong></a></li><li><a href="https://www.tomsguide.com/home/coffee-makers/i-tried-lelits-brand-new-entry-level-espresso-machine-and-i-wish-i-had-usd2-000-so-i-could-buy-it"><strong>I tried Lelit's brand-new 'entry-level' espresso machine — and I wish I had $2,000 so I could buy it</strong></a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/home/coffee-makers/usd300-vs-usd2-000-espresso-machine-i-ran-a-blind-taste-test-to-see-if-you-need-to-spend-usd-usd-usd-for-barista-coffee-at-home</link>
                                                                            <description>
                            <![CDATA[ I ran a blind taste test to answer the age-old question: Does a more expensive espresso machine make better coffee? ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">KdYVZFAVcHcRjWVLqLNuG9</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/gj6E9VE3uZhnKh7qz2MQvJ-1280-80.png" type="image/png" length="0"></enclosure>
                                                                        <pubDate>Wed, 29 Jul 2026 08:00:00 +0000</pubDate>                                                                                                                                <updated>Mon, 03 Aug 2026 08:35:00 +0000</updated>
                                                                                                                                            <category><![CDATA[Coffee Makers]]></category>
                                                    <category><![CDATA[Home]]></category>
                                                    <category><![CDATA[Home Appliances]]></category>
                                                    <category><![CDATA[Kitchen & Dining]]></category>
                                                                                                <author><![CDATA[ erin.bashford@futurenet.com (Erin Bashford) ]]></author>                    <dc:creator><![CDATA[ Erin Bashford ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/rLvJvJVZx43hEzSsJy3BpL.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Erin Bashford is a senior reviews writer at Tom’s Guide. She has a Master’s in Broadcast and Digital Journalism from the University of East Anglia and 7 years of experience reviewing music and events for various publications. She has edited publications such as Outline Magazine’s Guide to Norwich, and she has written for a number of music magazines and websites such as Clash Magazine, Outline Magazine and Dork Magazine. She has a strong interest in audio gear and the music world. &lt;/p&gt;&lt;p&gt;As an ex-barista, Erin is passionate about coffee tech. She also loves finding the best cooking hacks and kitchen appliances, including her beloved Instant Pot. &lt;/p&gt;&lt;p&gt;In her spare time, you can find her reading, practising yoga, hiking, writing fantasy novels, or stressing over NYT Games.&lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                <media:content type="image/png" url="https://cdn.mos.cms.futurecdn.net/gj6E9VE3uZhnKh7qz2MQvJ-1280-80.png">
                                                            <media:credit><![CDATA[Erin Bashford]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[the breville bambino and lelit mara x3 photographed in a kitchen set with specialty coffee in the foreground]]></media:description>                                                            <media:text><![CDATA[the breville bambino and lelit mara x3 photographed in a kitchen set with specialty coffee in the foreground]]></media:text>
                                <media:title type="plain"><![CDATA[the breville bambino and lelit mara x3 photographed in a kitchen set with specialty coffee in the foreground]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/gj6E9VE3uZhnKh7qz2MQvJ-1280-80.png" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Very little comes close to the satisfaction I feel when I take my first sip of an expensive flat white from an equally expensive independent cafe. I love everything about frequenting coffeehouses: the adventure of actually going outside, deciding which of the plentiful bean varietals I fancy, then scrutinizing — ahem, <em>watching</em> — the barista as they make my oat milk flat white. </p><p>But patronizing cafes is costly, and I know I'm not the only one to say I don't have the money for it. But even if you want to make cafe-quality coffee at home, there's a catch. Many home espresso machines carry a staggering initial cost. Even the best-value stalwarts, like the <a href="https://www.tomsguide.com/home/coffee-makers/delonghi-la-specialista-arte-evo-review">De'Longhi La Specialista Arte Evo</a> ($699) and my personal machine, the <a href="https://www.tomsguide.com/home/home-appliances/breville-sage-bambino-plus-review">Breville Bambino Plus</a> ($499), are objectively expensive. And don't even get me started on grinders. </p><p>But could you get away with a cheaper espresso machine, and instead invest in a grinder and high-quality beans? To find out, I pitted two of my favorite espresso machines against one another in a blind taste test: the gorgeous prosumer <a href="https://www.tomsguide.com/home/coffee-makers/lelit-mara-x3-review">Lelit MaraX3</a> ($1,999) and the cheap <a href="https://www.tomsguide.com/home/coffee-makers/sage-breville-bambino-review">Breville Bambino</a> ($299). </p><p>So which machine won — and which machine should you buy?</p><h2 class="article-body__section" id="section-the-competitors"><span>The competitors</span></h2>        <div class="featured_product_block featured_block_versus" data-id="5495463a-8a95-11f1-8df2-3be1201f93a3">            <a href="https://www.amazon.com/Breville-Bambino-Espresso-Machine-Stainless/dp/B0B1JPPG2L" data-model-name="Sage Bambino" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/VFx8KQ3FReuyYgDviuN5hS.jpg" alt="the breville bambino espresso machine in silver with steam wand and drip tray visible"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                                            <div class='featured__brand'>Breville</div>                    <div class="featured__title">Bambino</div>                                    </div>                <div class="subtitle__description">                                                            <p><p>The Breville Bambino is, without a doubt, the best budget espresso machine you can buy. It has premium features like customizable pre-infusion and a PID controller for much cheaper than most of the competition.</p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_versus" data-id="549546b2-8a95-11f1-a176-878bfda703d5">            <a href="https://www.seattlecoffeegear.com/products/lelit-mara-x3-espresso-machine?variant=53213339648307" data-model-name="Lelit Mara X3" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/K72vsuo35nBPsGGzk4K8xU.webp" alt="Lelit, Mara X3"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                                            <div class='featured__brand'>Lelit</div>                    <div class="featured__title">MaraX3</div>                                    </div>                <div class="subtitle__description">                                                            <p><p>The Lelit MaraX3 is the newest entry-level prosumer model by the Australian manufacturer Breville, designed and manufactured in Italy, combining a dual-boiler system, customizable pressure paddle, a live manometer, and a 58mm portafilter. You've even got real wood finishes.</p></p>                </div>                            </div>        </div><h2 class="article-body__section" id="section-the-control"><span>The control</span></h2><p>I used the same beans — <a href="https://cartercoffee.uk/products/mendoza-peru-anaerobic-nat-copy" target="_blank" rel="nofollow">Carter Coffee's Two Trees Geisha</a>, £21 ($28) for 200g. With tasting notes of passion fruit, white peach, and an aromatic finish, I knew my espresso testers were in for a treat. When I first opened the bag, it made my brain light up like I was seeing my long-lost dog for the first time in thirty years. </p><p>I ground the beans using my <a href="https://www.tomsguide.com/home/coffee-makers/mazzer-philos-review">Mazzer Philos</a> ($1,500), the best grinder in the world. I'll acknowledge that this grinder is blindingly expensive, and not reasonable for most people at all. You do <em>not</em> need to buy this grinder to achieve similar results. I would recommend the <a href="https://www.tomsguide.com/home/home-appliances/baratza-encore-esp-review#section-baratza-encore-esp-review-performance">Baratza Encore ESP</a> ($199) or <a href="https://www.tomsguide.com/home/home-appliances/comandante-c40-mk4-review">Comandante C40 MK4</a> (usually around $300) for most people. </p><p>A brief disclaimer: I use the Mazzer Philos in all my espresso experiments, so if any issues arise, I <em>know</em> it wasn't the grinder.</p><p>Admittedly, I ground the beans to slightly different sizes: click 22 for the Lelit, and click 25 for the Breville. This is because anything under click 25 resulted in an overextracted shot on the Breville, and anything over click 22 resulted in an underextracted shot on the Lelit. I dialed in my beans for each machine before commencing.</p><h2 class="article-body__section" id="section-the-test"><span>The test</span></h2><p>I ran three blind taste tests: Black Americano, oat milk flat white, and pure espresso. </p><h2 id="black-americano">Black Americano</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:4574px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="bL9oJxo4z7fjCxHhFGNHPc" name="bambino vs mara x3" alt="a photo of a black americano made on the breville bambino and lelit mara x3" src="https://cdn.mos.cms.futurecdn.net/bL9oJxo4z7fjCxHhFGNHPc.png" mos="" align="middle" fullscreen="" width="4574" height="2573" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="caption-text">Can you guess which is which? (Coffee B on your left, and Coffee A on your right — confusing, I know. Sorry!) </span><span class="credit" itemprop="copyrightHolder">(Image credit: Erin Bashford)</span></figcaption></figure><p>I made the black Americanos identically: 18g of coffee for 36g out between 25-28 seconds. Topped up with 8 ounces of thirty-seconds-off-the-boil water.</p><p>For now, we'll call them <strong>Coffee A </strong>and <strong>Coffee B</strong>.<strong> </strong></p><p>My colleague Pete said <strong>Coffee A</strong> tasted "sour and bitter with less nuance, but still delicious." Lucy said <strong>A</strong> didn't have "much flavor," which was supported by James and Caspar, who said <strong>A</strong> tasted "a little thin" and "quite watery," respectively. </p><p>Josh was the only tester to prefer <strong>Coffee</strong> <strong>A</strong>: he reported it had a "richer aftertaste" and "more flavor in the afternotes" than <strong>Coffee B</strong>. </p><p>Lucy said <strong>Coffee B </strong>had a "more nuanced flavor than <strong>A,</strong>" which was supported by James: "tastes a lot fuller and stronger," and Caspar, who enjoyed <strong>B</strong>'s smoothness. Pete noticed the crema was thicker on <strong>Coffee B</strong>, which he thought meant it had a higher-quality group head. He preferred<strong> B </strong>overall due to the balanced bitter, caramel, and sour notes. </p><p>Josh was the only person to criticize <strong>B</strong>: he said it tasted "slightly more muted" and chose <strong>Coffee A</strong> as his favorite. </p><p>Can you guess which was which? </p><h2 id="oat-milk-flat-white">Oat milk flat white</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:4418px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="gfQQW7XvBvsedj6nZ4rpe7" name="bambino and mara flat white" alt="two flat whites made on the breville bambino and lelit mara x3" src="https://cdn.mos.cms.futurecdn.net/gfQQW7XvBvsedj6nZ4rpe7.png" mos="" align="middle" fullscreen="" width="4418" height="2485" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="caption-text">Can you guess which is which? Coffee B on your left, and Coffee A on your right. Confusing — sorry (again)! </span><span class="credit" itemprop="copyrightHolder">(Image credit: Erin Bashford)</span></figcaption></figure><p>The second test: oat milk flat white. I had a few fewer testers due to other responsibilities for this one. </p><p>Again, I made the coffees identically: 18g of coffee for 36g out within 25-28 seconds. I steamed milk using my usual barista-taught method (I am an ex-barista, after all). </p><p>Let's give them their names: <strong>Coffee A </strong>and <strong>Coffee B</strong>.</p><p>Pete preferred <strong>Coffee A</strong>, saying, "Milk is better textured on A. It's less aerated; smoother and silkier." He also preferred the coffee flavor on A. "Slight bit more flavor poking through. But very difficult to tell." </p><p>James said <strong>Coffee A </strong>was "really nice," but he liked the "darker, more intense flavor" on <strong>Coffee B </strong>more, so that was his favorite. Josh agreed with James, choosing <strong>Coffee B</strong> due to its "smoother" and "more coffee-like" flavor. </p><h2 id="espresso-2">Espresso</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2340px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="4S8Vvtr3M23SSgCY5jyxuY" name="bambino and mara x3 espresso" alt="two shots of espresso one made on lelit mara x3 one on the breville bambino" src="https://cdn.mos.cms.futurecdn.net/4S8Vvtr3M23SSgCY5jyxuY.png" mos="" align="middle" fullscreen="" width="2340" height="1316" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="caption-text">Can you tell which is which? Coffee A is on the right and Coffee B on the left (sorry — for the third and final time). </span><span class="credit" itemprop="copyrightHolder">(Image credit: Erin Bashford)</span></figcaption></figure><p>Now for the most important test: straight espresso. There's nowhere to hide here. </p><p>I actually made a single espresso for this one, using 12g of coffee for 24g of espresso out. I don't have two espresso glasses, so apologies for the unconventional container in the photographs above. </p><p>Again, I'll introduce the players: <strong>Coffee A </strong>and <strong>Coffee B</strong>. </p><p>Pete said <strong>Coffee A</strong> had a better crema and smelled "more potently of chocolate." When he took a sip, he said, "Oh, that's good." Not really much else for me to say, is there? Overall, he said <strong>Coffee A</strong> had "a lot of body and a bit of acidity." Spoiler alert, but after drinking <strong>Coffee B</strong>, he said <strong>Coffee A </strong>was, and I quote, "So much nicer."</p><p>James and Caspar also preferred <strong>Coffee A</strong>; James said it had "a lot more going on, with more levels to the coffee flavor."  </p><p>Josh mostly agreed — he said <strong>Coffee A</strong> had more fruit notes with a richer mouthfeel. I'll note here that Josh had the most sips out of anyone and mulled on his decision for much longer than anyone else, so his decision was almost too close to call.</p><p>Lucy was the only outlier, saying <strong>Coffee A</strong> had a "nice" espresso taste but not as rich as <strong>Coffee B</strong>, which had a more diverse flavor, with more dynamism in the sip. Interestingly, I also agreed — is this female vs male taste buds in action? (I'm joking — obviously there's no difference in female vs male taste buds).</p><p>What do you think? Ready for the results? </p><h2 class="article-body__section" id="section-the-results"><span>The results</span></h2><div ><table><thead><tr><th class="firstcol " ><p>Taster</p></th><th  ><p>Americano</p></th><th  ><p>Flat white</p></th><th  ><p>Espresso</p></th></tr></thead><tbody><tr><td class="firstcol " ><p>Pete</p></td><td  ><p>Coffee B - Bambino</p></td><td  ><p>Coffee A - Lelit</p></td><td  ><p>Coffee A - Bambino</p></td></tr><tr><td class="firstcol " ><p>Josh</p></td><td  ><p>Coffee A - Lelit</p></td><td  ><p>Coffee B - Bambino</p></td><td  ><p>Coffee A - Bambino</p></td></tr><tr><td class="firstcol " ><p>James</p></td><td  ><p>Coffee B - Bambino</p></td><td  ><p>Coffee B - Bambino</p></td><td  ><p>Coffee A - Bambino</p></td></tr><tr><td class="firstcol " ><p>Caspar</p></td><td  ><p>Coffee B - Bambino</p></td><td  ><p>-</p></td><td  ><p>Coffee A - Bambino</p></td></tr><tr><td class="firstcol " ><p>Lucy</p></td><td  ><p>Coffee B - Bambino</p></td><td  ><p>-</p></td><td  ><p>Coffee B - Lelit</p></td></tr><tr><td class="firstcol " ><p>Winner</p></td><td  ><p>Bambino</p></td><td  ><p>Bambino</p></td><td  ><p>Bambino</p></td></tr></tbody></table></div><p>And now I get to crown the $299 machine the winner! I didn't expect the Bambino to win — and neither did any of my testers. They were all shocked when I told them.</p><p>Of course, I tried all the drinks before I offered them to my taste-testers... and I preferred the Lelit MaraX3 every time. But is that because <em>I </em>knew it was the more expensive one, therefore I assumed it should have been tastier? Or because I personally prefer an acidic coffee, so this appealed to my unique taste buds?  </p><p>I suppose I'll never know. </p><h2 class="article-body__section" id="section-but-taste-isn-t-the-only-thing-you-should-consider"><span>But taste isn't the only thing you should consider</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="yRWDPrYTJUqnrzGTyAvGyZ" name="Sage_bambino_.JPG" alt="the breville bambino / sage bambino in silver photographed against a blue background with a wooden feature wall, showing the steam wand, group head, water tank, button controls, and espresso" src="https://cdn.mos.cms.futurecdn.net/yRWDPrYTJUqnrzGTyAvGyZ.jpg" mos="" align="middle" fullscreen="" width="1920" height="1080" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>Although I love the Breville Bambino — it's my favorite budget espresso machine, and there's literally zero competition — winning the taste test doesn't mean it's the <a href="https://www.tomsguide.com/home/coffee-makers/im-an-ex-barista-heres-my-top-3-espresso-machines-for-every-budget">best espresso machine</a> in every situation. </p><p>The MaraX3 and Bambino are (mostly) intended for a different audience. You're not just paying $2,000 for coffee. You're paying $2,000 for a dual boiler, meaning you can steam milk and pull shots at the same time. You're paying $2,000 for the all-metal (+wood) construction, which might last longer than the Bambino's plastic. You're paying $2,000 for the steam, milk, and pressure configuration tools. </p><p>We're all thinking it, so I might as well say it: You're paying $2,000 for the Lelit branding and the Lelit design. </p><p>The MaraX3 is a work of art, and you should treat it like one. </p><p>If I had $2k, I know which machine I'd choose. The Lelit would already be in my kitchen.</p><p>Despite all of this, though, Lelit and Breville are part of the same company. Lelit is literally Breville's prosumer brand. The Baratza Encore ESP grinder I mentioned earlier? Also owned by Breville. </p><p>So, at the end of the day, your money's going to the same pocket. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1820px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="Unvedt68K7JGoD2qj6ro63" name="Lelit_Mara_X320.JPG" alt="the lelit mara x3 in white and walnut photographed against a blue tom's guide background" src="https://cdn.mos.cms.futurecdn.net/Unvedt68K7JGoD2qj6ro63.jpg" mos="" align="middle" fullscreen="" width="1820" height="1024" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>If you want more coffee content, don't fret. I've got bucketloads (cuploads?). Every week, I release new episodes of <a href="https://www.tomsguide.com/tag/the-coffee-lab">The Coffee Lab</a>, my series dedicated to forgetting coffee snobbery and figuring out what actually matters in your daily brew. </p><figure class="inline-layout"><div style="min-height: 400px;"><fw-embed-feed channel="toms_guide" playlist="ojE0pK" mode="row" player_placement="bottom-right"></fw-embed-feed></div></figure><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h3><ul><li><a href="https://www.tomsguide.com/home/coffee-makers/i-tried-the-new-nespresso-summer-flavors-heres-my-favorite"><strong>I tried the new Nespresso summer flavors — here's my favorite</strong></a></li><li><a href="https://www.tomsguide.com/home/coffee-makers/non-plastic-coffee-makers-are-trending-and-this-low-plastic-ratio-model-is-my-favorite-for-coffee-snobs"><strong>Non-plastic coffee makers are trending — and this low-plastic Ratio model is my favorite for coffee snobs</strong></a></li><li><a href="https://www.tomsguide.com/home/coffee-makers/i-tried-lelits-brand-new-entry-level-espresso-machine-and-i-wish-i-had-usd2-000-so-i-could-buy-it"><strong>I tried Lelit's brand-new 'entry-level' espresso machine — and I wish I had $2,000 so I could buy it</strong></a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ I mixed the exact same smoothie in a $30 blender and a $129 one — here's my verdict ]]></title>
                                                                                                <dc:content><![CDATA[ <p>At the start of the year, I <a href="https://www.tomsguide.com/home/kitchen-dining/i-upgraded-my-usd30-budget-blender-to-a-nutribullet-and-its-made-smoothies-fun-again">upgraded our household blender</a> from a regular non-brand contraption we picked up at the local Aldi to a <a href="https://www.tomsguide.com/home/home-appliances/nutribullet-ultra-1200-personal-blender-review">Nutribullet Ultra 1200. </a>The benefits were that it was easier to clean, looked a lot nicer, and blends your ingredients straight into the shaker you can drink from.</p><p>Over six months later, I decided to return to the pair of them (we haven't got rid of the old one; it's good to have a spare) to put a little bit more testing on the table.</p><p>Part of this, I admit, is due to selfishly wanting to mix up my smoothie game. I'm guilty of going back to the same old recipe time and time again and, with summer here, I'm feeling the need for a change. </p><p>Secondly, although I swapped to the Nutribullet without a second thought — was I giving my old blender its due? What if I fed both machines the <em>exact same ingredients</em> and measured them directly in a head-to-head? Which would really come out on top?</p><p>There are a ton of things the Nutribullet does better: it's objectively smaller, lighter, simpler to use <em>and</em> comes with a better warranty. But I was surprised at a couple of outcomes from this experiment if I'm being totally honest. I'll spoil the big one for you now: <strong>I couldn't tell the difference when it came to tasting the final product</strong>.</p><p>But we're getting ahead of ourselves. Read on to discover just what I found out from my budget vs. premium experiment.</p>                    <div class= "tiktok-wrapper" style="min-height: 750px;"><blockquote class="tiktok-embed" cite="https://www.tiktok.com/@tomsguide/video/7667954816726895886" data-video-id="7667954816726895886" style="max-width: 605px; min-width: 325px;">                        <section>                            <a target="_blank" title="@tomsguide" href="https://www.tiktok.com/@tomsguide">@tomsguide</a>                            <p></p><a target="_blank" title="♬ miffy cafe - sakuracloud" href="https://www.tiktok.com/music/miffy-cafe-7425305480727889936">♬ miffy cafe - sakuracloud</a></section>                    </blockquote></div>                <h3 class="article-body__section" id="section-the-recipe"><span>The recipe</span></h3><p>The wonderful thing about smoothies is they're uncomplicated. Pick stuff you like, throw it inside one of <a href="https://www.tomsguide.com/best-picks/best-blenders">the best blenders</a>, and chances are it'll come out alright. But this test had to be scientific, so here are the exact ingredients I used with both machines:</p><p><strong>100g strawberries </strong>(~1 cup, yields a thick texture and rich color)</p><p><strong>50g ripe banana</strong> (~1/2 medium banana, sliced)</p><p><strong>100g strawberry flavored Greek yogurt</strong> (~½ cup)</p><p><strong>180ml milk</strong> (~¾ cup)</p><p><strong>1 tbsp of honey</strong></p><p>Note that both of these machines are blenders and not bespoke juicers. Here's a <a href="https://www.tomsguide.com/news/juicer-vs-blender-what-is-the-differnce">complete rundown of the differences,</a> but in a nutshell, juicers squeeze and extract the juice from fruits and vegetables. A juicer breaks down the fruit by separating the pulp, peel/skin, and seeds from the fruit, as the juice flows out through a sieve. </p><p>Blenders, on the other hand, pulverize all of the ingredients together. Think of them as a sledgehammer rather than a scalpel.</p><h3 class="article-body__section" id="section-the-blend"><span>The blend</span></h3><p>Forget just throwing the above ingredients into the pot without a care. This is the process I followed with both blenders — just to make sure I did what I could to make the experiment fair.</p><ul><li><strong>Add liquids and soft ingredients first: </strong>Pour in the <strong>milk</strong> and spoon in the <strong>Greek yogurt</strong>. Placing liquid at the bottom helps the blender blades turn smoothly without getting stuck on the fruit.</li><li><strong>Layer in solids and the fruit: Next in went the</strong> <strong>banana slices</strong>, chopped <strong>strawberries</strong>, and finally I added the honey.</li><li><strong>Blend on high power for 30 seconds </strong>(I used my trusty Casio stopwatch to make sure they each got the same time)</li><li>Pour out and enjoy</li></ul><h3 class="article-body__section" id="section-the-result"><span>The result</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:5712px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="5rUCzNkPzywGJQtUU5KPJG" name="IMG_4627.JPG" alt="Two blenders with a glass each of smoothie" src="https://cdn.mos.cms.futurecdn.net/5rUCzNkPzywGJQtUU5KPJG.jpg" mos="" align="middle" fullscreen="" width="5712" height="3213" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="caption-text">Not pictured: All the washing up that needed to be done after this experiment was complete </span><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide / Jeff Parsons)</span></figcaption></figure><p>I appreciate you can't <em>taste</em> the results of my experiment through the screen, but as I said at the outset. I didn't notice any difference in taste in the final product. If pressed, I would say the $129 result was a fractionally smoother than the cheaper alternative. Maybe my smoothie chops aren't what they used to be, but my takeaway is that if all you're interested in is the consistency and the taste of the final result, the cheap option will do you proud.</p><p>Also despite costing more and supposedly being quieter (Nutribullet says 87dB), the more expensive blender was louder than the budget one. It's more powerful 1,200W vs 600W and that showed when the noise level just crested 100dB for the Nutribullet compared to 99dB for the Blaupunkt. I know this is nitpicking, but I still wanted to mention it.</p><p>The Nutribullet uses a 6-point titanium-coated extractor blade rather than a 4-point one in the $30 Blaupunkt. But it's also got a lower capacity (32oz vs 52oz), so if you're mixing smoothies for a family or to batch, that may play a factor. Those two elements come in clutch because there were definitely some lumps left in the bottom of the jug on the cheaper blender when I poured out the drink.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:4096px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="ekPC5sugsCFx3xYSw2WPsF" name="Nutribullet Ultra 1200" alt="Nutribullet Ultra 1200 vs budget blender" src="https://cdn.mos.cms.futurecdn.net/ekPC5sugsCFx3xYSw2WPsF.jpg" mos="" align="middle" fullscreen="" width="4096" height="2304" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>Whereas I put the contents into a glass for the sake of this article, normally I would just cap off the Nutribullet shaker and be on my way. Similarly, I cranked the Blaupunkt all the way to five on its antiquated knob rather than the simple on/off capacitive touch of the Nutribullet. </p><p>And, last but by no means least, cleaning the Nutribullet was a simpler, quicker affair than my old budget blender.</p><p>So, both got the job done — one just did it with a little more style than the other.</p><h3 class="article-body__section" id="section-final-thoughts"><span>Final thoughts</span></h3><div class="product"><a data-dimension112="e59b75e6-8676-11f1-9acc-718a67d38a99" data-action="Deal Block" data-label="Ultra" data-dimension48="Ultra" data-dimension25="$124" href="https://www.amazon.com/gp/aw/d/B0CBWD3PN7" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1546px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="X2G4ud3wXRFEsYCZi8Hs9C" name="Nutribullet ultra" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/X2G4ud3wXRFEsYCZi8Hs9C.jpg" mos="" align="middle" fullscreen="" width="1546" height="1546" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>The Nutribullet Ultra 1200 is a powerhouse of a blender boasting a 1200-watt motor, titanium-coated extractor blade and Tritan Renew cups (700ml and 900ml) that are both durable and sustainable. In Nutribullet's signature Gunmetal Grey, it's a sleek yet powerful combo that aims to deliver smoothies in just 30 seconds flat.<a class="view-deal button" href="https://www.amazon.com/gp/aw/d/B0CBWD3PN7" target="_blank" rel="nofollow" data-dimension112="e59b75e6-8676-11f1-9acc-718a67d38a99" data-action="Deal Block" data-label="Ultra" data-dimension48="Ultra" data-dimension25="$124">View Deal</a></p></div><div class="product"><a data-dimension112="e59b7640-8676-11f1-9b53-dd2c078d49e7" data-action="Deal Block" data-label="Ultra" data-dimension48="Ultra" data-dimension25="£129" href="https://www.amazon.co.uk/nutribullet-Ultra-1200W-Personal-Blender/dp/B0CSDWRT8N" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1546px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="X2G4ud3wXRFEsYCZi8Hs9C" name="Nutribullet ultra" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/X2G4ud3wXRFEsYCZi8Hs9C.jpg" mos="" align="middle" fullscreen="" width="1546" height="1546" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.co.uk/nutribullet-Ultra-1200W-Personal-Blender/dp/B0CSDWRT8N" target="_blank" rel="nofollow" data-dimension112="e59b7640-8676-11f1-9b53-dd2c078d49e7" data-action="Deal Block" data-label="Ultra" data-dimension48="Ultra" data-dimension25="£129">Ultra: £129</a></strong><br>This product is also available in the U.K. where it's currently sitting at full price. During sales events, however, it can drop down to under £100 so it may be worth adding to your wishlist and keeping an eye on it.<a class="view-deal button" href="https://www.amazon.co.uk/nutribullet-Ultra-1200W-Personal-Blender/dp/B0CSDWRT8N" target="_blank" rel="nofollow" data-dimension112="e59b7640-8676-11f1-9b53-dd2c078d49e7" data-action="Deal Block" data-label="Ultra" data-dimension48="Ultra" data-dimension25="£129">View Deal</a></p></div><p>This little experiment has reinforced what I felt about leveling up blenders back at the start of the year. When it comes to the nuts and bolts of the taste of the final product, there's no difference — at least for someone with my unrefined palate.</p><p>Moreover, I can put up with a bit of noise for 30 seconds, so the fact my Nutribullet was louder than advertised is also something I can overlook.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:4096px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="WLz7mEum8qLNUquUQUJUrF" name="Nutribullet Ultra 1200" alt="Nutribullet Ultra 1200 vs budget blender" src="https://cdn.mos.cms.futurecdn.net/WLz7mEum8qLNUquUQUJUrF.jpg" mos="" align="middle" fullscreen="" width="4096" height="2304" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>But, all the other aspects of using a blender were far superior with the more expensive model. I like that: <strong>a) it takes up less countertop space, b) it doesn't take as long to clean, c) it comes with a dedicated shaker for less fuss c) it genuinely just looks cooler and d) if it breaks, I can claim on the warranty for longer.</strong></p><p>Are those advantages worth $100 more? For my current lifestyle: yes. If you'd have asked me years ago when I was a student watching every dime I spent, then probably no.</p><p>The lesson I learned here was that despite our constant fixation on the end result, there's more to choosing a product than what it delivers. Less destination, more journey. </p><p>Of course, what works for me might not work for you. I happen to value how easy and quick the Nutribullet is to use so that makes the extra $100 worth it. Do you agree or not? Let me know in the comments below.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-XZKP2e"></div>                            </div>                            <script src="https://kwizly.com/embed/XZKP2e.js" async></script><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h3><ul><li><a href="https://www.tomsguide.com/news/masticating-vs-centrifugal-juicer-which-is-best">Masticating vs centrifugal juicer: Which is best?</a></li><li><a href="https://www.tomsguide.com/best-picks/best-blenders">This is the best blender in the world, and two trusty, cheaper alternatives</a></li><li><a href="https://www.tomsguide.com/news/juicer-vs-blender-what-is-the-differnce">Juicer vs Blender: What's the difference?</a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/home/kitchen-dining/i-mixed-the-exact-same-smoothie-in-a-usd30-blender-and-a-usd129-one-i-learned-a-valuable-lesson-in-the-process</link>
                                                                            <description>
                            <![CDATA[ After upgrading my blender at the start of the year, I felt it was time for a head-to-head test on which was better. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">iZB5DiXnxdDdR3sBqhSfri</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/bosNuKcBn37ynDukz8DqZm-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Wed, 29 Jul 2026 05:30:00 +0000</pubDate>                                                                                                                                <updated>Wed, 29 Jul 2026 14:23:23 +0000</updated>
                                                                                                                                            <category><![CDATA[Kitchen & Dining]]></category>
                                                    <category><![CDATA[Home]]></category>
                                                    <category><![CDATA[Home Appliances]]></category>
                                                                                                <author><![CDATA[ jeff.parsons@futurenet.com (Jeff Parsons) ]]></author>                    <dc:creator><![CDATA[ Jeff Parsons ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/7z3UTGGrmSokMKxTWHmhjX.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Jeff is U.K. Editor-in-Chief for Tom’s Guide looking after the day-to-day output of the site’s British contingent. &lt;/p&gt;&lt;p&gt;Rising early and heading straight for the coffee machine, Jeff loves nothing more than dialling into the zeitgeist of the day’s tech news. A journalist for over a decade, he&#039;s travelled around the world testing and reviewing any gadget he can get his hands on.&lt;/p&gt;&lt;p&gt;Before joining the team at Tom’s Guide, Jeff covered technology and science for two of the U.K.’s biggest national news sites: Metro.co.uk and the Daily Mirror. Memorable moments include getting lost in Vienna in an electric Audi, touring Lockheed Martin’s mile-long jet factory in Fort Worth and filming a Netflix documentary about Elon Musk in West London.&lt;/p&gt;&lt;p&gt;When not plugged into the current news agenda, editing or commissioning a series of articles or debating the merits of Apple vs Android, Jeff can usually be found out for a run trying to shave precious seconds off his PB. Or lifting weights in a vain attempt to offset the ageing process.&lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/bosNuKcBn37ynDukz8DqZm-1280-80.jpg">
                                                            <media:credit><![CDATA[Tom&#039;s Guide]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[I mixed the exact same smoothie in a $30 blender and a $129 one]]></media:description>                                                            <media:text><![CDATA[I mixed the exact same smoothie in a $30 blender and a $129 one]]></media:text>
                                <media:title type="plain"><![CDATA[I mixed the exact same smoothie in a $30 blender and a $129 one]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/bosNuKcBn37ynDukz8DqZm-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>At the start of the year, I <a href="https://www.tomsguide.com/home/kitchen-dining/i-upgraded-my-usd30-budget-blender-to-a-nutribullet-and-its-made-smoothies-fun-again">upgraded our household blender</a> from a regular non-brand contraption we picked up at the local Aldi to a <a href="https://www.tomsguide.com/home/home-appliances/nutribullet-ultra-1200-personal-blender-review">Nutribullet Ultra 1200. </a>The benefits were that it was easier to clean, looked a lot nicer, and blends your ingredients straight into the shaker you can drink from.</p><p>Over six months later, I decided to return to the pair of them (we haven't got rid of the old one; it's good to have a spare) to put a little bit more testing on the table.</p><p>Part of this, I admit, is due to selfishly wanting to mix up my smoothie game. I'm guilty of going back to the same old recipe time and time again and, with summer here, I'm feeling the need for a change. </p><p>Secondly, although I swapped to the Nutribullet without a second thought — was I giving my old blender its due? What if I fed both machines the <em>exact same ingredients</em> and measured them directly in a head-to-head? Which would really come out on top?</p><p>There are a ton of things the Nutribullet does better: it's objectively smaller, lighter, simpler to use <em>and</em> comes with a better warranty. But I was surprised at a couple of outcomes from this experiment if I'm being totally honest. I'll spoil the big one for you now: <strong>I couldn't tell the difference when it came to tasting the final product</strong>.</p><p>But we're getting ahead of ourselves. Read on to discover just what I found out from my budget vs. premium experiment.</p>                    <div class= "tiktok-wrapper" style="min-height: 750px;"><blockquote class="tiktok-embed" cite="https://www.tiktok.com/@tomsguide/video/7667954816726895886" data-video-id="7667954816726895886" style="max-width: 605px; min-width: 325px;">                        <section>                            <a target="_blank" title="@tomsguide" href="https://www.tiktok.com/@tomsguide">@tomsguide</a>                            <p></p><a target="_blank" title="♬ miffy cafe - sakuracloud" href="https://www.tiktok.com/music/miffy-cafe-7425305480727889936">♬ miffy cafe - sakuracloud</a></section>                    </blockquote></div>                <h3 class="article-body__section" id="section-the-recipe"><span>The recipe</span></h3><p>The wonderful thing about smoothies is they're uncomplicated. Pick stuff you like, throw it inside one of <a href="https://www.tomsguide.com/best-picks/best-blenders">the best blenders</a>, and chances are it'll come out alright. But this test had to be scientific, so here are the exact ingredients I used with both machines:</p><p><strong>100g strawberries </strong>(~1 cup, yields a thick texture and rich color)</p><p><strong>50g ripe banana</strong> (~1/2 medium banana, sliced)</p><p><strong>100g strawberry flavored Greek yogurt</strong> (~½ cup)</p><p><strong>180ml milk</strong> (~¾ cup)</p><p><strong>1 tbsp of honey</strong></p><p>Note that both of these machines are blenders and not bespoke juicers. Here's a <a href="https://www.tomsguide.com/news/juicer-vs-blender-what-is-the-differnce">complete rundown of the differences,</a> but in a nutshell, juicers squeeze and extract the juice from fruits and vegetables. A juicer breaks down the fruit by separating the pulp, peel/skin, and seeds from the fruit, as the juice flows out through a sieve. </p><p>Blenders, on the other hand, pulverize all of the ingredients together. Think of them as a sledgehammer rather than a scalpel.</p><h3 class="article-body__section" id="section-the-blend"><span>The blend</span></h3><p>Forget just throwing the above ingredients into the pot without a care. This is the process I followed with both blenders — just to make sure I did what I could to make the experiment fair.</p><ul><li><strong>Add liquids and soft ingredients first: </strong>Pour in the <strong>milk</strong> and spoon in the <strong>Greek yogurt</strong>. Placing liquid at the bottom helps the blender blades turn smoothly without getting stuck on the fruit.</li><li><strong>Layer in solids and the fruit: Next in went the</strong> <strong>banana slices</strong>, chopped <strong>strawberries</strong>, and finally I added the honey.</li><li><strong>Blend on high power for 30 seconds </strong>(I used my trusty Casio stopwatch to make sure they each got the same time)</li><li>Pour out and enjoy</li></ul><h3 class="article-body__section" id="section-the-result"><span>The result</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:5712px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="5rUCzNkPzywGJQtUU5KPJG" name="IMG_4627.JPG" alt="Two blenders with a glass each of smoothie" src="https://cdn.mos.cms.futurecdn.net/5rUCzNkPzywGJQtUU5KPJG.jpg" mos="" align="middle" fullscreen="" width="5712" height="3213" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="caption-text">Not pictured: All the washing up that needed to be done after this experiment was complete </span><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide / Jeff Parsons)</span></figcaption></figure><p>I appreciate you can't <em>taste</em> the results of my experiment through the screen, but as I said at the outset. I didn't notice any difference in taste in the final product. If pressed, I would say the $129 result was a fractionally smoother than the cheaper alternative. Maybe my smoothie chops aren't what they used to be, but my takeaway is that if all you're interested in is the consistency and the taste of the final result, the cheap option will do you proud.</p><p>Also despite costing more and supposedly being quieter (Nutribullet says 87dB), the more expensive blender was louder than the budget one. It's more powerful 1,200W vs 600W and that showed when the noise level just crested 100dB for the Nutribullet compared to 99dB for the Blaupunkt. I know this is nitpicking, but I still wanted to mention it.</p><p>The Nutribullet uses a 6-point titanium-coated extractor blade rather than a 4-point one in the $30 Blaupunkt. But it's also got a lower capacity (32oz vs 52oz), so if you're mixing smoothies for a family or to batch, that may play a factor. Those two elements come in clutch because there were definitely some lumps left in the bottom of the jug on the cheaper blender when I poured out the drink.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:4096px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="ekPC5sugsCFx3xYSw2WPsF" name="Nutribullet Ultra 1200" alt="Nutribullet Ultra 1200 vs budget blender" src="https://cdn.mos.cms.futurecdn.net/ekPC5sugsCFx3xYSw2WPsF.jpg" mos="" align="middle" fullscreen="" width="4096" height="2304" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>Whereas I put the contents into a glass for the sake of this article, normally I would just cap off the Nutribullet shaker and be on my way. Similarly, I cranked the Blaupunkt all the way to five on its antiquated knob rather than the simple on/off capacitive touch of the Nutribullet. </p><p>And, last but by no means least, cleaning the Nutribullet was a simpler, quicker affair than my old budget blender.</p><p>So, both got the job done — one just did it with a little more style than the other.</p><h3 class="article-body__section" id="section-final-thoughts"><span>Final thoughts</span></h3><div class="product"><a data-dimension112="e59b75e6-8676-11f1-9acc-718a67d38a99" data-action="Deal Block" data-label="Ultra" data-dimension48="Ultra" data-dimension25="$124" href="https://www.amazon.com/gp/aw/d/B0CBWD3PN7" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1546px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="X2G4ud3wXRFEsYCZi8Hs9C" name="Nutribullet ultra" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/X2G4ud3wXRFEsYCZi8Hs9C.jpg" mos="" align="middle" fullscreen="" width="1546" height="1546" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>The Nutribullet Ultra 1200 is a powerhouse of a blender boasting a 1200-watt motor, titanium-coated extractor blade and Tritan Renew cups (700ml and 900ml) that are both durable and sustainable. In Nutribullet's signature Gunmetal Grey, it's a sleek yet powerful combo that aims to deliver smoothies in just 30 seconds flat.<a class="view-deal button" href="https://www.amazon.com/gp/aw/d/B0CBWD3PN7" target="_blank" rel="nofollow" data-dimension112="e59b75e6-8676-11f1-9acc-718a67d38a99" data-action="Deal Block" data-label="Ultra" data-dimension48="Ultra" data-dimension25="$124">View Deal</a></p></div><div class="product"><a data-dimension112="e59b7640-8676-11f1-9b53-dd2c078d49e7" data-action="Deal Block" data-label="Ultra" data-dimension48="Ultra" data-dimension25="£129" href="https://www.amazon.co.uk/nutribullet-Ultra-1200W-Personal-Blender/dp/B0CSDWRT8N" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1546px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="X2G4ud3wXRFEsYCZi8Hs9C" name="Nutribullet ultra" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/X2G4ud3wXRFEsYCZi8Hs9C.jpg" mos="" align="middle" fullscreen="" width="1546" height="1546" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.co.uk/nutribullet-Ultra-1200W-Personal-Blender/dp/B0CSDWRT8N" target="_blank" rel="nofollow" data-dimension112="e59b7640-8676-11f1-9b53-dd2c078d49e7" data-action="Deal Block" data-label="Ultra" data-dimension48="Ultra" data-dimension25="£129">Ultra: £129</a></strong><br>This product is also available in the U.K. where it's currently sitting at full price. During sales events, however, it can drop down to under £100 so it may be worth adding to your wishlist and keeping an eye on it.<a class="view-deal button" href="https://www.amazon.co.uk/nutribullet-Ultra-1200W-Personal-Blender/dp/B0CSDWRT8N" target="_blank" rel="nofollow" data-dimension112="e59b7640-8676-11f1-9b53-dd2c078d49e7" data-action="Deal Block" data-label="Ultra" data-dimension48="Ultra" data-dimension25="£129">View Deal</a></p></div><p>This little experiment has reinforced what I felt about leveling up blenders back at the start of the year. When it comes to the nuts and bolts of the taste of the final product, there's no difference — at least for someone with my unrefined palate.</p><p>Moreover, I can put up with a bit of noise for 30 seconds, so the fact my Nutribullet was louder than advertised is also something I can overlook.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:4096px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="WLz7mEum8qLNUquUQUJUrF" name="Nutribullet Ultra 1200" alt="Nutribullet Ultra 1200 vs budget blender" src="https://cdn.mos.cms.futurecdn.net/WLz7mEum8qLNUquUQUJUrF.jpg" mos="" align="middle" fullscreen="" width="4096" height="2304" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>But, all the other aspects of using a blender were far superior with the more expensive model. I like that: <strong>a) it takes up less countertop space, b) it doesn't take as long to clean, c) it comes with a dedicated shaker for less fuss c) it genuinely just looks cooler and d) if it breaks, I can claim on the warranty for longer.</strong></p><p>Are those advantages worth $100 more? For my current lifestyle: yes. If you'd have asked me years ago when I was a student watching every dime I spent, then probably no.</p><p>The lesson I learned here was that despite our constant fixation on the end result, there's more to choosing a product than what it delivers. Less destination, more journey. </p><p>Of course, what works for me might not work for you. I happen to value how easy and quick the Nutribullet is to use so that makes the extra $100 worth it. Do you agree or not? Let me know in the comments below.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-XZKP2e"></div>                            </div>                            <script src="https://kwizly.com/embed/XZKP2e.js" async></script><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h3><ul><li><a href="https://www.tomsguide.com/news/masticating-vs-centrifugal-juicer-which-is-best">Masticating vs centrifugal juicer: Which is best?</a></li><li><a href="https://www.tomsguide.com/best-picks/best-blenders">This is the best blender in the world, and two trusty, cheaper alternatives</a></li><li><a href="https://www.tomsguide.com/news/juicer-vs-blender-what-is-the-differnce">Juicer vs Blender: What's the difference?</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ I tried Shark's freshly launched wet-to-dry stylers — and they might just be my new favourite hair tools ]]></title>
                                                                                                <dc:content><![CDATA[ <p>There's nothing worse than heat damage. It can cause breakage, impact your hair and scalp health, and leave ends severely dry. Thankfully, Shark Beauty has thought of everything to eliminate heat damage, with the launch of two new wet-to-dry stylers in Australia.</p><p>Designed with heat damage in mind, the new Shark <a href="https://sharkninja.com.au/products/shark-silkipro-straight">SilkiPro Straight</a> and <a href="https://sharkninja.com.au/products/shark-glossi-2-in-1-hot-tool-and-air-glosser">Glossi</a> maximise airflow and heat settings to ensure minimal hair damage. As a hair tool reviewer, I was beyond eager to get my hands on the first wet-to-dry stylers for the brand. </p><p>I did approach using the stylers with a degree of scepticism, however. Although I appreciate airstylers because they minimise hair damage, I typically have to rely heavily on hairspray to keep my styles intact. This is largely because airtools like the Dyson Airstrait do not use heated plates, effectively cutting down on the amount of direct heat applied to the hair, and therefore, don't clamp the hair into a pin-straight finish. </p><p>This was the case during my <a href="https://www.tomsguide.com/home/personal-grooming/dyson-airstrait-review">Dyson Airstrait review</a>. Even though the Airstrait excelled at drying and styling my hair from wet to dry in a matter of minutes, it only achieved a naturally straight finish with its angled airflow. However, the SilkiPro has ceramic elements, meaning there's a heated plate at play alongside Shark's impressive heat and airflow tech. While my experience with the Dyson Airstrait was generally positive, I was curious to see if the SilkiPro’s ceramic plates could offer a more polished finish.</p><p>On the other hand, the Glossi also has ceramic elements, but it's a blowout brush with wet and dry modes. In my experience, blowout brushes can be used on damp hair, but not soaking wet, so my curiosity was piqued. Both tools can also be used on totally dry hair to achieve shiny, frizz-free styles. </p><p>I put both of Shark's wet-to-dry stylers to the test to see how they fare — and ultimately which one I'd recommend — below. If you're keen to check out Shark's other highly-rated hair tools, including the <a href="https://www.tomsguide.com/home/home-appliances/shark-glam-hair-styler-review">Shark Glam</a> and the <a href="https://www.tomsguide.com/reviews/shark-flexstyle">Shark FlexStyle</a>, you can view them in the widget below.</p><div data-widget-type="multimodelreview" data-model-name="Shark SilkiPro Straight,Shark Glossi 2-in-1 Hot Tool and Air Glosser"></div><h3 class="article-body__section" id="section-shark-silkipro-straight"><span>Shark SilkiPro Straight</span></h3><figure role="gallery"><figure><img src="https://cdn.mos.cms.futurecdn.net/EXMiUuEMhp2qtuAZuaqzyV.jpg" alt="Hand holding device" /><figcaption>Shark SilkiPro Straight in purple<small role="credit">Future / Lucy Scotting</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/pNW9tsQGhMiXvWgBU2barW.jpg" alt="Hand holding device" /><figcaption>Shark SilkiPro Straight lock<small role="credit">Future / Lucy Scotting</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/B8yQubo2Br3wFu7PCcD9XV.jpg" alt="Hand holding device" /><figcaption>Shark SilkiPro Straight ceramic plates<small role="credit">Future / Lucy Scotting</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/DPGmjGsbLwUCwD824BoR2T.jpg" alt="Hand holding device" /><figcaption>Shark SilkiPro Straight switch button showing wet and dry modes<small role="credit">Future / Lucy Scotting</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/SpCKWdyAMdymNRN3Qza4nW.jpg" alt="hair tool, combs and carry bag" /><figcaption>Shark SilkiPro Straight in purple with carry case and combs<small role="credit">Future / Lucy Scotting</small></figcaption></figure></figure><p>Using the HeatSense ceramic plates — which automatically monitors and adjusts temperature to minimise heat damage — and the airflow from the high-velocity air vents, the Silki acts as a comparable Dyson Airstrait dupe. </p><p>Retailing at AU$449.99, the Shark SilkiPro Straight really puts Dyson's inflated AU$749 price tag to shame. Not only is it AU$300 cheaper, the SilkiPro performs — dare I say — better, but there are a few caveats involved in that judgement. </p><p>Throughout my month of testing, I used both wet and dry modes of the SilkiPro Straight and used all three of the styling comb attachments. I also used each of the three temperature settings — low (100℃ wet / 160℃ dry), medium (110℃ wet / 190℃ dry) and high (120℃ wet / 220℃ dry) and the three airflow settings — again, low, medium and high — throughout my tests. </p><p>Much like when using the Dyson Airstrait, you need to rough dry your hair before using the SilkiPro on wet hair by clamping the styler together and locking it into place. The rough dry didn't take long during my first use, around 5 minutes or so, and I was ready to start straightening. </p><p>Shark recommends that your hair is at least 70% dry before straightening in wet mode. Shark also recommends sectioning your hair in smaller 2.5cm to 5cm sections to ensure you have minimal passes when straightening. I took this advice on and set the styler to the recommended heat and air settings for my hair type — which was medium heat and high airflow for my wavy hair. </p><p>Even though the presence of ceramic plates left me slightly confused as to why airflow would even be necessary for styling, it turned out to be vital. The angled design of the airflow significantly accelerated the overall wet-to-dry process. </p><figure role="gallery"><figure><img src="https://cdn.mos.cms.futurecdn.net/hwMvE9HF9UWX2gAVDKJp4P.jpg" alt="Woman with natural hair " /><figcaption>Before using the SilkiPro Straight on my naturally wavy hair<small role="credit">Future / Lucy Scotting</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/C5nZQdh2CUwnwAAdQg6pRP.jpg" alt="Woman with straight hair" /><figcaption>After using the SilkiPro Straight on my naturally wavy hair<small role="credit">Future / Lucy Scotting</small></figcaption></figure></figure><p>Sure enough, after extensively sectioning and straightening, my hair was damn near perfectly straight, thanks to the plates and airflow combination. I could have stopped there, considering my hair was completely styled and dry, but the brand suggests using the dry mode on the device to help lock in the style and shine. I opted to use medium heat and airflow to minimise thermal damage and dry mode was pretty spot on at correcting any imperfections. </p><p>After using the SilkiPro a few more times throughout the month, I ultimately decided that high heat and airflow worked better for me in wet mode. If I needed to touch up any strands, I used dry mode on medium settings to straighten things out. </p><p>The styling combs are supposed to help straighten and lengthen hair, but they didn't do too much for my wavy, thick hair. I didn't love using the comb attachments on my hair when it was wet, but I found the experience much more pleasant when it was dry. Regardless, I am still not convinced that the combs are overly necessary to the SilkiPro experience and may work better for those with curly or coily hair.</p><p>Overall, I was highly satisfied with the SilkiPro and turned to it more than my Dyson Airstrait. This is largely due to the results, as my hair turned out much straighter, shiner and lasted longer using the Silki. However, I know that this is because of the Silki's ceramic plates, making it much more comparable to the results of a normal hair straightener. The Silki's plates use lower temperatures than other straighteners, so it still minimises heat damage, but you can't guarantee that your hair will be totally damage-free. And that's just part of the risks involved with hair stylers and hot tools in general, not just the SilkiPro Straight. </p><h3 class="article-body__section" id="section-shark-glossi"><span>Shark Glossi</span></h3><figure role="gallery"><figure><img src="https://cdn.mos.cms.futurecdn.net/QrwnMdsYreaRPuPssGG5AW.jpg" alt="Hand holding device" /><figcaption>Shark Glossi bristle brush<small role="credit">Future / Lucy Scotting</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/iKNaqqhDoRUrHkahGtJGfV.jpg" alt="Hand holding device" /><figcaption>Shark Glossi ceramic brush<small role="credit">Future / Lucy Scotting</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/pQYY3z5R6EpvHf8U8iKhVV.jpg" alt="Hand holding device" /><figcaption>Shark Glossi brush <small role="credit">Future / Lucy Scotting</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/5VoWjvEPqDHZ7BkDrqbTaT.jpg" alt="Hand holding device" /><figcaption>Shark Glossi switch button showing both wet and dry modes<small role="credit">Future / Lucy Scotting</small></figcaption></figure></figure><p>Out of all the hair tools I've tried, I always struggle styling my hair with a blowout brush. I've watched many hair tutorials on TikTok and Instagram, and even invested in the Revlon Volumiser 2.0, thinking I could do a 90s-style blowout with ease. But I was so wrong. </p><p>That said, the Shark Glossi has really surprised me as a one-pass-wonder (yes, I've coined that term) in a wet-to-dry styler. Priced at AU$199.99, the Glossi is a much more affordable option for most blowout lovers. It did take some time to get used to how to properly work the brush, but if you've managed to get a voluminous, bouncy blowout by using a roller brush and hair dryer before, then I could see it eliminating that strenuous process entirely. </p><p>Unlike other hot brushes, one side of the Glossi is dedicated to a standard bristle brush, and the other is a ceramic plate-coated comb. The ceramic side is supposed to support shine and lock in smoothing styles, whereas the bristle brush is for volume and bouncy waves. Personally, I prefer silky finishes with some volume by my roots, so I leant towards the ceramic side in most use cases, and finished my roots with the bristle. </p><p>Much like the SilkiPro, the Glossi has a wet and dry mode, and has three temperature and airflow settings. Unfortunately, much to my dismay, I couldn't use it on soaking wet hair, as per the brand's instructions, so I had to rough dry my hair before styling. This wasn't the biggest deal — I had suspected as such with most blowout brushes that it couldn't be used on sopping wet hair — but I was a touch disappointed that I couldn't reach for it immediately out of the shower. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1754px;"><p class="vanilla-image-block" style="padding-top:56.21%;"><img id="yPmKMFsTHLWkziW6C3xBpP" name="glossi-5" alt="Hair" src="https://cdn.mos.cms.futurecdn.net/yPmKMFsTHLWkziW6C3xBpP.jpg" mos="" align="middle" fullscreen="" width="1754" height="986" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="caption-text">Before and after of using the Shark Glossi on my naturally wavy hair </span><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Lucy Scotting)</span></figcaption></figure><p>Instead, wet mode is largely exclusive to 70% damp hair, like the SilkiPro. I followed Shark's instructions for wet mode by detangling my hair, sectioning it in smaller 5cm sections and placing the ceramic plates at my roots before turning the styler. In each turn, I allowed the bristles to grip my hair and help it comb through the ceramic in an anticlockwise motion to ensure sleek, yet bouncy waves. </p><p>Getting the perfect blowout for my hair was a bit tricky. I was a bit perplexed by the airflow and heat settings on the Glossi, as there were no strict brand recommendations for my hair type. The highest airflow was very powerful — to the point where my hair was flying all over the place — and the lowest heat setting did very little for my ends. After some trial and error, I landed on high heat and medium airflow, and that delivered great results every time. I also found myself reaching for the Glossi to fix my bangs and apply volume when I felt they were falling. </p><p>Again, the brand recommends using dry mode to smooth and correct any imperfections, and after doing so for the initial test, I didn't find myself needing to lock in the style with dry mode. Sure, I could have easily guaranteed a longer-lasting hairstyle by following through, but the Glossi wet mode results just speak for themselves. The Glossi's dry mode also has to heat up for 45 seconds before use — and if I'm being honest here, I didn't always feel like waiting… sue me. </p><h3 class="article-body__section" id="section-which-one-should-i-buy"><span>Which one should I buy?</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:5494px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="KjcG4mVACKT3rEBFrFZzDY" name="shark-hero" alt="shark hair tools on display" src="https://cdn.mos.cms.futurecdn.net/KjcG4mVACKT3rEBFrFZzDY.jpg" mos="" align="middle" fullscreen="" width="5494" height="3090" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Lucy Scotting)</span></figcaption></figure><p>After a good month of washing my hair at least a dozen times for science, it's safe to say that Shark's newest wet-to-dry stylers did not disappoint me in the slightest. While the devices have very similar use cases — they do dry hair after all — both tools tick different styling boxes. </p><p>I am a fan of the Shark Glossi for its simplicity and price point. Although, practically, it felt like I was unlocking a whole new skillset to to get the best blowout out of it. However, I am very much impressed with the device and I'm beyond certain that it would garner a happy fanbase. </p><p>But tete-a-tete, I'm an even bigger fan of the Shark SilkiPro Straight for my everyday routine, especially as it's a dryer and straightener all-in-one. And dare I admit, it's coming for my Dyson Airstrait's crown as it can deliver pin-straight results without any touchups. Did I mention it's also AU$300 cheaper?</p><p>So if you're thinking of upgrading or stepping into the world of wet-to-dry hair stylers, Shark Beauty's range is one to consider. </p><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h3><ul><li><a href="https://www.tomsguide.com/home/i-cut-my-curly-hair-routine-from-2-hours-to-20-minutes-heres-the-lazy-girl-method-thatll-help-you-do-the-same">I cut my curly hair routine from 2 hours to 20 minutes. Here’s the 'lazy girl' method that'll help you do the same</a></li><li><a href="https://www.tomsguide.com/ai/google-gemini/i-used-googles-nano-banana-to-try-a-bunch-of-different-hairstyles-and-the-results-blew-me-away">I used Google's Nano Banana to try a bunch of different hairstyles — and the results blew me away</a></li><li><a href="https://www.tomsguide.com/home/home-appliances/sharks-new-wet-to-dry-styler-is-cheaper-than-the-dyson-airstrait-and-comes-with-this-one-unique-feature">Shark's new wet-to-dry styler is cheaper than the Dyson Airstrait, and comes with this one unique feature</a></li><li><a href="https://www.tomsguide.com/home/i-was-skeptical-about-the-dyson-airwrap-i-d-curly-coily-two-months-later-im-a-convert">I tested the Dyson Airwrap i.d. Curly + Coily on my hair — the hype is completely justified</a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/home/home-appliances/i-tried-sharks-freshly-launched-wet-to-dry-stylers-and-they-might-just-be-my-new-favourite-hair-tools</link>
                                                                            <description>
                            <![CDATA[ Shark Beauty has just launched two new wet-to-dry hair tools in Australia and Dyson should be quaking in its boots. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">3fA7Pf3ZutawJ6udnr9PAc</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/ftxD5xM929mjLyWpmsShrR-1280-80.png" type="image/png" length="0"></enclosure>
                                                                        <pubDate>Wed, 29 Jul 2026 01:06:58 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Home Appliances]]></category>
                                                    <category><![CDATA[Home]]></category>
                                                                                                <author><![CDATA[ lucy.scotting@futurenet.com (Lucy Scotting) ]]></author>                    <dc:creator><![CDATA[ Lucy Scotting ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/UC9ncAYxkmJ5ipHEyX44ri.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Lucy Scotting is a staff writer for Tom’s Guide Australia, primarily covering lifestyle, streaming and internet-related news. Lucy started her career writing for HR and staffing industry publications, with articles covering emerging tech, business and finance.&lt;/p&gt;&lt;p&gt;In her spare time, Lucy can be found watching sci-fi movies, working on her dystopian fiction novel (in progress since 2017) or hanging out with her dog, Fletcher. If she’s not found doing any of the above, she’s likely on her next adventure to a new city, country, or continent. &lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                <media:content type="image/png" url="https://cdn.mos.cms.futurecdn.net/ftxD5xM929mjLyWpmsShrR-1280-80.png">
                                                            <media:credit><![CDATA[Future / Lucy Scotting / Shark]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Shark models using hair tools and hair tools in the middle of collage]]></media:description>                                                            <media:text><![CDATA[Shark models using hair tools and hair tools in the middle of collage]]></media:text>
                                <media:title type="plain"><![CDATA[Shark models using hair tools and hair tools in the middle of collage]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/ftxD5xM929mjLyWpmsShrR-1280-80.png" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>There's nothing worse than heat damage. It can cause breakage, impact your hair and scalp health, and leave ends severely dry. Thankfully, Shark Beauty has thought of everything to eliminate heat damage, with the launch of two new wet-to-dry stylers in Australia.</p><p>Designed with heat damage in mind, the new Shark <a href="https://sharkninja.com.au/products/shark-silkipro-straight">SilkiPro Straight</a> and <a href="https://sharkninja.com.au/products/shark-glossi-2-in-1-hot-tool-and-air-glosser">Glossi</a> maximise airflow and heat settings to ensure minimal hair damage. As a hair tool reviewer, I was beyond eager to get my hands on the first wet-to-dry stylers for the brand. </p><p>I did approach using the stylers with a degree of scepticism, however. Although I appreciate airstylers because they minimise hair damage, I typically have to rely heavily on hairspray to keep my styles intact. This is largely because airtools like the Dyson Airstrait do not use heated plates, effectively cutting down on the amount of direct heat applied to the hair, and therefore, don't clamp the hair into a pin-straight finish. </p><p>This was the case during my <a href="https://www.tomsguide.com/home/personal-grooming/dyson-airstrait-review">Dyson Airstrait review</a>. Even though the Airstrait excelled at drying and styling my hair from wet to dry in a matter of minutes, it only achieved a naturally straight finish with its angled airflow. However, the SilkiPro has ceramic elements, meaning there's a heated plate at play alongside Shark's impressive heat and airflow tech. While my experience with the Dyson Airstrait was generally positive, I was curious to see if the SilkiPro’s ceramic plates could offer a more polished finish.</p><p>On the other hand, the Glossi also has ceramic elements, but it's a blowout brush with wet and dry modes. In my experience, blowout brushes can be used on damp hair, but not soaking wet, so my curiosity was piqued. Both tools can also be used on totally dry hair to achieve shiny, frizz-free styles. </p><p>I put both of Shark's wet-to-dry stylers to the test to see how they fare — and ultimately which one I'd recommend — below. If you're keen to check out Shark's other highly-rated hair tools, including the <a href="https://www.tomsguide.com/home/home-appliances/shark-glam-hair-styler-review">Shark Glam</a> and the <a href="https://www.tomsguide.com/reviews/shark-flexstyle">Shark FlexStyle</a>, you can view them in the widget below.</p><div data-widget-type="multimodelreview" data-model-name="Shark SilkiPro Straight,Shark Glossi 2-in-1 Hot Tool and Air Glosser"></div><h3 class="article-body__section" id="section-shark-silkipro-straight"><span>Shark SilkiPro Straight</span></h3><figure role="gallery"><figure><img src="https://cdn.mos.cms.futurecdn.net/EXMiUuEMhp2qtuAZuaqzyV.jpg" alt="Hand holding device" /><figcaption>Shark SilkiPro Straight in purple<small role="credit">Future / Lucy Scotting</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/pNW9tsQGhMiXvWgBU2barW.jpg" alt="Hand holding device" /><figcaption>Shark SilkiPro Straight lock<small role="credit">Future / Lucy Scotting</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/B8yQubo2Br3wFu7PCcD9XV.jpg" alt="Hand holding device" /><figcaption>Shark SilkiPro Straight ceramic plates<small role="credit">Future / Lucy Scotting</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/DPGmjGsbLwUCwD824BoR2T.jpg" alt="Hand holding device" /><figcaption>Shark SilkiPro Straight switch button showing wet and dry modes<small role="credit">Future / Lucy Scotting</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/SpCKWdyAMdymNRN3Qza4nW.jpg" alt="hair tool, combs and carry bag" /><figcaption>Shark SilkiPro Straight in purple with carry case and combs<small role="credit">Future / Lucy Scotting</small></figcaption></figure></figure><p>Using the HeatSense ceramic plates — which automatically monitors and adjusts temperature to minimise heat damage — and the airflow from the high-velocity air vents, the Silki acts as a comparable Dyson Airstrait dupe. </p><p>Retailing at AU$449.99, the Shark SilkiPro Straight really puts Dyson's inflated AU$749 price tag to shame. Not only is it AU$300 cheaper, the SilkiPro performs — dare I say — better, but there are a few caveats involved in that judgement. </p><p>Throughout my month of testing, I used both wet and dry modes of the SilkiPro Straight and used all three of the styling comb attachments. I also used each of the three temperature settings — low (100℃ wet / 160℃ dry), medium (110℃ wet / 190℃ dry) and high (120℃ wet / 220℃ dry) and the three airflow settings — again, low, medium and high — throughout my tests. </p><p>Much like when using the Dyson Airstrait, you need to rough dry your hair before using the SilkiPro on wet hair by clamping the styler together and locking it into place. The rough dry didn't take long during my first use, around 5 minutes or so, and I was ready to start straightening. </p><p>Shark recommends that your hair is at least 70% dry before straightening in wet mode. Shark also recommends sectioning your hair in smaller 2.5cm to 5cm sections to ensure you have minimal passes when straightening. I took this advice on and set the styler to the recommended heat and air settings for my hair type — which was medium heat and high airflow for my wavy hair. </p><p>Even though the presence of ceramic plates left me slightly confused as to why airflow would even be necessary for styling, it turned out to be vital. The angled design of the airflow significantly accelerated the overall wet-to-dry process. </p><figure role="gallery"><figure><img src="https://cdn.mos.cms.futurecdn.net/hwMvE9HF9UWX2gAVDKJp4P.jpg" alt="Woman with natural hair " /><figcaption>Before using the SilkiPro Straight on my naturally wavy hair<small role="credit">Future / Lucy Scotting</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/C5nZQdh2CUwnwAAdQg6pRP.jpg" alt="Woman with straight hair" /><figcaption>After using the SilkiPro Straight on my naturally wavy hair<small role="credit">Future / Lucy Scotting</small></figcaption></figure></figure><p>Sure enough, after extensively sectioning and straightening, my hair was damn near perfectly straight, thanks to the plates and airflow combination. I could have stopped there, considering my hair was completely styled and dry, but the brand suggests using the dry mode on the device to help lock in the style and shine. I opted to use medium heat and airflow to minimise thermal damage and dry mode was pretty spot on at correcting any imperfections. </p><p>After using the SilkiPro a few more times throughout the month, I ultimately decided that high heat and airflow worked better for me in wet mode. If I needed to touch up any strands, I used dry mode on medium settings to straighten things out. </p><p>The styling combs are supposed to help straighten and lengthen hair, but they didn't do too much for my wavy, thick hair. I didn't love using the comb attachments on my hair when it was wet, but I found the experience much more pleasant when it was dry. Regardless, I am still not convinced that the combs are overly necessary to the SilkiPro experience and may work better for those with curly or coily hair.</p><p>Overall, I was highly satisfied with the SilkiPro and turned to it more than my Dyson Airstrait. This is largely due to the results, as my hair turned out much straighter, shiner and lasted longer using the Silki. However, I know that this is because of the Silki's ceramic plates, making it much more comparable to the results of a normal hair straightener. The Silki's plates use lower temperatures than other straighteners, so it still minimises heat damage, but you can't guarantee that your hair will be totally damage-free. And that's just part of the risks involved with hair stylers and hot tools in general, not just the SilkiPro Straight. </p><h3 class="article-body__section" id="section-shark-glossi"><span>Shark Glossi</span></h3><figure role="gallery"><figure><img src="https://cdn.mos.cms.futurecdn.net/QrwnMdsYreaRPuPssGG5AW.jpg" alt="Hand holding device" /><figcaption>Shark Glossi bristle brush<small role="credit">Future / Lucy Scotting</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/iKNaqqhDoRUrHkahGtJGfV.jpg" alt="Hand holding device" /><figcaption>Shark Glossi ceramic brush<small role="credit">Future / Lucy Scotting</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/pQYY3z5R6EpvHf8U8iKhVV.jpg" alt="Hand holding device" /><figcaption>Shark Glossi brush <small role="credit">Future / Lucy Scotting</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/5VoWjvEPqDHZ7BkDrqbTaT.jpg" alt="Hand holding device" /><figcaption>Shark Glossi switch button showing both wet and dry modes<small role="credit">Future / Lucy Scotting</small></figcaption></figure></figure><p>Out of all the hair tools I've tried, I always struggle styling my hair with a blowout brush. I've watched many hair tutorials on TikTok and Instagram, and even invested in the Revlon Volumiser 2.0, thinking I could do a 90s-style blowout with ease. But I was so wrong. </p><p>That said, the Shark Glossi has really surprised me as a one-pass-wonder (yes, I've coined that term) in a wet-to-dry styler. Priced at AU$199.99, the Glossi is a much more affordable option for most blowout lovers. It did take some time to get used to how to properly work the brush, but if you've managed to get a voluminous, bouncy blowout by using a roller brush and hair dryer before, then I could see it eliminating that strenuous process entirely. </p><p>Unlike other hot brushes, one side of the Glossi is dedicated to a standard bristle brush, and the other is a ceramic plate-coated comb. The ceramic side is supposed to support shine and lock in smoothing styles, whereas the bristle brush is for volume and bouncy waves. Personally, I prefer silky finishes with some volume by my roots, so I leant towards the ceramic side in most use cases, and finished my roots with the bristle. </p><p>Much like the SilkiPro, the Glossi has a wet and dry mode, and has three temperature and airflow settings. Unfortunately, much to my dismay, I couldn't use it on soaking wet hair, as per the brand's instructions, so I had to rough dry my hair before styling. This wasn't the biggest deal — I had suspected as such with most blowout brushes that it couldn't be used on sopping wet hair — but I was a touch disappointed that I couldn't reach for it immediately out of the shower. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1754px;"><p class="vanilla-image-block" style="padding-top:56.21%;"><img id="yPmKMFsTHLWkziW6C3xBpP" name="glossi-5" alt="Hair" src="https://cdn.mos.cms.futurecdn.net/yPmKMFsTHLWkziW6C3xBpP.jpg" mos="" align="middle" fullscreen="" width="1754" height="986" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="caption-text">Before and after of using the Shark Glossi on my naturally wavy hair </span><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Lucy Scotting)</span></figcaption></figure><p>Instead, wet mode is largely exclusive to 70% damp hair, like the SilkiPro. I followed Shark's instructions for wet mode by detangling my hair, sectioning it in smaller 5cm sections and placing the ceramic plates at my roots before turning the styler. In each turn, I allowed the bristles to grip my hair and help it comb through the ceramic in an anticlockwise motion to ensure sleek, yet bouncy waves. </p><p>Getting the perfect blowout for my hair was a bit tricky. I was a bit perplexed by the airflow and heat settings on the Glossi, as there were no strict brand recommendations for my hair type. The highest airflow was very powerful — to the point where my hair was flying all over the place — and the lowest heat setting did very little for my ends. After some trial and error, I landed on high heat and medium airflow, and that delivered great results every time. I also found myself reaching for the Glossi to fix my bangs and apply volume when I felt they were falling. </p><p>Again, the brand recommends using dry mode to smooth and correct any imperfections, and after doing so for the initial test, I didn't find myself needing to lock in the style with dry mode. Sure, I could have easily guaranteed a longer-lasting hairstyle by following through, but the Glossi wet mode results just speak for themselves. The Glossi's dry mode also has to heat up for 45 seconds before use — and if I'm being honest here, I didn't always feel like waiting… sue me. </p><h3 class="article-body__section" id="section-which-one-should-i-buy"><span>Which one should I buy?</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:5494px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="KjcG4mVACKT3rEBFrFZzDY" name="shark-hero" alt="shark hair tools on display" src="https://cdn.mos.cms.futurecdn.net/KjcG4mVACKT3rEBFrFZzDY.jpg" mos="" align="middle" fullscreen="" width="5494" height="3090" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Lucy Scotting)</span></figcaption></figure><p>After a good month of washing my hair at least a dozen times for science, it's safe to say that Shark's newest wet-to-dry stylers did not disappoint me in the slightest. While the devices have very similar use cases — they do dry hair after all — both tools tick different styling boxes. </p><p>I am a fan of the Shark Glossi for its simplicity and price point. Although, practically, it felt like I was unlocking a whole new skillset to to get the best blowout out of it. However, I am very much impressed with the device and I'm beyond certain that it would garner a happy fanbase. </p><p>But tete-a-tete, I'm an even bigger fan of the Shark SilkiPro Straight for my everyday routine, especially as it's a dryer and straightener all-in-one. And dare I admit, it's coming for my Dyson Airstrait's crown as it can deliver pin-straight results without any touchups. Did I mention it's also AU$300 cheaper?</p><p>So if you're thinking of upgrading or stepping into the world of wet-to-dry hair stylers, Shark Beauty's range is one to consider. </p><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h3><ul><li><a href="https://www.tomsguide.com/home/i-cut-my-curly-hair-routine-from-2-hours-to-20-minutes-heres-the-lazy-girl-method-thatll-help-you-do-the-same">I cut my curly hair routine from 2 hours to 20 minutes. Here’s the 'lazy girl' method that'll help you do the same</a></li><li><a href="https://www.tomsguide.com/ai/google-gemini/i-used-googles-nano-banana-to-try-a-bunch-of-different-hairstyles-and-the-results-blew-me-away">I used Google's Nano Banana to try a bunch of different hairstyles — and the results blew me away</a></li><li><a href="https://www.tomsguide.com/home/home-appliances/sharks-new-wet-to-dry-styler-is-cheaper-than-the-dyson-airstrait-and-comes-with-this-one-unique-feature">Shark's new wet-to-dry styler is cheaper than the Dyson Airstrait, and comes with this one unique feature</a></li><li><a href="https://www.tomsguide.com/home/i-was-skeptical-about-the-dyson-airwrap-i-d-curly-coily-two-months-later-im-a-convert">I tested the Dyson Airwrap i.d. Curly + Coily on my hair — the hype is completely justified</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ I swapped my hot oven for an air fryer to bake summer treats — here’s why I'm not going back ]]></title>
                                                                                                <dc:content><![CDATA[ <p>During this scorching heat, what’s a home baker to do? Having the oven switched on to satisfy a craving for sponge cake will have your <a href="https://www.tomsguide.com/us/smart-air-conditioner-buying-guide,review-5615.html">air conditioning</a> on overdrive, or your fan blowing around powdered sugar. But I won’t let the high temperatures stop me from baking, so I put aside my reservations and tried to make some cupcakes in an <a href="https://www.tomsguide.com/best-picks/best-air-fryers">air fryer</a>. </p><p>Could this countertop appliance that I rely on for crisping fries and grilling burgers bake a decent cake? The answer is a resounding yes, but you will have to make some changes.</p><p>Here’s exactly what happened when I baked a batch of lemon cupcakes in my air fryer, along with expert advice on mastering the countertop bake.</p><div class="product"><a data-dimension112="51fde800-81d5-11f1-8bca-ed6595bbd10c" data-action="Deal Block" data-label="ClearView 4-Quart Air Fryer with Glass Basket" data-dimension48="ClearView 4-Quart Air Fryer with Glass Basket" data-dimension25="$139" href="https://www.amazon.com/dp/B0GVPBSXXF?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="t5fXiTswZJ6ouWjQJi7zdi" name="Cuisinart Clear View 4-Quart Air Fryer" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/t5fXiTswZJ6ouWjQJi7zdi.jpg" mos="" align="middle" fullscreen="" width="2000" height="2000" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0GVPBSXXF?" target="_blank" rel="nofollow" data-dimension112="51fde800-81d5-11f1-8bca-ed6595bbd10c" data-action="Deal Block" data-label="ClearView 4-Quart Air Fryer with Glass Basket" data-dimension48="ClearView 4-Quart Air Fryer with Glass Basket" data-dimension25="$139">ClearView 4-Quart Air Fryer with Glass Basket: $139</a></strong><br>Cuisinart’s ClearView air fryer has a 4-quart capacity and 5 cooking functions. Choose air fry, bake, broil, keep warm or recrisp. Plus, it has two presets for your favorite settings. Reaching up to 450°F, it has 1600 watts of power and the capacity to cook 1.5 lb of French fries, 2 lbs of wings, or a whole 4 lb chicken. View your food’s progress as it cooks through the clean bowl, which can also works for food prep and storage.<a class="view-deal button" href="https://www.amazon.com/dp/B0GVPBSXXF?" target="_blank" rel="nofollow" data-dimension112="51fde800-81d5-11f1-8bca-ed6595bbd10c" data-action="Deal Block" data-label="ClearView 4-Quart Air Fryer with Glass Basket" data-dimension48="ClearView 4-Quart Air Fryer with Glass Basket" data-dimension25="$139">View Deal</a></p></div><h2 id="how-i-made-lemon-cupcakes-in-an-air-fryer">How I made lemon cupcakes in an air fryer</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="4qzU784L8A84aaea4wjWNG" name="Lemon cupcakes made in air fryer" alt="Lemon cupcakes baked in air fryer" src="https://cdn.mos.cms.futurecdn.net/4qzU784L8A84aaea4wjWNG.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Camilla Sharman)</span></figcaption></figure><p>Lemon cupcakes are the ultimate refreshing summer treat and happen to be one of my family’s favorite go-to sweet treats.</p><p>I often search online for recipes, and I found an <a href="https://www.bbcgoodfood.com/recipes/easy-lemon-muffins" target="_blank">Easy lemon muffin recipe</a> at BBC Good Food. What’s brilliant about this particular recipe is that all of the batter ingredients can be tipped into a single bowl and mixed in one go. You can do this by hand or with one of the <a href="https://www.tomsguide.com/best-picks/best-stand-mixers">best stand mixers</a>; either way, as long as your butter is soft, you won’t break a sweat.</p><p>The recipe calls for a muffin tray, which is a non-starter for my compact <a href="https://www.tomsguide.com/home/stop-the-guesswork-cuisinarts-clearview-air-fryer-gives-you-dinner-in-plain-sight">Cuisinart Clearview Air Fryer</a>. To improvise, I doubled up my paper cupcake liners for extra stability. Luckily, they held up well when I spooned in the batter. </p><p>After preheating the air fryer to 200°C  (390°F) for four minutes, I then carefully placed the cupcake cases into the glass basket, but I could only bake five at a time.</p><p>Knowing that air fryers run hotter and faster than conventional ovens, I selected ‘Bake’ mode, at 160°C (320°F) for 15 minutes — 20°C lower and 15 minutes shorter than the original bake time.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="ZDBV36Tgb2ZmLMg8ukx68H" name="Lemon cupcakes made in air fryer" alt="Lemon cupcakes baked in air fryer" src="https://cdn.mos.cms.futurecdn.net/ZDBV36Tgb2ZmLMg8ukx68H.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Camilla Sharman)</span></figcaption></figure><p>I had a massive advantage during this bake thanks to my air fryer’s design. Because of its glass viewing window, I had a full view of the action. Unlike standard air fryer models, I didn’t have to pull the basket to see how the bake was progressing.</p><p>At the 11-minute mark, I noticed the tops had started to brown. By 15 minutes, I was satisfied they were perfectly cooked.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="jhFFvU5PiC2kiGgfWbDC4H" name="Lemon cupcakes made in air fryer" alt="Lemon cupcakes baked in air fryer" src="https://cdn.mos.cms.futurecdn.net/jhFFvU5PiC2kiGgfWbDC4H.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Camilla Sharman)</span></figcaption></figure><h2 id="what-i-noticed-when-cooking-cupcakes-in-an-air-fryer">What I noticed when cooking cupcakes in an air fryer</h2><p>Although you can cook cupcakes in an air fryer, I did notice a few differences between this method and using a traditional oven.<br><br><strong>1.</strong> You have to reduce the cooking time and temperature.<br><strong>2.</strong> Forget about making a big cake.<br><strong>3. </strong>The final shape is a little different and may need disguising with icing.<br><strong>4.</strong> The bake was just as moist.</p><p>I’d be happy to continue baking in an air fryer, although I won’t be taking on any elaborate challenges. But be warned, even though they didn’t look as appetizing as when baked in a traditional oven, they still tasted delicious.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-exVzoO"></div>                            </div>                            <script src="https://kwizly.com/embed/exVzoO.js" async></script><h3 class="article-body__section" id="section-what-do-the-professionals-think-about-air-fryer-baking"><span>What do the professionals think about air fryer baking?</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="EeDHv7oUxsg27WnTLwUh3H" name="Lemon cupcakes made in air fryer" alt="Lemon cupcakes baked in air fryer" src="https://cdn.mos.cms.futurecdn.net/EeDHv7oUxsg27WnTLwUh3H.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Camilla Sharman)</span></figcaption></figure><p>I was able to prove that you can bake a cake in an air fryer, though many factors differ from using an oven. To help you navigate them and ensure a perfect bake every time, I reached out to some baking pros for their insider advice. </p><h2 id="can-baking-a-cake-in-an-air-fryer-deliver-the-same-results-as-an-oven">Can baking a cake in an air fryer deliver the same results as an oven?</h2><p>You can definitely bake a cake in an air fryer, but experts say it’s not a straight swap.</p><p>“The result is not that air fryers bake worse; it is that they bake differently,” explains Andreas Hansen, founder at <a href="https://fritaire.com/" target="_blank">Fritaire</a>. “Dense, moist batters like brownies, banana bread, pound cake, and lava cakes perform genuinely well. Tall, delicate sponges that depend on a slow, even rise are where a conventional oven still wins.”</p><p>Isaac Bernal Carbajo, <a href="https://www.instagram.com/chef_isaac_bernal/" target="_blank">executive chef</a>, explains, “The moving air shoves loose batter around before it can set, which is why delicate sponges and anything chiffon-adjacent are a bad bet. What you do get is speed, no long preheat, and a lovely crust on sturdier bakes.”</p><div><blockquote><p>The result is not that air fryers bake worse; it is that they bake differently</p><p>Andreas Hansen, Fritaire</p></blockquote></div><p>Minoo Mahdavian, founder at <a href="https://minoomakesstuff.com/" target="_blank">MinooMakesStuff</a>, says, “Many people treat an air fryer like a multipurpose ‘little oven’, when it’s actually closer to a wind tunnel with a heating element parked right above your cake.”</p><p><strong>How an air fryer actually works</strong></p><p>It helps to know how an air fryer works to understand why it produces different results from a conventional oven. Hansen explains the three main differences.</p><p><strong>Proximity to heat: </strong>“The heating element sits much closer to the food, which is why tops brown fast.”</p><p><strong>Aggressive airflow:</strong> “The fan moves air more aggressively in a smaller chamber, which can pull moisture from the batter surface before the crumb sets.”</p><p><strong>Rapid heat recovery:</strong> “The small cavity means temperature recovers very quickly when you open it, which is actually an advantage: you lose less heat checking on a cake than you would in a full-size oven.”</p><h2 id="are-there-any-differences-that-would-make-the-bake-better-or-worse">Are there any differences that would make the bake better or worse?</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="hpP7iXUkvH8BPQYGVCpzSG" name="Lemon cupcakes made in air fryer" alt="Lemon cupcakes baked in air fryer" src="https://cdn.mos.cms.futurecdn.net/hpP7iXUkvH8BPQYGVCpzSG.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Camilla Sharman)</span></figcaption></figure><p>Because air fryers work differently from conventional ovens, if you follow the same baking temperatures for standard recipes, you won’t necessarily get the same result. </p><p>“The fan sets and browns the top long before the middle catches up, so you pull out something that looks gorgeous, cracks hard down the center, and is still gummy in the bottom third,” says Mahdavian.</p><p>Carbajo suggests making a few changes: “I usually lower the temperature slightly compared to the oven recipe, about 15 - 20°F. Start checking on the cake a few minutes early. Every air fryer behaves a little differently, so I suggest practicing once or twice to get the feel of it."</p><h2 id="apart-from-size-are-there-any-other-limitations">Apart from size, are there any other limitations?</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1600px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="fJTqCx2aMs3DJffXCJQ3TJ" name="Ninja Pro 4in1 air fryer drawer pulled out" alt="Ninja Pro 4in1 air fryer" src="https://cdn.mos.cms.futurecdn.net/fJTqCx2aMs3DJffXCJQ3TJ.jpg" mos="" align="middle" fullscreen="" width="1600" height="900" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide / Millie Fender)</span></figcaption></figure><p>As soon as you start baking in an air fryer, you’ll realize that your conventional baking tins won’t fit. When I made the lemon cupcakes in my air fryer, I had to swap from my habit of making a larger loaf cake and opt for individual paper cases instead.</p><p>Apart from downsizing your bakeware, what else do you consider?<br><br><strong>Pan clearance and airflow</strong><br>“The cake pan needs space around it for air to circulate,” says Hansen. “A pan that fits snugly will bake unevenly because you have effectively blocked the convection that the appliance depends on.”</p><p>Carbajo adds, “Even if a pan technically fits, if it’s crowding the walls or sitting too close to the element, it won’t bake evenly. I use a 6-inch round, anything wider and I’m just making a burnt frisbee.”</p><div><blockquote><p>Even if a pan technically fits, if it's crowding the walls or sitting too close to the element, it won't bake evenly</p><p>Isaac Bernal Carbajo, Executive Chef</p></blockquote></div><p><strong>No bottom heat (in most models)</strong><br>The lack of heat at the bottom of the air fryer can also cause issues with some bakes. Hansen says, “Cakes that need a strong base set, like some cheesecakes and fruit-heavy batters, can end up with soft bottoms.”</p><p><strong>Batter height</strong><br>If you’re hoping to bake a nice tall fruit cake or deep sponge cake, think again. “Anything that rises tall gets close to the top element and browns or burns before the center cooks,” says Hansen, “Low, wide bakes beat tall, narrow ones in an air fryer every time.”<br><br><strong>When using an air fryer makes sense</strong><br>Baking in an air fryer undoubtedly limits the scope of what you can make. However, on hot summer days, when you don’t fancy turning your kitchen into a sauna, an air fryer makes a good swap. </p><p>It’s also an ideal solution if you’re only baking for one or two people and won’t eat your way through a whole cake. </p><h2 id="air-frying-baking-tips">Air frying baking tips</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="2zThsCykzzKr2DcXfAmY7E" name="shutterstock_2421039309" alt="Baked muffins in an air fryer" src="https://cdn.mos.cms.futurecdn.net/2zThsCykzzKr2DcXfAmY7E.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Shutterstock)</span></figcaption></figure><p>To successfully transition from oven baking to air fryer baking, the experts recommend these five key adjustments.</p><p><strong>1. Lower the temperature</strong><br>Drop the temperature about 35°F (20°C) below the conventional oven recipe. “The compact chamber and close element run effectively hotter,” says Hansen. </p><p><strong>2. Tent with foil</strong><br>As air fryers can dry out a cake, Carbajo suggests covering the top with foil once it starts to brown to prevent moisture from escaping. </p><p><strong>3. Go low and wide</strong><br>Hansen says to go low and wide, and adds, “Two shallow layers bake far better than one tall cake, and you can stack them afterward.”</p><p><strong>4. Don’t overfill</strong><br>Air fryer bakes need more headroom than oven bakes, for this reason Hansen recommends to fill pans halfway to two-thirds, and no more. </p><p><strong>5. Let it rest</strong><br>“Let the cake sit in the residual warmth for a few minutes after the cycle ends,” says Hansen. “The small chamber holds gentle heat that finishes the center without further browning.”</p><p><strong>6. Experiment </strong><br>Be prepared to experiment and find out what works with your air fryer. Mantiri says, “Just like how ovens can behave differently depending on the brand, how old it is, or even the altitude you’re at, a similar thing goes for air fryers.”</p><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h3><ul><li><a href="https://www.tomsguide.com/home/kitchen-dining/i-discovered-how-to-make-homemade-bread-on-my-air-fryer-heres-how">I discovered how to make homemade bread in my air fryer — here's how</a></li><li><a href="https://www.tomsguide.com/home/ive-never-given-a-product-a-5-star-rating-heres-why-kitchenaids-new-stand-mixer-won-me-over">I’ve never given a product a 5-star rating — here’s why KitchenAid’s new stand mixer won me over</a></li><li><a href="https://www.tomsguide.com/home/kitchen-dining/watch-out-kitchenaid-oonis-launching-its-second-stand-mixer-and-at-usd599-it-price-matches-the-artisan-pro">Watch out KitchenAid! Ooni’s launching its second stand mixer, and at $599 its price matches the Artisan Pro</a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/home/air-fryers/i-tried-baking-in-an-air-fryer-and-now-im-seriously-close-to-ditching-my-oven</link>
                                                                            <description>
                            <![CDATA[ Can an air fryer replace baking a cake in an oven? I tried it to find out, and was pleasantly surprised. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">4SfQAvoxkMF36WtPdBdmAm</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/Ej3xVv4Ak2vhsnS9qdLHYG-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Mon, 27 Jul 2026 08:30:00 +0000</pubDate>                                                                                                                                <updated>Thu, 30 Jul 2026 13:58:42 +0000</updated>
                                                                                                                                            <category><![CDATA[Air Fryers]]></category>
                                                    <category><![CDATA[Home]]></category>
                                                    <category><![CDATA[Home Appliances]]></category>
                                                    <category><![CDATA[Kitchen & Dining]]></category>
                                                                                                <author><![CDATA[ camilla.sharman@futurenet.com (Camilla Sharman) ]]></author>                    <dc:creator><![CDATA[ Camilla Sharman ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/nY4nvWzofHKHpvzAqN5LVH.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Camilla is the Homes Staff Writer and covers everything to do with homes and gardens. She has a wealth of editorial experience, mounting over 30 years, and covers news and features, tests products for reviews and compiles buying guides.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;p&gt;Her work has appeared in business and consumer titles, including Ideal Home, Real Homes, House Beautiful, Homebuilding &amp;amp; Renovation, and Kitchen &amp;amp; Bathroom Business. She’s even appeared on the cover of Your Home, writing about her own house renovation.&lt;/p&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;p&gt;Although she’s obsessed with decorating her home, she also enjoys baking and trying out the latest kitchen appliances. But when she’s not inside, you’ll find her pottering about in her yard, tending to her vegetable patch or taking in her prized hydrangeas. She also enjoys keeping fit, and if she&#039;s not on a spin bike trying to keep up with the class, she&#039;ll be in the pool, or trying to perfect her headstand in a yoga class.&lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/Ej3xVv4Ak2vhsnS9qdLHYG-1280-80.jpg">
                                                            <media:credit><![CDATA[Future / Camilla Sharman]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Lemon cupcakes baked in air fryer]]></media:description>                                                            <media:text><![CDATA[Lemon cupcakes baked in air fryer]]></media:text>
                                <media:title type="plain"><![CDATA[Lemon cupcakes baked in air fryer]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/Ej3xVv4Ak2vhsnS9qdLHYG-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>During this scorching heat, what’s a home baker to do? Having the oven switched on to satisfy a craving for sponge cake will have your <a href="https://www.tomsguide.com/us/smart-air-conditioner-buying-guide,review-5615.html">air conditioning</a> on overdrive, or your fan blowing around powdered sugar. But I won’t let the high temperatures stop me from baking, so I put aside my reservations and tried to make some cupcakes in an <a href="https://www.tomsguide.com/best-picks/best-air-fryers">air fryer</a>. </p><p>Could this countertop appliance that I rely on for crisping fries and grilling burgers bake a decent cake? The answer is a resounding yes, but you will have to make some changes.</p><p>Here’s exactly what happened when I baked a batch of lemon cupcakes in my air fryer, along with expert advice on mastering the countertop bake.</p><div class="product"><a data-dimension112="51fde800-81d5-11f1-8bca-ed6595bbd10c" data-action="Deal Block" data-label="ClearView 4-Quart Air Fryer with Glass Basket" data-dimension48="ClearView 4-Quart Air Fryer with Glass Basket" data-dimension25="$139" href="https://www.amazon.com/dp/B0GVPBSXXF?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="t5fXiTswZJ6ouWjQJi7zdi" name="Cuisinart Clear View 4-Quart Air Fryer" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/t5fXiTswZJ6ouWjQJi7zdi.jpg" mos="" align="middle" fullscreen="" width="2000" height="2000" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0GVPBSXXF?" target="_blank" rel="nofollow" data-dimension112="51fde800-81d5-11f1-8bca-ed6595bbd10c" data-action="Deal Block" data-label="ClearView 4-Quart Air Fryer with Glass Basket" data-dimension48="ClearView 4-Quart Air Fryer with Glass Basket" data-dimension25="$139">ClearView 4-Quart Air Fryer with Glass Basket: $139</a></strong><br>Cuisinart’s ClearView air fryer has a 4-quart capacity and 5 cooking functions. Choose air fry, bake, broil, keep warm or recrisp. Plus, it has two presets for your favorite settings. Reaching up to 450°F, it has 1600 watts of power and the capacity to cook 1.5 lb of French fries, 2 lbs of wings, or a whole 4 lb chicken. View your food’s progress as it cooks through the clean bowl, which can also works for food prep and storage.<a class="view-deal button" href="https://www.amazon.com/dp/B0GVPBSXXF?" target="_blank" rel="nofollow" data-dimension112="51fde800-81d5-11f1-8bca-ed6595bbd10c" data-action="Deal Block" data-label="ClearView 4-Quart Air Fryer with Glass Basket" data-dimension48="ClearView 4-Quart Air Fryer with Glass Basket" data-dimension25="$139">View Deal</a></p></div><h2 id="how-i-made-lemon-cupcakes-in-an-air-fryer">How I made lemon cupcakes in an air fryer</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="4qzU784L8A84aaea4wjWNG" name="Lemon cupcakes made in air fryer" alt="Lemon cupcakes baked in air fryer" src="https://cdn.mos.cms.futurecdn.net/4qzU784L8A84aaea4wjWNG.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Camilla Sharman)</span></figcaption></figure><p>Lemon cupcakes are the ultimate refreshing summer treat and happen to be one of my family’s favorite go-to sweet treats.</p><p>I often search online for recipes, and I found an <a href="https://www.bbcgoodfood.com/recipes/easy-lemon-muffins" target="_blank">Easy lemon muffin recipe</a> at BBC Good Food. What’s brilliant about this particular recipe is that all of the batter ingredients can be tipped into a single bowl and mixed in one go. You can do this by hand or with one of the <a href="https://www.tomsguide.com/best-picks/best-stand-mixers">best stand mixers</a>; either way, as long as your butter is soft, you won’t break a sweat.</p><p>The recipe calls for a muffin tray, which is a non-starter for my compact <a href="https://www.tomsguide.com/home/stop-the-guesswork-cuisinarts-clearview-air-fryer-gives-you-dinner-in-plain-sight">Cuisinart Clearview Air Fryer</a>. To improvise, I doubled up my paper cupcake liners for extra stability. Luckily, they held up well when I spooned in the batter. </p><p>After preheating the air fryer to 200°C  (390°F) for four minutes, I then carefully placed the cupcake cases into the glass basket, but I could only bake five at a time.</p><p>Knowing that air fryers run hotter and faster than conventional ovens, I selected ‘Bake’ mode, at 160°C (320°F) for 15 minutes — 20°C lower and 15 minutes shorter than the original bake time.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="ZDBV36Tgb2ZmLMg8ukx68H" name="Lemon cupcakes made in air fryer" alt="Lemon cupcakes baked in air fryer" src="https://cdn.mos.cms.futurecdn.net/ZDBV36Tgb2ZmLMg8ukx68H.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Camilla Sharman)</span></figcaption></figure><p>I had a massive advantage during this bake thanks to my air fryer’s design. Because of its glass viewing window, I had a full view of the action. Unlike standard air fryer models, I didn’t have to pull the basket to see how the bake was progressing.</p><p>At the 11-minute mark, I noticed the tops had started to brown. By 15 minutes, I was satisfied they were perfectly cooked.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="jhFFvU5PiC2kiGgfWbDC4H" name="Lemon cupcakes made in air fryer" alt="Lemon cupcakes baked in air fryer" src="https://cdn.mos.cms.futurecdn.net/jhFFvU5PiC2kiGgfWbDC4H.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Camilla Sharman)</span></figcaption></figure><h2 id="what-i-noticed-when-cooking-cupcakes-in-an-air-fryer">What I noticed when cooking cupcakes in an air fryer</h2><p>Although you can cook cupcakes in an air fryer, I did notice a few differences between this method and using a traditional oven.<br><br><strong>1.</strong> You have to reduce the cooking time and temperature.<br><strong>2.</strong> Forget about making a big cake.<br><strong>3. </strong>The final shape is a little different and may need disguising with icing.<br><strong>4.</strong> The bake was just as moist.</p><p>I’d be happy to continue baking in an air fryer, although I won’t be taking on any elaborate challenges. But be warned, even though they didn’t look as appetizing as when baked in a traditional oven, they still tasted delicious.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-exVzoO"></div>                            </div>                            <script src="https://kwizly.com/embed/exVzoO.js" async></script><h3 class="article-body__section" id="section-what-do-the-professionals-think-about-air-fryer-baking"><span>What do the professionals think about air fryer baking?</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="EeDHv7oUxsg27WnTLwUh3H" name="Lemon cupcakes made in air fryer" alt="Lemon cupcakes baked in air fryer" src="https://cdn.mos.cms.futurecdn.net/EeDHv7oUxsg27WnTLwUh3H.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Camilla Sharman)</span></figcaption></figure><p>I was able to prove that you can bake a cake in an air fryer, though many factors differ from using an oven. To help you navigate them and ensure a perfect bake every time, I reached out to some baking pros for their insider advice. </p><h2 id="can-baking-a-cake-in-an-air-fryer-deliver-the-same-results-as-an-oven">Can baking a cake in an air fryer deliver the same results as an oven?</h2><p>You can definitely bake a cake in an air fryer, but experts say it’s not a straight swap.</p><p>“The result is not that air fryers bake worse; it is that they bake differently,” explains Andreas Hansen, founder at <a href="https://fritaire.com/" target="_blank">Fritaire</a>. “Dense, moist batters like brownies, banana bread, pound cake, and lava cakes perform genuinely well. Tall, delicate sponges that depend on a slow, even rise are where a conventional oven still wins.”</p><p>Isaac Bernal Carbajo, <a href="https://www.instagram.com/chef_isaac_bernal/" target="_blank">executive chef</a>, explains, “The moving air shoves loose batter around before it can set, which is why delicate sponges and anything chiffon-adjacent are a bad bet. What you do get is speed, no long preheat, and a lovely crust on sturdier bakes.”</p><div><blockquote><p>The result is not that air fryers bake worse; it is that they bake differently</p><p>Andreas Hansen, Fritaire</p></blockquote></div><p>Minoo Mahdavian, founder at <a href="https://minoomakesstuff.com/" target="_blank">MinooMakesStuff</a>, says, “Many people treat an air fryer like a multipurpose ‘little oven’, when it’s actually closer to a wind tunnel with a heating element parked right above your cake.”</p><p><strong>How an air fryer actually works</strong></p><p>It helps to know how an air fryer works to understand why it produces different results from a conventional oven. Hansen explains the three main differences.</p><p><strong>Proximity to heat: </strong>“The heating element sits much closer to the food, which is why tops brown fast.”</p><p><strong>Aggressive airflow:</strong> “The fan moves air more aggressively in a smaller chamber, which can pull moisture from the batter surface before the crumb sets.”</p><p><strong>Rapid heat recovery:</strong> “The small cavity means temperature recovers very quickly when you open it, which is actually an advantage: you lose less heat checking on a cake than you would in a full-size oven.”</p><h2 id="are-there-any-differences-that-would-make-the-bake-better-or-worse">Are there any differences that would make the bake better or worse?</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="hpP7iXUkvH8BPQYGVCpzSG" name="Lemon cupcakes made in air fryer" alt="Lemon cupcakes baked in air fryer" src="https://cdn.mos.cms.futurecdn.net/hpP7iXUkvH8BPQYGVCpzSG.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future / Camilla Sharman)</span></figcaption></figure><p>Because air fryers work differently from conventional ovens, if you follow the same baking temperatures for standard recipes, you won’t necessarily get the same result. </p><p>“The fan sets and browns the top long before the middle catches up, so you pull out something that looks gorgeous, cracks hard down the center, and is still gummy in the bottom third,” says Mahdavian.</p><p>Carbajo suggests making a few changes: “I usually lower the temperature slightly compared to the oven recipe, about 15 - 20°F. Start checking on the cake a few minutes early. Every air fryer behaves a little differently, so I suggest practicing once or twice to get the feel of it."</p><h2 id="apart-from-size-are-there-any-other-limitations">Apart from size, are there any other limitations?</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1600px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="fJTqCx2aMs3DJffXCJQ3TJ" name="Ninja Pro 4in1 air fryer drawer pulled out" alt="Ninja Pro 4in1 air fryer" src="https://cdn.mos.cms.futurecdn.net/fJTqCx2aMs3DJffXCJQ3TJ.jpg" mos="" align="middle" fullscreen="" width="1600" height="900" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide / Millie Fender)</span></figcaption></figure><p>As soon as you start baking in an air fryer, you’ll realize that your conventional baking tins won’t fit. When I made the lemon cupcakes in my air fryer, I had to swap from my habit of making a larger loaf cake and opt for individual paper cases instead.</p><p>Apart from downsizing your bakeware, what else do you consider?<br><br><strong>Pan clearance and airflow</strong><br>“The cake pan needs space around it for air to circulate,” says Hansen. “A pan that fits snugly will bake unevenly because you have effectively blocked the convection that the appliance depends on.”</p><p>Carbajo adds, “Even if a pan technically fits, if it’s crowding the walls or sitting too close to the element, it won’t bake evenly. I use a 6-inch round, anything wider and I’m just making a burnt frisbee.”</p><div><blockquote><p>Even if a pan technically fits, if it's crowding the walls or sitting too close to the element, it won't bake evenly</p><p>Isaac Bernal Carbajo, Executive Chef</p></blockquote></div><p><strong>No bottom heat (in most models)</strong><br>The lack of heat at the bottom of the air fryer can also cause issues with some bakes. Hansen says, “Cakes that need a strong base set, like some cheesecakes and fruit-heavy batters, can end up with soft bottoms.”</p><p><strong>Batter height</strong><br>If you’re hoping to bake a nice tall fruit cake or deep sponge cake, think again. “Anything that rises tall gets close to the top element and browns or burns before the center cooks,” says Hansen, “Low, wide bakes beat tall, narrow ones in an air fryer every time.”<br><br><strong>When using an air fryer makes sense</strong><br>Baking in an air fryer undoubtedly limits the scope of what you can make. However, on hot summer days, when you don’t fancy turning your kitchen into a sauna, an air fryer makes a good swap. </p><p>It’s also an ideal solution if you’re only baking for one or two people and won’t eat your way through a whole cake. </p><h2 id="air-frying-baking-tips">Air frying baking tips</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="2zThsCykzzKr2DcXfAmY7E" name="shutterstock_2421039309" alt="Baked muffins in an air fryer" src="https://cdn.mos.cms.futurecdn.net/2zThsCykzzKr2DcXfAmY7E.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Shutterstock)</span></figcaption></figure><p>To successfully transition from oven baking to air fryer baking, the experts recommend these five key adjustments.</p><p><strong>1. Lower the temperature</strong><br>Drop the temperature about 35°F (20°C) below the conventional oven recipe. “The compact chamber and close element run effectively hotter,” says Hansen. </p><p><strong>2. Tent with foil</strong><br>As air fryers can dry out a cake, Carbajo suggests covering the top with foil once it starts to brown to prevent moisture from escaping. </p><p><strong>3. Go low and wide</strong><br>Hansen says to go low and wide, and adds, “Two shallow layers bake far better than one tall cake, and you can stack them afterward.”</p><p><strong>4. Don’t overfill</strong><br>Air fryer bakes need more headroom than oven bakes, for this reason Hansen recommends to fill pans halfway to two-thirds, and no more. </p><p><strong>5. Let it rest</strong><br>“Let the cake sit in the residual warmth for a few minutes after the cycle ends,” says Hansen. “The small chamber holds gentle heat that finishes the center without further browning.”</p><p><strong>6. Experiment </strong><br>Be prepared to experiment and find out what works with your air fryer. Mantiri says, “Just like how ovens can behave differently depending on the brand, how old it is, or even the altitude you’re at, a similar thing goes for air fryers.”</p><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h3><ul><li><a href="https://www.tomsguide.com/home/kitchen-dining/i-discovered-how-to-make-homemade-bread-on-my-air-fryer-heres-how">I discovered how to make homemade bread in my air fryer — here's how</a></li><li><a href="https://www.tomsguide.com/home/ive-never-given-a-product-a-5-star-rating-heres-why-kitchenaids-new-stand-mixer-won-me-over">I’ve never given a product a 5-star rating — here’s why KitchenAid’s new stand mixer won me over</a></li><li><a href="https://www.tomsguide.com/home/kitchen-dining/watch-out-kitchenaid-oonis-launching-its-second-stand-mixer-and-at-usd599-it-price-matches-the-artisan-pro">Watch out KitchenAid! Ooni’s launching its second stand mixer, and at $599 its price matches the Artisan Pro</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ You told me your three biggest issues with Moccamaster — and I have solutions for all of them ]]></title>
                                                                                                <dc:content><![CDATA[ <div  class="fancy-box"><div class="fancy_box-title">The Coffee Lab</div><div class="fancy_box_body"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' ><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="UwFdgr6xkNzHUWjapZThcN" name="smeg edited2" caption="" alt="the smeg emc02 mini pro manual espresso machine in jade green" src="https://cdn.mos.cms.futurecdn.net/UwFdgr6xkNzHUWjapZThcN.jpg" mos="" link="" align="" fullscreen="" width="" height="" attribution="" endorsement="" class="pinterest-pin-exclude"></p></div></div><figcaption itemprop="caption description" class=""><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p class="fancy-box__body-text">I'm Erin, and welcome to the seventeenth episode of <a data-analytics-id="inline-link" href="https://www.tomsguide.com/tag/the-coffee-lab">The Coffee Lab</a>, the series where we forget coffee snobbery. The Coffee Lab is all about making coffee fun. Join me as I help you kickstart your coffee journey!</p></div></div><p>I love my <a href="https://www.tomsguide.com/home/coffee-makers/technivorm-moccamaster-kgbv-select-review">Moccamaster</a>. It's one of the <a href="https://www.tomsguide.com/home/coffee-makers/best-coffee-makers">best coffee makers</a> in the world, by a mile. It brews consistently delicious coffee with zero bitterness, minimal silt, and looks darn cool while doing it. </p><p>However, not everyone gets on with Moccamaster as well as I do — and that's the nature of life. Some issues are integral, which means those people would likely be better off with an alternative. But some are super easy fixes — and two of these three issues are <em>incredibly</em> easy fixes. </p><p>Last week, I troubleshot three other Moccamaster problems: "too much plastic," "horrible water distribution," and the "hot plate burning the coffee." This week, I'm teaching you how to prevent the Moccamaster from "scaling easily," dealing with the Moccamaster's "high price," and my favorite question of all: Does the Moccamaster come in a single-serve model?</p>                    <div class= "tiktok-wrapper" style="min-height: 750px;"><blockquote class="tiktok-embed" cite="https://www.tiktok.com/@tomsguide/video/7666132122834341134" data-video-id="7666132122834341134" style="max-width: 605px; min-width: 325px;">                        <section>                            <a target="_blank" title="@tomsguide" href="https://www.tiktok.com/@tomsguide">@tomsguide</a>                            <p></p><a target="_blank" title="♬ Jazz, ambient taste, hip-ho ... - TOKYO Lonesome Blue" href="https://www.tiktok.com/music/Jazz-ambient-taste-hip-ho-6817677146459211778">♬ Jazz, ambient taste, hip-ho ... - TOKYO Lonesome Blue</a></section>                    </blockquote></div>                <div class="product"><a data-dimension112="1acfeb9e-8694-11f1-be07-451ef8a8d123" data-action="Deal Block" data-label="Moccamaster KGBV Select" data-dimension48="Moccamaster KGBV Select" data-dimension25="$239" href="https://www.amazon.com/Moccamaster-53941-Select-10-Cup-Polished/dp/B093DYPBYR" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2297px;"><p class="vanilla-image-block" style="padding-top:108.84%;"><img id="ViCKNPMdH4jYKkGFaBFznF" name="moccamaster_sorbet_deal" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/ViCKNPMdH4jYKkGFaBFznF.jpg" mos="" align="middle" fullscreen="" width="2297" height="2500" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Moccamaster-53941-Select-10-Cup-Polished/dp/B093DYPBYR" target="_blank" rel="nofollow" data-dimension112="1acfeb9e-8694-11f1-be07-451ef8a8d123" data-action="Deal Block" data-label="Moccamaster KGBV Select" data-dimension48="Moccamaster KGBV Select" data-dimension25="$239">Moccamaster KGBV Select: was $369 now $239</a></strong><br>There's a reason why the <a href="https://www.tomsguide.com/home/coffee-makers/technivorm-moccamaster-kgbv-select-review">Moccamaster</a> is so revered in the coffee world: it seriously is that good. It's super easy to use, SCA-accredited (for both full-batch and half-batch), and makes full-bodied-but-not-bitter coffee.  </p><p><strong>Warranty check:</strong> 5 years as standard and <em>lifetime repairs</em>.<a class="view-deal button" href="https://www.amazon.com/Moccamaster-53941-Select-10-Cup-Polished/dp/B093DYPBYR" target="_blank" rel="nofollow" data-dimension112="1acfeb9e-8694-11f1-be07-451ef8a8d123" data-action="Deal Block" data-label="Moccamaster KGBV Select" data-dimension48="Moccamaster KGBV Select" data-dimension25="$239">View Deal</a></p></div><h2 id="you-said-the-moccamaster-scales-easily">You said the Moccamaster "scales easily"</h2><p>I <em>loved</em> receiving this question — because it's so easily fixed! The Moccamaster will scale up. Everything that touches water will scale up. Pretty much all water contains minerals, which create limescale. </p><p>However, this is super easy to deal with.</p><div class="product"><a data-dimension112="14dbad1e-8693-11f1-b8af-21193dcaa8f1" data-action="Deal Block" data-label="Descaler" data-dimension48="Descaler" data-dimension25="$16" href="https://www.amazon.com/Durgol-0298-Universal-Multipurpose-Decalcifier/dp/B076D99C1B" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1000px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="cW8kTnKEQiWWwMVxM5zGUE" name="durgol descaler" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/cW8kTnKEQiWWwMVxM5zGUE.png" mos="" align="middle" fullscreen="" width="1000" height="1000" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>This is the descaler Moccamaster recommends. All you have to do is dilute the solution in water, run a brew cycle, and then flush it out with clean water. It's so straightforward.<a class="view-deal button" href="https://www.amazon.com/Durgol-0298-Universal-Multipurpose-Decalcifier/dp/B076D99C1B" target="_blank" rel="nofollow" data-dimension112="14dbad1e-8693-11f1-b8af-21193dcaa8f1" data-action="Deal Block" data-label="Descaler" data-dimension48="Descaler" data-dimension25="$16">View Deal</a></p></div><p>And there you have it! Super easy. Didn't I tell you?</p><h2 id="you-said-the-moccamaster-is-too-expensive">You said the Moccamaster is "too expensive"</h2><p>I wasn't surprised when I received this question. The Moccamaster <em>is</em> expensive. Personally, I think the <a href="https://www.tomsguide.com/home/coffee-makers/the-moccamaster-is-the-perfect-example-of-buy-it-nice-or-buy-it-twice-i-did-the-coffee-math-vs-bonavita-breville-and-more-so-you-dont-have-to">Moccamaster is the perfect example of "buy it nice or buy it twice"</a>. I would rather spend $370 on the Moccamaster than buy a $100 coffee maker three times — but I know that's not realistic for some people.</p><p>Moccamaster also offers a 5-year warranty and lifetime repairs, which no other coffee machine brand has matched yet. Again, personally, I would invest in the Moccamaster due to this after-purchase benefit — but I know that's not realistic for some people. </p><p>Here are some coffee makers with a lower initial cost. </p><div class="product"><a data-dimension112="fef08884-8693-11f1-a8e4-012ef16156b4" data-action="Deal Block" data-label="12-Cup Coffee Maker" data-dimension48="12-Cup Coffee Maker" data-dimension25="$89" href="https://www.amazon.com/Ninja-12-Cup-Programmable-CE251-Stainless/dp/B07S98411N" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1500px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="bmf4eyPRXLCcbTSHSFkUhE" name="Ninja 12 Cup Coffee maker.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/bmf4eyPRXLCcbTSHSFkUhE.jpg" mos="" align="middle" fullscreen="" width="1500" height="1500" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Ninja-12-Cup-Programmable-CE251-Stainless/dp/B07S98411N" target="_blank" rel="nofollow" data-dimension112="fef08884-8693-11f1-a8e4-012ef16156b4" data-action="Deal Block" data-label="12-Cup Coffee Maker" data-dimension48="12-Cup Coffee Maker" data-dimension25="$89">12-Cup Coffee Maker: $89</a></strong><br>I always recommend this model as a super-cheap Moccamaster alternative. While it's not available in the U.K., therefore I've not been able to personally test it, my U.S.-based colleagues have it in the New York office and <em>love it</em>. This model can make coffee in two styles: "Classic" and "Rich" and has a delayed brew start so you can wake up to fresh coffee every morning. </p><p><strong>Warranty check:</strong> 1 year standard.<a class="view-deal button" href="https://www.amazon.com/Ninja-12-Cup-Programmable-CE251-Stainless/dp/B07S98411N" target="_blank" rel="nofollow" data-dimension112="fef08884-8693-11f1-a8e4-012ef16156b4" data-action="Deal Block" data-label="12-Cup Coffee Maker" data-dimension48="12-Cup Coffee Maker" data-dimension25="$89">View Deal</a></p></div><div class="product"><a data-dimension112="fef088fc-8693-11f1-ae11-93d654b4b3ea" data-action="Deal Block" data-label="5-Cup Coffee Maker" data-dimension48="5-Cup Coffee Maker" data-dimension25="$119" href="https://www.amazon.com/dp/B0DK5B7L6V" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1664px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="4J8VE2KSc7uX8rkWUn5bJH" name="bonavita 5-cup coffee maker" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/4J8VE2KSc7uX8rkWUn5bJH.jpg" mos="" align="middle" fullscreen="" width="1664" height="1664" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>Bonavita makes some majorly affordable coffee makers, and the 5-Cup Coffee Maker is definitely one of them. You'd think a coffee maker this cheap wouldn't be SCA-accredited, but it actually is! As far as I'm aware, this is the cheapest SCA-accredited drip brewer out there. </p><p><strong>Warranty check: </strong>1 year limited.<a class="view-deal button" href="https://www.amazon.com/dp/B0DK5B7L6V" target="_blank" rel="nofollow" data-dimension112="fef088fc-8693-11f1-ae11-93d654b4b3ea" data-action="Deal Block" data-label="5-Cup Coffee Maker" data-dimension48="5-Cup Coffee Maker" data-dimension25="$119">View Deal</a></p></div><p>But Moccamaster also make a cheaper alternative...</p><h2 id="you-said-the-moccamaster-should-make-a-single-pot-version">You said the Moccamaster should make a "single-pot version"</h2><p>This was my favorite question to receive because I have a definitive answer for this: Moccamaster makes the Cup-One, too! I <a href="https://www.tomsguide.com/home/home-appliances/moccamaster-cup-one-review">reviewed the Cup-One</a> last year and loved it. It's exactly the same as the standard Moccamaster KGBV Select — but smaller.</p><div class="product"><a data-dimension112="b74dc9c4-868e-11f1-bee8-ad64bf0f7212" data-action="Deal Block" data-label="Moccamaster Cup-One" data-dimension48="Moccamaster Cup-One" data-dimension25="$250" href="https://www.amazon.com/Technivorm-Moccamaster-69212-Polished-Silver/dp/B014I5OWCO" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="noLEzUB33zqhKEgg2ojgS6" name="moccamaster cup-one deal block" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/noLEzUB33zqhKEgg2ojgS6.jpg" mos="" align="middle" fullscreen="" width="2000" height="2000" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>The Moccamaster Cup-One is the perfect drip brewer for solo households or small households — or if you want fresh coffee every time. You can brew one cup at a time in just a few minutes.<a class="view-deal button" href="https://www.amazon.com/Technivorm-Moccamaster-69212-Polished-Silver/dp/B014I5OWCO" target="_blank" rel="nofollow" data-dimension112="b74dc9c4-868e-11f1-bee8-ad64bf0f7212" data-action="Deal Block" data-label="Moccamaster Cup-One" data-dimension48="Moccamaster Cup-One" data-dimension25="$250">View Deal</a></p></div><p>I recommend the Cup-One to anyone who wants the consistent, stress-free performance of the Moccamaster without being obligated to brew an entire carafe. </p><p>So that brings us to the end! I've answered all the questions you asked me. Any more? Leave them in the comments and I'll get back to you shortly. </p><p>Stay tuned for the next episode of The Coffee Lab. I release a video every Friday on our Instagram, TikTok, and YouTube. </p><figure class="inline-layout"><div style="min-height: 400px;"><fw-embed-feed channel="toms_guide" playlist="ojE0pK" mode="row" player_placement="bottom-right"></fw-embed-feed></div></figure><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h3><ul><li><a href="https://www.tomsguide.com/home/coffee-makers/i-tried-the-new-nespresso-summer-flavors-heres-my-favorite"><strong>I tried the new Nespresso summer flavors — here's my favorite</strong></a></li><li><a href="https://www.tomsguide.com/home/coffee-makers/non-plastic-coffee-makers-are-trending-and-this-low-plastic-ratio-model-is-my-favorite-for-coffee-snobs"><strong>Non-plastic coffee makers are trending — and this low-plastic Ratio model is my favorite for coffee snobs</strong></a></li><li><a href="https://www.tomsguide.com/home/coffee-makers/i-tried-lelits-brand-new-entry-level-espresso-machine-and-i-wish-i-had-usd2-000-so-i-could-buy-it"><strong>I tried Lelit's brand-new 'entry-level' espresso machine — and I wish I had $2,000 so I could buy it</strong></a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/home/coffee-makers/you-told-me-your-three-biggest-issues-with-moccamaster-and-i-have-solutions-for-all-of-them</link>
                                                                            <description>
                            <![CDATA[ On the sixteenth episode of The Coffee Lab, I answer your most-asked questions about the Moccamaster: Part 2! ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">uPUMRSWAY5cYnLKQFBBwj</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/5WxCooa2RG8Cwr85JEe9pP-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Fri, 24 Jul 2026 13:00:00 +0000</pubDate>                                                                                                                                <updated>Wed, 29 Jul 2026 09:26:51 +0000</updated>
                                                                                                                                            <category><![CDATA[Coffee Makers]]></category>
                                                    <category><![CDATA[Home]]></category>
                                                    <category><![CDATA[Home Appliances]]></category>
                                                    <category><![CDATA[Kitchen & Dining]]></category>
                                                                                                <author><![CDATA[ erin.bashford@futurenet.com (Erin Bashford) ]]></author>                    <dc:creator><![CDATA[ Erin Bashford ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/rLvJvJVZx43hEzSsJy3BpL.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Erin Bashford is a senior reviews writer at Tom’s Guide. She has a Master’s in Broadcast and Digital Journalism from the University of East Anglia and 7 years of experience reviewing music and events for various publications. She has edited publications such as Outline Magazine’s Guide to Norwich, and she has written for a number of music magazines and websites such as Clash Magazine, Outline Magazine and Dork Magazine. She has a strong interest in audio gear and the music world. &lt;/p&gt;&lt;p&gt;As an ex-barista, Erin is passionate about coffee tech. She also loves finding the best cooking hacks and kitchen appliances, including her beloved Instant Pot. &lt;/p&gt;&lt;p&gt;In her spare time, you can find her reading, practising yoga, hiking, writing fantasy novels, or stressing over NYT Games.&lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/5WxCooa2RG8Cwr85JEe9pP-1280-80.jpg">
                                                            <media:credit><![CDATA[Tom&#039;s Guide]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[a side-by-side image of the moccamaster and the moccamaster cup one with the coffee lab logo]]></media:description>                                                            <media:text><![CDATA[a side-by-side image of the moccamaster and the moccamaster cup one with the coffee lab logo]]></media:text>
                                <media:title type="plain"><![CDATA[a side-by-side image of the moccamaster and the moccamaster cup one with the coffee lab logo]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/5WxCooa2RG8Cwr85JEe9pP-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <div  class="fancy-box"><div class="fancy_box-title">The Coffee Lab</div><div class="fancy_box_body"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' ><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="UwFdgr6xkNzHUWjapZThcN" name="smeg edited2" caption="" alt="the smeg emc02 mini pro manual espresso machine in jade green" src="https://cdn.mos.cms.futurecdn.net/UwFdgr6xkNzHUWjapZThcN.jpg" mos="" link="" align="" fullscreen="" width="" height="" attribution="" endorsement="" class="pinterest-pin-exclude"></p></div></div><figcaption itemprop="caption description" class=""><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p class="fancy-box__body-text">I'm Erin, and welcome to the seventeenth episode of <a data-analytics-id="inline-link" href="https://www.tomsguide.com/tag/the-coffee-lab">The Coffee Lab</a>, the series where we forget coffee snobbery. The Coffee Lab is all about making coffee fun. Join me as I help you kickstart your coffee journey!</p></div></div><p>I love my <a href="https://www.tomsguide.com/home/coffee-makers/technivorm-moccamaster-kgbv-select-review">Moccamaster</a>. It's one of the <a href="https://www.tomsguide.com/home/coffee-makers/best-coffee-makers">best coffee makers</a> in the world, by a mile. It brews consistently delicious coffee with zero bitterness, minimal silt, and looks darn cool while doing it. </p><p>However, not everyone gets on with Moccamaster as well as I do — and that's the nature of life. Some issues are integral, which means those people would likely be better off with an alternative. But some are super easy fixes — and two of these three issues are <em>incredibly</em> easy fixes. </p><p>Last week, I troubleshot three other Moccamaster problems: "too much plastic," "horrible water distribution," and the "hot plate burning the coffee." This week, I'm teaching you how to prevent the Moccamaster from "scaling easily," dealing with the Moccamaster's "high price," and my favorite question of all: Does the Moccamaster come in a single-serve model?</p>                    <div class= "tiktok-wrapper" style="min-height: 750px;"><blockquote class="tiktok-embed" cite="https://www.tiktok.com/@tomsguide/video/7666132122834341134" data-video-id="7666132122834341134" style="max-width: 605px; min-width: 325px;">                        <section>                            <a target="_blank" title="@tomsguide" href="https://www.tiktok.com/@tomsguide">@tomsguide</a>                            <p></p><a target="_blank" title="♬ Jazz, ambient taste, hip-ho ... - TOKYO Lonesome Blue" href="https://www.tiktok.com/music/Jazz-ambient-taste-hip-ho-6817677146459211778">♬ Jazz, ambient taste, hip-ho ... - TOKYO Lonesome Blue</a></section>                    </blockquote></div>                <div class="product"><a data-dimension112="1acfeb9e-8694-11f1-be07-451ef8a8d123" data-action="Deal Block" data-label="Moccamaster KGBV Select" data-dimension48="Moccamaster KGBV Select" data-dimension25="$239" href="https://www.amazon.com/Moccamaster-53941-Select-10-Cup-Polished/dp/B093DYPBYR" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2297px;"><p class="vanilla-image-block" style="padding-top:108.84%;"><img id="ViCKNPMdH4jYKkGFaBFznF" name="moccamaster_sorbet_deal" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/ViCKNPMdH4jYKkGFaBFznF.jpg" mos="" align="middle" fullscreen="" width="2297" height="2500" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Moccamaster-53941-Select-10-Cup-Polished/dp/B093DYPBYR" target="_blank" rel="nofollow" data-dimension112="1acfeb9e-8694-11f1-be07-451ef8a8d123" data-action="Deal Block" data-label="Moccamaster KGBV Select" data-dimension48="Moccamaster KGBV Select" data-dimension25="$239">Moccamaster KGBV Select: was $369 now $239</a></strong><br>There's a reason why the <a href="https://www.tomsguide.com/home/coffee-makers/technivorm-moccamaster-kgbv-select-review">Moccamaster</a> is so revered in the coffee world: it seriously is that good. It's super easy to use, SCA-accredited (for both full-batch and half-batch), and makes full-bodied-but-not-bitter coffee.  </p><p><strong>Warranty check:</strong> 5 years as standard and <em>lifetime repairs</em>.<a class="view-deal button" href="https://www.amazon.com/Moccamaster-53941-Select-10-Cup-Polished/dp/B093DYPBYR" target="_blank" rel="nofollow" data-dimension112="1acfeb9e-8694-11f1-be07-451ef8a8d123" data-action="Deal Block" data-label="Moccamaster KGBV Select" data-dimension48="Moccamaster KGBV Select" data-dimension25="$239">View Deal</a></p></div><h2 id="you-said-the-moccamaster-scales-easily">You said the Moccamaster "scales easily"</h2><p>I <em>loved</em> receiving this question — because it's so easily fixed! The Moccamaster will scale up. Everything that touches water will scale up. Pretty much all water contains minerals, which create limescale. </p><p>However, this is super easy to deal with.</p><div class="product"><a data-dimension112="14dbad1e-8693-11f1-b8af-21193dcaa8f1" data-action="Deal Block" data-label="Descaler" data-dimension48="Descaler" data-dimension25="$16" href="https://www.amazon.com/Durgol-0298-Universal-Multipurpose-Decalcifier/dp/B076D99C1B" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1000px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="cW8kTnKEQiWWwMVxM5zGUE" name="durgol descaler" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/cW8kTnKEQiWWwMVxM5zGUE.png" mos="" align="middle" fullscreen="" width="1000" height="1000" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>This is the descaler Moccamaster recommends. All you have to do is dilute the solution in water, run a brew cycle, and then flush it out with clean water. It's so straightforward.<a class="view-deal button" href="https://www.amazon.com/Durgol-0298-Universal-Multipurpose-Decalcifier/dp/B076D99C1B" target="_blank" rel="nofollow" data-dimension112="14dbad1e-8693-11f1-b8af-21193dcaa8f1" data-action="Deal Block" data-label="Descaler" data-dimension48="Descaler" data-dimension25="$16">View Deal</a></p></div><p>And there you have it! Super easy. Didn't I tell you?</p><h2 id="you-said-the-moccamaster-is-too-expensive">You said the Moccamaster is "too expensive"</h2><p>I wasn't surprised when I received this question. The Moccamaster <em>is</em> expensive. Personally, I think the <a href="https://www.tomsguide.com/home/coffee-makers/the-moccamaster-is-the-perfect-example-of-buy-it-nice-or-buy-it-twice-i-did-the-coffee-math-vs-bonavita-breville-and-more-so-you-dont-have-to">Moccamaster is the perfect example of "buy it nice or buy it twice"</a>. I would rather spend $370 on the Moccamaster than buy a $100 coffee maker three times — but I know that's not realistic for some people.</p><p>Moccamaster also offers a 5-year warranty and lifetime repairs, which no other coffee machine brand has matched yet. Again, personally, I would invest in the Moccamaster due to this after-purchase benefit — but I know that's not realistic for some people. </p><p>Here are some coffee makers with a lower initial cost. </p><div class="product"><a data-dimension112="fef08884-8693-11f1-a8e4-012ef16156b4" data-action="Deal Block" data-label="12-Cup Coffee Maker" data-dimension48="12-Cup Coffee Maker" data-dimension25="$89" href="https://www.amazon.com/Ninja-12-Cup-Programmable-CE251-Stainless/dp/B07S98411N" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1500px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="bmf4eyPRXLCcbTSHSFkUhE" name="Ninja 12 Cup Coffee maker.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/bmf4eyPRXLCcbTSHSFkUhE.jpg" mos="" align="middle" fullscreen="" width="1500" height="1500" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Ninja-12-Cup-Programmable-CE251-Stainless/dp/B07S98411N" target="_blank" rel="nofollow" data-dimension112="fef08884-8693-11f1-a8e4-012ef16156b4" data-action="Deal Block" data-label="12-Cup Coffee Maker" data-dimension48="12-Cup Coffee Maker" data-dimension25="$89">12-Cup Coffee Maker: $89</a></strong><br>I always recommend this model as a super-cheap Moccamaster alternative. While it's not available in the U.K., therefore I've not been able to personally test it, my U.S.-based colleagues have it in the New York office and <em>love it</em>. This model can make coffee in two styles: "Classic" and "Rich" and has a delayed brew start so you can wake up to fresh coffee every morning. </p><p><strong>Warranty check:</strong> 1 year standard.<a class="view-deal button" href="https://www.amazon.com/Ninja-12-Cup-Programmable-CE251-Stainless/dp/B07S98411N" target="_blank" rel="nofollow" data-dimension112="fef08884-8693-11f1-a8e4-012ef16156b4" data-action="Deal Block" data-label="12-Cup Coffee Maker" data-dimension48="12-Cup Coffee Maker" data-dimension25="$89">View Deal</a></p></div><div class="product"><a data-dimension112="fef088fc-8693-11f1-ae11-93d654b4b3ea" data-action="Deal Block" data-label="5-Cup Coffee Maker" data-dimension48="5-Cup Coffee Maker" data-dimension25="$119" href="https://www.amazon.com/dp/B0DK5B7L6V" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1664px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="4J8VE2KSc7uX8rkWUn5bJH" name="bonavita 5-cup coffee maker" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/4J8VE2KSc7uX8rkWUn5bJH.jpg" mos="" align="middle" fullscreen="" width="1664" height="1664" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>Bonavita makes some majorly affordable coffee makers, and the 5-Cup Coffee Maker is definitely one of them. You'd think a coffee maker this cheap wouldn't be SCA-accredited, but it actually is! As far as I'm aware, this is the cheapest SCA-accredited drip brewer out there. </p><p><strong>Warranty check: </strong>1 year limited.<a class="view-deal button" href="https://www.amazon.com/dp/B0DK5B7L6V" target="_blank" rel="nofollow" data-dimension112="fef088fc-8693-11f1-ae11-93d654b4b3ea" data-action="Deal Block" data-label="5-Cup Coffee Maker" data-dimension48="5-Cup Coffee Maker" data-dimension25="$119">View Deal</a></p></div><p>But Moccamaster also make a cheaper alternative...</p><h2 id="you-said-the-moccamaster-should-make-a-single-pot-version">You said the Moccamaster should make a "single-pot version"</h2><p>This was my favorite question to receive because I have a definitive answer for this: Moccamaster makes the Cup-One, too! I <a href="https://www.tomsguide.com/home/home-appliances/moccamaster-cup-one-review">reviewed the Cup-One</a> last year and loved it. It's exactly the same as the standard Moccamaster KGBV Select — but smaller.</p><div class="product"><a data-dimension112="b74dc9c4-868e-11f1-bee8-ad64bf0f7212" data-action="Deal Block" data-label="Moccamaster Cup-One" data-dimension48="Moccamaster Cup-One" data-dimension25="$250" href="https://www.amazon.com/Technivorm-Moccamaster-69212-Polished-Silver/dp/B014I5OWCO" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="noLEzUB33zqhKEgg2ojgS6" name="moccamaster cup-one deal block" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/noLEzUB33zqhKEgg2ojgS6.jpg" mos="" align="middle" fullscreen="" width="2000" height="2000" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>The Moccamaster Cup-One is the perfect drip brewer for solo households or small households — or if you want fresh coffee every time. You can brew one cup at a time in just a few minutes.<a class="view-deal button" href="https://www.amazon.com/Technivorm-Moccamaster-69212-Polished-Silver/dp/B014I5OWCO" target="_blank" rel="nofollow" data-dimension112="b74dc9c4-868e-11f1-bee8-ad64bf0f7212" data-action="Deal Block" data-label="Moccamaster Cup-One" data-dimension48="Moccamaster Cup-One" data-dimension25="$250">View Deal</a></p></div><p>I recommend the Cup-One to anyone who wants the consistent, stress-free performance of the Moccamaster without being obligated to brew an entire carafe. </p><p>So that brings us to the end! I've answered all the questions you asked me. Any more? Leave them in the comments and I'll get back to you shortly. </p><p>Stay tuned for the next episode of The Coffee Lab. I release a video every Friday on our Instagram, TikTok, and YouTube. </p><figure class="inline-layout"><div style="min-height: 400px;"><fw-embed-feed channel="toms_guide" playlist="ojE0pK" mode="row" player_placement="bottom-right"></fw-embed-feed></div></figure><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h3><ul><li><a href="https://www.tomsguide.com/home/coffee-makers/i-tried-the-new-nespresso-summer-flavors-heres-my-favorite"><strong>I tried the new Nespresso summer flavors — here's my favorite</strong></a></li><li><a href="https://www.tomsguide.com/home/coffee-makers/non-plastic-coffee-makers-are-trending-and-this-low-plastic-ratio-model-is-my-favorite-for-coffee-snobs"><strong>Non-plastic coffee makers are trending — and this low-plastic Ratio model is my favorite for coffee snobs</strong></a></li><li><a href="https://www.tomsguide.com/home/coffee-makers/i-tried-lelits-brand-new-entry-level-espresso-machine-and-i-wish-i-had-usd2-000-so-i-could-buy-it"><strong>I tried Lelit's brand-new 'entry-level' espresso machine — and I wish I had $2,000 so I could buy it</strong></a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
            </channel>
</rss>