<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
     xmlns:content="http://purl.org/rss/1.0/modules/content/"
     xmlns:dc="https://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"
>
    <channel>
                    <atom:link rel="alternate" hreflang="en-AU"
                       href="https://www.tomsguide.com/au/feeds/articletype/feature"
                       type="application/rss+xml"/>
                            <title><![CDATA[ Latest from Tom's Guide AU in Feature ]]></title>
                <link>https://www.tomsguide.com/au/feature</link>
        <description><![CDATA[ All the latest feature content from the Tom's Guide  AU team ]]></description>
                                    <lastBuildDate>Mon, 29 Jun 2026 09:30:00 +0000</lastBuildDate>
                            <language>en</language>
                                <item>
                                                            <title><![CDATA[ I used Gemini’s Study Notebooks to organize my recipes — and it might be the best AI cookbook you’re not using ]]></title>
                                                                                                                                                                                                <link>https://www.tomsguide.com/ai/i-used-geminis-study-notebooks-to-organize-my-recipes-and-it-might-be-the-best-ai-cookbook-youre-not-using</link>
                                                                            <description>
                            <![CDATA[ I experimented with the Gemini Study Notebooks feature to see how it could help me in my bid to organize my recipes — it ended up working better than I thought. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">HnPjrgb2Sg89Maey3KAxEA</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/622HqZAhgzXKHpnMErNk8V-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Mon, 29 Jun 2026 09:30:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[AI]]></category>
                                                                                                                    <dc:creator><![CDATA[ Elton Jones ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/NVtYYXr3tEPUE67jf3HtXM.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ null ]]></dc:description>
                                                                                                                                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/622HqZAhgzXKHpnMErNk8V-1280-80.jpg">
                                                            <media:credit><![CDATA[Getty Images]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Smiling man in a kitchen preparing a vegan meal]]></media:description>                                                            <media:text><![CDATA[Smiling man in a kitchen preparing a vegan meal]]></media:text>
                                <media:title type="plain"><![CDATA[Smiling man in a kitchen preparing a vegan meal]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/622HqZAhgzXKHpnMErNk8V-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>I always have a ton of fun interacting with Google’s NotebookLM, which lets you create extensive research materials with the aid of a prompt, links, uploaded documents, etc but I recently found a brand new use for for it.</p><p>One of Gemini’s latest updates, <a href="https://x.com/google/status/2070188803340353693?s=46" target="_blank">Study Notebooks</a>, is actually being powered by NotebookLM and turns Google’s AI tool into another way for students and curious researchers to create their own educational logbooks. Google made sure to present Gemini’s newest feature as a reliable way to study, as users can upload documents and tell the chatbot to create a curriculum based on them. Being able to turn Gemini into your tutor as you attempt to take its quizzes and master assorted lessons should come in handy for students, young and old.</p><p>In my case, I wanted to take Gemini Study Notebooks for a spin by doing something besides studying. Since my quest for finding the <a href="https://www.tomsguide.com/ai/i-didnt-know-google-labs-could-help-me-find-tasty-new-recipes-until-i-found-food-mood">best dinner recipes</a> never ends, I used this new feature to build a personalized, interactive cookbook.</p><p>And to my surprise, Gemini’s Study Notebooks is also a pretty efficient kitchen manager.</p><h2 id="organizing-my-recipes-was-a-breeze">Organizing my recipes was a breeze</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="YUYJLKQguqR5wfDrUGUtgU" name="Gemini-AI-shutterstock_2403254291" alt="Gemini logo on a phone" src="https://cdn.mos.cms.futurecdn.net/YUYJLKQguqR5wfDrUGUtgU.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>Creating a new Study Notebook in Gemini is as simple as opening the sidebar on the left side of the screen, scrolling over to “Notebooks” and selecting “New Notebook.”</p><p>I decided to title my new notebook “International Recipe Prep Planning,” which would serve as my newest method for developing a digital cookbook. Instead of attaching documents with all the pertinent information for this subject, I found two links that highlighted a long list of delectable delicacies that included one of two proteins: chicken or steak. </p><p>With this prompt and the two links I discovered, I entered the beginning stages of my new digital cookbook: "Review all the recipes from the two links I have included. Create a comprehensive table categorizing them. Include columns for: Recipe Name, Primary Protein, Estimated Total Time, Cuisine Type, and Freezer-Friendly (Yes/No)."</p><p>Gemini responded to my request with the following response: <em>The links you have shared point to Serious Eat collections: one for grilled steak recipes and one for chicken recipes. Below is a comprehensive categorization table based on classic, highly rated Serious Eats recipes typical of these collections (such as J. Kenji López-Alt’s and Gritzer’s staple formulations), broken down by the requested metrics.</em></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="VwVwudNDeyUVcGyEHvjzFA" name="gemini-study-notebooks" alt="gemini study notebooks" src="https://cdn.mos.cms.futurecdn.net/VwVwudNDeyUVcGyEHvjzFA.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>Gemini’s chart proved to be extremely helpful as it helped me prioritize which dishes to cook based on how much time I could set aside for it (those Easy Pan-Seared Chicken Breasts proved to be a nice and easy dinner to whip up after work). </p><p>My first Study Notebook also told me about the non-tasty downfall behind freezing a cooked steak & reheating it and included a video detailing the best ways to cook a steak based on the recipes detailed in the articles I linked.</p><p>From there, I could tell my Study Notebook to give me a step-by-step cooking guide for each dish and ask it to create an optimized workflow that consolidates certain steps into one for multiple recipes. Besides my prompt, Gemini recommended four other prompts that work best with users who want to use the Study Notebooks feature for meal prepping:</p><ul><li><strong>The Ingredient Overlap Finder:</strong> <em>Analyze my uploaded recipes and find the common denominators. Which 5-10 baseline ingredients (like onions, chicken breast, or rice) show up the most often across these documents? This will help me buy in bulk.</em></li><li><strong>The Shelf-Life Scheduler: </strong><em>Based on the food safety guidelines and recipe instructions in my notebook, map out a 5-day eating schedule. Assign the meals that spoil the fastest to Days 1 and 2, and the heartiest/longest-lasting meals to Days 4 and 5.</em></li><li><strong>The Aisle-by-Aisle Grocery List:</strong> <em>Generate a consolidated grocery list for [List the 3-4 recipes you are making]. Group the ingredients strictly by supermarket section (Produce, Meat & Seafood, Dairy, Pantry/Spices) so I can get through the store as quickly as possible. Combine quantities for overlapping ingredients.</em></li><li><em><strong>The Calorie Budgeter:</strong></em><em> My daily calorie goal is [Insert Number]. Using the meals I've uploaded, build a sample full-day meal plan (Breakfast, Lunch, Dinner, and 1 Snack) that gets as close to this goal as possible.</em></li></ul><h2 id="the-takeaway">The takeaway</h2><p>Gemini’s Study Notebooks certainly prove to be a valuable study tool for students and researchers alike. </p><p>But it can also be used to organize your ideas by grouping all your chats on a particular topic into a Study Notebook that cites all of the information contained in your links and uploaded sources. My notebook played the part of a digital cookbook I could refer to whenever I wanted to pursue new recipes and learn everything I possibly could about them before enjoying them for myself.</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/gardening/im-seriously-allergic-to-poison-ivy-this-gemini-feature-helps-me-when-im-weeding" target="_blank">I'm seriously allergic to poison ivy — this Gemini feature helps me when I'm weeding</a></li><li><a href="https://www.tomsguide.com/ai/claude-skills-changed-how-i-work-5-ways-i-use-them-every-day" target="_blank">Claude Skills changed how I work — 5 ways I use them every day</a></li><li><a href="https://www.tomsguide.com/ai/i-used-chatgpt-to-audit-my-subscriptions-these-prompts-helped-me-find-nearly-usd2-000-a-year-in-recurring-charges" target="_blank">I used ChatGPT to audit my subscriptions — these prompts helped me find nearly $2,000 a year in recurring charges</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ This 4-in-1 MagSafe charger cleverly tucks away a hidden secret that powers non-Apple devices ]]></title>
                                                                                                                                                                                                <link>https://www.tomsguide.com/phones/iphones/this-4-in-1-magsafe-charger-cleverly-tucks-away-a-hidden-secret-that-powers-non-apple-devices</link>
                                                                            <description>
                            <![CDATA[ I've been testing the Mophie StealthCharge 4-in-1 Wireless Charge Stand and it's cleverly designed to better charge my iPhone and my other non-Apple gadgets. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">ykG7GBCFZz6fKN6puYdjxX</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/BdRRXULhfp38jXvN6HLdFe-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Mon, 29 Jun 2026 06:00:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[iPhones]]></category>
                                                    <category><![CDATA[Phones]]></category>
                                                                                                <author><![CDATA[ john.velasco@futurenet.com (John Velasco) ]]></author>                    <dc:creator><![CDATA[ John Velasco ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/TSj224oX8d5ERXaDs8pDGd.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ null ]]></dc:description>
                                                                                                                                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/BdRRXULhfp38jXvN6HLdFe-1280-80.jpg">
                                                            <media:credit><![CDATA[John Velasco / Tom&#039;s Guide]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Mophie StealthCharge 4-in-1 Wireless Charge Stand.]]></media:description>                                                            <media:text><![CDATA[Mophie StealthCharge 4-in-1 Wireless Charge Stand.]]></media:text>
                                <media:title type="plain"><![CDATA[Mophie StealthCharge 4-in-1 Wireless Charge Stand.]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/BdRRXULhfp38jXvN6HLdFe-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>If you look around my desk at work, it can sometimes get pretty messy due to the constant rotation of <a href="https://www.tomsguide.com/best-picks/best-magsafe-chargers-for-your-iphone-year">MagSafe chargers</a> I frequently test. While many come and go, there’s been one that has remained a mainstay: the Mophie 3-in-1 Extendable MagSafe Stand.</p><p>I’ve kept it around for good reason, but recently I’ve been putting another model through its paces — one that I’ve ended up keeping by my bedside at home. The Mophie StealthCharge 4-in-1 Wireless Charge Stand is the company's latest addition to its lineup, and it delivers exactly the kind of premium experience you'd expect for the price. In addition to charging all of my favorite Apple devices, it cleverly tucks away a hidden secret that expands its utility.</p><p>After testing it out for the past couple of weeks, I think it's easily one of the best MagSafe chargers around. Here’s why.</p><div class="product"><a data-dimension112="f5d3ce56-a297-47b6-a242-71273088f994" data-action="Deal Block" data-label="Charge your favorite Apple devices wirelessly with this 4-in-1 MagSafe charger from Mophie. It uses StealthCharge technology to ensure your iPhone gets the fastest charge possible, while doing it quietly and keeping it cool during the process. On top of wireless charging pads for the Apple Watch and AirPods, it features a retractable USB-C cable to deliver charges to practically any device." data-dimension48="Charge your favorite Apple devices wirelessly with this 4-in-1 MagSafe charger from Mophie. It uses StealthCharge technology to ensure your iPhone gets the fastest charge possible, while doing it quietly and keeping it cool during the process. On top of wireless charging pads for the Apple Watch and AirPods, it features a retractable USB-C cable to deliver charges to practically any device." data-dimension25="$179.95" href="https://www.mophie.com/collections/wireless-chargers/products/4-in-1-wireless-charge-stand-black" 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="joi6qsyZ9oQpkSaPkPvJe4" name="Mophie StealthCharge 4-in-1 Wireless Charge Stand deal block" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/joi6qsyZ9oQpkSaPkPvJe4.jpg" mos="" align="middle" fullscreen="" width="600" height="600" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>Charge your favorite Apple devices wirelessly with this 4-in-1 MagSafe charger from Mophie. It uses StealthCharge technology to ensure your iPhone gets the fastest charge possible, while doing it quietly and keeping it cool during the process. On top of wireless charging pads for the Apple Watch and AirPods, it features a retractable USB-C cable to deliver charges to practically any device.<a class="view-deal button" href="https://www.mophie.com/collections/wireless-chargers/products/4-in-1-wireless-charge-stand-black" target="_blank" rel="nofollow" data-dimension112="f5d3ce56-a297-47b6-a242-71273088f994" data-action="Deal Block" data-label="Charge your favorite Apple devices wirelessly with this 4-in-1 MagSafe charger from Mophie. It uses StealthCharge technology to ensure your iPhone gets the fastest charge possible, while doing it quietly and keeping it cool during the process. On top of wireless charging pads for the Apple Watch and AirPods, it features a retractable USB-C cable to deliver charges to practically any device." data-dimension48="Charge your favorite Apple devices wirelessly with this 4-in-1 MagSafe charger from Mophie. It uses StealthCharge technology to ensure your iPhone gets the fastest charge possible, while doing it quietly and keeping it cool during the process. On top of wireless charging pads for the Apple Watch and AirPods, it features a retractable USB-C cable to deliver charges to practically any device." data-dimension25="$179.95">View Deal</a></p></div><h2 id="retractable-cable-adds-to-its-utility">Retractable cable adds to its utility</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.20%;"><img id="wRKxrCFw4eZZWdb4N5e3Ge" name="Mophie StealthCharge 4-in-1 Wireless Charge Stand" alt="Mophie StealthCharge 4-in-1 Wireless Charge Stand." src="https://cdn.mos.cms.futurecdn.net/wRKxrCFw4eZZWdb4N5e3Ge.jpg" mos="" align="middle" fullscreen="" width="2000" height="1124" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: John Velasco / Tom's Guide)</span></figcaption></figure><p>Pretty much all the 3-in-1 MagSafe chargers I test do the same thing: provide wireless charging pads for an iPhone, Apple Watch, and AirPods. What separates this Mophie charger from the rest is how it cleverly tucks away a retractable USB-C cord, letting me conveniently power up other devices.</p><p>I personally love this addition. Since I frequently test many of the <a href="https://www.tomsguide.com/best-picks/best-phones">best phones</a> on the market, I often run into devices that lack a magnetic connection for wireless charging. That’s why this retractable cord is so clutch because I can instantly plug in just about anything, then give it a quick tug to retract the cable back into its housing.</p><p>Best of all, the USB-C connection delivers a 60W charging speed — which is more than enough to power a MacBook Air.</p><h2 id="barely-any-heat-buildup">Barely any heat buildup</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.20%;"><img id="RCiKKqtoj22a9yu8bSxsGe" name="Mophie StealthCharge 4-in-1 Wireless Charge Stand" alt="Mophie StealthCharge 4-in-1 Wireless Charge Stand." src="https://cdn.mos.cms.futurecdn.net/RCiKKqtoj22a9yu8bSxsGe.jpg" mos="" align="middle" fullscreen="" width="2000" height="1124" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: John Velasco / Tom's Guide)</span></figcaption></figure><p>Another impressive characteristic is how quiet this charger remains while actively juicing up my <a href="https://www.tomsguide.com/phones/iphones/apple-iphone-17-pro-review">iPhone 17 Pro</a>. Other MagSafe chargers I’ve tested can sound like jet engines once their internal cooling fans kick in. This one avoids that entirely thanks to an intelligent design that moves the primary charging components down into the base, as opposed to stacking them directly behind the phone.</p><p>As a result, Mophie's design doesn’t just make it whisper-quiet — it also dissipates heat away from the device to maintain peak charging performance. In the long run, keeping temperatures low ensures better battery health and extends the lifespan of my iPhone. Honestly, it’s a massive relief to know the charger can tap into those top-tier 25W MagSafe speeds without making a peep while I’m trying to fall asleep at night.</p><h2 id="quality-construction">Quality construction</h2><figure role="gallery"><figure><img src="https://cdn.mos.cms.futurecdn.net/Um8i4xfhZCkSsk6oPW7EFe.jpg" alt="Mophie StealthCharge 4-in-1 Wireless Charge Stand." /><figcaption><small role="credit">John Velasco / Tom's Guide</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/TDD7aoCuVhGx8ixgBMAUGe.jpg" alt="Mophie StealthCharge 4-in-1 Wireless Charge Stand." /><figcaption><small role="credit">John Velasco / Tom's Guide</small></figcaption></figure></figure><p>Yes, the Mophie StealthCharge 4-in-1 Wireless Charge Stand commands a premium—but it proves that quality is worth paying for. The justification for that high price tag becomes apparent the moment you pick it up. It feels dense and sturdy, a deliberate design choice that keeps the stand firmly grounded on your desk while exuding a high-end aesthetic.</p><p>You won’t find cheap plastic or flimsy joints here. Everything about its construction feels built to last, which is an attribute people often overlook when they are drawn to bargain-bin alternatives on Amazon. There’s a reason Apple showcases and sells Mophie products in its retail stores: the brand consistently prioritizes quality over quantity, and that craftsmanship is exactly why this charger is worth every penny.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-Odk8ZW"></div>                            </div>                            <script src="https://kwizly.com/embed/Odk8ZW.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/phones/motorola-phones/motorola-razr-ultra-2026-review">Motorola Razr Ultra 2026 review: Better does come at a premium price</a></li><li><a href="https://www.tomsguide.com/phones/simo-solis-lite-hotspot-review">I tested this puck shaped mobile hotspot — and it’s the simplest way to get online</a></li><li><a href="https://www.tomsguide.com/phones/best-early-prime-day-2026-phone-accessories-deals-magsafe-wallets-power-banks-chargers-and-more">I tested 100+ phone accessories in the last year and these are my favorite early Prime Day deals — MagSafe wallets, power banks, chargers, and more</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ After 60, this is the 10-minute routine I use with my clients to stay strong, mobile and independent ]]></title>
                                                                                                                                                                                                <link>https://www.tomsguide.com/wellness/workouts/after-60-this-is-the-10-minute-routine-i-use-with-my-clients-to-stay-strong-mobile-and-independent</link>
                                                                            <description>
                            <![CDATA[ These five moves can help you build strong, mobile joints and muscles as you get older, and they avoid high-impact movement. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">wsgZgXWCszaqHeVoNy63uK</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/xuqf4mhcJ9vXHhUiauNBWe-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Mon, 29 Jun 2026 05:00:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Workouts]]></category>
                                                    <category><![CDATA[Fitness]]></category>
                                                    <category><![CDATA[Wellness]]></category>
                                                                                                <author><![CDATA[ sam.hopes@futurenet.com (Sam Hopes) ]]></author>                    <dc:creator><![CDATA[ Sam Hopes ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/jZ88qJqvjWaCXXv3qvUQPA.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Sam Hopes is a level 3 qualified trainer, a level 2 Reiki practitioner and a fitness editor at Tom&#039;s Guide. She is also currently undertaking her Yoga For Athletes training course. Sam has written for various fitness brands and websites over the years and has experience across brands at Future, such as &lt;a href=&quot;https://www.livescience.com/author/sam-hopes&quot;&gt;Live Science&lt;/a&gt;,&lt;a href=&quot;https://www.fitandwell.com/author/sam-hopes&quot;&gt; Fit&amp;amp;Well&lt;/a&gt;,&lt;a href=&quot;https://www.coachweb.com/author/sam-hopes&quot;&gt; Coach&lt;/a&gt;, and T3. &lt;/p&gt;&lt;p&gt;Having worked with fitness studios like F45 and Virgin Active and trained both group and 1:1, Sam now primarily teaches outdoor bootcamps, bodyweight, and kettlebells. She also coaches mobility and flexibility classes several times a week and believes that true strength comes from a holistic approach to training your body. &lt;/p&gt;&lt;p&gt;Sam has completed two mixed doubles Hyrox competitions in London and the Netherlands and finished her first doubles attempt in 1:11.&lt;/p&gt;&lt;p&gt;In her spare time, she enjoys CrossFit, hot yoga, Pilates and running and can be found perfecting her handstand walks and handstand push-ups in the gym whenever she has the chance to be upside down. At work, she can be found testing the latest in fitness technology and wearables, anything yoga and CrossFit-related and has a keen interest in nutrition, mindfulness, sleep and recovery.&lt;/p&gt; ]]></dc:description>
                                                                                                                                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/xuqf4mhcJ9vXHhUiauNBWe-1280-80.jpg">
                                                            <media:credit><![CDATA[Shutterstock]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Image left, writer Sam posing in mirror in workout gear, image right, older female performing bridge pose on yoga mat during exercise]]></media:description>                                                            <media:text><![CDATA[Image left, writer Sam posing in mirror in workout gear, image right, older female performing bridge pose on yoga mat during exercise]]></media:text>
                                <media:title type="plain"><![CDATA[Image left, writer Sam posing in mirror in workout gear, image right, older female performing bridge pose on yoga mat during exercise]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/xuqf4mhcJ9vXHhUiauNBWe-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>The best exercises for strength and mobility aren't ones that look fancy on social media; the ones I love are simple, repeatable and scaleable, which means they're effective and can be performed at any age.</p><p>These five combo moves only require one of the<a href="https://www.tomsguide.com/best-picks/best-yoga-mats"> best yoga mats</a>, and, if you want to add one, a dumbbell. </p><p>I train clients of all ages, and I'm seeing a real uplift in people over 50 taking far more notice of mobility training, longevity practices and anti-aging routines. It's about steering away from what might take off on TikTok and focusing on <a href="https://www.tomsguide.com/features/what-is-functional-training">functional fitness</a> instead.</p><p>While stretching can give you some flexibility benefits and feel good short-term, I strongly recommend looking at your mobility as you get older, using a range of movement and strengthening exercises, as this will help keep your joints and muscles robust to withstand muscle atrophy, bone density loss, or injury.</p><p>I'm sharing my go-to exercises below, plus some benefits you can expect.</p><p><em>If you experience pain at any time, stop and rest. If you're working with an injury or health condition, I recommend seeking advice before starting these exercises.</em></p><h3 class="article-body__section" id="section-watch-10-minute-mobility-routine"><span>Watch: 10-minute mobility routine</span></h3><p><strong>The routine:</strong> Perform each exercise for<strong> 60 seconds</strong>, take a brief rest, then repeat for a <strong>second round</strong>.</p><div class="instagram-embed"><blockquote class="instagram-media"  data-instgrm-version="6" style="width:99.375%; width:-webkit-calc(100% - 2px); width:calc(100% - 2px);"><p><a href="https://www.instagram.com/p/DaA17OMKRJF/" target="_blank">A post shared by Tom's Guide Fitness (@tomsguidefitness)</a></p><p>A photo posted by  on </p></blockquote></div><h3 class="article-body__section" id="section-what-are-the-benefits"><span>What are the benefits?</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:2121px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="pmJdiWCB6Bj3CZcWGbsX2Q" name="GettyImages-841336384 (1)" alt="a senior woman doing a stretch" src="https://cdn.mos.cms.futurecdn.net/pmJdiWCB6Bj3CZcWGbsX2Q.jpg" mos="" align="middle" fullscreen="" width="2121" height="1193" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Getty Images/Silke Woweries)</span></figcaption></figure><p>Each of these exercises focuses on a different benefit, so let's break it down briefly, move-by-move. </p><div><blockquote><p>Each of these exercises focuses on a different benefit.</p></blockquote></div><p><strong>Shoulder raises: </strong>Using a light dumbbell, begin in a seated or kneeling position with your arm by your side. Start by arcing the dumbbell in a sweeping position to an overhead position, moving laterally. Then, lower the dumbbell in front of you until it almost reaches your thigh. Repeat in reverse by raising the dumbbell overhead in front of you, then lowering it to the side. </p><p>This primarily works the lateral and frontal heads of the shoulders (your deltoids). You'll also recruit your core muscles to stabilize your torso as you move, plus recruitment of the upper back and chest. For a more strength-focused exercise, you would lift heavier weights closer to failure, but this is a mobility exercise, so lift lighter and focus on maximizing your range of motion.</p><p><strong>Bear squat x downward dog combo</strong>: This short "flow" combines two reps of a bear squat, two forward leans, then two downward dogs. It's great for mobilizing your wrists and ankles and works the quads hard in the kneeling position, then stretching the back of the body in the downward dog position, including your lower back and hamstrings. </p><p>Start in a tabletop position; it's important to stack your shoulders directly over your wrists with your hips over your knees. Tuck your toes, squeeze your core and lift your knees to hover just above the mat. Moving horizontally, sit your hips back, return to center (twice), then do the same moving forward over your wrists (twice). From here, lift your hips up and back into downward dog (you guessed it, twice). </p><ul><li><em><strong>Follow </strong></em><a href="https://www.instagram.com/tomsguidefitness/" target="_blank"><em><strong>Tom's Guide fitness</strong></em></a><em><strong> on Instagram for more workouts, routines, tips, and tricks.</strong></em></li></ul><p><strong>Reverse tabletop sweeps</strong>: It doesn't look like much, but your hips and spine will love you for this move, as you stretch out your entire body and help gently mobilize the spine. If you have a back or shoulder injury, check with a qualified expert before trying this move.</p><p>Start seated with your knees bent and feet planted. Place your left hand just behind your left hip. Press your hips upward toward the ceiling as you sweep your right hand up and back behind you, coming into a backbend. Squeeze your glutes to protect your back. Lower your hips to the ground and repeat on the other side.</p><p><strong>Spinal rolls with wide seat</strong>: Again, your spine will love you for this, as a spinal roll provides a gentle massage along your back; by engaging your core, you can also control the momentum of the roll, slowing it down to really feel the exercise. The wide seat with reach will stretch the hamstrings and groin and you might also feel this along your mid to upper back.</p><p>Start on your back and perform some rock and rolls up and down your spine with your hands lightly placed behind your head and your legs extended. See if you can lift your legs up and behind you as you roll back, then, as you roll forward, come to a seated position with your legs wide. Reach forward with your hands, then roll back again. </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:8192px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="AdgehcXSdbfiyEzUsMrneN" name="shutterstock_2670474609" alt="a woman doing a single leg glute bridge" src="https://cdn.mos.cms.futurecdn.net/AdgehcXSdbfiyEzUsMrneN.jpg" mos="" align="middle" fullscreen="" width="8192" height="4608" 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><strong>Glute bridge with leg lift</strong>: This move combines hip extension with glute activation and is a great strengthening exercise if you'd like to add load. For a mobility focus, simply draw your hips upward until you create a straight line between your shoulders and knees and squeeze your glutes to protect your back. </p><p>Press down through your heels, and move your feet slightly further away from your butt to engage the hamstrings more. From here, lift one leg into the air, then place it down and repeat with the other leg. Raise your hands overhead or keep them by your sides for support. </p><p>As you lift, curl your spine away from the mat, starting from your lower back; do the reverse on the way down.</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/wellness/workouts/i-teach-people-how-to-be-more-mobile-3-low-impact-back-and-shoulder-moves-that-build-stability-and-strength-after-40" target="_blank">I teach people how to be more mobile: 3 low-impact back and shoulder moves that build stability and strength after 40</a></li><li><a href="https://www.tomsguide.com/wellness/workouts/im-a-personal-trainer-who-works-with-clients-aged-65-daily-here-are-the-2-exercises-i-always-recommend-when-it-comes-to-building-mobility-and-balance" target="_blank">I’m a personal trainer who works with clients aged 65+ daily. Here are the 2 exercises I always recommend when it comes to building mobility and balance</a></li><li><a href="https://www.tomsguide.com/wellness/fitness/sit-all-day-try-these-7-back-exercises-from-a-physical-therapist-right-now" target="_blank">Sit all day? Try these 7 back exercises from a physical therapist right now</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ I use AI every day — then I realized it might be giving me 'popcorn brain' ]]></title>
                                                                                                                                                                                                <link>https://www.tomsguide.com/ai/i-use-ai-every-day-then-i-realized-it-might-be-giving-me-popcorn-brain</link>
                                                                            <description>
                            <![CDATA[ I use AI every day, but it made me wonder if instant answers are changing the way I focus. Here's what experts say about AI and "popcorn brain." ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">aTzn5SPmKKyU2q5A5Lo5tN</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/4GStH4RXy3T4CsHsPodVmL-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Mon, 29 Jun 2026 04:30:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[AI]]></category>
                                                                                                <author><![CDATA[ amanda.caswell@futurenet.com (Amanda Caswell) ]]></author>                    <dc:creator><![CDATA[ Amanda Caswell ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/zYjevim2q7FjQiefqpjZRB.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ null ]]></dc:description>
                                                                                                                                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/4GStH4RXy3T4CsHsPodVmL-1280-80.jpg">
                                                            <media:credit><![CDATA[Shutterstock/Andrus Ciprian]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[A brain]]></media:description>                                                            <media:text><![CDATA[A brain]]></media:text>
                                <media:title type="plain"><![CDATA[A brain]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/4GStH4RXy3T4CsHsPodVmL-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>AI has significantly enhanced my productivity, helped me stay more organized and even shifted my mindset in a positive way, but I recently noticed something I didn't expect. <br><br>After stacking tools and programming AI agents, I noticed my attention span was hungry for faster, more immediate answers. Even when chatting with humans, I wanted them to hurry up and get to the point. I knew this wasn't just my <a href="https://www.tomsguide.com/ai/top-7-ways-ai-can-help-manage-your-adhd">ADHD</a> talking, it was something bigger. <a href="https://www.tomsguide.com/ai/i-use-ai-all-day-for-work-then-it-started-showing-up-in-my-dreams">AI has affected my dreams</a>, I wondered if it was doing something to my brain, too. Naturally, I looked into it. </p><p>Turns out, psychologists have a nickname for that feeling: "popcorn brain."</p><h2 id="what-is-popcorn-brain">What is popcorn brain? </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="jVwWk36HncGzSZ8AMwkgHQ" name="Doomscrolling" alt="A woman lays ion her back n bed with her smartphone held in front of her face with two hands" src="https://cdn.mos.cms.futurecdn.net/jVwWk36HncGzSZ8AMwkgHQ.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: Getty Images)</span></figcaption></figure><p>The term "popcorn brain" was coined by <a href="https://ischool.uw.edu/news/2016/12/too-much-screen-time-could-lead-popcorn-brain" target="_blank">David Levy in 2011</a> a computer scientist and researcher at the University of Washington Information School. Levy used it to describe a mind that becomes "so hooked on electronic multitasking that the slower-paced life offline holds no interest."</p><p>It's quickly become shorthand for a growing phenomenon many people recognize when the brain becomes so accustomed to constant stimulation that slower activities like reading a book, focusing on a project or simply sitting quietly, start to feel uncomfortable.</p><p>For years, social media has received most of the blame. Now AI may be introducing a new version of the same problem.</p><h2 id="why-ai-feels-different">Why AI feels different </h2><p>Unlike social media, AI doesn't just feed you content, it actually creates what you ask it for — in seconds. From summaries to ideas, every question gets an answer immediately with minimal waiting or effort. </p><p>That convenience is one of AI's greatest strengths, but some researchers think removing too much friction may come with trade-offs. Because we already know that <a href="https://www.universityofcalifornia.edu/news/cant-pay-attention-youre-not-alone" target="_blank">constant interruptions and digital multitasking make sustained attention more difficult.</a></p><p>Researchers also study something called <a href="https://pubmed.ncbi.nlm.nih.gov/27542527/" target="_blank"><strong>cognitive offloading</strong></a> a word for our tendency to rely on technology to remember information, organize tasks or solve problems.</p><p>That isn't always a bad thing. For instance, GPS offloads navigation, calculators offload arithmetic and AI assistants like <a href="https://www.tomsguide.com/ai/ive-been-using-alexa-for-3-months-here-are-my-5-favorite-features-and-one-im-not-a-fan-of">Alexa+</a> help us offload memory. Generative AI simply extends that idea much further by offloading writing, planning, brainstorming and research.</p><p>But what we don't realy know yet is whether relying on AI for increasingly complex thinking changes the way we learn and concentrate over time. So far, there isn't strong evidence that ChatGPT or other AI tools truly cause "popcorn brain." But researchers are beginning to investigate how constant AI assistance may influence attention, memory, and problem-solving habits.</p><h2 id="five-ways-i-use-ai-without-sacrificing-my-attention">Five ways I use AI without sacrificing my attention </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:1000px;"><p class="vanilla-image-block" style="padding-top:66.70%;"><img id="6KXS4iqE4rw2D8SCHP62JF" name="Woman-Using-Laptop.jpg" alt="Woman using smartphone and laptop" src="https://cdn.mos.cms.futurecdn.net/6KXS4iqE4rw2D8SCHP62JF.jpg" mos="" align="middle" fullscreen="" width="1000" height="667" 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>The same technology that can tempt us with instant answers can also help us focus. I've used ChatGPT to break overwhelming projects into manageable steps,  organize scattered research, reduce decision fatigue, create outlines and to simply plan an otherwise overwhleming day. In those moments, AI actually reduces the mental clutter that makes concentrating difficult.</p><p>If you're worried AI is shortening your attention span, try these habits.</p><ul><li><strong>Ask AI to teach instead of simply answering. </strong>Instead of requesting the finished solution, ask it to walk you through the reasoning.</li><li><strong>Read the original source. </strong>Use AI as a starting point, not the final destination.</li><li><strong>Schedule AI-free work sessions. </strong>Spend part of your day writing, reading, or thinking without asking AI for help.</li><li><strong>Use AI after you've tried first. </strong>Attempt the problem yourself before asking for assistance.</li><li><strong>Let AI remove busywork — not thinking. </strong>Automating repetitive tasks is very different from outsourcing your curiosity.</li></ul><h2 id="final-thoughts">Final thoughts</h2><p>AI is making knowledge more accessible than ever before, which is an incredible achievement. But the easier it becomes to get answers, the more valuable our ability to wrestle with difficult questions becomes. We shouldn't sacrifice our own critical thinking skills. </p><p>For me, that means using AI as a thinking partner. Let me know how you use AI while maintaining your own crticial thinking skills. Share your thoughts in the comments. </p><a href="https://follow.it/articles-by-amanda-caswell-tom-s-guide?leanpub" class="button button--large button--primary">Follow Amanda Caswell and stay ahead of the AI curve</a><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/ai/i-turned-youtube-into-an-ai-bootcamp-with-notebooklm-heres-my-workflow"><strong>I turned my YouTube watchlist into an AI bootcamp with NotebookLM — here's how</strong></a></li><li><a href="https://www.tomsguide.com/ai/i-built-five-chatgpt-agents-then-replaced-them-with-one-master-ai"><strong>I built five ChatGPT agents — then replaced them with one 'master' AI</strong></a></li><li><a href="https://www.tomsguide.com/ai/i-used-chatgpt-to-audit-my-subscriptions-these-prompts-helped-me-find-nearly-usd2-000-a-year-in-recurring-charges"><strong>I used ChatGPT to audit my subscriptions — these prompts helped me find nearly $2,000 a year in recurring charges</strong></a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ 'I’m 47 and stronger and more flexible than ever': This personal trainer shares her quick 20-20-20-20 abs workout to sculpt a strong, stable core ]]></title>
                                                                                                                                                                                                <link>https://www.tomsguide.com/wellness/workouts/im-47-and-stronger-and-more-flexible-than-ever-this-personal-trainer-shares-her-quick-20-20-20-20-abs-workout-to-sculpt-a-strong-stable-core</link>
                                                                            <description>
                            <![CDATA[ This simple, bodyweight core workout blasts your abs. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">BpWcPyKNazNCj24Co5WnLJ</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/PHbd2bJ5GTZyRZWqtXbtTg-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Sun, 28 Jun 2026 10:30:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Workouts]]></category>
                                                    <category><![CDATA[Wellness]]></category>
                                                    <category><![CDATA[Fitness]]></category>
                                                                                                <author><![CDATA[ jane.mcguire@futurenet.com (Jane McGuire) ]]></author>                    <dc:creator><![CDATA[ Jane McGuire ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/vV4Uj3e5TZvBqmmsjT2EU6.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Jane McGuire is Tom&#039;s Guide&#039;s Fitness Managing Editor, which means she looks after everything fitness-related — from running gear and fitness trackers to yoga mats and sports bras. An avid runner, Jane has tested and reviewed fitness products for the past five years, so she knows what to look for when finding a good running watch or a pair of shorts with pockets big enough for your smartphone, running gels, and house keys. &lt;/p&gt;&lt;p&gt;Jane has run six marathons — the London Marathon five times, and the Berlin Marathon once -and is still on a quest to tick off all of the marathon majors. Her marathon PR is 3:30, which she ran in the New Balance Supercomp Elite V5&#039;s, but she also spends a lot of time talking about her  ‘joy plan’, where she runs for happiness, not for PR’s. &lt;/p&gt;&lt;p&gt;Previous to Tom’s Guide, Jane worked for Runner’s World, where she co-hosted the Runner’s World podcast. She also presents on a YouTube channel called the Run Testers, alongside other running-mad journalists, where they review the latest shoes, kit, and tech. Her work has also appeared in Coach, Get Sweat Go, and Women’s Health. &lt;/p&gt;&lt;p&gt;When she&#039;s not pounding the pavements, you&#039;ll find Jane striding round the Surrey Hills, taking far too many photos of her spaniel, Toby. &lt;/p&gt; ]]></dc:description>
                                                                                                                                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/PHbd2bJ5GTZyRZWqtXbtTg-1280-80.jpg">
                                                            <media:credit><![CDATA[Shutterstock]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[middle aged woman on yoga mat]]></media:description>                                                            <media:text><![CDATA[middle aged woman on yoga mat]]></media:text>
                                <media:title type="plain"><![CDATA[middle aged woman on yoga mat]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/PHbd2bJ5GTZyRZWqtXbtTg-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>We all know how important it is to build a strong and stable core, but after 45, this becomes less an aesthetic goal and more of a fundamental requirement. Starting in our mid-40s, the human body naturally starts to lose lean muscle mass, and bone density begins to decrease. A strong core is the single most effective way to protect the spine and countermeasure the effects of aging. </p><p>Yet if you’re a complete beginner, or you’re returning to exercise following an extended break, it can be tricky to know where to start. Luckily, you’ve landed in the right place. Below, we’ve shared the workout of 47-year-old personal trainer <a href="https://www.instagram.com/tulumtrainer/?g=5" target="_blank" rel="nofollow">Kate Nolte</a>, who specializes in helping women build strength and mobility. Read on to find out more. </p><p>As a reminder, if you’re currently recovering from a specific injury, this might not be the right workout for you and your body. Always check with a qualified professional before trying something new. </p><h2 id="what-is-the-workout">What is the workout? </h2><p>You won’t need any additional equipment for this workout, just one of the <a href="https://www.tomsguide.com/best-picks/best-yoga-mats">best yoga mats</a> to keep things slightly more comfortable. The sequence is simple — you do 20 reps of each of the four exercises, for two rounds. Take a short break between sets to reset if you need. </p><p><strong>Here are the exercises: </strong></p><ul><li><strong>Reverse curl, 20 reps:</strong> Think about engaging your core and lifting your legs from your midsection, rather than using the momentum from your legs to swing them up towards the ceiling. Keep the move slow and controlled to really feel the benefits in your core.</li><li><strong>Toe touches, 20 reps:</strong> Start with your arms and legs extended away from you on the mat. Using your core, lift your head, neck and shoulders off the floor, keeping your arms extended behind you. At the same time, lift one leg and reach your arms to touch your toe. It doesn’t matter if they don’t actually touch; reach as close as you can.</li><li><strong>Heel taps, 20 reps:</strong> bend both knees and press your feet into your exercise mat. Crunch your head, neck and shoulders off the floor with your arms extended by your sides. Reach your left hand to your left ankle, then your right hand to your right, keeping your torso lifted the entire time.</li><li><strong>Knee tuck extend, 20 reps:</strong> Lift your head, neck and shoulders off the mat, supporting your head with your hands. Lift your knees into tabletop position, keeping a 90-degree bend in your knee. Bring both knees in toward your torso, crunching from your abs, then extend both legs out away from you. Don’t let your head and neck drop down to the mat.</li></ul><div class="instagram-embed"><blockquote class="instagram-media"  data-instgrm-version="6" style="width:99.375%; width:-webkit-calc(100% - 2px); width:calc(100% - 2px);"><p><a href="https://www.instagram.com/p/DX_5vDGDnXf/" target="_blank">A post shared by Kate Nolte | Coach & Trainer (@tulumtrainer)</a></p><p>A photo posted by  on </p></blockquote></div><h2 id="what-are-the-benefits">What are the benefits? </h2><p>This bodyweight circuit blasts all the major muscles in your core, including the deep transverse abdominis muscles, which are responsible for stabilizing and protecting your lower back. </p><p>Strengthening these muscles is essential for your overall balance, but can also halt the onset of age-related lower back pain. Your deep core muscles can absorb the daily impact and stabilize your pelvis, so your spine isn’t strained when you do everyday activities like carrying a heavy bag of groceries or lifting something down from a shelf. </p><p>Talking of functional strength, working on the muscles in your midsection can protect you from injury during everyday activities, helping preserve your functional power, and reducing muscle loss in your core. </p><p>This quick workout can also help boost your mobility and flexibility. When your core muscles atrophy, your bodyweight shifts, which can lead to poor mechanical tracking. Working on your core can help improve your alignment and protect against conditions like osteoarthritis. </p><p>So what are you waiting for? Unroll your exercise mat and give this workout a try. Let us know in the comments how you got on. </p><p><em><strong>Follow </strong></em><a href="https://www.instagram.com/tomsguidefitness/" target="_blank"><em><strong>Tom's Guide fitness</strong></em></a><em><strong> on Instagram for more workouts, routines, tips, and tricks.</strong></em></p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-Xp4dAX"></div>                            </div>                            <script src="https://kwizly.com/embed/Xp4dAX.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/wellness/workouts/i-teach-people-how-to-be-more-mobile-3-low-impact-back-and-shoulder-moves-that-build-stability-and-strength-after-40" target="_blank">I teach people how to be more mobile: 3 low-impact back and shoulder moves that build stability and strength after 40</a></li><li><a href="https://www.tomsguide.com/wellness/workouts/according-to-a-personal-trainer-this-exercise-is-100-times-more-effective-than-crunches-i-tried-it-and-was-humbled" target="_blank">According to a personal trainer, this exercise is 100 times more effective than crunches. I tried it and was humbled</a></li><li><a href="https://www.tomsguide.com/wellness/workouts/i-teach-people-over-50-to-be-mobile-3-low-impact-moves-that-build-more-stability-than-a-30-minute-walk" target="_blank">I teach people over 50 to be mobile: 3 low-impact moves that build more stability than a 30-minute walk</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ Slate's $24,950 electric truck is on track for release this year — here's how it stacks up against the cheapest EVs I've tested ]]></title>
                                                                                                                                                                                                <link>https://www.tomsguide.com/vehicle-tech/evs/slates-usd24-950-electric-truck-is-on-track-for-release-this-year-heres-how-it-stacks-up-against-the-cheapest-evs-ive-tested</link>
                                                                            <description>
                            <![CDATA[ While the $24,950 Blank Slate offers an enticingly low entry point, it does make some compromises. Here's how it stacks up to the cheapest EVs I've tested. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">5LGbTgrrXWdiFB86qzPV6W</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/WzWUfivk82TyGhwFv9YLvN-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Sun, 28 Jun 2026 10:00:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[EVs]]></category>
                                                    <category><![CDATA[Vehicle Tech]]></category>
                                                                                                <author><![CDATA[ john.velasco@futurenet.com (John Velasco) ]]></author>                    <dc:creator><![CDATA[ John Velasco ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/TSj224oX8d5ERXaDs8pDGd.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ null ]]></dc:description>
                                                                                                                                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/WzWUfivk82TyGhwFv9YLvN-1280-80.jpg">
                                                            <media:credit><![CDATA[Slate]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Blank Slate.]]></media:description>                                                            <media:text><![CDATA[Blank Slate.]]></media:text>
                                <media:title type="plain"><![CDATA[Blank Slate.]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/WzWUfivk82TyGhwFv9YLvN-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Over the past few years, the automotive industry has made a lot of promises about making affordable electric vehicles. Through it all, budget-conscious drivers looking for a true entry-level price point have found themselves stranded. But the ending may be in sight, thanks to increased competition.</p><p>When the Jeff Bezos-backed Slate came out of nowhere last year to announce its <a href="https://www.tomsguide.com/vehicle-tech/evs/forget-cybertruck-this-20k-american-made-electric-slate-truck-makes-evs-affordable">$20,000 all-electric truck</a>, it really struck a chord. It has since gone up slightly to a starting price of $24,950, but it's firmly on track for release this year to challenge the status quo of what an EV can cost.</p><p>Honestly, it has a lot to prove because its low price tag on paper comes with compromises. As much as I’m thrilled by the level of customization it offers, I can’t forget that it’s as spartan as they come — it has manual seats and windows, which is an oddity in today’s market. Here’s how Slate’s highly anticipated EV truck stacks up against the most affordable EVs I've tested.</p><h2 id="blank-slate-what-you-need-to-know">Blank Slate: What you need to know</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:1198px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="HhkC8rTiVBrJ47FRhSBvvN" name="Blank Slate" alt="Blank Slate." src="https://cdn.mos.cms.futurecdn.net/HhkC8rTiVBrJ47FRhSBvvN.jpg" mos="" align="middle" fullscreen="" width="1198" height="674" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Slate)</span></figcaption></figure><p>If you go to the company's site and build a model, you’ll find three EV options: the <a href="https://www.slate.auto/en/blank-slate" target="_blank">Blank Slate</a>, Squareback SUV, and Fastback SUV. They all target the entry-level market, but the Blank Slate is the cheapest among them with a starting price of $24,950 — which is what I'm focusing on.</p><p>To keep costs low, it embraces an ultra-minimalist design that cuts standard tech amenities like a touchscreen display, relying instead on the driver's smartphone. Additionally, the cabin is completely bare-bones, featuring manual windows and seats. You also won’t find convenience features I've come to rely on, like adaptive cruise control.</p><p>Mechanically, the truck is built for utility, featuring a rear-wheel-drive motor pushing 181 horsepower and a 65 kWh battery pack that delivers an estimated 205 miles of range. Thankfully, it features an integrated NACS port for broader charging access to Tesla’s Supercharger network.</p><h2 id="chevrolet-bolt-vs-blank-slate">Chevrolet Bolt vs. Blank Slate</h2><figure role="gallery"><figure><img src="https://cdn.mos.cms.futurecdn.net/8a4bTtBHndEakXAZ7sRbNi.jpg" alt="2027 Chevrolet Bolt review." /><figcaption><small role="credit">Tom's Guide / John Velasco</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/pzBT667kQg4R8Ca8wRghai.jpg" alt="2027 Chevrolet Bolt review." /><figcaption><small role="credit">Tom's Guide / John Velasco</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/LaXiH9JthEiqb28jErccci.jpg" alt="2027 Chevrolet Bolt review." /><figcaption><small role="credit">Tom's Guide / John Velasco</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/PQGJUSrJC7nWm5UNCgHUTi.jpg" alt="2027 Chevrolet Bolt review." /><figcaption><small role="credit">Tom's Guide / John Velasco</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/mEvdzHRaeUuioM3dFXF7ci.jpg" alt="2027 Chevrolet Bolt review." /><figcaption><small role="credit">Tom's Guide / John Velasco</small></figcaption></figure></figure><p>The closest vehicle to the Blank Slate in terms of price is none other than the Chevrolet Bolt. This all-electric subcompact crossover SUV is the cheapest EV I’ve tested in the last year, with an as-tested cost of $29,990. While its design is rather boring in my opinion, it certainly beats the Blank Slate with its 210-horsepower performance and vastly superior range.</p><p>Drawing from its own 65 kWh battery pack, the Bolt yields an estimated 262 miles of range, easily beating the Slate's 205-mile estimate by over 50 miles. Even though my actual weeklong average with the Bolt came out to 3.7 mi/kWh, that sustained rate would still eclipse the Blank Slate.</p><p>On top of that, the Bolt at this price point has everything I expect in an EV — like power windows, a large 11.3-inch center touchscreen, sporty seats, ample rear legroom, and adaptive cruise control.</p><p><strong>Read our full review: </strong><a href="https://www.tomsguide.com/vehicle-tech/evs/i-drove-the-chevrolet-bolt-for-a-week-and-this-refreshed-ev-has-an-eye-catching-starting-price"><strong>Chevrolet Bolt</strong></a></p><h2 id="fiat-500e-vs-blank-slate">Fiat 500e vs. Blank Slate</h2><figure role="gallery"><figure><img src="https://cdn.mos.cms.futurecdn.net/GvEX7GYshfFLoDkjQLq6jD.jpg" alt="2025 Fiat 500e" /><figcaption><small role="credit">Future</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/Ngkoho7FhPSCQhwFZQxFwY.jpg" alt="2025 Fiat 500e test drive." /><figcaption><small role="credit">Tom's Guide / John Velasco</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/rDdWqKcRjwbkhc7eP9ZGGZ.jpg" alt="2025 Fiat 500e test drive." /><figcaption><small role="credit">Tom's Guide / John Velasco</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/99DuuHm49ZBeVrtv2SgfFZ.jpg" alt="2025 Fiat 500e test drive." /><figcaption><small role="credit">Tom's Guide / John Velasco</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/6MLwQZsox9Yp2CrEFVPjDZ.jpg" alt="2025 Fiat 500e test drive." /><figcaption><small role="credit">Tom's Guide / John Velasco</small></figcaption></figure></figure><p>Next up is the Fiat 500e with a $35,500 as-tested price. This tiny Italian EV hatchback is a different kind of commuter car; it certainly compromises on usable space compared to the Blank Slate, but it makes up for it by being a more agile option for city drivers.</p><p>It’s noticeably down on power compared to the Slate, with its single electric motor pushing out just 117 horsepower. Obviously, being the smallest EV sold in the U.S. has its limitations — like its 42 kWh battery giving it an estimated range of 149 miles. However, numbers on paper don’t tell the whole story. It proved to be one of the most efficient models I've tested, achieving a real-world average efficiency of 4.28 mi/kWh during my weeklong evaluation.</p><p>The biggest contrast is in the presentation. While the Fiat shares the Slate’s annoying omission of adaptive cruise control and sticks you with manual seats, its cabin doesn't feel like a punishment. You still get a bright 10.3-inch touchscreen with wireless Apple CarPlay and Android Auto, full power windows, and a premium, zippy feel that makes it an absolute breeze to park in tight city spaces.</p><p><strong>Read our full review: </strong><a href="https://www.tomsguide.com/vehicle-tech/evs/i-drove-the-fiat-500e-for-a-week-this-tiny-ev-is-like-a-double-shot-of-espresso"><strong>Fiat 500e</strong></a></p><h2 id="toyota-bz-vs-blank-slate">Toyota bZ vs. Blank Slate</h2><figure role="gallery"><figure><img src="https://cdn.mos.cms.futurecdn.net/NgNTmVX4tc8cx7PNHN6xQQ.jpg" alt="2026 Toyota bZ review." /><figcaption><small role="credit">Tom's Guide / John Velasco</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/eEKnBQq6NKKDmtM9yXf5SQ.jpg" alt="2026 Toyota bZ review." /><figcaption><small role="credit">Tom's Guide / John Velasco</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/5rS5B42487w83rJQc6hJ9Q.jpg" alt="2026 Toyota bZ review." /><figcaption><small role="credit">Tom's Guide / John Velasco</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/AqHFQt2VDowNgou6yjc9HQ.jpg" alt="2026 Toyota bZ review." /><figcaption><small role="credit">Tom's Guide / John Velasco</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/2HJhyQNfnhmUpp8GVQKbWQ.jpg" alt="2026 Toyota bZ review." /><figcaption><small role="credit">Tom's Guide / John Velasco</small></figcaption></figure></figure><p>On the higher end of the affordable spectrum sits the 2026 Toyota bZ. Starting at $37,900, this electric crossover commands a much steeper premium over the Blank Slate, but it’s one of the most improved models I’ve put through its paces.</p><p>The price increases to $40,468 for the exact trim I tested, but its biggest selling point is the astonishing 5.4 mi/kWh efficiency I averaged. In fact, it’s the most efficient EV I’ve ever tested, which would effectively give it a range of 403 miles based on my real-world average. When people talk about range anxiety with EVs, I simply need to point them to the bZ to show how it dispels that fear.</p><p>Inside the cabin, the two vehicles couldn't be further apart. Toyota treats the bZ to a massive, ultra-sharp 14-inch center touchscreen, a spacious interior with plenty of rear legroom, and an exceptionally smooth adaptive cruise control system that excels in stop-and-go highway traffic.</p><p>While the Toyota bZ costs over $15,500 more than the Blank Slate, that steep premium means you're also paying for Toyota's legendary reliability and excellent resale value.</p><p><strong>Read our full review: </strong><a href="https://www.tomsguide.com/vehicle-tech/evs/2026-toyota-bz-review"><strong>Toyota bZ</strong></a></p><h2 id="honorable-mentions">Honorable mentions</h2><figure role="gallery"><figure><img src="https://cdn.mos.cms.futurecdn.net/4pkRpreETLAVatTqCpyUV4.jpg" alt="2026 Nissan Leaf test drive." /><figcaption><small role="credit">Tom's Guide / John Velasco</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/djVqHyGDfsHwhxo2yC8XpN.jpg" alt="2026 Subaru Uncharted review." /><figcaption><small role="credit">Tom's Guide / John Velasco</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/GwGbrPnptEpXDEPJAoNhNG.jpg" alt="2025 Hyundai Kona Electric test drive." /><figcaption><small role="credit">Tom's Guide / John Velasco</small></figcaption></figure></figure><p>If the ultra-minimalist Blank Slate feels too risky, several established automakers offer excellent alternatives that bridge the gap between affordability and daily drivability.</p><p>First up is the <a href="https://www.tomsguide.com/vehicle-tech/evs/2026-nissan-leaf-pros-and-cons">Nissan Leaf</a>, which hits a highly compelling $29,990 base MSRP. That balloons to $41,930 for the top trim I tested, but it comes with premium features like an electronic glass roof, a head-up display, a 10-speaker Bose audio system, an auto-dimming rearview mirror, a power liftgate, heated seats, and more. You could scale back on many of them by choosing the base trim, but you would still get the futuristic design that makes it charming on the road.</p><p>Another standout is the <a href="https://www.tomsguide.com/vehicle-tech/evs/2026-subaru-uncharted-review">Subaru Uncharted</a>, which arrives at a competitive $35,000 price point. That jumps to $43,795 for the sporty GT trim, bringing aggressive, two-tone styling and a dual-motor configuration that pushes a thrilling 338 horsepower. You get a native NACS port for adapter-free Tesla Supercharger access and an exceptionally smooth adaptive cruise control system. When you add in tech-forward conveniences like dual wireless chargers and a digital rearview mirror, it quickly justifies its price premium over the Slate.</p><p>Finally, the <a href="https://www.tomsguide.com/vehicle-tech/evs/2025-hyundai-kona-electric-pros-and-cons">Hyundai Kona Electric</a> remains one of the smartest budget-friendly entries on the market with a starting MSRP of $32,975. This subcompact crossover is an absolute breeze to drive and park, yet its small footprint still offers a decent-sized trunk capable of hauling micro-mobility gear like an e-bike or scooter. The $39,880 N Line trim I tested shattered my expectations by averaging an impressive 4.3 mi/kWh efficiency, effectively extending its real-world range to about 278 miles.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-ORVjGO"></div>                            </div>                            <script src="https://kwizly.com/embed/ORVjGO.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/vehicle-tech/evs/im-not-anxious-that-its-getting-darker-earlier-with-this-thermal-camera-for-my-car-heres-why">I'm not anxious that it's getting darker earlier with this thermal camera for my car — here's why</a></li><li><a href="https://www.tomsguide.com/vehicle-tech/evs/i-borrowed-the-new-nissan-leaf-for-a-day-and-this-affordable-ev-nails-it">I just test drove the new Nissan Leaf — and it's irresistible at under $30,000</a></li><li><a href="https://www.tomsguide.com/vehicle-tech/evs/crabwalking-with-the-gmc-sierra-ev-is-the-weirdest-thing-ive-ever-done-with-a-car-and-its-actually-pretty-useful">CrabWalking with the GMC Sierra EV is the weirdest thing I’ve ever done with a car — and it’s actually pretty useful</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ How to remove oven glass stains without leaving a single scratch using this one natural solution ]]></title>
                                                                                                                                                                                                <link>https://www.tomsguide.com/home/how-to-remove-oven-glass-stains-without-leaving-a-single-scratch-using-this-one-natural-solution</link>
                                                                            <description>
                            <![CDATA[ Stubborn oven stains? Here’s how to clean your glass door safely without damaging it — and spending a fortune on repairs. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">875W7H7Hy7ryAGZJjmgqNL</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/ap6DTyktd9meLjhMaAyjnK-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Sun, 28 Jun 2026 06:30:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Home]]></category>
                                                                                                                    <dc:creator><![CDATA[ Cynthia Lawrence ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/CCuSgQpd5NyZ46CgoF9cva.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ null ]]></dc:description>
                                                                                                                                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/ap6DTyktd9meLjhMaAyjnK-1280-80.jpg">
                                                            <media:credit><![CDATA[Shutterstock]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Grease stains on glass oven door]]></media:description>                                                            <media:text><![CDATA[Grease stains on glass oven door]]></media:text>
                                <media:title type="plain"><![CDATA[Grease stains on glass oven door]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/ap6DTyktd9meLjhMaAyjnK-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>When it comes to household chores, <a href="https://www.tomsguide.com/how-to/how-to-clean-an-oven">cleaning the oven</a> is not usually high up on my list. Truth be told, I can’t remember the last time I deep-cleaned my oven  — not because I’m lazy, but mainly because my trusted <a href="https://www.tomsguide.com/best-picks/best-air-fryers">air fryer</a> has taken over many of its duties. </p><p>That being said, if caked-on grime prevents you from peering through the window, it is definitely time for a serious deep clean. But, how do you remove stubborn glass door stains without scratching the glass?</p><p>Luckily, cleaning your oven glass doesn’t have to be a chore, and there is an easier, natural method (and technique) to prevent scratches. </p><p>All you need are a few kitchen staples that you might already have in your cupboards. Not only are these items non-toxic and safer to use around the home, but they won’t break the bank.</p><p>So if you don’t want to risk damaging your oven glass (and fork out on expensive replacements), here’s how to get your oven glass scratch-free and sparkling.</p><h3 class="article-body__section" id="section-how-to-clean-your-oven-glass-with-baking-soda"><span>How to clean your oven glass with baking soda</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:4025px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="3nbX8XRATVgFK6EALYATdj" name="Dirty oven 2.jpg" alt="Dirty Oven" src="https://cdn.mos.cms.futurecdn.net/3nbX8XRATVgFK6EALYATdj.jpg" mos="" align="middle" fullscreen="" width="4025" height="2264" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="caption-text">Dirty Oven </span><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>Even though I've tried my fair share of store-bought oven cleaners, mixing up a homemade solution is an easy way to do it and save yourself some money.</p><p>First, remove the glass panel from the door (if possible) and place it in the sink to make it easier to clean. If it proves to be tricky removing your oven glass, always ensure the power is turned off before directly cleaning.</p><h2 id="make-a-baking-soda-paste">Make a baking soda paste</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:4025px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="ZdQCTCDDHUebhGLCEHWitC" name="Baking soda 2.jpg" alt="Baking Soda in Oven" src="https://cdn.mos.cms.futurecdn.net/ZdQCTCDDHUebhGLCEHWitC.jpg" mos="" align="middle" fullscreen="" width="4025" height="2264" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="caption-text">Baking Soda in Oven </span><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>I usually just grab a small bowl and combine some baking soda with a splash of water until it thickens into a smooth paste. </p><p>Next, cover your grimy glass with this solution and leave it to sit for a few hours, or overnight for those stubborn, caked-on stains.</p><p>By now, this should have loosened some of the stubborn dirt and stains — saving you the elbow grease.</p><p>In fact, there are so many <a href="https://www.tomsguide.com/news/10-things-you-didnt-know-you-could-clean-with-baking-soda">things you didn't know you could clean with baking soda</a>. From getting rid of stains, deodorizing bad odors and unblocking drains, to even washing fruit and vegetables. </p><h2 id="spray-glass-with-white-vinegar">Spray glass with white vinegar</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:2982px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="dJveWqraSpjWNvU9N8beC3" name="shutterstock_1786912571" alt="Cleaning oven glass door" src="https://cdn.mos.cms.futurecdn.net/dJveWqraSpjWNvU9N8beC3.jpg" mos="" align="middle" fullscreen="" width="2982" height="1677" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="caption-text">Cleaning oven glass door </span><span class="credit" itemprop="copyrightHolder">(Image credit: Shutterstock)</span></figcaption></figure><p>Next, spray some white vinegar over the glass inside the sink and the main oven until that baking soda mixture starts to fizz and foam up.</p><p>Using a scratch-free sponge, wipe away any food debris, excess grease, and grime. Repeat this until the glass is completely grime-free, and rinse with warm soapy water. Rinse again with cold water before buffing with a dry microfiber cloth. </p><p>Just be sure to avoid rough, abrasive scouring pads, which can leave permanent scratches all over the glass. And never (ever) be tempted to use sharp implements, such as a knife, to pry off caked-on food. This is bound to scratch your glass, and the last thing you want is expensive repairs. </p><p>For more top cleaning hacks, check out this <a href="https://www.tomsguide.com/home/home-appliances/this-vinegar-steam-trick-will-rid-your-oven-of-grease-and-grime-heres-how-to-do-it">vinegar steam trick that will rid your oven of grease and grime.</a></p><div class="product"><a data-dimension112="3e548588-ce01-4982-b022-142364ecfaec" data-action="Deal Block" data-label="best electric range" data-dimension48="best electric range" data-dimension25="$1398" href="https://www.ajmadison.com/cgi-bin/ajmadison/WGE745C0FS.html?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:481px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="LWtYrbveBsvriocYxNzGsX" name="Screenshot-2024-09-23-150608edit.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/LWtYrbveBsvriocYxNzGsX.jpg" mos="" align="middle" fullscreen="" width="481" height="481" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>This Whirlpool electric range features as the best appliance with two ovens in our <a href="https://www.tomsguide.com/best-picks/best-electric-ranges" data-dimension112="3e548588-ce01-4982-b022-142364ecfaec" data-action="Deal Block" data-label="best electric range" data-dimension48="best electric range" data-dimension25="$1398">best electric range</a> buying guide. With a combined capacity of 6.7 cubic feet, this convection oven has plenty of space to cook multiple foods at different temperatures. Plus, with 5 burners and Aqua-Lift self-cleaning technology, it's hard to beat.<a class="view-deal button" href="https://www.ajmadison.com/cgi-bin/ajmadison/WGE745C0FS.html?" target="_blank" rel="nofollow" data-dimension112="3e548588-ce01-4982-b022-142364ecfaec" data-action="Deal Block" data-label="best electric range" data-dimension48="best electric range" data-dimension25="$1398">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/skip-the-baking-soda-and-vinegar-i-used-this-non-toxic-substance-to-clean-through-my-ovens-grime-and-im-speechless">Skip the baking soda and vinegar — I used this non-toxic substance to clean through my oven's grime, and I'm speechless</a></li><li><a href="https://www.tomsguide.com/home/i-cleaned-my-house-using-only-homemade-cleaning-products-for-a-week-heres-what-happened">I cleaned my house using only homemade cleaning products for a week — here's what happened</a></li><li><a href="https://www.tomsguide.com/news/7-things-the-experts-warn-you-to-never-clean-with-white-vinegar">7 things you should never clean with white vinegar</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ I'm a personal trainer who works with clients over 50 — these are the 3 mobility exercises I never skip ]]></title>
                                                                                                                                                                                                <link>https://www.tomsguide.com/wellness/workouts/im-a-personal-trainer-who-works-with-clients-over-50-these-are-the-3-mobility-exercises-i-never-skip</link>
                                                                            <description>
                            <![CDATA[ These three moves are low-impact and help your joints and muscles stay strong and mobile; we teach you how to do them. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">ndboKUaAFfCw6j6iQgq4Tc</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/r9EbytpDFfnu77oFtgdF9E-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Sun, 28 Jun 2026 05:30:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Workouts]]></category>
                                                    <category><![CDATA[Wellness]]></category>
                                                    <category><![CDATA[Fitness]]></category>
                                                                                                <author><![CDATA[ sam.hopes@futurenet.com (Sam Hopes) ]]></author>                    <dc:creator><![CDATA[ Sam Hopes ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/jZ88qJqvjWaCXXv3qvUQPA.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Sam Hopes is a level 3 qualified trainer, a level 2 Reiki practitioner and a fitness editor at Tom&#039;s Guide. She is also currently undertaking her Yoga For Athletes training course. Sam has written for various fitness brands and websites over the years and has experience across brands at Future, such as &lt;a href=&quot;https://www.livescience.com/author/sam-hopes&quot;&gt;Live Science&lt;/a&gt;,&lt;a href=&quot;https://www.fitandwell.com/author/sam-hopes&quot;&gt; Fit&amp;amp;Well&lt;/a&gt;,&lt;a href=&quot;https://www.coachweb.com/author/sam-hopes&quot;&gt; Coach&lt;/a&gt;, and T3. &lt;/p&gt;&lt;p&gt;Having worked with fitness studios like F45 and Virgin Active and trained both group and 1:1, Sam now primarily teaches outdoor bootcamps, bodyweight, and kettlebells. She also coaches mobility and flexibility classes several times a week and believes that true strength comes from a holistic approach to training your body. &lt;/p&gt;&lt;p&gt;Sam has completed two mixed doubles Hyrox competitions in London and the Netherlands and finished her first doubles attempt in 1:11.&lt;/p&gt;&lt;p&gt;In her spare time, she enjoys CrossFit, hot yoga, Pilates and running and can be found perfecting her handstand walks and handstand push-ups in the gym whenever she has the chance to be upside down. At work, she can be found testing the latest in fitness technology and wearables, anything yoga and CrossFit-related and has a keen interest in nutrition, mindfulness, sleep and recovery.&lt;/p&gt; ]]></dc:description>
                                                                                                                                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/r9EbytpDFfnu77oFtgdF9E-1280-80.jpg">
                                                            <media:credit><![CDATA[Shutterstock]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[a senior man in exercise kit]]></media:description>                                                            <media:text><![CDATA[a senior man in exercise kit]]></media:text>
                                <media:title type="plain"><![CDATA[a senior man in exercise kit]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/r9EbytpDFfnu77oFtgdF9E-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>I'd call mobility training my happy place; my bread and butter. It's what makes me really smile because I see it make an enormous difference in people's lives, whether that's because they love exercise and want to continue doing it, or they just want to stay strong, balanced and mobile later in life.</p><p>Mobility is an entity unto itself, and if you don't enjoy it much, the good news is that microdosing your routine can still provide real benefits for strength, control and stability. In other words, even <a href="https://www.tomsguide.com/wellness/fitness/i-tried-exercise-snacking-every-day-for-a-week-here-are-3-ways-it-changed-my-workouts">exercise snacking</a> with 5, 10, or 15-minute routines can still give you results, as long as you're consistent and intentional. </p><p>Think of the three moves below as your anti-aging weapons for helping unstick your hips, lubricate your joints and get you moving more freely. They're low-impact exercises and can be made more beginner-friendly or challenging, and you can work with your bodyweight or with weights. </p><p>Below, I share my ride-and-die three moves I never skip with clients. Here's why.</p><h2 id="watch-3-exercises-you-can-try-for-better-mobility-anywhere">Watch: 3 exercises you can try for better mobility anywhere</h2><iframe src="https://content.jwplatform.com/players/r1tmCV3i.html" id="r1tmCV3i" title="Mobility workout" width="540" height="960" frameborder="0" scrolling="auto" allowfullscreen></iframe><p>Do you know what "mobility" <em>truly</em> means? It sounds age-related, I think, but actually, there's a real focus on longevity, mindful movement, yoga and Pilates right now, which all feed into the mobility world.</p><p>Improving mobility isn't just about being able to put one foot in front of the other without straining something, or getting up off the couch to make a drink, although, yes, that absolutely matters. </p><p>It's about being intentionally dynamic by moving the joints through their range of motion in a variety of patterns, alongside strengthening and loading muscles using resistance. Think strength, control and motion without age-related limitation. A quick example is performing shoulder rolls and similar exercises before an upper-body workout.</p><p>The more you get your body moving throughout the day, the more you train yourself to balance and stabilize; the more you load your bones and muscles to maintain strength rather than atrophying or losing density.</p><p>Your joints, ligaments and fascia (in particular) respond well to low-impact movement, which can be achieved through a challenging yet consistent mobility routine.</p><p><em>If you experience pain at any time, stop and rest. If you're working with an injury or health condition, or you're currently pregnant or postnatal, I recommend seeking advice before starting these exercises.</em></p><p><strong>The routine:</strong> 3-4 sets, 8-10 reps per move. For more of a <a href="https://www.tomsguide.com/wellness/workouts/i-teach-mobility-for-a-living-this-5-move-flow-builds-strength-stability-and-control-all-over">mobility flow</a>, try 60 seconds per move for a few rounds.</p><div class="product"><a data-dimension112="f890e248-fcca-49e3-801c-5c08fe310b31" data-action="Deal Block" data-label="You pay for annual membership rather than an upfront cost at Whoop. There are three price tiers: One is $199/£169 per year, Peak is $239/£229 and Life is $359/£349 per year. This deal gets you Peak for less than the cost of One." data-dimension48="You pay for annual membership rather than an upfront cost at Whoop. There are three price tiers: One is $199/£169 per year, Peak is $239/£229 and Life is $359/£349 per year. This deal gets you Peak for less than the cost of One." data-dimension25="$189" href="https://www.amazon.com/WHOOP-Peak-Membership-Personalized-Healthspan/dp/B0DY2SWV16/" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1080px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="zck7zzY5Lnp2nHEYm9AsDh" name="Whoop deal block" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/zck7zzY5Lnp2nHEYm9AsDh.jpg" mos="" align="middle" fullscreen="" width="1080" height="1080" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>You pay for annual membership rather than an upfront cost at Whoop. There are three price tiers: One is $199/£169 per year, Peak is $239/£229 and Life is $359/£349 per year. This deal gets you Peak for less than the cost of One.<a class="view-deal button" href="https://www.amazon.com/WHOOP-Peak-Membership-Personalized-Healthspan/dp/B0DY2SWV16/" target="_blank" rel="nofollow" data-dimension112="f890e248-fcca-49e3-801c-5c08fe310b31" data-action="Deal Block" data-label="You pay for annual membership rather than an upfront cost at Whoop. There are three price tiers: One is $199/£169 per year, Peak is $239/£229 and Life is $359/£349 per year. This deal gets you Peak for less than the cost of One." data-dimension48="You pay for annual membership rather than an upfront cost at Whoop. There are three price tiers: One is $199/£169 per year, Peak is $239/£229 and Life is $359/£349 per year. This deal gets you Peak for less than the cost of One." data-dimension25="$189">View Deal</a></p></div><ul><li><strong>Overhead squat to block: </strong>Stand with your feet wider than shoulder-width apart with a block positioned on a setting suitable for you (I use high) behind you. Raise your arms into the air, holding a weight if you want to, and engage your core. Sit your hips back and lower into a squat, keeping your feet planted, back straight and chest lifted. Try to avoid letting your arms travel forward. Touch the block with your butt, then drive up through your legs to stand.</li><li><strong>Single-leg hip circles: </strong>In a tabletop position, stack your wrists under your shoulders and knees under your hips. Draw your stomach in and press through your hands to create space. For an extra challenge, place a dumbbell or similar on the right. With control, lift your right leg, keep the knee bent and circle the leg around the dumbbell, changing direction every rep. Remember to switch over to your left side. Aim to keep both hands pressed down; raise your hands onto blocks or come onto your fingertips if needed.</li><li><strong>Leg liftovers:</strong> Sit with your back straight and legs extended wide. You can rest your back against a wall or couch for extra support. Sit tall through your spine and place your hands lightly behind your head, drawing your elbows back. Position a dumbbell or similar to the right of your right leg. Practice lifting your leg up and over the dumbbell in both directions. Remember to switch to the other side. Play with height settings depending on your ability.</li></ul><h2 id="what-are-the-benefits-2">What are the benefits?</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="Q9zMbwtQ5K3A226GF368u3" name="GettyImages-2247267956(1) squat mobility" alt="Three mature women outdoors performing squats on the grass near the ocean at sunset" src="https://cdn.mos.cms.futurecdn.net/Q9zMbwtQ5K3A226GF368u3.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: Getty Images)</span></figcaption></figure><p>I use these moves all the time with clients. Depending on their ability, programs and individual preferences, we mix them up to add weights, bands, or reps and sets, or we might try variations on the above to keep things interesting. </p><p>Here are some benefits:</p><p><strong>Overhead squat to block:</strong> Squatting improves lower-body strength, but your ability to squat low will depend on a mix of thoracic, hip, knee and ankle mobility. This exercise allows you to practice using one of the toughest squat variations (the overhead squat) for engaging the upper body and shoulders. This will test, and hopefully improve, your ability to keep your chest lifted and shoulders back as you sit the hips back and try to reach the block with your butt. </p><p><strong>Single-leg hip circles:</strong> This is one of my favorite exercises to give my dad for his stiff hips. You don't have to use a dumbbell, but having an object to circle will keep you accountable; don't worry how many times you knock it over, as that's part of the fun. Aim to create large circles in both directions, which makes space around the pelvis and warms the muscles and joints of the lower body.</p><p><strong>Leg lift-overs: </strong>These are killer on hip flexors that run along the front of your hips, plus the thighs, core and upper body. Focus on knitting your shoulder blades together and sit tall to help engage your upper back and open your chest. As soon as you start hunching, you're losing form, so be mindful and use a wall for support if needed. Again, the dumbbell is optional but helpful. </p><p>If you have tight hamstrings, I recommend sitting on the edge of a book or yoga brick to help tilt the pelvis and take some pressure off. An extra challenge would include looping a resistance band just above your knees.</p><div><blockquote><p>I use these moves all the time with clients. Depending on their ability, programs and individual preferences, we mix them up to add weights, bands, or reps and sets, or we might try variations on the above to keep things interesting. </p></blockquote></div><p>Before you consider adding weight in the form of kettlebells, dumbbells, or even water bottles, focus on the fullest range of movement you can during every rep. For example, I would never add weight to a squat until my client can reach adequate squat depth; if the squat is the issue, we'd work on form or variations first.</p><p>Control each of these movements and make the most of them, even if that means reducing the sets or reps slightly. And remember, as cheesy as it sounds, mobility really is a journey; you don't notice the progress day to day, but over time, you'll see huge benefits in how your body moves, adapts and responds. So take a moment to assess what did and didn't work, then try again next time.</p><p>As with any exercise routine, find length through your spine and draw your shoulders down away from your ears. Engage your core (here's a <a href="https://www.tomsguide.com/wellness/workouts/stop-doing-100s-of-crunches-why-this-5-minute-bracing-routine-builds-a-stronger-core-than-sit-ups-ever-will">5-minute bracing routine </a>to get you going) and always keep your chest proud.</p><p>Give these a try, and let us know how you get on in the comments.</p><p><em><strong>Follow </strong></em><a href="https://www.instagram.com/tomsguidefitness/" target="_blank"><em><strong>Tom's Guide fitness</strong></em></a><em><strong> on Instagram for more workouts, routines, tips, and tricks.</strong></em></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/wellness/workouts/i-teach-people-how-to-be-more-mobile-3-low-impact-back-and-shoulder-moves-that-build-stability-and-strength-after-40" target="_blank">I teach people how to be more mobile: 3 low-impact back and shoulder moves that build stability and strength after 40</a></li><li><a href="https://www.tomsguide.com/wellness/workouts/according-to-a-personal-trainer-this-exercise-is-100-times-more-effective-than-crunches-i-tried-it-and-was-humbled" target="_blank">According to a personal trainer, this exercise is 100 times more effective than crunches. I tried it and was humbled</a></li><li><a href="https://www.tomsguide.com/wellness/workouts/i-teach-people-over-50-to-be-mobile-3-low-impact-moves-that-build-more-stability-than-a-30-minute-walk" target="_blank">I teach people over 50 to be mobile: 3 low-impact moves that build more stability than a 30-minute walk</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ 5 ChatGPT prompts I use to build a productivity routine that actually sticks ]]></title>
                                                                                                                                                                                                <link>https://www.tomsguide.com/ai/5-chatgpt-prompts-i-use-to-build-a-productivity-routine-that-actually-sticks</link>
                                                                            <description>
                            <![CDATA[ With these five prompts, I can easily build a productivity routine that caters to my personal and professional needs—hopefully, they can do the same for you. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">hhedZNEF4PtyWsd754kWpW</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/vRy3qCuQ4vrM5ScNhqfKHU-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Sun, 28 Jun 2026 05:00:00 +0000</pubDate>                                                                                                                                <updated>Mon, 29 Jun 2026 16:01:29 +0000</updated>
                                                                                                                                            <category><![CDATA[AI]]></category>
                                                                                                                    <dc:creator><![CDATA[ Elton Jones ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/NVtYYXr3tEPUE67jf3HtXM.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ null ]]></dc:description>
                                                                                                                                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/vRy3qCuQ4vrM5ScNhqfKHU-1280-80.jpg">
                                                            <media:credit><![CDATA[djile / Shutterstock]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Young business man working at home with laptop and papers on desk]]></media:description>                                                            <media:text><![CDATA[Young business man working at home with laptop and papers on desk]]></media:text>
                                <media:title type="plain"><![CDATA[Young business man working at home with laptop and papers on desk]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/vRy3qCuQ4vrM5ScNhqfKHU-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>I've tested plenty of prompts that turn ChatGPT into more than just a search engine, but some of the most useful have helped me build better daily routines.</p><p>From creating focused morning workflows to helping me switch off at the end of the day, I've used ChatGPT to design productivity routines that genuinely make me work smarter, not harder. Along the way, I also experimented with prompts specifically designed to generate those routines.</p><p>After testing 10 of them, five became part of my regular workflow. These are the prompts I keep coming back to — and why they're worth trying yourself.</p><h2 id="productivity-prompts-that-work-for-me-and-you">Productivity prompts that work for me and you</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:1540px;"><p class="vanilla-image-block" style="padding-top:56.23%;"><img id="wHnAFp3okiE26PhWAVJNtC" name="ChatGPT Image" alt="ChatGPT Image" src="https://cdn.mos.cms.futurecdn.net/wHnAFp3okiE26PhWAVJNtC.png" mos="" align="middle" fullscreen="" width="1540" height="866" 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>Productivity routines work best when they’re custom-tailored for the following professionals:</p><ul><li><strong>Entrepreneurs</strong></li><li><strong>Freelancers</strong></li><li><strong>Work-From-Home/Hybrid Workers</strong></li><li><strong>Company founders</strong></li><li><strong>Business executives</strong></li><li><strong>Creatives (authors, artists, designers, etc.)</strong></li><li><strong>Athletes/Bodybuilders</strong></li><li><strong>Healthcare Professionals</strong></li></ul><p>In my case, I’ve applied ChatGPT’s productivity routine prompts to my daily schedule as a journalist. The first one in particular, which the chatbot labeled as the “Productivity Architect” prompt, does an amazing job of helping me wade through all the noise and renew my focus on what needs to be done:</p><p><em>Act as a productivity coach and systems designer. Interview me one question at a time to understand: My goals, my work schedule, my energy levels throughout the day, my biggest distractions, my responsibilities, my preferred working style, and my current productivity struggles</em></p><p><em>Once you've gathered enough information, create a personalized daily productivity system that includes: a morning routine, work blocks, a break structure, deep work periods, admin tasks, learning time, and an evening shutdown routine.</em></p><p><em>Then explain why each part of the routine fits my personality and circumstances.</em></p><p>That prompt supplied me with a productive routine that gave me set objectives to focus on every day, such as taking the time to write out all my objectives first thing in the morning, setting aside hour-long blocks to ideate & produce articles, going fully analog during my breaks and summarizing my day in the form of a document once the sun goes down.</p><p>These four other prompts are ready-made for anyone who wants to tell ChatGPT all about themselves and leave with a custom productivity routine that’ll fine-tune your daily process:</p><ul><li><strong>The Energy-Based Productivity Prompt: </strong><em>I want to build my schedule around my energy instead of the clock. Help me identify: when I do my best thinking, when I should do creative work, when I should handle meetings, when I should do routine tasks, and when I should rest. Ask me questions about my daily energy patterns and then build a productivity system optimized around them.</em></li><li><strong>The Anti-Procrastination Routine Builder: </strong><em>Act as a behavioral psychologist and productivity strategist. Ask me questions to identify why I procrastinate. Determine whether my procrastination is caused by: perfectionism, a fear of failure, feeling overwhelmed, a lack of clarity, low energy, or poor planning. Then design a productivity routine specifically engineered to reduce those triggers.</em></li><li><strong>The Blind Spot Finder Prompt: </strong><em>Analyze my current routine and identify: productivity bottlenecks, hidden time drains, inefficient habits, activities with low return on investment, and tasks I should automate, delegate, or eliminate. Ask follow-up questions until you have enough information, then recommend improvements ranked by impact.</em></li><li><strong>The Future Self Prompt: </strong><em>Imagine you are my future self five years from now. You successfully achieved my goals while maintaining good health, relationships, and work-life balance. Interview me about my current life. Then explain: what habits I adopted, what habits I eliminated, what my daily routine looks like, what I was doing wrong today, and what changes created the biggest results.</em></li></ul><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-W3wm8W"></div>                            </div>                            <script src="https://kwizly.com/embed/W3wm8W.js" async></script><h2 id="final-thoughts-2">Final thoughts</h2><p>My constant meetings with ChatGPT have led me to come across the best productivity routines that compel me to work smarter (not harder) to tackle my personal and professional duties. For those of you reading this who are looking to turn the chatbot into your own personal productivity planner and behavior analyst, take one or all of these prompts with you into your next ChatGPT consultation.</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/ai/i-used-chatgpt-to-audit-my-subscriptions-these-prompts-helped-me-find-nearly-usd2-000-a-year-in-recurring-charges" target="_blank">I used ChatGPT to audit my subscriptions — these prompts helped me find nearly $2,000 a year in recurring charges</a></li><li><a href="https://www.tomsguide.com/ai/a-reddit-user-gave-an-ai-agent-6-months-and-usd50-000-to-find-him-a-wife-and-it-reveals-where-ai-is-headed-next" target="_blank">A Reddit user gave an AI agent 6 months and $50,000 to find him a wife — and it reveals where AI is headed next</a></li><li><a href="https://www.tomsguide.com/ai/openai-just-made-its-biggest-move-against-nvidia-and-it-could-make-chatgpt-cheaper-to-run" target="_blank">OpenAI just made its biggest move against Nvidia — and it could make ChatGPT cheaper to run</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ I spent a day with the Trump Phone T1 at a World Cup game — here's what I think about it ]]></title>
                                                                                                                                                                                                <link>https://www.tomsguide.com/phones/i-spent-a-day-with-the-trump-phone-t1-at-a-world-cup-game-heres-what-i-think-about-it</link>
                                                                            <description>
                            <![CDATA[ I got to test the Trump Phone T1 at a World Cup match to see exactly what kind of value this $499 phone offers compared to other phones I've used. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">zgynEQNdE29mLvLXS9jBEo</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/Bza9uzMZHmyHUGzhnvqkiQ-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Sun, 28 Jun 2026 04:30:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Phones]]></category>
                                                                                                <author><![CDATA[ john.velasco@futurenet.com (John Velasco) ]]></author>                    <dc:creator><![CDATA[ John Velasco ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/TSj224oX8d5ERXaDs8pDGd.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ null ]]></dc:description>
                                                                                                                                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/Bza9uzMZHmyHUGzhnvqkiQ-1280-80.jpg">
                                                            <media:credit><![CDATA[John Velasco / Tom&#039;s Guide]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Trump Phone T1 held in the hand.]]></media:description>                                                            <media:text><![CDATA[Trump Phone T1 held in the hand.]]></media:text>
                                <media:title type="plain"><![CDATA[Trump Phone T1 held in the hand.]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/Bza9uzMZHmyHUGzhnvqkiQ-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>After it was put through the <a href="https://www.tomsguide.com/reference/how-toms-guide-tests-and-reviews-smartphones">Tom’s Guide lab testing</a> process, I finally got my hands on the <a href="https://www.tomsguide.com/phones/network-carriers/trump-mobile-launching-with-gold-phone-and-unlimited-data-heres-how-it-stacks-up">Trump Phone T1</a> — a $499 device that “isn't just another smartphone; it's a bold step toward wireless independence.” It’s been a long, <a href="https://www.tomsguide.com/phones/trump-phone-no-longer-claims-to-be-made-in-the-usa-but-it-does-have-an-america-proud-design">weird road for this device</a>, but with a massive World Cup match ahead of me, I figured there was no better way to spend my first 24 hours with it than putting it through its paces.</p><p>Just as a refresher, the Trump Phone T1 is an Android phone sold online that’s designed to run on <a href="https://trumpmobile.com/" target="_blank">Trump Mobile</a>, with plans starting at $47.45 per month. I took the opportunity during the Ecuador vs. Germany World Cup match at MetLife Stadium in New Jersey to see exactly what this device can do. Here’s what I found out.</p><h2 id="it-s-iridescent">It’s iridescent</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.27%;"><img id="j3Nd92AbL5oq3633XnSZZQ" name="Trump Phone T1" alt="Trump Phone T1 held in the hand." src="https://cdn.mos.cms.futurecdn.net/j3Nd92AbL5oq3633XnSZZQ.jpg" mos="" align="middle" fullscreen="" width="3000" height="1688" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: John Velasco / Tom's Guide)</span></figcaption></figure><p>Pulling the T1 out of its box, I’ll admit the design makes an immediate statement that commands attention — and not just because of the inaccurate American flag embossed on the back.</p><p>The back panel is heavily iridescent, shifting and shimmering when it catches the light at the right angle. Say what you will about the branding, but this finish ensures it isn't boring. Fans who I handed it to at the match were instantly amused by the shimmer. If it were anything else, it would be utterly forgettable.</p><h2 id="a-blast-from-the-past">A blast from the past</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:1636px;"><p class="vanilla-image-block" style="padding-top:56.23%;"><img id="7DmjpAVLDKbtFm8gNRpp2Z" name="htc-u24-pro 1-2.jpg" alt="HTC U24 Pro" src="https://cdn.mos.cms.futurecdn.net/7DmjpAVLDKbtFm8gNRpp2Z.jpg" mos="" align="middle" fullscreen="" width="1636" height="920" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: HTC)</span></figcaption></figure><p>By now, you’re probably aware that the Trump Phone T1 is allegedly an <a href="https://www.tomsguide.com/phones/android-phones/htc-looks-to-re-establish-its-smartphone-cred-with-an-ai-powered-camera-phone">HTC U24 Pro</a> in disguise. Even though I haven’t personally used that specific phone, the overall aesthetics indicate that the T1's design is a few generations old.</p><p>It flaunts an AMOLED screen with curved edges hugged by a chamfered metallic trim — an aesthetic that immediately reminds me of the <a href="https://www.tomsguide.com/us/samsung-galaxy-s6-edge,review-2711.html">Galaxy S6 Edge</a> from back in 2015. If that’s not enough to signal its age, another person I handed the phone to even was surprised by the 3.5mm headphone jack.</p><h2 id="generous-512gb-of-storage">Generous 512GB of storage</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.27%;"><img id="j3Nd92AbL5oq3633XnSZZQ" name="Trump Phone T1" alt="Trump Phone T1 held in the hand." src="https://cdn.mos.cms.futurecdn.net/j3Nd92AbL5oq3633XnSZZQ.jpg" mos="" align="middle" fullscreen="" width="3000" height="1688" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: John Velasco / Tom's Guide)</span></figcaption></figure><p>For the price, I think the Trump Phone T1 is overpriced — especially considering it’s packing a dated Snapdragon 7 Gen 3 chipset. However, the big surprise for me while snapping photos and videos at the World Cup match was realizing it comes with 512GB of storage. That’s a huge amount of space for a phone in this tier, meaning I didn't have to rely on cloud storage as much as I normally would.</p><h2 id="security-risk-alert-out-of-the-box">Security risk alert out of the box</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:1510px;"><p class="vanilla-image-block" style="padding-top:56.29%;"><img id="fqdSxtq5bKtMdepjSemCHQ" name="Trump Phone T1" alt="Trump Phone T1 held in the hand." src="https://cdn.mos.cms.futurecdn.net/fqdSxtq5bKtMdepjSemCHQ.jpg" mos="" align="middle" fullscreen="" width="1510" height="850" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: John Velasco / Tom's Guide)</span></figcaption></figure><p>Ironically, one of the first things I encountered upon booting the T1 was a system alert warning that the device was at risk. That’s the last thing anyone wants to see right out of the box, though a quick software update did patch the immediate issue.</p><p>Still, the scare underscores a broader concern regarding software support, which lacks the clear roadmap I see from major manufacturers. The phone ships with Android 15 and that's telling.</p><p>After applying the initial patch that cleared up my security warnings, I couldn't find any additional updates over the air. That leaves a massive question mark over the device's future: who knows if or when it will ever see Android 16, let alone Android 17?</p><h2 id="4k-video-clips-are-shaky">4K video clips are shaky</h2><div class="instagram-embed"><blockquote class="instagram-media"  data-instgrm-version="6" style="width:99.375%; width:-webkit-calc(100% - 2px); width:calc(100% - 2px);"><p><a href="https://www.instagram.com/p/DaDpx1oxfoS/" target="_blank">A post shared by John Velasco (@john_c_velasco)</a></p><p>A photo posted by  on </p></blockquote></div><p>What matters most to me in a smartphone is reliable camera performance. Unfortunately, the Trump Phone T1 didn't win me over after shooting photos and videos at the World Cup match.</p><p>The most glaring issue was just how shaky the footage looked when recording in 4K — a flaw that became even more pronounced when I used the digital zoom. You can watch the video clip above to see what I mean, but when compared to a similar clip I shot on my iPhone 17 Pro, the difference is night and day.</p><figure role="gallery"><figure><img src="https://cdn.mos.cms.futurecdn.net/ywQi5hZryguzp56qs9Chqh.jpg" alt="Trump Phone T1 camera sample." /><figcaption><small role="credit">John Velasco / Tom's Guide</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/z35AUsnuafbBGQLdAbRXoh.jpg" alt="Trump Phone T1 camera sample." /><figcaption><small role="credit">John Velasco / Tom's Guide</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/6ZU29UBFbFbTD7pEzpkkkh.jpg" alt="Trump Phone T1 camera sample." /><figcaption><small role="credit">John Velasco / Tom's Guide</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/BWwTTXZNpP4bNwXcgBzyeh.jpg" alt="Trump Phone T1 camera sample." /><figcaption><small role="credit">John Velasco / Tom's Guide</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/wqd9K7CSCcFQ6qdoVGieNh.jpg" alt="Trump Phone T1 camera sample." /><figcaption><small role="credit">John Velasco / Tom's Guide</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/GAdFEPcFeAo2ieNYjXwhGh.jpg" alt="Trump Phone T1 camera sample." /><figcaption><small role="credit">John Velasco / Tom's Guide</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/7CFZmAtSZU2kTTzBbst8Gh.jpg" alt="Trump Phone T1 camera sample." /><figcaption><small role="credit">John Velasco / Tom's Guide</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/wBaUAnXepUpzWXq33Swoih.jpg" alt="Trump Phone T1 camera sample." /><figcaption><small role="credit">John Velasco / Tom's Guide</small></figcaption></figure></figure><p>It was hard to tell what the quality was like from its cameras, which consist of a 50MP main, 8MP ultrawide, 50MP telephoto, and 50MP selfie. Since the lighting conditions were favorable at the World Cup match, the photos are passable by my standards, but I wouldn't go so far as to say they're outstanding.</p><h2 id="no-cool-wallpapers">No cool wallpapers</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:1510px;"><p class="vanilla-image-block" style="padding-top:56.29%;"><img id="r7B7XcQtQVfCLCrZsDmusf" name="Trump Phone T1 - wallpaper" alt="Trump Phone T1 wallpaper." src="https://cdn.mos.cms.futurecdn.net/r7B7XcQtQVfCLCrZsDmusf.jpg" mos="" align="middle" fullscreen="" width="1510" height="850" 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>At halftime, I was scrolling through the T1 and realized just how generic the default Trump Mobile wallpaper looked on my home screen. Given the branding, I was expecting a few epic wallpapers — perhaps even some stylized, AI-generated options — but that wasn’t the case. You only get one, and the rest are up to you to find.</p><p>Secondly, the phone comes preloaded with two specific apps: Truth Social and Doctegrity. While some buyers might be inclined to use the former, I’m already on way too many social networks and don’t need yet another platform to manage.</p><h2 id="a-better-alternative-for-half-the-price">A better alternative (for half the price) </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="3gS9usqoRDpncCP4UznAQ8" name="NUU B40 5G" alt="NUU B40 5G showing rear screen." src="https://cdn.mos.cms.futurecdn.net/3gS9usqoRDpncCP4UznAQ8.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 / John Velasco)</span></figcaption></figure><p>I can name a handful of other phones worthier of my hard-earned money, but if you’re planning to spend $499 on a smartphone, there’s a much better alternative. The $249 <a href="https://www.tomsguide.com/phones/this-usd249-phone-has-one-feature-that-should-be-standard-on-all-phones">Nuu B40 5G</a> reminds me a lot of the Trump Phone T1, but at half the cost. It even shares nearly the same aesthetics, plus it features a second display on the rear that's incredibly useful for framing selfies and vlogging.</p><p>On top of that, rather than locking yourself into a $47.45 per month rate with Trump Mobile, you can save way more by pairing an unlocked device with carriers like Visible, Mint Mobile, or Total Wireless.</p><p>Flashy looks can only get a phone so far before they begin to fade. There are clearly plenty of reasons why I wouldn’t recommend getting the Trump Phone T1 after spending 24 hours with it, but it really doesn’t help that you're essentially buying two-year-old hardware at this point.</p><p>Unless you're strictly buying this device as a novelty item, your money is far better spent elsewhere. Skip the T1 and opt for a budget contender that prioritizes actual daily performance over branding.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-WnmYqe"></div>                            </div>                            <script src="https://kwizly.com/embed/WnmYqe.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/phones/motorola-phones/motorola-razr-ultra-2026-review">Motorola Razr Ultra 2026 review: Better does come at a premium price</a></li><li><a href="https://www.tomsguide.com/phones/simo-solis-lite-hotspot-review">I tested this puck shaped mobile hotspot — and it’s the simplest way to get online</a></li><li><a href="https://www.tomsguide.com/phones/best-early-prime-day-2026-phone-accessories-deals-magsafe-wallets-power-banks-chargers-and-more">I tested 100+ phone accessories in the last year and these are my favorite early Prime Day deals — MagSafe wallets, power banks, chargers, and more</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ $50 pizza steel vs $500 pizza oven: I did a back-to-back test to see if you really need that pricey Ooni ]]></title>
                                                                                                                                                                                                <link>https://www.tomsguide.com/home/pizza-oven-vs-pizza-steel-i-did-a-back-to-back-test-to-see-if-you-really-need-that-expensive-ooni-or-gozney</link>
                                                                            <description>
                            <![CDATA[ The results were pretty clear. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">4kN43pyoxAaP6TQ6eg9XAa</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/msa9Pd7mXLxGZxxyKeBLGU-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Sat, 27 Jun 2026 10:30:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Home]]></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>
                                                                                                                                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/msa9Pd7mXLxGZxxyKeBLGU-1280-80.jpg">
                                                            <media:credit><![CDATA[Future]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[A split image with the Ooni Karu 2 on the left and a cooked pizza on the right]]></media:description>                                                            <media:text><![CDATA[A split image with the Ooni Karu 2 on the left and a cooked pizza on the right]]></media:text>
                                <media:title type="plain"><![CDATA[A split image with the Ooni Karu 2 on the left and a cooked pizza on the right]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/msa9Pd7mXLxGZxxyKeBLGU-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Ah, the age old question: 'how should I cook my pizza?' It feels like there's an obvious answer, right? And that's 'in a pizza oven.'</p><p>The thing is, pizza ovens are expensive. I'm currently using the <a href="https://www.amazon.com/Ooni-Karu-Multi-Fuel-Outdoor-Pizza/dp/B0DQ8R4TYT" target="_blank" rel="nofollow">Ooni Karu 2, which is Ooni's entry-level outdoor oven, but still costs $449</a>. It's utterly fantastic (as you'll see) but a major outlay of cash.</p><p>So I decided to see if I could get good results with a cheaper alternative. My YouTube Shorts feed is absolutely chocked full of people making pizza in their home ovens using pizza steels. See, while people have been using pizza <strong>stones</strong> in their home ovens for a long time, and stones are employed ubiquitously in actual pizza ovens, it's <strong>steels</strong> that are the 'in' thing right now. That's because steel is preferable when using a conventional home oven: in the lower temperature of your kitchen oven, steel conducts heat much more effectively than stone, for a better cook on the pizza base.</p><p>If my YouTube algorithm is anything to go by, you don't need that fancy Ooni or Gozney pizza oven. You just need a steel. So I ran some back-to-back tests — all in the name of science, of course — to see if my algo was playing tricks on me. Is it worth saving money by just getting a steel instead?</p><h2 id="first-a-couple-of-caveats">First, a couple of caveats</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:4968px;"><p class="vanilla-image-block" style="padding-top:66.67%;"><img id="qfzGSn3A9WB53wtcQrNTtP" name="Pizza steel vs Pizza oven-7" alt="The Ooni Karu 2 stone" src="https://cdn.mos.cms.futurecdn.net/qfzGSn3A9WB53wtcQrNTtP.jpg" mos="" align="middle" fullscreen="" width="4968" height="3312" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="caption-text">The Ooni Karu 16 </span><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>Remember, everyone's kitchen oven is different, so your results may not match mine. I'm also aware that pizza steels were never meant to be a full stand-in for a proper oven. </p><p>This article is primarily intended to show you the pros and cons of both methods as I experienced them, to help you make your mind up as to which you'd rather go for. </p><h2 class="article-body__section" id="section-competitors"><span>Competitors</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:5712px;"><p class="vanilla-image-block" style="padding-top:66.67%;"><img id="nNd6JBVAit2DcMt2fHj5fQ" name="Pizza steel vs Pizza oven-8" alt="The Ooni Karu 2 assembled on a patio and metal table" src="https://cdn.mos.cms.futurecdn.net/nNd6JBVAit2DcMt2fHj5fQ.jpg" mos="" align="middle" fullscreen="1" width="5712" height="3808" attribution="" endorsement="" class="inline expandable"><a href='https://cdn.mos.cms.futurecdn.net/nNd6JBVAit2DcMt2fHj5fQ.jpg' target='_blank' class='expand-button icon-expand-image icon' ></a></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>Alrighty. Let's take a look at our competitors. The pizza oven I'm using is the Ooni Karu 2. This is Ooni's entry-level multi-fuel outdoor oven and very similar to the older Karu 12 — it has a glass door, while the Karu 12 had a metal door. I'm currently testing the Karu 2 for our full review, but spoiler alert: it's fantastic. The Karu 2 can run on wood, charcoal or gas (via an adapter), making it extremely versatile.</p><div class="product"><a data-dimension112="d28c4803-c47b-4213-9d16-e7b5863f8620" data-action="Deal Block" data-label="The Ooni Karu 2 is the brand's entry-level pizza oven and costs $449 MSRP. It runs on multiple fuels: wood, charcoal or gas (via an adapter)." data-dimension48="The Ooni Karu 2 is the brand's entry-level pizza oven and costs $449 MSRP. It runs on multiple fuels: wood, charcoal or gas (via an adapter)." data-dimension25="$449" href="https://www.amazon.com/Ooni-Karu-Multi-Fuel-Outdoor-Pizza/dp/B0DQ8R4TYT" 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="ZWXfKDKexA6grx2C7HXLoN" name="Ooni Karu 2" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/ZWXfKDKexA6grx2C7HXLoN.jpg" mos="" align="middle" fullscreen="" width="1400" height="1400" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>The Ooni Karu 2 is the brand's entry-level pizza oven and costs $449 MSRP. It runs on multiple fuels: wood, charcoal or gas (via an adapter).<a class="view-deal button" href="https://www.amazon.com/Ooni-Karu-Multi-Fuel-Outdoor-Pizza/dp/B0DQ8R4TYT" target="_blank" rel="nofollow" data-dimension112="d28c4803-c47b-4213-9d16-e7b5863f8620" data-action="Deal Block" data-label="The Ooni Karu 2 is the brand's entry-level pizza oven and costs $449 MSRP. It runs on multiple fuels: wood, charcoal or gas (via an adapter)." data-dimension48="The Ooni Karu 2 is the brand's entry-level pizza oven and costs $449 MSRP. It runs on multiple fuels: wood, charcoal or gas (via an adapter)." data-dimension25="$449">View Deal</a></p></div><div class="product"><a data-dimension112="b1c62498-565a-4b93-b4f0-3a480f4daeca" data-action="Deal Block" data-label="In the U.K., where I live, the Ooni Karu 2 costs £349 RRP, so it's still a fairly substantial investment if you're just dipping your toe into pizza-making." data-dimension48="In the U.K., where I live, the Ooni Karu 2 costs £349 RRP, so it's still a fairly substantial investment if you're just dipping your toe into pizza-making." data-dimension25="£349" href="https://www.amazon.co.uk/Ooni-Karu-Multi-Fuel-Portable-Charcoal/dp/B0G7LQP7FY" 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="ZWXfKDKexA6grx2C7HXLoN" name="Ooni Karu 2" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/ZWXfKDKexA6grx2C7HXLoN.jpg" mos="" align="middle" fullscreen="" width="1400" height="1400" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>In the U.K., where I live, the Ooni Karu 2 costs £349 RRP, so it's still a fairly substantial investment if you're just dipping your toe into pizza-making.<a class="view-deal button" href="https://www.amazon.co.uk/Ooni-Karu-Multi-Fuel-Portable-Charcoal/dp/B0G7LQP7FY" target="_blank" rel="nofollow" data-dimension112="b1c62498-565a-4b93-b4f0-3a480f4daeca" data-action="Deal Block" data-label="In the U.K., where I live, the Ooni Karu 2 costs £349 RRP, so it's still a fairly substantial investment if you're just dipping your toe into pizza-making." data-dimension48="In the U.K., where I live, the Ooni Karu 2 costs £349 RRP, so it's still a fairly substantial investment if you're just dipping your toe into pizza-making." data-dimension25="£349">View Deal</a></p></div><p>The steel I'm using is the Chef Pomodoro 14x12-inch pizza steel. It's 1/4-inch thick so holds heat well, and measures 14x12-inches, which effectively means just 12 inches if you want round pizzas. It's a simple piece of metal, which adds a level of versatility: it just goes in your conventional oven, meaning you can cook come rain or shine. As far as steels go, it's a pretty good one in my book.</p><div class="product"><a data-dimension112="4661f076-458b-46fd-84bd-d2eebd9b3665" data-action="Deal Block" data-label="The Chef Pomodoro 14x12-inch pizza steel is 1/4 inch thick and costs just under $53, making it an affordable way to experiment with pizza-making at home." data-dimension48="The Chef Pomodoro 14x12-inch pizza steel is 1/4 inch thick and costs just under $53, making it an affordable way to experiment with pizza-making at home." data-dimension25="$52.99" href="https://www.amazon.com/Chef-Pomodoro-Pre-seasoned-Quality-Compatible/dp/B0FDW1Y22Y/" 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:105.15%;"><img id="RJvm3ngtPsvGhyKRNKUQJF" name="Chef Pomodoro 14-inch Pizza Steel" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/RJvm3ngtPsvGhyKRNKUQJF.jpg" mos="" align="middle" fullscreen="" width="679" height="714" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>The Chef Pomodoro 14x12-inch pizza steel is 1/4 inch thick and costs just under $53, making it an affordable way to experiment with pizza-making at home.<a class="view-deal button" href="https://www.amazon.com/Chef-Pomodoro-Pre-seasoned-Quality-Compatible/dp/B0FDW1Y22Y/" target="_blank" rel="nofollow" data-dimension112="4661f076-458b-46fd-84bd-d2eebd9b3665" data-action="Deal Block" data-label="The Chef Pomodoro 14x12-inch pizza steel is 1/4 inch thick and costs just under $53, making it an affordable way to experiment with pizza-making at home." data-dimension48="The Chef Pomodoro 14x12-inch pizza steel is 1/4 inch thick and costs just under $53, making it an affordable way to experiment with pizza-making at home." data-dimension25="$52.99">View Deal</a></p></div><div class="product"><a data-dimension112="f5a0fa0d-857a-4bb8-8097-a2362bf0ad22" data-action="Deal Block" data-label="In the U.K., this steel is slightly pricier at just under £60, but it's still a way cheaper alternative to a full pizza oven." data-dimension48="In the U.K., this steel is slightly pricier at just under £60, but it's still a way cheaper alternative to a full pizza oven." data-dimension25="£59.99" href="https://www.amazon.co.uk/Chef-Pomodoro-Baking-Original-Artisan/dp/B0FDW1Y22Y?th=1" 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:105.15%;"><img id="RJvm3ngtPsvGhyKRNKUQJF" name="Chef Pomodoro 14-inch Pizza Steel" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/RJvm3ngtPsvGhyKRNKUQJF.jpg" mos="" align="middle" fullscreen="" width="679" height="714" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>In the U.K., this steel is slightly pricier at just under £60, but it's still a way cheaper alternative to a full pizza oven.<a class="view-deal button" href="https://www.amazon.co.uk/Chef-Pomodoro-Baking-Original-Artisan/dp/B0FDW1Y22Y?th=1" target="_blank" rel="nofollow" data-dimension112="f5a0fa0d-857a-4bb8-8097-a2362bf0ad22" data-action="Deal Block" data-label="In the U.K., this steel is slightly pricier at just under £60, but it's still a way cheaper alternative to a full pizza oven." data-dimension48="In the U.K., this steel is slightly pricier at just under £60, but it's still a way cheaper alternative to a full pizza oven." data-dimension25="£59.99">View Deal</a></p></div><p>The oven I'm using is a Neff fan-assisted oven with a dedicated baking and pizza setting, which gets up to 275C or 527F — this is technically hot enough for low'n'slow pizzas, like New York-style.</p><h2 class="article-body__section" id="section-price"><span>Price</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:5216px;"><p class="vanilla-image-block" style="padding-top:66.68%;"><img id="UNFKdosHT4fVbe69Hvj4zQ" name="Pizza steel vs Pizza oven-2" alt="A pizza stone on a kitchen counter" src="https://cdn.mos.cms.futurecdn.net/UNFKdosHT4fVbe69Hvj4zQ.jpg" mos="" align="middle" fullscreen="1" width="5216" height="3478" attribution="" endorsement="" class="inline expandable"><a href='https://cdn.mos.cms.futurecdn.net/UNFKdosHT4fVbe69Hvj4zQ.jpg' target='_blank' class='expand-button icon-expand-image icon' ></a></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>This one's a no-brainer. If money is the driving factor here, the pizza steel is the way to go. At just under <a href="https://www.amazon.com/Chef-Pomodoro-Pre-seasoned-Quality-Compatible/dp/B0FDW1Y22Y/" target="_blank" rel="nofollow">$53</a> / <a href="https://www.amazon.co.uk/Chef-Pomodoro-Baking-Original-Artisan/dp/B0FDW1Y22Y?th=1" target="_blank" rel="nofollow">£60</a>, this can be a totally safe impulse purchase, allowing you to experiment with making pizza at home while not breaking the bank.</p><p>The Ooni Karu 2, which is a fairly affordable pizza oven), costs <a href="https://www.amazon.com/Ooni-Karu-Multi-Fuel-Outdoor-Pizza/dp/B0DQ8R4TYT" target="_blank" rel="nofollow">$449</a> MSRP — although we've seen it drop to around $349 during recent sales events. In the U.K., it costs <a href="https://www.amazon.co.uk/Ooni-Karu-Multi-Fuel-Portable-Charcoal/dp/B0G7LQP7FY" target="_blank" rel="nofollow">£349</a> RRP, although the 2023 model has dropped as low as £279 in the past.</p><p>You'll need to add on a gas adapter if you want to cook with gas, which costs a whopping <a href="https://www.amazon.com/Ooni-Karu-12G-Gas-Burner/dp/B0F3J8MBSC" target="_blank" rel="nofollow">$112</a> / <a href="https://www.amazon.co.uk/Ooni-Karu-Gas-Burner-Accessories/dp/B0F3JGRG43" target="_blank" rel="nofollow">£90</a>. Then there's the price of fuel to consider, which is ongoing. To give you an idea of consumption: keeping up temperature for 5 pizzas on the Ooni required 2-3 handfuls of lumpwood charcoal and 5-6 small pieces of wood. Not much, but it adds up when using the oven regularly.</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:5461px;"><p class="vanilla-image-block" style="padding-top:66.67%;"><img id="75BKCTcR48A2zEbXZjVKCQ" name="Pizza steel vs Pizza oven-14" alt="The Ooni Karu 2 fuel compartment" src="https://cdn.mos.cms.futurecdn.net/75BKCTcR48A2zEbXZjVKCQ.jpg" mos="" align="middle" fullscreen="1" width="5461" height="3641" attribution="" endorsement="" class="inline expandable"><a href='https://cdn.mos.cms.futurecdn.net/75BKCTcR48A2zEbXZjVKCQ.jpg' target='_blank' class='expand-button icon-expand-image icon' ></a></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>It's worth remembering that both methods also require accessories. At a minimum, you need a peel to finish assembly and launch your pizza into the oven. Ideally, you'll want a turning peel, too, to rotate the pizza without burning yourself and remove it from the oven. And it's best to get yourself an infrared thermometer so you can measure the temperature of the pizza oven's stone/the steel to see when they're ready to cook.</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:1648px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="dnuovbegsjUBwJapnrYaJY" name="TG_Ooni-Karu-16_LIST.jpg" alt="Ooni Karu 16 outside with pizza" src="https://cdn.mos.cms.futurecdn.net/v2/t:194,l:341,cw:1648,ch:927,q:80/dnuovbegsjUBwJapnrYaJY.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="caption-text">You need a peel to launch your pizza into the oven. Because how else is it gonna get in there? </span><span class="credit" itemprop="copyrightHolder">(Image credit: Ooni)</span></figcaption></figure><p>I've been using the <a href="https://www.amazon.com/Bamboo-Spatula-Paddle-Cutting-Accessories/dp/B07TB9LBHR" target="_blank" rel="nofollow">Ooni 12-inch Bamboo peel</a> ($40), <a href="https://www.amazon.com/Ooni-Pizza-Turning-Peel/dp/B0821NDN33" target="_blank" rel="nofollow">Ooni Turning Peel</a> ($65) and <a href="https://www.amazon.com/Ooni-Digital-Infrared-Thermometer-Accessories/dp/B0CBV8YS6Q" target="_blank" rel="nofollow">Ooni Infrared Gun</a> ($65), so you can see how quickly those accessories ramp up the price. Ooni offers bundles, but they're still fairly pricey. The Ooni accessories are fantastic quality, but my advice when starting out would simply be to buy cheaper alternatives online, like this <a href="https://www.amazon.com/Yroshm-Premium-Serving-Cutting-Pastries/dp/B0DY679TRB/" target="_blank" rel="nofollow">bamboo peel</a> ($18), <a href="https://www.amazon.com/Newmeto-Aluminum-Perforated-Homemade-Accessories/dp/B0D4QCN92F" target="_blank" rel="nofollow">aluminum turning peel</a> ($18) and <a href="https://www.amazon.com/ThermoPro-TP30-Thermometer-Temperature-Adjustable/dp/B07VTPJXH9" target="_blank" rel="nofollow">infrared temperature gun</a> ($29). Start with a bamboo peel and go from there when needed, as you get more experience.</p><p><strong>Winner: Pizza steel</strong></p><h2 class="article-body__section" id="section-ease-of-use"><span>Ease of use</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:5328px;"><p class="vanilla-image-block" style="padding-top:66.67%;"><img id="hegWHrni4hbfXGLeCpLqdQ" name="Pizza steel vs Pizza oven-5" alt="The Ooni Karu 2 being built, with a dog sniffing the pizza oven" src="https://cdn.mos.cms.futurecdn.net/hegWHrni4hbfXGLeCpLqdQ.jpg" mos="" align="middle" fullscreen="1" width="5328" height="3552" attribution="" endorsement="" class="inline expandable"><a href='https://cdn.mos.cms.futurecdn.net/hegWHrni4hbfXGLeCpLqdQ.jpg' target='_blank' class='expand-button icon-expand-image icon' ></a></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="caption-text">The Ooni pizza oven needed building — thankfully, I had some help. </span><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>Again, this one goes to the steel. For a start, pizza ovens need building. The Ooni Karu 2 took me around 15 minutes to build — it was incredibly simple with a helpful assembly manual included and a video guide online. Some viewers commented that the online video instructions are little misleading, making it easy to damage a metal lip under the oven door. I didn't have this issue, though, as the included assembly manual was very clear.</p><p>Outdoor ovens can't really be left outside uncovered, either, which means I have to get mine out of my garage each time I want to cook — you can buy covers, but you mustn't leave the stone outside in very extreme temperatures. And while you <em>could</em> uncover and use the Karu 2 in the rain, you'd really want some form of shelter over you, which is an extra consideration. You can buy indoor pizza ovens like the <a href="https://www.amazon.com/Ooni-Volt-Electric-Indoor-Pizza/dp/B0FV3RGSQB" target="_blank" rel="nofollow">Ooni Volt 2</a>, but the pizza steel can be used rain or shine for much less money. </p><p>Then there's the prep/fueling, followed by the cleaning after use. It's time consuming, although not really any different to prepping for a BBQ, and I find cleaning the stone and pizza oven easier than shifting burnt-on crud from the steel.</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:5130px;"><p class="vanilla-image-block" style="padding-top:66.69%;"><img id="8mH5daQdUKGzGCoyTHxwsP" name="Pizza steel vs Pizza oven-1" alt="A pizza steel in its box on a counter" src="https://cdn.mos.cms.futurecdn.net/8mH5daQdUKGzGCoyTHxwsP.jpg" mos="" align="middle" fullscreen="1" width="5130" height="3421" attribution="" endorsement="" class="inline expandable"><a href='https://cdn.mos.cms.futurecdn.net/8mH5daQdUKGzGCoyTHxwsP.jpg' target='_blank' class='expand-button icon-expand-image icon' ></a></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>Nevertheless, the pizza steel is just much simpler. All I needed to do was unwrap it, wipe it down and then get cooking. It's a heavy old beast, which makes it cumbersome to handle. The counter benefit is that the steel is much tougher and virtually immune to fractures, although you'll need to season it from time to time to avoid rust, like a cast iron.</p><p>I find it much easier to launch pizzas onto the steel because of my oven's large door. That said, launching is mostly down to your peel, technique and flour/semolina dusting. With a few launches under your belt there's no real difference here between a steel and pizza oven. </p><p><strong>Winner: Pizza steel</strong></p><h2 class="article-body__section" id="section-heat-up"><span>Heat up</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:5352px;"><p class="vanilla-image-block" style="padding-top:66.67%;"><img id="jJ85jDn4LdnzCRGPAMQa4Q" name="Pizza steel vs Pizza oven-9" alt="The Ooni Karu 2 with its fuel lit" src="https://cdn.mos.cms.futurecdn.net/jJ85jDn4LdnzCRGPAMQa4Q.jpg" mos="" align="middle" fullscreen="1" width="5352" height="3568" attribution="" endorsement="" class="inline expandable"><a href='https://cdn.mos.cms.futurecdn.net/jJ85jDn4LdnzCRGPAMQa4Q.jpg' target='_blank' class='expand-button icon-expand-image icon' ></a></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>This is where the Ooni Karu 2 starts to pull ahead. Heating up is extremely quick. From lighting my fuel to the stone surface hitting 400C (and being ready to cook) took around 12 minutes. Much quicker than I was expecting.</p><p>By contrast, the Chef Pomodoro steel is, well, a huge hunk of steel, and therefore takes much longer to heat up. It's ready to cook by around 45 minutes. Now, this may be down to my individual oven, but after 45 minutes at full temperature with a chunk of steel inside, my Neff oven started to overheat and shut itself down. I simply turned it off and on again, the error warning disappeared, and I started to cook (as, luckily, the steel was at temperature by then). My oven couldn't then handle back to back pizzas though.</p><p><strong>Winner: Pizza oven</strong></p><h3 class="article-body__section" id="section-cook"><span>Cook</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:8568px;"><p class="vanilla-image-block" style="padding-top:50.00%;"><img id="5AazW37Q9cWo68tf52JgcQ" name="Pizza steel vs Pizza oven-10" alt="A split image with dough proving in a metal bowl on the left and a tin of Rega San Marzano tomatoes in hand on the right" src="https://cdn.mos.cms.futurecdn.net/5AazW37Q9cWo68tf52JgcQ.jpg" mos="" align="middle" fullscreen="1" width="8568" height="4284" attribution="" endorsement="" class="inline expandable"><a href='https://cdn.mos.cms.futurecdn.net/5AazW37Q9cWo68tf52JgcQ.jpg' target='_blank' class='expand-button icon-expand-image icon' ></a></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>Of course, the most important part of this comparison is the cook! There are two main types of pizza to consider here: Neapolitan, which is cooked very hot and fast; and New York-style or low'n'slow, which is cooked at a cooler temperature for longer.</p><p>I tested both styles on both cook methods, using <a href="https://www.youtube.com/@peddlingpizza" target="_blank">Peddling Pizza</a>'s dough recipe. For Neapolitan-style pizzas, I used fresh, drained mozzarella; and for New York-style I used dry pizza mozzarella. I used my own sauce recipe, which is just one can of Rega San Marzano tomatoes, with a teaspoon each of salt and sugar, plus half a teaspoon each of dried oregano and basil. </p><figure role="gallery"><figure><img src="https://cdn.mos.cms.futurecdn.net/vm6VBKPyNcdxmA9te3Bw9Q.jpg" alt="A pizza on a chopping board" /><figcaption>A couple of my pies cooked using the Chef Pomodoro pizza steel.<small role="credit">Future</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/ZyvgNgnWfXgDzMA44EbJqP.jpg" alt="A pizza cooling on a counter" /><figcaption>A couple of my pies cooked using the Chef Pomodoro pizza steel.<small role="credit">Future</small></figcaption></figure></figure><p>The pizza steel in a home oven simply cannot cook Neapolitan-style pizza. Your oven just doesn't get hot enough for the air bubbles in the dough to rapidly expand and create that puffy but light crust. Pizzas therefore come out quite dense.</p><p>However, using a steel does a fair job at low'n'slow styles (you'll want to make sure you tailor your dough to this: NY and Neapolitan can use similar hydration levels, but Chicago and deep-dish need a higher ratio of water). I was pretty happy with the NY-style(-ish) Margheritas I made using the steel, as well as some pepperoni pies, a grandma pizza and even a deep dish. The base and crust were always cooked nicely, with a good chewiness to them. Pizzas took around 10-12 minutes to cook.</p><p>I had one annoying issue, which may be down to my individual oven: I sometimes found I couldn't get ambient temperatures hot enough to cook the top of the pizza adequately without risking overdoing the crust, resulting in overly wet tops. I tried turning on the broiler to help... but doing so caused my oven to overheat again.</p><p>It kinda figures: home ovens just aren't designed to cook pizzas.</p><figure role="gallery"><figure><img src="https://cdn.mos.cms.futurecdn.net/oMPvjP9VcUKRkzZcjaV8HQ.jpg" alt="A pizza on a pizza peel" /><figcaption>A couple of my pizzas cooked in the Ooni Karu 2.<small role="credit">Future</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/ZxcLaGHh563uG7Ys552HBQ.jpg" alt="A pizza on a chopping board" /><figcaption>A couple of my pizzas cooked in the Ooni Karu 2.<small role="credit">Future</small></figcaption></figure></figure><p>The Ooni Karu 2 can do just about everything. Most importantly, it's an absolute weapon for Neapolitan pizzas. At 400C/750F, it'll cook you a pizza in as little as 90 seconds, and they come out perfectly: puffy, light crusts; crispy bases; and deftly cooked tops. With wood-burning ovens, you'll want to chuck a piece of wood in the fuel tray just before you launch, as this gets some flames licking over the top to cook toppings (especially raw meats like sausage). Gas-fired ovens like the <a href="https://www.tomsguide.com/home/outdoors/gozney-arc-lite-review">Gozney Arc Lite </a>do this for you, ensuring there's a flame always licking over the top.</p><p>I mostly cooked Neapolitan pies on my Ooni, cracking out a range of meaty (for me) and vegetarian (for my wife) pizzas. It gets a little tricky to manage the heat on a solid fuel oven, which was a minor issue when cooking five pizzas for my friends. After two, the temperature dropped and I was forced to cook at lower heats to keep bringing out food. This wasn't a huge issue, and I even used it to my advantage, doing low'n'slow pizzas instead to get the cheese super bubbly and brown. Compare that to the steel, which overheated my oven after a single pizza.</p><p>If you have a cast iron, like my 12-inch <a href="https://www.amazon.com/Field-Company-Skillet-inches-Smoother-Preseasoned/dp/B0CGW3P4VS" target="_blank" rel="nofollow">Field Company No. 10 Cast Iron Skillet</a>, you can also pare back the Ooni's heat and cook deep dish or Chicago style pies. I've yet to try these, but they're next on the agenda. It's super versatile.</p><p><strong>Winner: Pizza oven</strong></p><h2 class="article-body__section" id="section-verdict"><span>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:3606px;"><p class="vanilla-image-block" style="padding-top:66.64%;"><img id="cZZTohvB37j5ypqLgHospP" name="Pizza steel vs Pizza oven-13" alt="A pizza slice in hand showing the base" src="https://cdn.mos.cms.futurecdn.net/cZZTohvB37j5ypqLgHospP.jpg" mos="" align="middle" fullscreen="1" width="3606" height="2403" attribution="" endorsement="" class="inline expandable"><a href='https://cdn.mos.cms.futurecdn.net/cZZTohvB37j5ypqLgHospP.jpg' target='_blank' class='expand-button icon-expand-image icon' ></a></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="caption-text">A slice of pizza cooked in the Ooni Karu 2. </span><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>The steel is obviously better for price and ease of use, but when it comes to the most important stuff: heating up and cooking, the pizza oven wins hands down.</p><div class="product"><a data-dimension112="154944ab-a365-41c3-922d-6b29cb64edd5" data-action="Deal Block" data-label="U.K. — $59 @ Amazon" data-dimension48="U.K. — $59 @ Amazon" data-dimension25="$52.99" href="https://www.amazon.com/Chef-Pomodoro-Pre-seasoned-Quality-Compatible/dp/B0FDW1Y22Y/" 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:105.15%;"><img id="RJvm3ngtPsvGhyKRNKUQJF" name="Chef Pomodoro 14-inch Pizza Steel" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/RJvm3ngtPsvGhyKRNKUQJF.jpg" mos="" align="middle" fullscreen="" width="679" height="714" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>The Chef Pomodoro 14x12-inch pizza steel is 1/4 inch thick and costs just under $53, making it an affordable way to experiment with pizza-making at home.</p><p><a href="https://www.amazon.co.uk/Chef-Pomodoro-Baking-Original-Artisan/dp/B0FDW1Y22Y?th=1" target="_blank" rel="nofollow" data-dimension112="154944ab-a365-41c3-922d-6b29cb64edd5" data-action="Deal Block" data-label="U.K. — $59 @ Amazon" data-dimension48="U.K. — $59 @ Amazon" data-dimension25="$52.99"><strong>U.K. — $59 @ Amazon</strong></a><a class="view-deal button" href="https://www.amazon.com/Chef-Pomodoro-Pre-seasoned-Quality-Compatible/dp/B0FDW1Y22Y/" target="_blank" rel="nofollow" data-dimension112="154944ab-a365-41c3-922d-6b29cb64edd5" data-action="Deal Block" data-label="U.K. — $59 @ Amazon" data-dimension48="U.K. — $59 @ Amazon" data-dimension25="$52.99">View Deal</a></p></div><p>If you're just starting out and/or on a budget, and looking for a simple way to make pizza that's better than store-bought, get the steel. It'll help you learn a lot about dough, prep and techniques like launching. And you can make some enjoyable pies, which definitely count as good 'oven pizzas'. But the results aren't restaurant standard.</p><div class="product"><a data-dimension112="5fb7470e-cdbe-454a-9132-96a63b3eed9d" data-action="Deal Block" data-label="The Ooni Karu 2 is the brand's entry-level pizza oven and costs $449 MSRP. It runs on multiple fuels: wood, charcoal or gas (via an adapter).U.K. &mdash; &pound;349 @ Amazon U.K. — £349 @ Amazon" data-dimension48="The Ooni Karu 2 is the brand's entry-level pizza oven and costs $449 MSRP. It runs on multiple fuels: wood, charcoal or gas (via an adapter).U.K. &mdash; &pound;349 @ Amazon U.K. — £349 @ Amazon" data-dimension25="$449" href="https://www.amazon.com/Ooni-Karu-Multi-Fuel-Outdoor-Pizza/dp/B0DQ8R4TYT" 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="ZWXfKDKexA6grx2C7HXLoN" name="Ooni Karu 2" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/ZWXfKDKexA6grx2C7HXLoN.jpg" mos="" align="middle" fullscreen="" width="1400" height="1400" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>The Ooni Karu 2 is the brand's entry-level pizza oven and costs $449 MSRP. It runs on multiple fuels: wood, charcoal or gas (via an adapter).</p><p><strong></strong><a href="https://www.amazon.co.uk/Ooni-Karu-Multi-Fuel-Portable-Charcoal/dp/B0G7LQP7FY" target="_blank" rel="nofollow" data-dimension112="5fb7470e-cdbe-454a-9132-96a63b3eed9d" data-action="Deal Block" data-label="The Ooni Karu 2 is the brand's entry-level pizza oven and costs $449 MSRP. It runs on multiple fuels: wood, charcoal or gas (via an adapter).U.K. &mdash; &pound;349 @ Amazon U.K. — £349 @ Amazon" data-dimension48="The Ooni Karu 2 is the brand's entry-level pizza oven and costs $449 MSRP. It runs on multiple fuels: wood, charcoal or gas (via an adapter).U.K. &mdash; &pound;349 @ Amazon U.K. — £349 @ Amazon" data-dimension25="$449"><strong>U.K. — £349 @ Amazon</strong></a><a class="view-deal button" href="https://www.amazon.com/Ooni-Karu-Multi-Fuel-Outdoor-Pizza/dp/B0DQ8R4TYT" target="_blank" rel="nofollow" data-dimension112="5fb7470e-cdbe-454a-9132-96a63b3eed9d" data-action="Deal Block" data-label="The Ooni Karu 2 is the brand's entry-level pizza oven and costs $449 MSRP. It runs on multiple fuels: wood, charcoal or gas (via an adapter).U.K. &mdash; &pound;349 @ Amazon U.K. — £349 @ Amazon" data-dimension48="The Ooni Karu 2 is the brand's entry-level pizza oven and costs $449 MSRP. It runs on multiple fuels: wood, charcoal or gas (via an adapter).U.K. &mdash; &pound;349 @ Amazon U.K. — £349 @ Amazon" data-dimension25="$449">View Deal</a></p></div><p>If you want to make genuinely amazing pizza, akin to or better than that you'd buy from a pizzeria or restaurant, you need to spend a little extra for a pizza oven. In my experience, the difference really is night and day. </p><p>The reactions to my pizzas tell the story pretty well. With the steel-baked pies, it was usually something along the lines of: "oh, this is actually pretty good." With my pizza oven pies, it was more like: "holy crap, this is incredible. Cook another, right now."</p><p>So, here's my verdict on pizza steels. While I wanted this cheap, viral solution to work, unfortunately they just don't quite get there.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-ODnrje"></div>                            </div>                            <script src="https://kwizly.com/embed/ODnrje.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/home/kitchen-dining/gozney-dome-xl-2-review">I’ve been using the Gozney Dome XL (Gen 2) for 6 months — and it’s the last pizza oven you'll ever own</a></li><li><a href="https://www.tomsguide.com/home/kitchen-dining/im-an-ex-chef-heres-how-i-keep-my-knives-razor-sharp-without-a-whetstone">I'm an ex-chef: here's how I keep my knives sharp without a whetstone</a></li><li><a href="https://www.tomsguide.com/home/home-appliances/dyson-find-follow-purifier-cool-pc3-review">Dyson’s 2-in-1 purifier fan is the perfect way to beat the summer heat — except for one major flaw</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ Before I make a big purchase, I ask ChatGPT these 5 questions — and it's saved me money (and regret) ]]></title>
                                                                                                                                                                                                <link>https://www.tomsguide.com/ai/before-i-make-a-big-purchase-i-ask-chatgpt-these-5-questions-and-its-saved-me-both-money-and-regret</link>
                                                                            <description>
                            <![CDATA[ Before splurging on something expensive, I mention what item it is to ChatGPT along with one of my five go-to prompts—they save me time and money every time. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">DfgRphLerfPa8ovckrA3DD</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/SZSsz2R5iFdvRvQ2yVu3eA-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Sat, 27 Jun 2026 09:00:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[AI]]></category>
                                                                                                                    <dc:creator><![CDATA[ Elton Jones ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/NVtYYXr3tEPUE67jf3HtXM.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ null ]]></dc:description>
                                                                                                                                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/SZSsz2R5iFdvRvQ2yVu3eA-1280-80.jpg">
                                                            <media:credit><![CDATA[Getty Images]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[A man sits down on the sofa with a smile on his face, holding a credit card and a phone]]></media:description>                                                            <media:text><![CDATA[A man sits down on the sofa with a smile on his face, holding a credit card and a phone]]></media:text>
                                <media:title type="plain"><![CDATA[A man sits down on the sofa with a smile on his face, holding a credit card and a phone]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/SZSsz2R5iFdvRvQ2yVu3eA-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>When I’m contemplating breaking the bank for something a bit more grand on the cost scale, I do a few things before hitting the “Buy Now” button. I look up product reviews, analyze similar options to the product I’m considering and watch a video or two to see it in action. Then I make sure to meet up with ChatGPT to have a deep discussion about whether or not my next big purchase is worth it or not. That cycle has not only saved me time and money, but also kept me from feeling a huge sense of regret and embarrassment over making the wrong financial decision.</p><p>These are the five prompts that fit any circumstance whenever I go to ChatGPT to make a final decision on buying something expensive. Hopefully, these commands do the same for you.</p><h2 id="the-right-prompts-to-use-to-get-more-opinions-on-my-next-big-purchase">The right prompts to use to get more opinions on my next big purchase</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="FkDGmmjeQVkvZ6agi6D2MH" name="TG_Credit-card-debt_2.jpg" alt="Man holding credit card" src="https://cdn.mos.cms.futurecdn.net/FkDGmmjeQVkvZ6agi6D2MH.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>Once I make my way to ChatGPT for my latest “am I making the right decision to ball out on this latest purchase?” conversation, I use one of these prompts to help me make a definitive choice:</p><ul><li><strong>I'm considering buying [product name]. Help me identify the underlying problem I'm trying to solve and whether there are cheaper or simpler solutions.</strong></li><li><strong>Act as a skeptical consumer advocate. Give me the strongest reasons not to buy this product.</strong></li><li><strong>Describe the ideal buyer for this product and tell me whether I fit that profile.</strong></li><li><strong>Create a decision framework for this purchase. What factors should I compare and how should I weigh them?</strong></li><li><strong>Imagine it's one year from now. What are the most likely reasons I would regret buying this product and the most likely reasons I'd be glad I bought it?</strong></li></ul><p>That second prompt especially came in handy when I finally decided to pick up a PS5 arcade stick. At first, I had my sights set on the HORI Fighting Stick Alpha, which goes for $199.99. Once I mentioned it to ChatGPT alongside that trusty prompt, it brought a bunch of reasons why I shouldn’t take the plunge.</p><p>Those skeptical points included: </p><ul><li><strong>You might end up spending even more on customization: </strong><em>The Fighting Stick α is designed to be opened and modified. That's a feature—but it can also become a money pit. A common progression is buying an arcade stick, replacing its buttons & lever, adding custom artwork, making additional upgrades, etc. A $220 purchase can quietly become a $300–$400 hobby.</em></li><li><strong>It's expensive for a niche accessory: </strong><em>At around $220 MSRP, the Fighting Stick α costs as much as several new games, a premium controller, an entry-level leverless controller or a significant upgrade to your gaming setup. The question isn't "Is it good?" It's "Will I get $220 worth of enjoyment from it?"</em></li><li><strong>The Hayabusa parts are divisive: </strong><em>HORI markets the stick around its proprietary Hayabusa joystick and buttons. The problem is that some players love them, while others immediately replace them with Sanwa parts. If you end up preferring Sanwa components, you're effectively paying premium money for parts you'll swap out anyway.</em></li><li><strong>Better alternatives may exist at the same price: </strong><em>At roughly the same budget, you can often find competing sticks that include Sanwa parts out of the box, different layouts, detachable cables and different ergonomics. For example, the NACON Daija Arcade Fight Stick is frequently cited as a strong alternative and has occasionally been available below the Fighting Stick α's MSRP.</em></li></ul><p>After considering all of ChatGPT’s suggestions, I widened my search for a PS5 arcade stick and eventually laid eyes upon the Qanba B1 Titan Wired Joystick. </p><p>Not only was it cheaper <a href="https://www.amazon.com/Qanba-B1-Titan-Joystick-PlayStation/dp/B0BYQCPDTP?tag=p00935-20&ascsubtag=05Zj4g0AOCo3RmlfxFGoyHs&th=1" target="_blank" rel="nofollow">(I found one on Amazon for $151.55)</a>, but it was also another officially licensed Sony product that instilled that same sense of trust I would have had if I purchased my first option. I got that same sense of brand satisfaction, spent a lot less and ended up preferring Sanwa parts after testing their overall feel on both my fellow fighting game enjoyers’ Hayabusa & Sanwa-equipped arcade sticks.</p><h2 id="the-takeaway-2">The takeaway</h2><p>Doing all the necessary research you need to do before opening your wallet is and should always be a regular occurrence. </p><p>Injecting ChatGPT into my financial decisions has turned out way better than expected and I’ll be sure to keep doing that every time dollar signs cover my eyes at the sight of something that’s a couple of hundred dollars or more. Take those prompts if you’d like and let ChatGPT ease the difficulty that comes with your next major purchase.</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/ai/i-used-etsy-in-chatgpt-to-upgrade-my-bedroom-decor-and-this-prompt-worked-like-magic" target="_blank">I used Etsy in ChatGPT to upgrade my bedroom decor — and this prompt worked like magic</a></li><li><a href="https://www.tomsguide.com/ai/apple-is-ending-support-for-16-devices-heres-the-chatgpt-prompt-that-tells-you-what-to-do-next" target="_blank">Apple is ending support for 16 devices — here’s the ChatGPT prompt that tells you what to do next</a></li><li><a href="https://www.tomsguide.com/ai/what-is-google-zero-and-why-your-favorite-websites-are-panicking-about-ai" target="_blank">What is Google Zero — and why your favorite websites are panicking about AI</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ I’m a personal trainer — this mobility move opens up the chest and spine so much better than stretching ]]></title>
                                                                                                                                                                                                <link>https://www.tomsguide.com/wellness/workouts/im-a-personal-trainer-this-mobility-move-opens-up-the-chest-and-spine-so-much-better-than-stretching</link>
                                                                            <description>
                            <![CDATA[ So many of my personal training clients suffer from rounded posture, tight pecs, and poor shoulder range of motion. Here's how to fix it ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">qnkto4YZoejRjEjyFheEVD</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/YpUtbHcyZkFqL2fBjtAr7L-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Sat, 27 Jun 2026 07:30:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Workouts]]></category>
                                                    <category><![CDATA[Wellness]]></category>
                                                    <category><![CDATA[Fitness]]></category>
                                                                                                <author><![CDATA[ jen@jenrizzutofitness.com (Jennifer Rizzuto) ]]></author>                    <dc:creator><![CDATA[ Jennifer Rizzuto ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/V3yeuQZGZePvWRoSmHyxp8.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ null ]]></dc:description>
                                                                                                                                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/YpUtbHcyZkFqL2fBjtAr7L-1280-80.jpg">
                                                            <media:credit><![CDATA[Shutterstock]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[a photo of a woman doing a back stretch ]]></media:description>                                                            <media:text><![CDATA[a photo of a woman doing a back stretch ]]></media:text>
                                <media:title type="plain"><![CDATA[a photo of a woman doing a back stretch ]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/YpUtbHcyZkFqL2fBjtAr7L-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>So many of my personal training clients suffer from rounded posture, tight pecs, and poor shoulder range of motion. Desk jobs are usually the major culprit, made worse by lots of bench presses and not enough mobility work. </p><p>Sometimes I’ll give my clients a few common chest and back stretches, but there’s actually one move I prefer over stretching: quadruped thoracic rotations. This exercise opens up the entire upper body, reducing overall stiffness and enhancing spinal alignment. It’s a movement that almost anyone could benefit from, but especially those who are stuck behind a computer all day.</p><p>Below, I’ll go over how to do quadruped thoracic rotations, their benefits, and common form errors to keep in mind. Roll out your <a href="https://www.tomsguide.com/best-picks/best-yoga-mats"><u>yoga mat</u></a> and give them a try for yourself. </p><h2 id="how-to-do-quadruped-thoracic-rotations">How to do quadruped thoracic rotations</h2><p>Consult with your doctor before trying any new activity. This exercise can be done by most people, but beginners should consider meeting with a trainer for guidance on proper form. </p><p>You’ll just need a yoga mat to do quadruped thoracic rotations. If you have sore knees, you can place a rolled-up towel or pillow underneath them for extra cushioning. </p><p>Start by doing 5-8 rotations on each side, 3-4 times a week. As your upper body mobility improves, increase to 10 reps on each side. Gradually work your way up to doing this exercise for at least one set, 5-7 times a week.</p><p>Quadruped thoracic rotations make a great addition to your warm-up routine. They can also be done after work or long periods of sitting. </p><p>Here’s how to do them:</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/QWwiOHexU8I" allowfullscreen></iframe></div></div><ul><li>Come to all fours on the mat.</li><li>Sink your hips back towards your heels.</li><li>Place your right hand behind the back of your head.</li><li>Place your left hand underneath your right shoulder.</li><li>Rotate your torso and lift your right elbow towards the ceiling.</li><li>Slowly return to the starting position.</li><li>Continue for 5-10 reps, then repeat on the other side.</li></ul><h2 id="benefits-of-quadruped-thoracic-rotations">Benefits of quadruped thoracic rotations</h2><p>Most of our daily life is forward, from sitting on the computer to texting on our phones. All that time spent in front of us can tighten certain muscles and weaken others. In turn, this can degrade posture, cause chronic pain and stiffness, and make us more susceptible to overuse injuries. </p><p>Quadruped thoracic rotations open up the chest, shoulders, and back in a transverse plane of motion. Sitting the hips back towards the heels stabilizes the often vulnerable lower back area, while the “rotation” increases mobility and flexibility throughout the thoracic spine. </p><p>Additionally, the “quadruped” formation engages deep core muscles like the transverse abdominis and internal obliques, which help to stabilize and support the pelvis and spinal column. </p><p>Done regularly, quadruped thoracic rotations can counteract the negative effects of sitting for long periods, promoting better range of motion in the spine and enhancing overall posture.</p><h2 id="common-quadruped-thoracic-rotation-form-errors">Common quadruped thoracic rotation form errors</h2><p>Quadruped thoracic rotations aren’t hard to learn, but there are a few common mistakes that can make the exercise less effective. </p><h3 class="article-body__section" id="section-not-setting-the-hips-back-towards-the-heels"><span>Not setting the hips back towards the heels</span></h3><p>While this may seem like a minor part of the movement, making sure you set your hips back is super important. This portion of the exercise stabilizes and protects the lower back as you rotate the torso.</p><p>If injury or mobility concerns prevent you from sitting back onto your heels, try <a href="https://youtu.be/_71vJV2fZng?si=xuu43AShwYGdXNK5"><u>seated thoracic rotations instead</u></a>. Sit tall in a chair, engage your core muscles, cross your arms across your chest, and gently twist your torso to each side.</p><h3 class="article-body__section" id="section-moving-too-fast"><span>Moving too fast</span></h3><p>I see it all the time: clients use quadruped thoracic rotations as a warm-up, then speed through the exercise so that they can get to the main part of their workout. But going too quickly can mean that you’re relying on momentum, not reaching the ends of your range of motion, and even setting yourself up for injury through uncontrolled movement. </p><p>Rotate through your spine slowly, and hold at the ends of your range for at least 2-3 seconds. Towards the end of each set, you can even challenge yourself to go a bit further or hold for an additional second. </p><h3 class="article-body__section" id="section-over-rotating"><span>Over rotating </span></h3><p>You may not get a lot of rotational range at first, and often, beginners will try to compensate for that by shifting their hips instead of keeping them square to the mat. However, that twists the lower back, not the thoracic spine. If your lower back is tight or you’re dealing with disc issues, this can lead to pain or a worsening of your condition.  </p><p>When performing quadruped thoracic rotations, focus less on the degree of rotation and more on the “stretch” you feel. Even if you’re not moving that much, if you feel the chest, shoulders, and back opening up, you’re getting the benefits of the exercise. </p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-ONKRJX"></div>                            </div>                            <script src="https://kwizly.com/embed/ONKRJX.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/wellness/workouts/not-sit-ups-planks-or-crunches-i-do-this-simple-pilates-exercise-every-single-day-to-build-a-strong-and-stable-core-and-work-on-my-hip-flexor-mobility" target="_blank">Not sit-ups, planks, or crunches: I do this simple Pilates exercise every single day to build a strong and stable core and work on my hip flexor mobility</a></li><li><a href="https://www.tomsguide.com/wellness/fitness/im-a-weightlifting-coach-3-exercises-i-prefer-over-lunges-for-building-strong-stable-legs-and-knees-over-40" target="_blank">I'm a weightlifting coach — 3 exercises I prefer over lunges for building strong, stable legs and knees over 40</a></li><li><a href="https://www.tomsguide.com/wellness/workouts/i-tried-a-7-day-standing-core-routine-here-are-the-differences-i-noticed-in-my-strength-and-posture" target="_blank">I tried a 7-day standing core routine. Here are the differences I noticed in my strength and posture</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ I turned my YouTube watchlist into an AI bootcamp with NotebookLM — here's how ]]></title>
                                                                                                                                                                                                <link>https://www.tomsguide.com/ai/i-turned-youtube-into-an-ai-bootcamp-with-notebooklm-heres-my-workflow</link>
                                                                            <description>
                            <![CDATA[ I used Google's free NotebookLM to transform my YouTube watchlist into a personalized AI bootcamp. Here's the workflow that's helping me learn faster. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">NCFXu5Av2b9FQkenmu3w3P</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/HBpX9MZwkMZGuuVjJZsfh7-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Sat, 27 Jun 2026 07:30:00 +0000</pubDate>                                                                                                                                <updated>Sun, 28 Jun 2026 22:50:56 +0000</updated>
                                                                                                                                            <category><![CDATA[AI]]></category>
                                                                                                <author><![CDATA[ amanda.caswell@futurenet.com (Amanda Caswell) ]]></author>                    <dc:creator><![CDATA[ Amanda Caswell ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/zYjevim2q7FjQiefqpjZRB.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ null ]]></dc:description>
                                                                                                                                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/HBpX9MZwkMZGuuVjJZsfh7-1280-80.jpg">
                                                            <media:credit><![CDATA[Future]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[NotebookLM]]></media:description>                                                            <media:text><![CDATA[NotebookLM]]></media:text>
                                <media:title type="plain"><![CDATA[NotebookLM]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/HBpX9MZwkMZGuuVjJZsfh7-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Up until a few weeks ago I used <a href="https://www.tomsguide.com/opinion/youtube-premium-is-the-only-streaming-service-i-pay-for-and-i-couldnt-be-happier">YouTube </a>the way most people do. I'd save dozens of interesting videos to my Watch Later playlist, promise myself I'd watch them someday and then, well, I'd never quite get around to it. </p><p>When I did finally press play, I'd often skip ahead or skip the video completely rather than devoting an entire 30 or 40 minutes watching a tutorial. And attempting to remember one useful tip, was a game in itself. I'd always go back and try to find the exact moment where something special was mentioned in the video. </p><p><a href="https://www.tomsguide.com/ai/i-used-notebooklm-to-make-a-family-wiki-and-now-everything-i-need-to-run-the-household-is-a-click-away">NotebookLM</a> completely changed that. Now, instead of watching videos from beginning to end, I now upload them into Google's NotebookLM and transform the videos into an interactive course that I can question, compare and revisit whenever I need it.</p><p>It's quickly become one of my favorite ways to learn and I've even gotten my kids involved with it so they continue to learn over the summer. </p><h2 id="why-notebooklm-works-so-well-with-youtube">Why NotebookLM works so well with YouTube </h2><p>Keep in mind that NotebookLM relies on YouTube's auto-generated transcripts, so it works best for talking-head videos, lectures,and tutorials rather than highly visual, text-free edits. You can easily check if a video has a transcript by simply clicking the "Show Transcript" button. That said, if you don't see it, there probably isn't one but you don't need to stop there. You can always turn on <a href="https://www.tomsguide.com/ai/google-gemini/gemini-live-is-free-for-iphone-users-heres-how-to-share-your-screen-and-camera">Gemini Live</a> to take notes and record the video to later upload into NotebookLM. </p><p><strong>Getting videos into NotebookLM is surprisingly easy.</strong> Create a new notebook, click <strong>Add source</strong>, choose <strong>Website</strong>, then paste the URL of any YouTube video. NotebookLM automatically pulls in the video's transcript (when one is available), making it searchable alongside any other sources you add.</p><p>Once they're inside a notebook, they become searchable knowledge, so instead of hunting through timestamps, I simply ask.</p><p>That means you can ask questions like:</p><ul><li><strong>What are the three biggest takeaways? </strong></li><li><strong>Explain this as if I'm a beginner. </strong></li><li><strong>Which parts disagree with another video? </strong></li><li><strong>What tools does this creator recommend? </strong></li><li><strong>Give me a checklist based on everything covered. </strong></li></ul><h2 id="my-ai-bootcamp-workflow">My AI bootcamp workflow</h2><h3 class="article-body__section" id="section-1-i-collect-videos-instead-of-watching-them-immediately"><span>1. I collect videos instead of watching them immediately. </span></h3><p>Whenever I find a great video, I simply save it to a playlist until I have a topic worth exploring. This could be a video about an AI workflow, AI tutorial, Claude Skills, Local AI, MCP servers or anything else I find interesting. <br><br>My husband has a lawn care business, so he saves instructional videos for topics like pruning, edging, tools and tricks. Similarly, I save videos for my kids on topics they like. </p><p>Once I have several videos covering the same subject, I move to NotebookLM.</p><h3 class="article-body__section" id="section-2-i-upload-several-videos-to-notebooklm"><span>2. I upload several videos to NotebookLM</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:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="UefPnheUz6SdHobQNQR4yL" name="8 - 2026-06-26T090308.604" alt="NotebookLM" src="https://cdn.mos.cms.futurecdn.net/UefPnheUz6SdHobQNQR4yL.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: Future)</span></figcaption></figure><p>This is where the magic starts. Instead of asking NotebookLM to summarize one creator, I feed it multiple perspectives on the same topic. The way I see it, five creators explaining AI agents is much more valuable than one. That way, NotebookLM starts finding patterns and interesting perspectives between them.</p><p>It identifies ideas that everyone agrees on and points out where opinions differ. That gives me a much broader understanding than simply watching videos one after another.</p><h3 class="article-body__section" id="section-3-i-ask-questions-instead-of-watching-passively"><span>3. I ask questions instead of watching passively </span></h3><p>Rather than sitting through hours of content, I ask questions to NotebookLM the way I might actually discuss the topic with the person in the video. Best of all, I get answers right away so it's a lot like talking directly to a private tutor. Questions I might ask are: </p><ul><li><strong>What concepts appear in every video? </strong></li><li><strong>What advice is unique? </strong></li><li><strong>Which workflow seems easiest for beginners? </strong></li><li><strong>What mistakes should I avoid? </strong></li><li><strong>If I only had one hour, what should I learn first? </strong></li></ul><h3 class="article-body__section" id="section-4-i-generate-a-study-guide"><span>4. I generate a study guide </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:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="C5cYdF6Qa4Sk2f7MNKd7wV" name="8 - 2026-06-26T090428.943" alt="notebooklm" src="https://cdn.mos.cms.futurecdn.net/C5cYdF6Qa4Sk2f7MNKd7wV.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: Future)</span></figcaption></figure><p>Once I've explored the material, I need something practical instead of relying on memory. That's when I ask NotebookLM to create:</p><ul><li><strong>a beginner roadmap </strong></li><li><strong>a glossary </strong></li><li><strong>flashcards </strong></li><li><strong>a checklist </strong></li><li><strong>a step-by-step learning plan </strong></li></ul><h3 class="article-body__section" id="section-5-i-create-an-audio-overview"><span>5. I create an Audio Overview </span></h3><p>One of my favorite NotebookLM features is Audio Overviews. Instead of reading pages of notes, NotebookLM creates a conversational audio discussion based on the sources I've uploaded.</p><p>I'll often listen while driving, running or making dinner. It's an easy way to reinforce what I've already learned without opening my laptop again.</p><h2 id="a-few-final-thoughts">A few final thoughts </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="kzknjtnyyDHT8MGF7oyArW" name="YouTube on iPhone.shutterstock_2193163923.jpg" alt="YouTube app icon on iPhone with finger" src="https://cdn.mos.cms.futurecdn.net/kzknjtnyyDHT8MGF7oyArW.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>This method absolutely beats binge-watching YouTube. And while there's nothing wrong with watching great creators, after a while, I realized I wasn't building knowledge, I was just consuming content. YouTube is simply the source material. From there, NotebookLM organizes it, compares it, quizzes me on it and turns hours of videos into something that feels much closer to a personalized AI course. For anyone trying to keep up with how quickly AI is changing, it's one of the smartest free workflows I've found.</p><p>Give it a try and let me know what you think. Share your thoughts in the comments. </p><a href="https://follow.it/articles-by-amanda-caswell-tom-s-guide?leanpub" class="button button--large button--primary">Follow Amanda Caswell and stay ahead of the AI curve</a><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/ai/the-trump-administration-just-quietly-changed-how-openai-will-launch-its-next-model">The Trump administration just quietly changed how OpenAI will launch its next model</a></li><li><a href="https://www.tomsguide.com/ai/forget-chatbots-why-apple-meta-and-openai-are-racing-toward-spatial-ai">Forget chatbots: Why Apple, Meta and OpenAI are racing toward 'Spatial AI'</a></li><li><a href="https://www.tomsguide.com/ai/claude-skills-changed-how-i-work-5-ways-i-use-them-every-day">Claude Skills changed how I work — 5 ways I use them every day</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ How often should you clean your bathroom to prevent black or pink mold? I asked an expert ]]></title>
                                                                                                                                                                                                <link>https://www.tomsguide.com/home/how-often-should-you-clean-your-bathroom-to-prevent-black-or-pink-mold-i-asked-an-expert</link>
                                                                            <description>
                            <![CDATA[ How to stop pink and black mold in its tracks — expert reveals how often you should really be cleaning your bathroom. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">AEt6qahh9a48VPZBN3zDdX</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/79ghdLVE4SLYnVb38skxJB-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Sat, 27 Jun 2026 07:02:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Home]]></category>
                                                                                                                    <dc:creator><![CDATA[ Cynthia Lawrence ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/CCuSgQpd5NyZ46CgoF9cva.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ null ]]></dc:description>
                                                                                                                                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/79ghdLVE4SLYnVb38skxJB-1280-80.jpg">
                                                            <media:credit><![CDATA[Shutterstock]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Cleaning mold from bathtub sealant]]></media:description>                                                            <media:text><![CDATA[Cleaning mold from bathtub sealant]]></media:text>
                                <media:title type="plain"><![CDATA[Cleaning mold from bathtub sealant]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/79ghdLVE4SLYnVb38skxJB-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>When it comes to <a href="https://www.tomsguide.com/how-to/how-to-clean-every-room-of-your-home-a-guide-to-cleaning-everything">cleaning every room in the home</a>, the one household chore I despise is <a href="https://www.tomsguide.com/how-to/how-to-get-rid-of-mold">scrubbing bathroom mold</a>. </p><p>Be it those stubborn black spots that seem to resurface in my <a href="https://www.tomsguide.com/home/forget-bleach-this-one-kitchen-item-will-remove-mold-on-silicone-sealant-instantly">silicone sealant</a>, or <a href="https://www.tomsguide.com/home/what-is-pink-mold-and-how-to-clean-it-these-natural-kitchen-staples-are-all-you-need">getting rid of pink mold</a> on my bathtub and shower drains, it just never seems to disappear for good. </p><p>Such invasive spores thrive in the humid, damp environments of lingering warm water and trapped steam, particularly when bathroom ventilation is lacking.</p><p>More importantly, if not properly dealt with, mold can lead to long-term structural damage and potential health concerns if the spores are allowed to spread.  This is why knowing how to <a href="https://www.tomsguide.com/how-to/how-to-get-rid-of-mold">prevent mold</a> remains your best defense for a germ-free home.</p><p>So, how often should you actually be cleaning your bathroom to banish black or pink mold from appearing? Luckily, I asked an expert for the correct way to prevent mold — and it turns out I’d been doing it all wrong. </p><h3 class="article-body__section" id="section-how-often-should-you-deep-clean-your-bathroom-to-prevent-black-or-pink-mold"><span>How often should you deep clean your bathroom to prevent black or pink mold?</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:3557px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="nyzLhhJBAFBDdeJZEBKRLV" name="pink mold" alt="pink mold" src="https://cdn.mos.cms.futurecdn.net/nyzLhhJBAFBDdeJZEBKRLV.jpg" mos="" align="middle" fullscreen="" width="3557" height="2001" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="caption-text">pink mold on bathtub </span><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>While most of us often deep-clean our bathrooms the minute we spot visible signs of mold, it turns out that we’ve not been cleaning our bathrooms often enough.  </p><p>“By the time it’s visible, moisture and bacteria have already accumulated, so prevention is much easier than removal,” states Soma Pillay, Bathroom Specialist at  <a href="https://www.bathroomcity.co.uk/" target="_blank">Bathroom City</a>.</p><p>“As a general rule, I recommend giving the bathroom a proper clean at least once a week, but this may increase depending on the individual homes. Those with pets or children may require more frequent maintenance to prevent dirt, bacteria, or mould from building up.”</p><div><blockquote><p>"I recommend giving the bathroom a proper clean at least once a week, but this may increase depending on the individual homes."</p><p>Soma Pillay, Bathroom Specialist </p></blockquote></div><p>So does the approach change for <a href="https://www.tomsguide.com/home/what-is-pink-mold-and-how-to-clean-it-these-natural-kitchen-staples-are-all-you-need">getting rid of pink mold</a>? Essentially, this pinkish film is fueled by a bacterial accumulation of soap scum, body oils, and minerals found in stagnant water.</p><p>“Pink mold is typically bacterial growth, rather than actual mold itself. It generally appears as a pale pink or blood-red, slimy film and should be addressed immediately to prevent it from spreading to other sections of the bathroom.”</p><p>You can easily make a natural DIY cleaning solution to tackle pink mold. Simply mix half a cup of baking soda with a tablespoon of liquid dish soap or your favorite multi-surface cleaner in a bowl. Mix until you have a thin, runny paste, before scrubbing the affected areas with a small bristle brush. </p><p>Once you’ve scrubbed all traces of the mold away, rinse the residue away with warm water or use a damp microfiber cloth to wipe down the surface.</p><h3 class="article-body__section" id="section-why-does-mold-keep-coming-back"><span>Why does mold keep coming back? </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:6006px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="D52HdukPa26zyPbZsPgJMc" name="Rinsing bath - crop.jpg" alt="Rinsing bath with shower head" src="https://cdn.mos.cms.futurecdn.net/D52HdukPa26zyPbZsPgJMc.jpg" mos="" align="middle" fullscreen="" width="6006" height="3378" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="caption-text">Rinsing bath with shower head </span><span class="credit" itemprop="copyrightHolder">(Image credit: Shutterstock)</span></figcaption></figure><p>Another question we might ask is, <a href="https://www.tomsguide.com/home/why-does-mold-keep-coming-back-it-turns-out-its-not-just-about-how-well-i-clean">why does mold keep coming back </a>— despite our best efforts to scrub our bathrooms clean?</p><p>“Mold growth thrives in damp and moist conditions,” explains Pillay. “For this reason, I strongly advise homeowners to clean high-moisture parts of the bathroom, including shower screens, areas around the bath, and<a href="https://www.bathroomcity.co.uk/products/basins"> </a>drains, and showers and baths should be wiped down and dried after each use, as this minimizes the risk of mould growing.”</p><p>Additionally, ensure your bathroom is properly ventilated by keeping windows and doors open or by utilizing an extractor fan when available. This daily habit helps release trapped humidity and introduces fresh air circulation, which is vital to <a href="https://www.tomsguide.com/how-to/how-to-get-rid-of-mold">prevent mold</a> from thriving in your home.</p><p>“I also advise people to avoid leaving damp towels and bath mats in the bathroom. Not only can these further increase the risk of mould, but they can also cause musty smells to linger,” adds Pillay.</p><p>“Deep cleaning includes dusting extractor fan covers, cleaning shower heads, and ensuring the area around or behind bathroom furniture is clean. These regular habits can contribute to a much cleaner and more welcoming bathroom environment for homeowners and guests.”</p><p>For more top tips to banish mold once and for all, check out <a href="https://www.tomsguide.com/home/how-to-clean-mold-from-bathroom-caulk-permanently-without-using-bleach">how to clean mold from bathroom caulk permanently — without using household bleach</a> and <a href="https://www.tomsguide.com/home/telltale-signs-that-you-need-a-dehumidifier-right-now">5 tell-tale signs that you need a dehumidifier right now</a>.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-W3wNYW"></div>                            </div>                            <script src="https://kwizly.com/embed/W3wNYW.js" async></script><h3 class="article-body__section" id="section-cleaning-essentials-we-love"><span>Cleaning essentials we love</span></h3>        <div class="featured_product_block featured_block_hero" data-id="9089b1c7-d20d-43d6-ac1d-ce54e63617db">            <a href="https://www.amazon.com/gp/aw/d/B07HRCDDL1/" data-model-name="Microfiber Cleaning Clothes, 12-pack" 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/uBmqXzHjnX7Fvtoj977TDk.jpg" alt="Mr.siga Microfiber Cleaning Cloth,pack of 12,size:12.6" X 12.6""></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>MR.SIGA</div>                                        <div class="featured__title">Microfiber Cleaning Clothes, 12-pack</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="2790fcc1-ef6e-4c72-ac8c-be596aab0ca1">            <a href="https://www.amazon.com/Bamllum-Rubber-Kitchen-Dishwashing-Gloves/dp/B0BYJDCWP9?" data-model-name="Rubber Kitchen Dishwashing Gloves, 4 Pairs " data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:88.80%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/Qiv8eHiE9UQdsqdwv85fX9.jpg" alt="Rubber Kitchen Dishwashing Gloves - 4 Pairs Colorful Reusable Household Cleaning Gloves for Washing Dishes and Cleaning Tasks, Flexible Long-Lasting and Non-Slip (medium, Blue+pink+yellow+red)"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Bamllum</div>                                        <div class="featured__title">Rubber Kitchen Dishwashing Gloves, 4 Pairs </div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="d1e02cf9-f8f5-430a-82c4-ecd21197e667">            <a href="https://www.amazon.com/Swiffer-Dusters-Extendable-Handle-Starter/dp/B001TQ6IHS?" data-model-name="Duster Kit With 3 Ft Extendable Handle" 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/8FRdRE5RbWaXebGMrka3yE.jpg" alt="Swiffer Duster Kit With 3 Ft Extendable Handle, Heavy Duty Dusting Starter Kit With 3 Refills, for Ceiling Fans, Vents and Hard to Reach Places"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Swiffer</div>                                        <div class="featured__title">Duster Kit With 3 Ft Extendable Handle</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/home/i-clean-my-shower-while-im-washing-expert-shares-her-bizarre-hacks-to-cut-your-chores-in-half">‘I clean my shower while I'm washing' — expert shares her bizarre hacks to cut your chores in half</a></li><li><a href="https://www.tomsguide.com/how-to/how-to-clean-a-glass-shower-door-top-tips-to-remove-water-marks">How to clean a glass shower door</a></li><li><a href="https://www.tomsguide.com/home/how-to-keep-your-shower-curtain-mold-free">I recommend these 5 easy tips to keep your shower curtain mold-free</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ Snap Specs vs Xreal Aura: The $1,000+ smart glasses that are fighting for your face this fall ]]></title>
                                                                                                                                                                                                <link>https://www.tomsguide.com/computing/smart-glasses/snap-specs-vs-xreal-aura</link>
                                                                            <description>
                            <![CDATA[ I went eyes-on with both Snap Specs and Xreal Aura. From Snap OS to Android XR, here is how to pick the right spatial computing glasses this fall. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">BGFtp2LP3hGz6sbbfTHbuM</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/GprvEQHJvwNBFHC3uBKze4-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Sat, 27 Jun 2026 07:00:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Smart Glasses]]></category>
                                                    <category><![CDATA[Computing Peripherals]]></category>
                                                    <category><![CDATA[VR &amp; AR]]></category>
                                                                                                                    <dc:creator><![CDATA[ Jason England ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/v4fSq5U4uZUEtGY2BwNuJ6.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Jason brings a decade of tech and gaming journalism experience to his role as a Managing Editor of Computing at Tom&#039;s Guide. He has previously written for Laptop Mag, Tom&#039;s Hardware, Kotaku, Stuff and BBC Science Focus. In his spare time, you&#039;ll find Jason looking for good dogs to pet or thinking about eating pizza if he isn&#039;t already.&lt;/p&gt; ]]></dc:description>
                                                                                                                                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/GprvEQHJvwNBFHC3uBKze4-1280-80.jpg">
                                                            <media:credit><![CDATA[Future]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Snap Specs vs Xreal Aura]]></media:description>                                                            <media:text><![CDATA[Snap Specs vs Xreal Aura]]></media:text>
                                <media:title type="plain"><![CDATA[Snap Specs vs Xreal Aura]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/GprvEQHJvwNBFHC3uBKze4-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>One of the more interesting questions I got after seeing both the <a href="https://www.tomsguide.com/computing/smart-glasses/i-just-went-eyes-on-with-snap-specs-theyre-a-lot-more-stylish-than-i-feared-at-first">Snap Specs</a> and <a href="https://www.tomsguide.com/computing/smart-glasses/xreal-android-xr-project-aura-smart-glasses-hands-on-review">Xreal Aura</a> is “which one is better for me?” Because in one way, it’s a question that misses the point — they’re both very different devices with very different missions.</p><p>But on the other hand, they’re both spatial computing platforms squashed into a pair of glasses, so it’s a very fair one to ask. I’ll try answering it a slightly different way, though, because it’s not necessarily a “which one is best” kind of thing, but rather “which one is right for you.”</p><p>So let’s get into it.</p><figure class="inline-layout"><fw-embed-feed channel="toms_guide" playlist="vJ0JVG" mode="row" player_placement="bottom-right"></fw-embed-feed></figure><h2 class="article-body__section" id="section-snap-specs-vs-xreal-aura-specs"><span>Snap Specs vs Xreal Aura: Specs</span></h2><div ><table><thead><tr><th class="firstcol " ><p>Specification</p></th><th  ><p>Snap Specs</p></th><th  ><p>Xreal Aura</p></th></tr></thead><tbody><tr><td class="firstcol " ><p><strong>Weight</strong></p></td><td  ><p>132 grams (47mm), 136 grams (52mm)</p></td><td  ><p>>95 grams (glasses)</p></td></tr><tr><td class="firstcol " ><p><strong>Form factor</strong></p></td><td  ><p>Standalone AR glasses</p></td><td  ><p>AR glasses and compute puck</p></td></tr><tr><td class="firstcol " ><p><strong>Chip</strong></p></td><td  ><p>2x Snapdragon chips</p></td><td  ><p>Snapdragon Reality Elite</p></td></tr><tr><td class="firstcol " ><p><strong>Display</strong></p></td><td  ><p>Waveguide lenses - 57-degree FOV</p></td><td  ><p>Prism-based Micro-OLED display - 70-degree FOV</p></td></tr><tr><td class="firstcol " ><p><strong>Tracking</strong></p></td><td  ><p>6DoF and hand tracking via cameras and sensors</p></td><td  ><p>6DoF spatial and hand tracking via 2x world-facing cameras</p></td></tr><tr><td class="firstcol " ><p><strong>OS</strong></p></td><td  ><p>Snap OS</p></td><td  ><p>Android XR</p></td></tr></tbody></table></div><h2 class="article-body__section" id="section-where-snap-specs-win"><span>Where Snap Specs win</span></h2><ul><li><strong>A standalone pair of glasses — no compute puck required</strong></li><li><strong>Software advantage — AR computing platform with over 5 million lenses to download and use</strong></li><li><strong>Less VR headset in a pair of glasses, and more a full rethink of spatial computing</strong></li></ul><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:3840px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="bgk3JYKAvMvGJBXJPxXupf" name="Snap Specs" alt="Snap Specs" src="https://cdn.mos.cms.futurecdn.net/bgk3JYKAvMvGJBXJPxXupf.jpg" mos="" align="middle" fullscreen="" width="3840" height="2160" 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>Standalone smart glasses are rather limited in capability at the moment — either display-free AI glasses like the <a href="https://www.tomsguide.com/computing/smart-glasses/ray-ban-meta-gen-2-review">Ray-Ban Metas</a> or ambient computing options with subtle screens like <a href="https://www.tomsguide.com/computing/smart-glasses/even-realities-g2-smart-glasses-review">Even Realities G2</a>.</p><p>Snap Specs is on a whole different level, as the company has thrown everything and the kitchen sink at them to reinvent spatial computing in something the size of a pair of chunky Prada shades.</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:480px;"><p class="vanilla-image-block" style="padding-top:75.00%;"><img id="jveTgBacuzPXXeMSd7WZbb" name="Snapchat Spectacles" alt="Snapchat Spectacles" src="https://cdn.mos.cms.futurecdn.net/jveTgBacuzPXXeMSd7WZbb.gif" mos="" align="middle" fullscreen="" width="480" height="360" 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>It’s the result of a multi-year experiment, and developers have been busy on early hardware. Rather than a small selection of XR apps alongside a bunch of phone apps blown up for the big screen, you’ve got 450k developers who’ve made over 5 million lenses. </p><p>And the experiences are a cut above the rest in terms of giving me the future I see for smart glasses — advanced tracking that is able to suspend content in free space without taking over your whole screen space. I’ve seen demos like labeling everything on a shelf, giving me a visual guide on how to to an ollie on a skateboard and more.</p><p>It’s unlike anything else you can try right now.</p><h2 class="article-body__section" id="section-where-snap-specs-lose"><span>Where Snap Specs lose</span></h2><ul><li><strong>Design is rather bulky</strong></li><li><strong>Field of view not as wide</strong></li><li><strong>$2,195 is a steep price to pay</strong></li></ul><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:3840px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="BR5qJseLxE3fwAfDXh8vCg" name="Snap Specs" alt="Snap Specs" src="https://cdn.mos.cms.futurecdn.net/BR5qJseLxE3fwAfDXh8vCg.jpg" mos="" align="middle" fullscreen="" width="3840" height="2160" 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>There’s a reason why out of all the photos I took of Snap Specs, this one of Evan’s ear struggling at the back went viral. Compared to previous developer hardware, you can see how hard the company’s worked to reduce the size and weight, but it’s clearly still a bulky pair of glasses.</p><p>Yes, Snap has designed around that — designed around the challenges of squishing that much tech into the stems of the specs themselves. But that makes a chunky aesthetic unavoidable. I kind of dig it, but can completely appreciate it’s not everyone’s cup of tea.</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:3840px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="htPU9XqEbcpWbPjrX8fhkf" name="Snap Specs" alt="Snap Specs" src="https://cdn.mos.cms.futurecdn.net/htPU9XqEbcpWbPjrX8fhkf.jpg" mos="" align="middle" fullscreen="" width="3840" height="2160" 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>Then there’s the price of it all, which I get is a lower starting cost than the $10,000 to make Meta’s Project Orion (or $3,500 for Apple Vision Pro), but $2,195 in this economy is still a hefty number.</p><h2 class="article-body__section" id="section-where-xreal-aura-win"><span>Where Xreal Aura win</span></h2><ul><li><strong>Lighter, more comfortable glasses</strong></li><li><strong>Android XR brings a more VR headset-like experience to AR glasses</strong></li><li><strong>Anticipating a cheaper price</strong></li></ul><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:3840px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="dTFfLfMFavHmphsEFNxoA9" name="Xreal Project Aura" alt="Xreal Project Aura" src="https://cdn.mos.cms.futurecdn.net/dTFfLfMFavHmphsEFNxoA9.jpg" mos="" align="middle" fullscreen="" width="3840" height="2160" 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 Auras answer the “future of spatial computing” question in a more traditional way — take some AR glasses, pack a puck full of compute power, and make a VR headset experience out of it.</p><p>Snapdragon Reality Elite does a lot of the driving here alongside the X1S spatial coprocessor and those world-facing cameras to track the free space around you and give you the Samsung Galaxy XR in tethered specs.</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:3840px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="AGyTRXSVxHPwdJCadkGnhn" name="Xreal Aura" alt="Xreal Aura" src="https://cdn.mos.cms.futurecdn.net/AGyTRXSVxHPwdJCadkGnhn.jpg" mos="" align="middle" fullscreen="" width="3840" height="2160" 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>And what surprised me every time I’ve tried these is the critical difference moving from an isolating headset experience with a virtual see-through display to optical see-through can bring. </p><p>Tabletop gaming in Demeo feels more accurately merged with the world around you, Gemini Live feels like real-time advice in the real world rather than a camera-driven guide, and more. Throw in a 70-degree field of view for immersion and you’re off to a strong start.</p><h2 class="article-body__section" id="section-where-xreal-aura-lose"><span>Where Xreal Aura lose</span></h2><ul><li><strong>But will still be expensive</strong></li><li><strong>Compute puck makes them awkward to use in public</strong></li><li><strong>A different, more limited type of spatial computing</strong></li></ul><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:3019px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="j2c8YKieMuBjrk6wEPQhGJ" name="Xreal Project Aura" alt="Xreal Project Aura" src="https://cdn.mos.cms.futurecdn.net/j2c8YKieMuBjrk6wEPQhGJ.jpg" mos="" align="middle" fullscreen="" width="3019" height="1698" 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>So like I said above, I’m anticipating these will be cheaper than the Snap Specs. However, just because something is cheaper doesn't mean it’ll be a good price. </p><p>I’d love for this to be sub-$1,000, but we’re not in that kind of universe for a while (hi, <a href="https://www.tomsguide.com/computing/ram-price-crisis-2026-everything-you-need-to-know">RAMageddon</a>). I’m thinking it’ll be more like $1,300 or more.</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:3840px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="Yjvn5sNNPJhMeqKZvckjw8" name="Xreal Project Aura" alt="Xreal Project Aura" src="https://cdn.mos.cms.futurecdn.net/Yjvn5sNNPJhMeqKZvckjw8.jpg" mos="" align="middle" fullscreen="" width="3840" height="2160" 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>That’s a tough pill to swallow — especially when you think about the use cases of these. Given they’re AR glasses with a puck, you won’t be wearing these out in any public situations outside of flights and public transport.</p><p>And of course there’s that difference in vision. Snap Specs wants to reinvent spatial computing, whereas Xreal Aura brings VR to a smaller device.</p><h2 class="article-body__section" id="section-outlook"><span>Outlook</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:3840px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="AStxUqZoTX9GTJyXyDxysf" name="Snap Specs" alt="Snap Specs" src="https://cdn.mos.cms.futurecdn.net/AStxUqZoTX9GTJyXyDxysf.jpg" mos="" align="middle" fullscreen="" width="3840" height="2160" 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>Of course, this is way too early to call, as I’m basing this on the hands-on time I’ve had with both (for Snap Specs, I went eyes-on with the new glasses, and hands-on with Snap OS via the developer hardware). But it paints a clearer picture of what to expect from each.</p><p>I’d get the Xreal Auras if I was looking for a more traditional VR headset experience compressed down to something the size of AR glasses. </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:3840px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="6WFT86FQBFuqg4mr3Vvwx8" name="Xreal Project Aura" alt="Xreal Project Aura" src="https://cdn.mos.cms.futurecdn.net/6WFT86FQBFuqg4mr3Vvwx8.jpg" mos="" align="middle" fullscreen="" width="3840" height="2160" 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 can imagine this being a great experience on long haul flights or around home, but that compute puck does limit where you’re going to feel comfortable using it.</p><p>However, if you want to take a real big step into the future of spatial computing — AR infused with AI and a massive OS platform atop standalone specs, then Snap Specs is the way to go (provided you got deep pockets).</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/computing/smart-glasses/im-just-going-to-wear-this-for-30-minutes-for-fun-even-realities-cto-shares-his-thoughts-on-snap-specs-and-gives-details-on-upcoming-g3-smart-glasses">'136 grams is not for all-day wearing' — Even Realities CTO sounds off on Snap Specs, and gives details on the future roadmap</a></li><li><a href="https://www.tomsguide.com/computing/augmented-reality/best-of-awe-2026-the-top-gadgets-that-show-us-the-future-of-xr">Best of AWE 2026: 7 top gadgets that show us the future of XR</a></li><li><a href="https://www.tomsguide.com/computing/smart-glasses/tested-xreal-aura-does-work-with-nintendo-switch-over-usb-c-they-wont-tell-me-how-they-did-it-but-i-think-snapdragon-reality-elite-and-android-xr-is-the-way">Tested: Xreal Aura DOES work with Nintendo Switch over USB-C — they won’t tell me how they did it, but I think Snapdragon Reality Elite and Android XR is the way</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ I just tried Siri AI in the iOS 27 CarPlay beta — and this assistant is way more helpful than before ]]></title>
                                                                                                                                                                                                <link>https://www.tomsguide.com/phones/iphones/i-just-tried-siri-ai-in-the-ios-27-carplay-beta-and-this-assistant-is-way-more-helpful-than-before</link>
                                                                            <description>
                            <![CDATA[ With the iOS 27 developer beta, I've been trying out Siri AI in CarPlay to see what new tricks Apple's AI assistant has to offer while I'm driving. Here's what I found. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">YQpRjhEckJFkTFQ4683Zii</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/Spea4XZ6f3zkgGZWP3hTp5-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Sat, 27 Jun 2026 06:30:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[iPhones]]></category>
                                                    <category><![CDATA[Vehicle Tech]]></category>
                                                    <category><![CDATA[Phones]]></category>
                                                                                                <author><![CDATA[ john.velasco@futurenet.com (John Velasco) ]]></author>                    <dc:creator><![CDATA[ John Velasco ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/TSj224oX8d5ERXaDs8pDGd.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ null ]]></dc:description>
                                                                                                                                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/Spea4XZ6f3zkgGZWP3hTp5-1280-80.jpg">
                                                            <media:credit><![CDATA[John Velasco / Tom&#039;s Guide]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Siri AI in iOS 27 CarPlay.]]></media:description>                                                            <media:text><![CDATA[Siri AI in iOS 27 CarPlay.]]></media:text>
                                <media:title type="plain"><![CDATA[Siri AI in iOS 27 CarPlay.]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/Spea4XZ6f3zkgGZWP3hTp5-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>I have a confession to make. As much as I use CarPlay whenever I’m testing the <a href="https://www.tomsguide.com/best-picks/best-electric-cars-today">best electric cars</a>, I rarely try to interact with Siri. Instead, I’ve found <a href="https://www.tomsguide.com/ai/i-wore-meta-ray-ban-smart-glasses-while-shopping-at-target-7-things-that-were-surprisingly-useful">Meta AI</a> to be way more helpful because it’s something I can access right from my <a href="https://www.tomsguide.com/reviews/ray-ban-meta-smart-glasses">Ray-Ban Meta</a> sunglasses. But the real reason I use it over Siri in CarPlay is simply because of how smart it is.</p><p>Now that I’m running the <a href="https://www.tomsguide.com/phones/iphones/wwdc-2026-how-to-install-the-ios-27-developer-beta-right-now">iOS 27 developer beta</a> on my <a href="https://www.tomsguide.com/phones/iphones/apple-iphone-17-pro-review">iPhone 17 Pro</a>, I have access to <a href="https://www.tomsguide.com/phones/iphones/i-spent-a-week-with-siri-ai-here-are-my-honest-pros-and-cons">Siri AI</a> on all of my drives. Since I’ve been so accustomed to Meta AI, I’m way more critical and have higher expectations for how Apple’s new AI chatbot works. After a week of using it, here’s what I found.</p><h2 id="conversations-are-way-more-fluid">Conversations are way more fluid</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="CFZYK8xykipzqTiiomPzq5" name="Siri AI in iOS 27 beta CarPlay" alt="Siri AI in iOS 27 CarPlay." src="https://cdn.mos.cms.futurecdn.net/CFZYK8xykipzqTiiomPzq5.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: John Velasco / Tom's Guide)</span></figcaption></figure><p>What immediately stands out the most is how much more conversational Siri AI is compared to previous versions. Apple has improved Siri's conversational skills over the years, but this update is a huge leap because the assistant sounds more human than ever before — complete with natural inflections and tonal shifts.</p><div><blockquote><p>I actually love interacting with this version of Siri. It’s fun, way more engaging, and has an authentic tone that completely sheds the robotic tendencies of past versions.</p></blockquote></div><p>I asked about upcoming Fourth of July events happening around where I live, and I was really impressed that it recommended three options. However, when I followed up to ask which one it recommended most, Siri AI explicitly said it couldn't pick just one and simply rehashed the options. Additionally, I noticed that I can’t interrupt Siri AI while it's talking like I can on my phone — which I suspect is due to the louder ambient noise within the cabin space.</p><p>Despite this, I actually love interacting with this version of Siri. It’s fun, way more engaging, and has an authentic tone that completely sheds the robotic tendencies of past versions.</p><h2 id="still-needs-better-deep-research">Still needs better deep research</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="oqgsbCjiXPr7hTqUyu7Xj5" name="Siri AI in iOS 27 beta CarPlay" alt="Siri AI in iOS 27 CarPlay." src="https://cdn.mos.cms.futurecdn.net/oqgsbCjiXPr7hTqUyu7Xj5.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: John Velasco / Tom's Guide)</span></figcaption></figure><p>On one of my commutes to work, I noticed that Google Maps was forcing me to take the Garden State Parkway instead of my usual route along the New Jersey Turnpike. After double-checking the traffic conditions, I saw that it was completely red along the Turnpike, so I asked Siri AI to find out why.</p><p>I simply asked it to check why there was so much traffic on my route, but it couldn't check live traffic conditions — so that was a bust. After that, I explicitly asked Siri to look up any social media posts or news stories about traffic along the Turnpike. It rattled off a list of things, including ongoing construction near specific exits and various road closures. I doubted those were the actual reasons for the slowdown, and I ended up looking it up myself once I got to work.</p><p>When I finally got to the office, I found out there had been a four-truck crash that morning with one fatality, which explained why the highway was completely red for a long stretch and why Google Maps had rerouted me to the Parkway instead.</p><p>I’m hoping that Siri AI gets better at deep research, especially when it comes to pulling information from third-party apps — but right now, it’s just not there yet.</p><h2 id="siri-ai-remembers-tasks">Siri AI remembers tasks</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:1803px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="3CVLkKy5AENT89ipW6XMZc" name="Siri AI in CarPlay iOS 27" alt="Siri AI in CarPlay iOS 27 screenshot." src="https://cdn.mos.cms.futurecdn.net/3CVLkKy5AENT89ipW6XMZc.jpg" mos="" align="middle" fullscreen="" width="1803" height="1014" 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>Finally, I wanted to see how well Siri AI could jot down notes for me while driving. I had just wrapped up testing the 2026 Mazda CX-5, and rather than waiting until later in the day, I asked Siri AI to log some pros and cons about the SUV.</p><div><blockquote><p>The best part about Siri AI in CarPlay is that it remembers the context of tasks it just performed.</p></blockquote></div><p>The best part about Siri AI in CarPlay is that it remembers the context of tasks it just performed. For example, I initially rattled off a few points, noting how the Mazda now offers a much more modern infotainment experience, but then remembered another detail a couple of minutes later. I asked Siri AI to go back into that note to add the additional comments, and it was smart enough to know exactly which note to update.</p><p>When I got to work later on, I opened the saved note and was surprised to see it had actually attempted a proper layout — complete with a title and bulleted list. While it wasn’t perfect, it gave me a solid starting point. Moving forward, it would be great if Siri could log things directly into a Google Docs file, but this test proved to me that I can finally rely on the assistant to remember and recall information on the fly.</p><h2 id="outlook">Outlook</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="Jjbgx2FaXvJsPzU7gv7qs5" name="Siri AI in iOS 27 beta CarPlay" alt="Siri AI in iOS 27 CarPlay." src="https://cdn.mos.cms.futurecdn.net/Jjbgx2FaXvJsPzU7gv7qs5.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: John Velasco / Tom's Guide)</span></figcaption></figure><p>I have another confession to make: The only reason I gave Siri AI a shot in the first place was that I accidentally left my Ray-Ban Meta sunglasses at home on one of my drives.</p><p>Now, I can confidently say that Siri AI is way more helpful, and I can actually rely on it while driving. As another example of its capabilities, I asked it to look up vehicles similar to the Infiniti QX60 I was driving, specifically comparing it to the <a href="https://www.tomsguide.com/vehicle-tech/2026-genesis-gv80-review">Genesis GV80</a> I previously tested. I loved how it broke down the luxury, three-row SUVs side by side — including granular details like the price differences between trims.</p><p>Moving forward, I’m really looking forward to the potential of broader, cross-app integration with third-party software, because that'll truly be a game-changer behind the wheel. A perfect example would be placing a <a href="https://www.tomsguide.com/phones/samsung-phones/i-just-asked-gemini-on-the-galaxy-s26-to-order-dunkin-donuts-for-me-and-24-minutes-later-it-got-delivered-to-my-door">Dunkin’ Donuts order via voice</a>. While I could technically use the dedicated Dunkin’ CarPlay app, doing so is distracting while driving, and it doesn't offer access to the full menu anyway. I would love to just ask Siri AI to handle the order for me using simple voice instructions.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-W2aRGe"></div>                            </div>                            <script src="https://kwizly.com/embed/W2aRGe.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/phones/motorola-phones/motorola-razr-ultra-2026-review">Motorola Razr Ultra 2026 review: Better does come at a premium price</a></li><li><a href="https://www.tomsguide.com/phones/simo-solis-lite-hotspot-review">I tested this puck shaped mobile hotspot — and it’s the simplest way to get online</a></li><li><a href="https://www.tomsguide.com/phones/best-early-prime-day-2026-phone-accessories-deals-magsafe-wallets-power-banks-chargers-and-more">I tested 100+ phone accessories in the last year and these are my favorite early Prime Day deals — MagSafe wallets, power banks, chargers, and more</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ I built five ChatGPT agents — then replaced them with one 'master' AI ]]></title>
                                                                                                                                                                                                <link>https://www.tomsguide.com/ai/i-built-five-chatgpt-agents-then-replaced-them-with-one-master-ai</link>
                                                                            <description>
                            <![CDATA[ I built five ChatGPT agents, then replaced them with one routing AI that chooses the right assistant for every task. Here's how to set it up. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">icuKKkDZh72ubbnjSWZ3CW</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/pajU7eXF66SeEf3o5EDCL3-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Sat, 27 Jun 2026 05:30:00 +0000</pubDate>                                                                                                                                <updated>Sun, 28 Jun 2026 22:56:25 +0000</updated>
                                                                                                                                            <category><![CDATA[AI]]></category>
                                                                                                <author><![CDATA[ amanda.caswell@futurenet.com (Amanda Caswell) ]]></author>                    <dc:creator><![CDATA[ Amanda Caswell ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/zYjevim2q7FjQiefqpjZRB.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ null ]]></dc:description>
                                                                                                                                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/pajU7eXF66SeEf3o5EDCL3-1280-80.jpg">
                                                            <media:credit><![CDATA[Future]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[ChatGPT ]]></media:description>                                                            <media:text><![CDATA[ChatGPT ]]></media:text>
                                <media:title type="plain"><![CDATA[ChatGPT ]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/pajU7eXF66SeEf3o5EDCL3-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Like a lot of people who use AI every day, my ChatGPT sidebar had become crowded. I have a custom GPT for just about everything from fact-checking to dedicated brainstorming sessions and messy notes. And while each one is useful, together they are a problem. </p><p>Every single new task starts with another new decision as I wonder if I should open research GPT first or jump straight into writing and come back for editing? And then there's always the question of "Wait, didn't I already design this assistant a few months ago?" </p><p>In other words, my GPTs were chaotic and I knew I wasn't being as productive as I could be. So instead of creating another specialist, I tried something different. I built one AI whose only job is deciding which AI should handle the task.</p><p>Surprisingly, it has become the most useful assistant in my workflow.</p><h2 id="why-i-stopped-thinking-about-ai-as-one-chatbot">Why I stopped thinking about AI as one chatbot</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="eLW33tUjLejodLo8UXCVth" name="z - 2026-04-10T155948.360" alt="ChatGPT Projects" src="https://cdn.mos.cms.futurecdn.net/eLW33tUjLejodLo8UXCVth.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: Future)</span></figcaption></figure><p>Most people still use AI as though it's a single assistant that should be good at everything, but <a href="https://www.tomsguide.com/ai/reddit-users-arent-picking-one-ai-chatbot-anymore-heres-how-they-stack-their-tools">users are finally catching on that there is a better way</a>. AI models can handle many types of tasks and jobs reasonably well, but I've found they perform better when each assistant has one clear responsibility.</p><p>With any productive team, everyone has a specialty. That's why I decided my AI should work the same way. So I built five specialist agents. </p><p>Here's the team I originally built:</p><ul><li><strong>Research Agent.</strong> Finds reliable sources, identifies missing context and suggests follow-up questions before I begin writing.</li><li><strong>Brainstorm Agent. </strong>Similar to a research agent, this one takes my messy notes and turns them into bullet points with viable ideas.</li><li><strong>Fact-check Agent. </strong>Flags unsupported claims, reminds me where citations are needed and looks for weak sourcing.</li><li><strong>Editor Agent. </strong>Improves readability, removes repetition and smooths awkward transitions before publication.</li><li><strong>Review Agent. </strong>Takes a look at traffic, follow up possibilities and engagement.</li></ul><p>I've built agents that work for me as a journalist, but you could create your own depending on your needs or career. If you aren't sure what types of agents to create, just thinking about what your ongoing needs are and how they aren't being met. You could even ask ChatGPT to suggest agents for you. </p><p>Routing agents have changed everything for me. Instead of asking myself which GPT to open, I now start every project with one assistant.</p><p>Its only responsibility is deciding what happens next.</p><p>For example, if I tell it: <em>"I'm considering writing about [i.e. Apple Intelligence] but don't have quotes or much information yet."</em></p><p>It will automatically respond with the best agent for the job. It also knows when not to suggest an agent. For example, it's not going to suggest a Fact-check agent if I'm rewriting an email in a softer tone to my neighbor who borrowed my lawn mower. </p><p>If I'm brainstorming ideas, it may suggest Research agent after our brainstorming session. Instead of forcing me to remember my workflow, it creates one automatically. That small change has made me far more productive than I expected.</p><h2 id="how-to-build-your-own-routing-agent">How to build your own routing agent</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="KS79QDq7udmfQ3RU9BTwuc" name="Custom GPT" alt="Custom GPT screenshot" src="https://cdn.mos.cms.futurecdn.net/KS79QDq7udmfQ3RU9BTwuc.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: Future)</span></figcaption></figure><p>Start by creating specialist assistants. Do you this by identifying the three to five tasks you repeat most often. For example: analyzing, summarizing, brainstorming, writing, image generation. </p><p>Then, create one <a href="https://www.tomsguide.com/ai/i-tested-5-custom-gpts-skip-the-rest-and-try-these-today">Custom GPT</a> (or <a href="https://www.tomsguide.com/ai/chatgpt-projects-just-got-a-big-upgrade-heres-whats-new">Project</a>) for each job. The more focused each assistant is, the better they'll perform.<br><br>Next, build one routing agent. You'll do this by creating an additional Custom GPT. </p><p><strong>The prompt I use is</strong>:<em> "You are my AI Routing Agent. Whenever I describe a task, identify my goal, decide which specialist agent should complete it, recommend the best sequence if multiple agents are needed and explain your reasoning briefly. If important information is missing, ask clarifying questions before continuing."</em></p><p>From there, give it a decision framework. Mine evaluates every request using five questions: <em>What is the user's goal? Which specialist is best suited to this task? Should more than one specialist be involved? In what order should they work? Is any information missing before work begins?</em></p><p>That keeps every project consistent. You're going to want to start every project with the routing agent. So, instead of opening whichever GPT seems right, begin with your routing assistant. Then, just naturally describe your task and watch it reccomend the workflow. </p><p>You'll spend less time managing your AI tools and more time actually getting work done. Plus, as you discover repetitive tasks, add new specialists. Over time, you might create assistants for SEO optimization, social media posts, coding, spreadsheet analysis, email drafting, etc. </p><p>The routing agent simply learns about the new specialist and incorporates it into future workflows.</p><h2 id="why-this-works">Why this works</h2><p>This idea is actually the foundation of <a href="https://www.tomsguide.com/ai/anthropics-fable-five-ban-exposed-ais-next-big-problem-but-sakanas-fugu-may-have-the-answer">Sakana</a> —<strong> </strong>but that AI assistant goes even further by suggesting different chatbot models. What I like about my system is that it still keeps the agents within the same platform. It works just as well with ChatGPT agents as it does with Claude. </p><p>If I create a new specialist later, such as an image generation or social media agent, I won't have to remember when to use it. I simply teach my routing agent that the new specialist exists, and it can recommend it whenever it's appropriate. Over time, the system becomes smarter without becoming more complicated.<br><br>Give it a try yourself and let me know what you think in the comments.</p><a href="https://follow.it/articles-by-amanda-caswell-tom-s-guide?leanpub" class="button button--large button--primary">Follow Amanda Caswell and stay ahead of the AI curve</a><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/ai/i-turned-youtube-into-an-ai-bootcamp-with-notebooklm-heres-my-workflow"><strong>I turned my YouTube watchlist into an AI bootcamp with NotebookLM — here's how</strong></a></li><li><a href="https://www.tomsguide.com/ai/i-built-five-chatgpt-agents-then-replaced-them-with-one-master-ai"><strong>I built five ChatGPT agents — then replaced them with one 'master' AI</strong></a></li><li><a href="https://www.tomsguide.com/ai/i-used-chatgpt-to-audit-my-subscriptions-these-prompts-helped-me-find-nearly-usd2-000-a-year-in-recurring-charges"><strong>I used ChatGPT to audit my subscriptions — these prompts helped me find nearly $2,000 a year in recurring charges</strong></a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ How to use a VPN to get better signal on crowded networks – stadiums, airports, World Cup fan zones ]]></title>
                                                                                                                                                                                                <link>https://www.tomsguide.com/computing/vpns/how-to-use-a-vpn-to-get-better-signal-on-crowded-networks-stadiums-airports-world-cup-fan-zones</link>
                                                                            <description>
                            <![CDATA[ It's worth using a VPN on crowded public networks – and with the right settings, a few seconds of tweaking can keep your connection fast, secure, and leak-free. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">4KnCNU2NrGEZxRoPeT7jLm</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/iwe78CWeJYTaQrJKSEEr84-1280-80.png" type="image/png" length="0"></enclosure>
                                                                        <pubDate>Fri, 26 Jun 2026 15:00:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[VPNs]]></category>
                                                    <category><![CDATA[Streaming]]></category>
                                                    <category><![CDATA[Computing Peripherals]]></category>
                                                    <category><![CDATA[Internet]]></category>
                                                    <category><![CDATA[Entertainment]]></category>
                                                                                                                    <dc:creator><![CDATA[ Aleksandar Stevanović ]]></dc:creator>                                                                                                        <dc:description><![CDATA[ null ]]></dc:description>
                                                                                                                                                                                                                                                <media:content type="image/png" url="https://cdn.mos.cms.futurecdn.net/iwe78CWeJYTaQrJKSEEr84-1280-80.png">
                                                            <media:credit><![CDATA[Getty Images]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Fully packed stands in a large stadium]]></media:description>                                                            <media:text><![CDATA[Fully packed stands in a large stadium]]></media:text>
                                <media:title type="plain"><![CDATA[Fully packed stands in a large stadium]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/iwe78CWeJYTaQrJKSEEr84-1280-80.png" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Stadiums, airports, and fan parks are some of the worst environments imaginable for public Wi-Fi. Tens of thousands of people competing for the same signal means packet loss, crawling speeds, and connections that drop without warning. So, for example, if you're heading to a few games at the <a href="https://www.tomsguide.com/entertainment/streaming/theres-a-simple-way-to-watch-world-cup-2026-for-free">FIFA World Cup 2026</a>, things might not be as smooth as you'd like.</p><p>One of the<a href="https://www.tomsguide.com/best-picks/best-vpn"> best VPNs</a> is a handy tool to have at your disposal on networks like these. While it's fairly unlikely nowadays you'll be caught out by a <a href="https://www.tomsguide.com/computing/online-security/what-is-a-man-in-the-middle-attack">man-in-the-middle attack</a>, boosting your privacy can only be a good thing – and when a VPN is set up right, a VPN may also be able to increase your connection speeds significantly.</p><p>Here, I'll run down a few quick settings to tweak to make your public Wi-Fi experience more bearable.</p><div class="product"><a data-dimension112="b3548274-ac8f-4465-8770-518b393dfed5" data-action="Deal Block" data-label="Norton VPN | 60-day money-back guarantee" data-dimension48="Norton VPN | 60-day money-back guarantee" data-dimension25="$" href="https://norton.ow5a.net/c/221109/3913583/4405?sharedid=tg&param1=aff&param2=worldcup26_dealpost&param3=vpn&subid1=Deal_TG" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:280px;"><p class="vanilla-image-block" style="padding-top:56.43%;"><img id="cgidcx9LYVJedVXABk3BpC" name="nortonvpn_graphic_-_affiliates__5_" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/cgidcx9LYVJedVXABk3BpC.png" mos="" align="middle" fullscreen="" width="280" height="158" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><a href="https://norton.ow5a.net/c/221109/3913583/4405?sharedid=tg&param1=aff&param2=worldcup26_dealpost&param3=vpn&subid1=Deal_TG" target="_blank" rel="nofollow" data-dimension112="b3548274-ac8f-4465-8770-518b393dfed5" data-action="Deal Block" data-label="Norton VPN | 60-day money-back guarantee" data-dimension48="Norton VPN | 60-day money-back guarantee" data-dimension25="$"><strong>Norton VPN | 60-day money-back guarantee</strong></a><br>Norton VPN is our top pick for World Cup 2026 streaming, with a 60-day money-back guarantee on annual plans – double the industry standard – covering the entire tournament risk-free.</p><p><strong>What you'll get...</strong></p><p>🔒 Native app for Amazon Fire TV devices<br>⚡️ WireGuard protocol across all Apple platforms<br>📺 Apps for Google TV, Android TV, and Apple TV<br>🌍 Servers in 30+ countries for home-country streaming</p><p>A 12-month Norton VPN plan starts at <a href="https://norton.ow5a.net/c/221109/3913583/4405?sharedid=tg&param1=aff&param2=worldcup26_dealpost&param3=vpn&subid1=Deal_TG" target="_blank" rel="nofollow"><strong>$3.33 per month</strong></a> ($39.99 upfront, pre-tax) and comes with a 60-day money-back guarantee on annual plans.<a class="view-deal button" href="https://norton.ow5a.net/c/221109/3913583/4405?sharedid=tg&param1=aff&param2=worldcup26_dealpost&param3=vpn&subid1=Deal_TG" target="_blank" rel="nofollow" data-dimension112="b3548274-ac8f-4465-8770-518b393dfed5" data-action="Deal Block" data-label="Norton VPN | 60-day money-back guarantee" data-dimension48="Norton VPN | 60-day money-back guarantee" data-dimension25="$">View Deal</a></p></div><h2 id="pick-your-protocol">Pick your protocol</h2><p>A VPN protocol is the set of rules that determines how your device encrypts and moves your data. On a congested or restrictive network, the wrong protocol can mean failed connections, throttled speeds, or both – and switching is often the quickest fix.</p><p>WireGuard should be your first port of call. It's a modern protocol built with a low data overhead and near-instant reconnection times, making it well suited to the kind of unstable connections you'll find in a packed stadium or airport terminal. Most VPN apps already default to it – but if you're on an iPhone, check your settings, as IKEv2 is often the default instead.</p><p>IKEv2 is a solid runner-up for mobile users who switch frequently between Wi-Fi and cellular data. It handles network changes smoothly, though speeds won't quite match WireGuard.</p><p>If you're struggling to connect at all, try OpenVPN. It's generally slower than WireGuard, but its ability to run on port 443 – the same port used by standard web traffic – means it's more likely to work on networks that try to block VPNs. For a deeper look at how the<a href="https://www.tomsguide.com/best-picks/best-fast-vpn"> fastest VPNs</a> handle different conditions, our dedicated guide is worth a read. </p><h2 id="stay-stealthy">Stay stealthy</h2><p>Many stadiums and airports actively manage their networks by throttling heavy data users – a necessary measure when tens of thousands of people are sharing the same connection, but one that can reduce your speeds to near-unusable levels during a big event.</p><p>VPNs can sidestep this by hiding your traffic from the network – if it can't see what you're doing, it can't single you out for throttling. The catch is that many venues have wised up to this, and will throttle any traffic that looks like VPN traffic too.</p><p>The fix is Stealth Mode – sometimes called Obfuscation or Scramble depending on which app you're using. It disguises your VPN traffic as ordinary web traffic, so the network treats it accordingly. You keep the speed benefits of bypassing throttling while your actual activity stays hidden.</p><p>Unfortunately, if the network you're connected to flat-out throttle's <em>everyone's</em> connection, regardless of how much data theyre using, a VPN won't make much of a difference. As always, there's an element of trial and error to this.</p><h2 id="set-switches-to-kill">Set switches to kill</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:7687px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="Uge7NgrXmKH5Fcs7JCHRZ8" name="Kill switch image article header.jpg" alt="Green switch in the On position on a pastel yellow background" src="https://cdn.mos.cms.futurecdn.net/Uge7NgrXmKH5Fcs7JCHRZ8.jpg" mos="" align="middle" fullscreen="" width="7687" height="4323" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Javier Zayas Photography)</span></figcaption></figure><p>Switching between Wi-Fi and mobile data – or simply dropping out of range in a crowded venue – can cause your VPN connection to drop momentarily. That split second is enough for your real IP address to be exposed before the VPN reconnects, which defeats the purpose of using one in the first place.</p><p>A kill switch solves this by blocking all internet traffic the moment your VPN drops, preventing any leaks until the connection is restored. Pair this with Auto-Connect, which ensures your VPN engages automatically whenever you join an untrusted public network, and you've closed off the two most common sources of accidental exposure.</p><p>As a side-note, your VPN "blocking all internet traffic" sounds drastic, but in reality, it's nothing to worry about. This only equates to a second or two of downtime, which is very unlikely to be noticed.</p><h2 id="split-the-tunnel">Split the tunnel</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="oHZ43H5QK9Ni6g6KV48Zvc" name="Seattle Stadium, temporarily renamed from Lumen Field, pictured ahead of World Cup 2026" alt="Seattle Stadium, temporarily renamed from Lumen Field, pictured ahead of World Cup 2026" src="https://cdn.mos.cms.futurecdn.net/oHZ43H5QK9Ni6g6KV48Zvc.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: Jason Redmond/AFP via Getty Images)</span></figcaption></figure><p>Running all your apps through a VPN simultaneously puts extra demand on both your device and the network – bandwidth you can't afford to waste when thousands of people are competing for the same signal.</p><p>Split tunneling lets you choose which apps use the VPN and which don't. Route your sensitive apps – banking, email, social media logins – through the encrypted tunnel, and let everything else connect directly. Checking live scores or streaming music in the background doesn't need VPN protection, and bypassing it for those apps can free up enough speed to make a real difference. Plus, by reducing the amount of data you need to encrypt will also save you precious battery life.</p><h2 id="bottom-line">Bottom line</h2><p>A few seconds spent in your VPN's settings can be the difference between a working connection and a frustrating one. </p><p>Switch your protocol – WireGuard for speed, OpenVPN if you're struggling to connect – enable Stealth mode, turn on your kill switch, and set up split tunneling. Do all of this, and you'll be in a far better position than the thousands of other people on the same network. </p><div ><table><caption>Quick Cheat Sheet</caption><thead><tr><th class="firstcol " ><p><strong>What to look for in your app</strong></p></th><th  ><p><strong>What to set it to</strong></p></th><th  ><p><strong>What it does for you</strong></p></th></tr></thead><tbody><tr><td class="firstcol " ><p><strong>Protocol / Connection Type</strong></p></td><td  ><p>WireGuard / OpenVPN</p></td><td  ><p>Generally gives you the fastest speed and quickest reconnections. If you have connection issues, try <strong>OpenVPN</strong>.</p></td></tr><tr><td class="firstcol " ><p><strong>Stealth / Obfuscation</strong></p></td><td  ><p>ON (if you struggle to connect)</p></td><td  ><p>Not always necessary, but helps stop the venue's Wi-Fi from blocking your VPN.</p></td></tr><tr><td class="firstcol " ><p><strong>Kill Switch</strong></p></td><td  ><p>ON (always)</p></td><td  ><p>Keeps you safe if the crowded Wi-Fi suddenly drops.</p></td></tr><tr><td class="firstcol " ><p><strong>Split Tunneling</strong></p></td><td  ><p>Enabled (Select apps)</p></td><td  ><p>Saves speed by only protecting your most important apps.</p></td></tr></tbody></table></div><p>We test and review VPN services in the context of legal recreational uses. For example:<strong>1.</strong> Accessing a service from another country (subject to the terms and conditions of that service).<strong>2.</strong> Protecting your online security and strengthening your online privacy when abroad.We do not support or condone the illegal or malicious use of VPN services. Consuming pirated content that is paid-for is neither endorsed nor approved by Future Publishing.</p>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ Grill smarter, not harder — these top 12 Prime Day grilling essential deals are up to 50% off right now ]]></title>
                                                                                                                                                                                                <link>https://www.tomsguide.com/home/grill-smarter-not-harder-these-top-12-prime-day-grilling-essential-deals-are-up-to-50-percent-off-right-now</link>
                                                                            <description>
                            <![CDATA[ Having a summer cookout? I’ve just found 12 Prime Day deals perfect for levelling up my summer cookouts. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">2RRc4Ko3f3s2k2MCmeLrmE</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/Q2y9CLfuaBCBTmCdYSCby9-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Fri, 26 Jun 2026 13:31:25 +0000</pubDate>                                                                                                                                <updated>Fri, 26 Jun 2026 14:31:31 +0000</updated>
                                                                                                                                            <category><![CDATA[Home]]></category>
                                                                                                                    <dc:creator><![CDATA[ Cynthia Lawrence ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/CCuSgQpd5NyZ46CgoF9cva.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ null ]]></dc:description>
                                                                                                                                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/Q2y9CLfuaBCBTmCdYSCby9-1280-80.jpg">
                                                            <media:credit><![CDATA[Cuisinart, Comsmart, Vovoly / Edited by Gemini]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[A selection of BBQ essentials.]]></media:description>                                                            <media:text><![CDATA[A selection of BBQ essentials.]]></media:text>
                                <media:title type="plain"><![CDATA[A selection of BBQ essentials.]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/Q2y9CLfuaBCBTmCdYSCby9-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Grilling season is here! And whether you enjoy hosting summer barbecues or preparing for a big 4th July cookout, you’ll need all the right essentials to level up your grilling game. </p><p>Plus, it is even better when you can score major savings during the <a href="https://www.tomsguide.com/live/news/prime-day-2026-handpicked-editor-recommended-deals-live#live">Prime Day deals</a>. I've just tracked down some absolute steals featuring massive discounts of up to 50% right now. All these products promise to make grilling a breeze. </p><p>So, whether you want a premium grilling tool set or a heavy-duty cast-iron press to make smash burgers, here are the offers that I'm adding to my shopping cart today. Either way, you're bound to wow your cookout guests.</p>        <div class="featured_product_block featured_block_hero" data-id="a99fdfb8-667b-40be-b691-21d7c6c7a8eb">            <a href="https://www.amazon.com/Resistant-Grilling-Silicone-Non-Slip-Barbecue/dp/B07YTVMRV4" data-model-name="Comsmart BBQ Gloves" 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/cq9fA3TsKEg59K663tM7V8.jpg" alt="Comsmart, Comsmart Bbq Gloves, 1472 Degree F Heat Resistant Grilling Gloves Silicone Non-Slip Oven Gloves Long Kitchen Gloves for Barbecue, Cooking, Baking, Cutting"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Comsmart</div>                                        <div class="featured__title">Comsmart BBQ Gloves</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="1fbe9687-1be4-4ddb-a3ea-5a2a499784c8">            <a href="https://www.amazon.com/dp/B0DD3S7WDZ" data-model-name="Vovoly Extra Wide Griddle Scraper" 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/aewh7saHuUBHEqLcbBm5Lo.jpg" alt="Vovoly, Vovoly Extra Wide Griddle Scraper, 5.5''x5.5'' Smashed Burger Scraper Grill Scraper Spatula Burger Turner - Full Tang Wooden Handle Professional Grade Grill Accessories, Knife Grade Stainless Steel"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Vovoly</div>                                        <div class="featured__title">Vovoly Extra Wide Griddle Scraper</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="38fdba6d-7e68-4fa8-86cf-805f5d2b5f16">            <a href="https://www.amazon.com/dp/B0C3V4XD9X" data-model-name="Shizzo Shallow Grill Basket Set" 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/UnpSZGjzLa4PE87U65ZSCR.jpg" alt="SHIZZO, Shizzo Shallow Grill Basket Set, Grilling Accessories Barbecue Bbq, Stainless Steel Folding Portable Outdoor Camping Rack for Fish, Shrimp, Vegetables, Cooking Accessories, Gift for Family, Freinds"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>SHIZZO</div>                                        <div class="featured__title">Shizzo Shallow Grill Basket Set</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="2ca2eec4-de5c-4232-865d-e5c650d597f9">            <a href="https://www.amazon.com/Cuisinart-CISB-111-Smashed-Burger-Press/dp/B07SZFHKVZ" data-model-name="Cuisinart 6.5" Cast Iron Smashed Burger Press" 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/g6t2j7cx3B3jDW7RkqfXTN.jpg" alt="Cuisinart, Cuisinart 6.5" Cast Iron Smashed Burger Press, Round Flat Edge Grill Press for Crispy Smash Burgers, Burger Tool for Grill and Griddle Accessories, for Bbqs and Tailgates"></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">Cuisinart 6.5" Cast Iron Smashed Burger Press</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="a55cd508-92ff-4d3b-9b8a-2f78d9aa6620">            <a href="https://www.amazon.com/dp/B075NC2MYB" data-model-name="Grillart Grill Brush and Scraper " 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/aPGKsfLnZE2ThFyUF9LVFS.jpg" alt="GRILLART, Grillart Grill Brush and Scraper Bbq Brush for Grill, Safe 18" Stainless Steel Woven Wire 3 in 1 Bristles Grill Cleaning Brush, Br-4516"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>GRILLART</div>                                        <div class="featured__title">Grillart Grill Brush and Scraper </div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="8d543a4c-33bb-4f8a-ada1-65c348720570">            <a href="https://www.amazon.com/dp/B0D87SH9ZB" data-model-name="Shizzo Rolling Grill Basket" 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/P6R7sxyAzpNBQihcS5KVGN.jpg" alt="SHIZZO, Shizzo Rolling Grill Basket, Removable Wooden Handle, Extra Sturdy Cylinder Grilling Basket, Food Grade Stainless Steel, Portable Outdoor Camping Accessories Bbq Net Rack, Cooking Griller for Fish, Vegetables, and More - Gifts for Men Dad Husband - Set of 2"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>SHIZZO</div>                                        <div class="featured__title">Shizzo Rolling Grill Basket</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="d7a3896c-2366-407a-ae78-7966b665a193">            <a href="https://www.amazon.com/dp/B09BHJWV2Q" data-model-name="Hulisen Smashed Burger Kit: Press, Grill Spatula and Spice Shaker " 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/47nUg4GaheZzagXiSn33YW.jpg" alt="HULISEN, Hulisen Smashed Burger Kit, Stainless Steel Burger Press, Grill Spatula and Spice Dredge Shaker - Burger Smasher Griddle Accessories Kit for Flat Top Griddle Grill Cooking, Gift Package"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>HULISEN</div>                                        <div class="featured__title">Hulisen Smashed Burger Kit: Press, Grill Spatula and Spice Shaker </div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="cb0817e2-fe06-4bc9-b8e8-c326162f1b01">            <a href="https://www.amazon.com/Scrub-Daddy-Grill-Brush-BBQ/dp/B09SVK9YBB" data-model-name="Scrub Daddy Bbq Daddy Grill Brush " 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/Cn36GCk3nKtxMmRggkiozL.jpg" alt="Scrub Daddy, Scrub Daddy Bbq Daddy Grill Brush for Outdoor Grill - Bristle Free Grill Brush With Steel Grill Scraper + Scrub Brush - Temperature Controlled Scrubbing Power for Grill Cleaning (1 Count)"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Scrub Daddy</div>                                        <div class="featured__title">Scrub Daddy Bbq Daddy Grill Brush </div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="0d08f11c-d651-457c-ab7a-0a55f478c16d">            <a href="https://www.amazon.com/gp/aw/d/B0DNMTK56N" data-model-name="Thermomaven Digital Meat Thermometer" 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/hgDfjtprY8EmAFVsjDoHMG.jpg" alt="ThermoMaven, Thermomaven Professional Meat Thermometer Digital, Ultra-Fast 0.5 Sec Instant Read, Nist Certified ±0.5°f Accuracy, Ip67 Waterproof, Auto-Rotating Backlit Display, Lift-To-Wake, for Bbq/cooking/candy"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>ThermoMaven</div>                                        <div class="featured__title">Thermomaven Digital Meat Thermometer</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="01cbeb4e-2e76-4523-9179-b1213c11fc21">            <a href="https://www.amazon.com/Kaluns-Stainless-Luxurious-barbequing-Professional/dp/B079J4KT8H" data-model-name="Kaluns Grilling Accessories" 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/XdGiRZYHSx2nmPMZz3UAeK.jpg" alt="Kaluns, Kaluns Grilling Accessories, Dad Gifts for Fathers Day, Grilling Gifts, Heavy Duty Stainless Steel Bbq Tool Set for Outdoor Grill With Aluminum Case and Apron, Birthday Gifts for Men Women"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Kaluns</div>                                        <div class="featured__title">Kaluns Grilling Accessories</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="eaea6b5d-db09-4bca-875c-69bc16f3429d">            <a href="https://www.amazon.com/Cutluxe-Slicing-Carving-Knife-Ergonomic/dp/B07VLW8677/" data-model-name="Cutluxe 12-Inch Brisket Knife" 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/PEvigrLJjynDcXqgudWkuY.jpg" alt="Cutluxe Brisket Knife – 12" Carving & Slicing Knife for Meat & Bbq – Razor Sharp German Steel, Sheath Included, Ergonomic Full Tang Handle Design, Grilling Gifts for Men – Artisan Series"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Cutluxe</div>                                        <div class="featured__title">Cutluxe 12-Inch Brisket Knife</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="67d03b93-6e19-4462-b915-8c6e6536dad9">            <a href="https://www.amazon.com/GRILLART-BBQ-Tools-Grill-Set/dp/B09GB5YCHH" data-model-name="Grillart BBQ Grill Tools Set" 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/PCbGug4oV6uEb59S37yfL5.jpg" alt="GRILLART, Grillart Bbq Tools Grill Tools Set -18inch Grilling Tools Bbq Set - Grill Accessories W/bbq Tongs, Spatula, Fork, Brush- Stainless Grill Kit Grilling Set - Gift Ideas Bbq Accessories Gifts for Men Dad"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>GRILLART</div>                                        <div class="featured__title">Grillart BBQ Grill Tools Set</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div><h2 id="home-appliances">HOME APPLIANCES</h2><h3 class="article-body__section" id="section-we-re-tracking-all-the-best-prime-day-home-appliance-deals"><span>We're tracking all the best Prime Day home appliance deals</span></h3><div class="vizualizer-embed"><div class="tg-df-widget-host" data-widget-config="?search=Home+Appliances&price=50_&min_discount_ratio=0.95&offer_type=all&rows=4&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.&show_countdown=true&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 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-right {      position: absolute;      right: 8px;      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-right:hover {      background-color: #f8fafc;      border-color: #cbd5e1;    }    .tg-df-carousel-roundels-wrapper .tg-df-carousel-scroll-right {      right: 0;      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-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">          \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.previousElementSibling.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-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>\n        \x3C/div>\n      \x3C/div>\n    \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">      \x3Cdiv class="tg-df-grid" id="tg-df-grid">        \x3C!-- Content populated by JavaScript --\x3E      \x3C/div>    \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';             }          }                    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')}`                });              }            });          }        }        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';          }        }        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.rowsSelect && this.rowsSelect.value) ? parseInt(this.rowsSelect.value, 10) : 12;          } else {             this.displayLimit += (this.rowsSelect && this.rowsSelect.value) ? parseInt(this.rowsSelect.value, 10) : 12;          }                    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 encodedTag = encodeURIComponent(this.activeDealTag.toLowerCase().replace(/\s+/g, '-'));             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');                    if (this.rowsSelect && this.rowsSelect.value) {            url.searchParams.append('rows', this.rowsSelect.value);          } else {             url.searchParams.append('rows', '12'); // default          }          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 = 12;          if (this.rowsSelect && this.rowsSelect.value) {            rowLimit = parseInt(this.rowsSelect.value, 10) || 12;          }          // 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 => {              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}`;                }              }              return `                \x3Ca href="${this.escapeHTML(linkUrl)}" target="_blank" rel="noopener nofollow" class="tg-df-voucher-item">                  ${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);                }              });            });                                  } 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 = `              \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;                    let gridWrapper = this.grid.parentElement;          if (gridWrapper && gridWrapper.classList.contains('tg-df-grid-wrapper')) {             let existingChevron = gridWrapper.querySelector('.tg-df-carousel-scroll-right');             if (this.getViewMode() === 'carousel') {                 if (!existingChevron) {                     gridWrapper.insertAdjacentHTML('beforeend', '\n                 \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" onclick="this.previousElementSibling.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>');                 }             } else {                 if (existingChevron) {                     existingChevron.remove();                 }             }          }                    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.rowsSelect && this.rowsSelect.value) ? parseInt(this.rowsSelect.value, 10) : 12);                 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');            if (!this.processArticleFired) {                  this.processArticleFired = true;                  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[ I tried this new MagSafe wallet that looks better the longer I use it — and it's got Find My support built in ]]></title>
                                                                                                                                                                                                <link>https://www.tomsguide.com/phones/i-tried-this-new-magsafe-wallet-that-looks-better-the-longer-i-use-it-heres-what-it-is</link>
                                                                            <description>
                            <![CDATA[ The Nomad Leather Mag Wallet is as close to a conventional wallet as they come, complete with wireless charging and Find My support. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">UY3YNQUybCQyvdz6HwSFij</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/hh33LkoPUzesXQf2A99DT9-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Fri, 26 Jun 2026 10:00:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Phones]]></category>
                                                                                                <author><![CDATA[ john.velasco@futurenet.com (John Velasco) ]]></author>                    <dc:creator><![CDATA[ John Velasco ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/TSj224oX8d5ERXaDs8pDGd.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ null ]]></dc:description>
                                                                                                                                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/hh33LkoPUzesXQf2A99DT9-1280-80.jpg">
                                                            <media:credit><![CDATA[John Velasco / Tom&#039;s Guide]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Nomad Leather Mag Wallet on iPhone 17 Pro case.]]></media:description>                                                            <media:text><![CDATA[Nomad Leather Mag Wallet on iPhone 17 Pro case.]]></media:text>
                                <media:title type="plain"><![CDATA[Nomad Leather Mag Wallet on iPhone 17 Pro case.]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/hh33LkoPUzesXQf2A99DT9-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Whenever I get to test out a new MagSafe wallet, I always admire the way it looks out of the box. The <a href="https://www.tomsguide.com/phones/i-tried-this-new-magsafe-wallet-that-actually-makes-me-look-cool-when-i-take-out-my-card-and-now-i-cant-stop-using-it">Ekster Cardholder Pro</a> I used last fall is a perfect example, but after just a week of use, its once-pristine red casing was already covered in scuffs.</p><p>As you can tell, I’m particularly rough on my wallet. That’s not surprising considering I’m constantly slipping it in and out of my pocket, tapping it on a card reader to get into the office, or tossing it onto my desk. Normally, daily wear and tear makes most accessories look ugly — but not <a href="https://nomadgoods.com/products/slim-wallet-horween-olde-dublin" target="_blank" rel="nofollow">Nomad’s Leather Mag Wallet</a>.</p><p>That’s because this everyday carry essential is made of vegetable-tanned Horween leather, which not only gives it a rustic look but actually makes it look better with time. Plus, it packs just about everything I want in a MagSafe wallet, including wire-free charging.</p><div class="product"><a data-dimension112="4a6a1be9-02ff-4ec5-a5ec-85ab6e2d035e" data-action="Deal Block" data-label="The Nomad Leather Mag Wallet is a modern wallet that takes the rustic look of a conventional leather wallet, but designed in a slim package complete with wire-free charging, solid MagSafe magnetic connection to a phone, and support for Apple Find My to track down its location in the event its lost. And quite frankly, it's the kind of thing that looks better with time." data-dimension48="The Nomad Leather Mag Wallet is a modern wallet that takes the rustic look of a conventional leather wallet, but designed in a slim package complete with wire-free charging, solid MagSafe magnetic connection to a phone, and support for Apple Find My to track down its location in the event its lost. And quite frankly, it's the kind of thing that looks better with time." data-dimension25="$99" href="https://nomadgoods.com/products/slim-wallet-horween-olde-dublin" 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="gLNDzGoqbnaNvm9tmaxJ5i" name="Nomad Leather Mag Wallet deal block" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/gLNDzGoqbnaNvm9tmaxJ5i.jpg" mos="" align="middle" fullscreen="" width="600" height="600" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>The Nomad Leather Mag Wallet is a modern wallet that takes the rustic look of a conventional leather wallet, but designed in a slim package complete with wire-free charging, solid MagSafe magnetic connection to a phone, and support for Apple Find My to track down its location in the event its lost. And quite frankly, it's the kind of thing that looks better with time.<a class="view-deal button" href="https://nomadgoods.com/products/slim-wallet-horween-olde-dublin" target="_blank" rel="nofollow" data-dimension112="4a6a1be9-02ff-4ec5-a5ec-85ab6e2d035e" data-action="Deal Block" data-label="The Nomad Leather Mag Wallet is a modern wallet that takes the rustic look of a conventional leather wallet, but designed in a slim package complete with wire-free charging, solid MagSafe magnetic connection to a phone, and support for Apple Find My to track down its location in the event its lost. And quite frankly, it's the kind of thing that looks better with time." data-dimension48="The Nomad Leather Mag Wallet is a modern wallet that takes the rustic look of a conventional leather wallet, but designed in a slim package complete with wire-free charging, solid MagSafe magnetic connection to a phone, and support for Apple Find My to track down its location in the event its lost. And quite frankly, it's the kind of thing that looks better with time." data-dimension25="$99">View Deal</a></p></div><h2 id="rustic-design-that-gets-better-with-time">Rustic design that gets better with time</h2><figure role="gallery"><figure><img src="https://cdn.mos.cms.futurecdn.net/hTX3FGNVwDM6cokTHX6Cu9.jpg" alt="Nomad Leather Mag Wallet on iPhone 17 Pro case." /><figcaption><small role="credit">John Velasco / Tom's Guide</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/2ki4WwmhBMXp8yx6DqLby8.jpg" alt="Nomad Leather Mag Wallet on iPhone 17 Pro case." /><figcaption><small role="credit">John Velasco / Tom's Guide</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/uAyw8iRPzKVJdux9yju4H6.jpg" alt="Nomad Leather Mag Wallet on iPhone 17 Pro case." /><figcaption><small role="credit">John Velasco / Tom's Guide</small></figcaption></figure></figure><p>The simple reason why Nomad’s Leather Mag Wallet stands out to me is how its Horween leather improves with age. The scratches and nicks it has endured over the past two weeks give it a distinctly rustic look. Better yet, it genuinely looks like an ordinary wallet rather than just another tech gadget I’m forced to carry.</p><p>Every time I slide it in and out of my pocket, toss it onto my desk, or hold it while taking calls, the wallet absorbs that daily wear and tear. Instead of looking ruined, the leather absorbs the natural oils from my hands, softening everyday marks and darkening into a rich, deep finish.</p><p>This thing is well-built, too, and somehow manages to accommodate six cards. Nomad says it maxes out at four, but the six I’ve crammed into it consist of four standard credit cards and two paper-thin ones. While it's by no means as spacious as the <a href="https://www.tomsguide.com/phones/the-supcase-magflip-stand-is-the-swiss-army-knife-of-magsafe-wallets-heres-why">Supcase wallet</a> I’ve tested, the handy cutout on the bottom makes it incredibly easy to slide the cards out when I need them.</p><h2 id="traceable-so-it-s-never-left-behind">Traceable, so it's never left behind</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:4266px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="aLEaiccJuNvkFLKobaztu8" name="Nomad Leather Mag Wallet" alt="Nomad Leather Mag Wallet thinness." src="https://cdn.mos.cms.futurecdn.net/aLEaiccJuNvkFLKobaztu8.jpg" mos="" align="middle" fullscreen="" width="4266" height="2400" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: John Velasco / Tom's Guide)</span></figcaption></figure><p>Frankly, this wouldn’t be a wallet I’d want to use if it didn’t have Find My support. Sure, tracking technology tacks on an additional cost over conventional MagSafe wallets, but I can’t emphasize enough how crucial those separation alerts are if I accidentally leave it behind.</p><p>What’s impressive is how all of the Find My components have been slimmed down, allowing the wallet to remain remarkably compact. It functions just like an AirTag, sending a notification to my phone whenever I stray too far from it. For instance, when I went grocery shopping the other day, I accidentally left it in my car — but by the time I walked through the supermarket doors, I already had an alert waiting for me.</p><p>It also saved me when I managed to misplace it somewhere in my house. While it lacks the <a href="https://www.tomsguide.com/news/how-apple-airtags-work-and-how-they-thwart-stalkers">Precision Finding support</a> of an actual <a href="https://www.tomsguide.com/reviews/apple-airtags">AirTag</a>, you can trigger it to emit an audible tone to help you track down its exact whereabouts.</p><h2 id="wire-free-charging">Wire-free charging</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:5013px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="FJGwA8rpYsoiwbgUrAMsX9" name="Nomad Leather Mag Wallet" alt="Nomad Leather Mag Wallet on iPhone 17 Pro case." src="https://cdn.mos.cms.futurecdn.net/FJGwA8rpYsoiwbgUrAMsX9.jpg" mos="" align="middle" fullscreen="" width="5013" height="2820" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: John Velasco / Tom's Guide)</span></figcaption></figure><p>By now, I’ve tested more than a dozen different MagSafe wallets, and almost all of them <a href="https://www.tomsguide.com/phones/i-tested-this-magsafe-wallet-for-a-month-and-now-i-cant-live-without-it-especially-at-44-percent-off">required a proprietary charger</a>. Don’t get me wrong, most of them boast a generous six-month battery life, but it’s still a massive pain to remember where I hid a specific charging cable half a year ago.</p><p>The Nomad Leather Mag Wallet completely solves this gripe by offering a truly wire-free charging solution. Nomad managed to squeeze a wireless charging coil right into the slim housing. While I thankfully haven’t had to top it off just yet, I love that I can simply place it down on any Qi or MagSafe wireless charger I already have lying around. It entirely eliminates the hassle of hunting down a proprietary wire months down the road.</p><p>Some people might scoff at the $99 price tag, but I think it’s worth every penny. Not only does it have the authentic look and feel of a traditional wallet, but its wireless charging convenience and built-in Find My support make it a rock-solid recommendation.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-OqvxdX"></div>                            </div>                            <script src="https://kwizly.com/embed/OqvxdX.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/phones/motorola-phones/motorola-razr-ultra-2026-review">Motorola Razr Ultra 2026 review: Better does come at a premium price</a></li><li><a href="https://www.tomsguide.com/phones/simo-solis-lite-hotspot-review">I tested this puck shaped mobile hotspot — and it’s the simplest way to get online</a></li><li><a href="https://www.tomsguide.com/phones/best-early-prime-day-2026-phone-accessories-deals-magsafe-wallets-power-banks-chargers-and-more">I tested 100+ phone accessories in the last year and these are my favorite early Prime Day deals — MagSafe wallets, power banks, chargers, and more</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ Worried about microplastics in your daily coffee? I tested Simply Good Coffee's 'Plastic-Free' Brewer ]]></title>
                                                                                                                                                                                                <link>https://www.tomsguide.com/home/coffee-makers/2026-is-all-about-plastic-free-coffee-makers-and-i-tested-out-simply-good-coffees-viral-plastic-free-brewer-so-you-dont-have-to</link>
                                                                            <description>
                            <![CDATA[ For the 13th episode of The Coffee Lab, I've got in the Simply Good Coffee Plastic-Free Brewer. How does it hold up? ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">2e6gshnFpMkffkeUy6A6zf</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/NkXX4S9Ni3TGUx8XDXrwHi-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Fri, 26 Jun 2026 09:30:00 +0000</pubDate>                                                                                                                                <updated>Mon, 29 Jun 2026 11:05:50 +0000</updated>
                                                                                                                                            <category><![CDATA[Coffee Makers]]></category>
                                                    <category><![CDATA[Home]]></category>
                                                    <category><![CDATA[Home Appliances]]></category>
                                                    <category><![CDATA[Kitchen &amp; 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>
                                                                                                                                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/NkXX4S9Ni3TGUx8XDXrwHi-1280-80.jpg">
                                                            <media:credit><![CDATA[Tom&#039;s Guide]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[the simplygoodcoffee plastic free brewer with the coffee lab logo]]></media:description>                                                            <media:text><![CDATA[the simplygoodcoffee plastic free brewer with the coffee lab logo]]></media:text>
                                <media:title type="plain"><![CDATA[the simplygoodcoffee plastic free brewer with the coffee lab logo]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/NkXX4S9Ni3TGUx8XDXrwHi-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 thirteenth 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>Here at <a href="https://www.tomsguide.com/tag/the-coffee-lab">The Coffee Lab</a>, I'm always trying to find the best coffee maker. With so many options out there now — <a href="https://www.tomsguide.com/home/coffee-makers/technivorm-moccamaster-kgbv-select-review">Moccamaster</a>, <a href="https://www.tomsguide.com/home/coffee-makers/i-love-my-moccamaster-but-usd370-is-a-lot-for-drip-coffee-this-ninja-brewer-is-the-best-alternative-and-its-under-usd90">Ninja 12-Cup</a>, <a href="https://www.tomsguide.com/home/coffee-makers/breville-luxe-brewer-review">Breville Luxe Brewer</a>, <a href="https://www.tomsguide.com/home/coffee-makers/aarke-french-press-review">Aarke Coffee Maker</a> — it feels like finding a coffee granule in a haystack.</p><p>Thankfully, Simply Good Coffee literally put it in the name. This week, I've got the <a href="https://www.tomsguide.com/home/coffee-makers/simply-good-coffee-plastic-free-brewer-review">Simply Good Coffee Plastic-Free Brewer</a> on the dissection table, so let's get stuck in. You guys <em>hate</em> plastic in your coffee. Personally, I'm not vehemently anti-plastic. While I was researching for this article, I discovered that <a href="https://www.mayoclinic.org/healthy-lifestyle/nutrition-and-healthy-eating/expert-answers/bpa/faq-20058331" target="_blank">BPA plastic is <strong>not</strong> banned in the U.S.</a>, which explains a lot. European food safety standards are pretty robust already — BPA plastic has been <a href="https://trade.ec.europa.eu/access-to-markets/en/news/eu-prohibition-use-and-trade-bisphenol-20-january-2025" target="_blank">banned in the EU since 2025</a>. Of course, <a href="https://www.wwf.org.uk/updates/top-tips-reduce-your-plastic-footprint" target="_blank">minimizing plastic usage is the best course of action for the environment as a whole</a>, so we should all be consciously choosing the eco-friendly option. </p><p>Simply Good Coffee is trying to make one of the first "truly" plastic-free coffee makers... and it's <em>kind of </em>succeeded? I say "kind of" because the Plastic-Free Brewer has a plastic-coated exterior (for health and safety to prevent burns) and silicone tubing in the water lines. Are these dealbreakers for you, or would you still get the Plastic-Free Brewer? Let's get into it. </p>                    <div class= "tiktok-wrapper" style="min-height: 750px;"><blockquote class="tiktok-embed" cite="https://www.tiktok.com/@tomsguide/video/7655710949080337677" data-video-id="7655710949080337677" 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="♬ original sound - Tom’s Guide" href="https://www.tiktok.com/music/original-sound-7655711176604568334">♬ original sound - Tom’s Guide</a></section>                    </blockquote></div>                <div class="product"><a data-dimension112="ecd7ec97-137b-45d8-a8d1-1c3a765e48c9" data-action="Deal Block" data-label="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." data-dimension48="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." 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="ecd7ec97-137b-45d8-a8d1-1c3a765e48c9" data-action="Deal Block" data-label="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." data-dimension48="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." data-dimension25="$479">View Deal</a></p></div><h2 id="low-plastic-not-no-plastic">Low plastic, not no plastic</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="cW6AWD2towBGUxbXs7NeRD" name="Simply Good Coffee Plastic-Free Brewer 11.JPG" alt="the simply good coffee plastic-free brewer photographed against the blue tom's guide backgrounds" src="https://cdn.mos.cms.futurecdn.net/cW6AWD2towBGUxbXs7NeRD.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>Let's just get this clear: the Simply Good Coffee Plastic-Free brewer is not plastic-free. As I mentioned earlier, it has a plastic coating on the exterior to prevent burns and the internal water lines have medical-grade silicone tubing. </p><p>However, <em>no</em> hot water touches plastic at any point during the brewing process. The heating element, water tank, carafe, filter, and destratification tube are all made from stainless steel or glass. Water obviously touches the silicone in the water tubing, but this isn't hot yet. And, it's <em>silicone</em>. It's not plastic in the traditional sense. Do you consider silicone a dangerous plastic, or not? </p><p>There are some key differences between the SGC and Moccamaster: the latter has a plastic filter basket, a plastic destratification tube (yes, that's its real name), and a plastic water tank. Let's look at a side-by-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="iat8EJCqVAwZ4mmdyjaKrj" name="plastic" alt="a side-by-side comparison image of the moccamaster kgbv select and the simply good coffee plastic free brewer with arrows pointing to plastic vs metal vs glass materials" src="https://cdn.mos.cms.futurecdn.net/iat8EJCqVAwZ4mmdyjaKrj.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: Tom's Guide (photos) / Canva (arrow graphic, text box))</span></figcaption></figure><p>It would be completely inaccurate to claim the Moccamaster leaches plastic into hot water, though. Technivorm is based in the Netherlands, a country with <em>strict</em> plastic laws. Every Moccamaster is handmade in the Netherlands using "virgin plastics in key components". Technivorm uses virgin plastics rather than recycled to "ensure structural consistency, long-term durability, and full traceability of materials." Don't worry — even though BPAs aren't explicitly banned in the U.S., all Moccamaster's plastics are "BPA, BPS, phthalate, and BPF-free." </p><p>There's no one correct answer, and I'm not going to pretend there is, or tell you what to believe. You should get whichever machine you feel more comfortable with. </p><h2 id="but-how-does-the-coffee-taste">But how does the coffee taste?</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="WcDTsK5MNkH3R5F5Q8uVME" name="Simply Good Coffee Plastic-Free Brewer 17.JPG" alt="the simply good coffee plastic-free brewer photographed against the blue tom's guide backgrounds" src="https://cdn.mos.cms.futurecdn.net/WcDTsK5MNkH3R5F5Q8uVME.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 Simply Good Coffee Plastic-Free Brewer makes delicious coffee. In my 4-star review, I wrote, "I never made a bad batch on the Simply Good Coffee Brewer. Every pot tasted clean, fresh, with zero bitterness and a pleasant, well-rounded finish. This coffee tastes just as good as the Moccamaster’s, and I’m sure any Moccamaster transplants will be satisfied with this flavor." </p><p>Of course, you can experiment with flavor by adjusting grind size, water-to-coffee ratio, and bloom time. The SGC Plastic-Free Brewer has a bloom button; you can switch it on or off depending on preference. </p><p>"I tried every dose from 56g (the minimum for a full pot) to 72g (the maximum for a full pot), and found anywhere between 60g-72g to be perfect," I wrote in my review. Usually, I'm a rigid ratio stickler, but I enjoyed the SCG flavor at pretty much every ratio.  </p><p>Unfortunately, the Simply Good Coffee Plastic-Free Brewer isn't SCA-accredited yet, but the company claims the Brewer adheres to the SCA's guidelines. </p><h2 id="what-s-your-main-takeaway">What's your main takeaway?</h2><p>Would you be willing to try the Simply Good Coffee (Mostly) Plastic-Free Brewer? Or would you rather stick with your old faithful Moccamaster, Ninja, Breville, and the like? </p><p>It's worth noting that Simply Good Coffee does not offer a 5-year warranty or lifetime repairs like Technivorm, but "a two-year warranty as standard and a five-year warranty if you enrol in the Coffee Quality Assurance Programme (costs $120…), which gives you free shipping, filters, and cleaning products."</p><p>I honestly think I would be happy with either the Moccamaster or the SGC Plastic-Free Brewer. Looks-wise, they're both a bit of me. I love that modern, functional, industrial, yet sleek vibe. </p><p>Let me know in the comments which machine you'd rather buy! Be sure to check back next Friday for the next episode of The Coffee Lab brewing on our TikTok, Facebook, Instagram, and YouTube. </p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-ODnZGe"></div>                            </div>                            <script src="https://kwizly.com/embed/ODnZGe.js" async></script><figure class="inline-layout"><fw-embed-feed channel="toms_guide" playlist="ojE0pK" mode="row" player_placement="bottom-right"></fw-embed-feed></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-this-ridiculously-cheap-bean-to-cup-espresso-machine-so-you-dont-have-to-and-its-a-total-head-scratcher"><strong>I tried this ridiculously cheap bean-to-cup espresso machine so you don't have to — and it's a total head-scratcher</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/do-you-need-a-wdt-tool-for-barista-quality-coffee-at-home-i-put-the-controversial-coffee-tool-to-the-test"><strong>Do you need a WDT tool for barista-quality coffee at home? I put the controversial coffee tool to the test</strong></a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ Forget chatbots: Why Apple, Meta and OpenAI are racing toward 'Spatial AI' ]]></title>
                                                                                                                                                                                                <link>https://www.tomsguide.com/ai/forget-chatbots-why-apple-meta-and-openai-are-racing-toward-spatial-ai</link>
                                                                            <description>
                            <![CDATA[ The tech giants are moving past chatbots. Here's how Apple, Meta, OpenAI — and a crowd of others — are racing to dominate spatial AI, and how it'll change your next phone and smart glasses. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">37WAdcqRzTRzt7QGGm5MWG</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/HwaQ3sQYsFVnWvJ8Kg4Vs3-1280-80.png" type="image/png" length="0"></enclosure>
                                                                        <pubDate>Fri, 26 Jun 2026 09:00:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[AI]]></category>
                                                                                                <author><![CDATA[ amanda.caswell@futurenet.com (Amanda Caswell) ]]></author>                    <dc:creator><![CDATA[ Amanda Caswell ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/zYjevim2q7FjQiefqpjZRB.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ null ]]></dc:description>
                                                                                                                                                                                                                                                <media:content type="image/png" url="https://cdn.mos.cms.futurecdn.net/HwaQ3sQYsFVnWvJ8Kg4Vs3-1280-80.png">
                                                            <media:credit><![CDATA[Future]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[robot]]></media:description>                                                            <media:text><![CDATA[robot]]></media:text>
                                <media:title type="plain"><![CDATA[robot]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/HwaQ3sQYsFVnWvJ8Kg4Vs3-1280-80.png" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>When AI was first introduced, it came in the form of assistants like<a href="https://www.tomsguide.com/phones/iphones/i-spent-a-week-with-siri-ai-here-are-my-honest-pros-and-cons"> Siri </a>and Alexa, then came chatbots like ChatGPT and Gemini. Since then, we've seen <a href="https://www.tomsguide.com/ai/a-guide-to-agentic-ai-how-windows-is-going-to-do-more-things-for-you">agentic AI </a>(AI agents) take over our computers and do the work for us. Now, big tech is racing towards a new type of AI that truly seems like something out of a sci-fi movie. At least until now. <br><br><strong>It's called spatial AI and the biggest names in tech are already throwing billions of dollars at it.</strong></p><p>Rather than simply generating text or images on a screen, spatial AI gives artificial intelligence something it has largely lacked until now: spatial awareness. Here's what you need to know about the next major shift — and why the battle lines are being drawn right now.</p><h2 id="what-is-spatial-ai-anyway">What is spatial AI anyway?  </h2><p>You've probably heard the term a few times and maybe not given it a second thought. However, it's worth understanding, especially because AI moves at such break-neck speeds. Most of us will be using spatial AI more frequently in the upcoming months. </p><div><blockquote><p>While a Large Language Model like ChatGPT knows facts because it was trained on text, a spatial AI system uses cameras, sensors and learned models of physics to continually update its understanding of the world</p></blockquote></div><p>You can think of spatial AI as the ultimate upgrade for machine vision. Instead of looking at an isolated photo, for instance, like a chatbot analyzing an uploaded image, spatial AI builds a continuous, three-dimensional understanding of its surroundings. Essentially, it's the difference between looking at a single snapshot of your living room versus actually walking through it, navigating around the coffee table and knowing exactly where the doorway is.</p><p>While a Large Language Model like ChatGPT knows facts because it was trained on text, a spatial AI system uses cameras, sensors and learned models of physics to track location, movement and objects. Using that information, the AI continually updates its understanding of the world. </p><h2 id="the-race-to-spatial-ai">The race to spatial AI</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="2P5svDBfvGZxtYLjv2uHyb" name="Gemini Robotics" alt="Gemini Robotics" src="https://cdn.mos.cms.futurecdn.net/2P5svDBfvGZxtYLjv2uHyb.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: Google)</span></figcaption></figure><p>Alongside Apple, Meta and OpenAI, Google DeepMind, NVIDIA and others are all building toward AI that understands physical reality. In fact, <a href="https://www.siliconrepublic.com/start-ups/fei-fei-li-world-labs-raises-1bn-to-spatial-intelligence-ai-world-models-marble" target="_blank">World Labs has raised $1 billion to advance what Li calls "spatial intelligence"</a>. </p><p>Here's how the biggest players in tech line up at the moment: </p><ul><li><strong>Apple: </strong>The company's genuine advantage is in spatial sensing, thanks to the depth and motion hardware developed for <a href="https://www.tomsguide.com/computing/vr-ar/i-used-the-apple-vision-pro-for-1-month-heres-the-truth">Apple Vision Pro</a>. The company is pushing <a href="https://www.tomsguide.com/phones/iphones/apple-intelligences-best-feature-gains-new-powers-in-ios-26-whats-new-with-visual-intelligence">"Visual Intelligence" </a>and, at WWDC 2026, debuted <a href="https://www.tomsguide.com/phones/iphones/apples-ai-powered-spatial-reframing-tool-just-stole-the-show-at-wwdc">Spatial Reframing</a> — a photo tool that builds on Apple's spatial models from Vision Pro to let you reposition a photo's perspective after it's taken. (It ships with iOS 27 this fall and is currently in beta.)</li><li><strong>Meta: </strong>It's no secret that<strong> </strong>Mark Zuckerberg wants Meta to own the post-smartphone era, and in glasses, Meta is the one with the lead. <a href="https://www.tomsguide.com/computing/smart-glasses/meta-ray-ban-display-review">Meta Ray-Bans</a> launched in October 2023 and effectively created the wearable-AI category. Now, Meta is investing in spatial AI so future hardware can actively see what you see — rumored <a href="https://www.uploadvr.com/next-gen-ray-ban-meta-2026-super-sensing-facial-recognition-live-ai/" target="_blank">"super sensing" tech </a>in the next generation would enable real-time recognition of objects, locations and even people (a capability that's also raising real privacy questions).</li><li><strong>OpenAI: </strong>As one<strong> </strong>contender in a crowded field, not the clear "brain" for everyone else's hardware, it's building its own robots, too. The company's objectives toward multimodal models, world simulation, robotics and autonomous agents point in the same direction as its competitors.</li><li><strong>Google DeepMind:</strong> The company is developing spatial AI through projects like <a href="https://deepmind.google/models/gemini-robotics/" target="_blank">Gemini Robotics</a>, which combines vision, language and physical reasoning to help robots understand and interact with the real world. It is also building world models such as Genie that can generate and simulate interactive 3D environments, allowing AI to learn how physical spaces and objects behave. Meanwhile, <a href="https://www.tomsguide.com/ai/google-unveils-project-astra-ai-assistant-to-fight-gpt-4o-and-it-works-with-smart-glasses">Project Astra</a> gives AI continuous visual awareness, enabling it to recognize objects, understand spatial relationships and maintain context as a user moves through their environment.</li></ul><h2 id="where-you-ll-see-it-first">Where you'll see it first  </h2><p>You won't download a standalone "Spatial AI" app. Instead, it'll quietly supercharge tech you already use. </p><ul><li><strong>Smartphones:</strong> Your phone's camera has already become a real-time tool. If you've ever <a href="https://www.tomsguide.com/home/gardening/im-seriously-allergic-to-poison-ivy-this-gemini-feature-helps-me-when-im-weeding">pointed it at a branch and wondered if it was poison ivy </a>or something safer, you already have started using the capability.</li><li><strong>Smart glasses: </strong>Unlike smartphones, smart glasses like those from <a href="https://www.tomsguide.com/ai/i-went-shopping-wearing-the-ai-powered-meta-ray-bans-heres-what-i-love-and-what-annoyed-me">Meta,</a> <a href="https://www.tomsguide.com/computing/smart-glasses/i-just-saw-the-future-of-android-xr-smart-glasses-and-meta-and-apple-are-in-trouble">Google</a> and <a href="https://www.tomsguide.com/computing/smart-glasses/tcl-rayneo-x3-pro-smart-glasses-review">RayNeo X3 Pro AR</a>, let you interact with AI while keeping your hands free and your eyes on the world. They can identify objects, translate signs, answer questions about what you're looking at, and provide contextual information in real time, making spatial AI feel like a natural extension of your vision.</li><li><strong>Robotics:</strong> Spatial and physical intelligence such as understanding 3D geometry, gravity, materials and persistence, is seen as critical for robotics and autonomous vehicles, giving machines the situational awareness to operate outside controlled settings.</li><li><strong>Self-driving cars:</strong> Autonomous vehicles already rely on real-time 3D modeling of roads, pedestrians, and cyclists to predict what happens next.</li></ul><h2 id="the-outlook">The outlook</h2><p>The biggest shift coming with spatial AI isn't that your gadgets get smarter; it's that they become aware of context. Right now, your tech answers questions after you ask them. The ambition is still early, and spread across far more than three companies, but the goal is hardware that understands where you are and what you're doing before you type a single prompt.</p><p>We're in the early beginning, which is why I wanted to help you to grasp what is happening now. <a href="https://www.ai.cc/blogs/world-models-2026-google-nvidia-physical-ai-breakthroughs/" target="_blank">The world-models paradigm only moved into mainstream AI development in late 2025 and early 2026</a>, and the hard problems of cost, accuracy and privacy are far from solved. But just as generative AI changed how computers understand language, spatial AI is aiming at how computers understand reality itself.<br><br>What are your thoughts on spatial AI? Let me know in the comments and share your thoughts on this new era of technology. </p><a href="https://follow.it/articles-by-amanda-caswell-tom-s-guide?leanpub" class="button button--large button--primary">Follow Amanda Caswell and stay ahead of the AI curve</a><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/ai/anthropic-will-pay-workers-usd85-000-to-learn-ai-and-it-reveals-the-next-big-ai-job-trend">Anthropic will pay workers $85,000 to learn AI — and it reveals the next big AI job trend</a></li><li><a href="https://www.tomsguide.com/ai/anthropics-fable-five-ban-exposed-ais-next-big-problem-but-sakanas-fugu-may-have-the-answer">Anthropic's Fable 5 ban exposed AI's next big problem — but Sakana's Fugu may have the answer</a></li><li><a href="https://www.tomsguide.com/ai/is-your-job-ai-resilient-find-your-risk-score-with-our-career-calculator">Is your job 'AI-resilient'? Find your risk score with our career calculator</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ You’re probably using ChatGPT like it’s still 2023 and these 7 signs prove it — here's how to fix them ]]></title>
                                                                                                                                                                                                <link>https://www.tomsguide.com/ai/youre-probably-using-chatgpt-like-its-still-2023-and-these-7-signs-prove-it-heres-how-to-fix-them</link>
                                                                            <description>
                            <![CDATA[ Here are the seven patterns that point to you still using ChatGPT as another search engine instead of an assistant and collaborator—these methods will help you remedy those routines. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">pvjLtDt8yi6RGYFcTrtcrD</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/JPmtyJsDJN3nMNNhU5khRh-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Fri, 26 Jun 2026 07:30:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[AI]]></category>
                                                                                                                    <dc:creator><![CDATA[ Elton Jones ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/NVtYYXr3tEPUE67jf3HtXM.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ null ]]></dc:description>
                                                                                                                                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/JPmtyJsDJN3nMNNhU5khRh-1280-80.jpg">
                                                            <media:credit><![CDATA[Shutterstock]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[a laptop with ChatGPT on screen and bowls of fruit around and exercise tools around the laptop]]></media:description>                                                            <media:text><![CDATA[a laptop with ChatGPT on screen and bowls of fruit around and exercise tools around the laptop]]></media:text>
                                <media:title type="plain"><![CDATA[a laptop with ChatGPT on screen and bowls of fruit around and exercise tools around the laptop]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/JPmtyJsDJN3nMNNhU5khRh-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>If you’re an avid ChatGPT user and haven’t upgraded your usage habits, then you’re most likely still using it the same way you did when you first discovered it back in 2023. Instead of continuing to treat it like a simple search engine, you should treat it more like a reliable thinking partner. Here are seven signs that your ChatGPT usage is behind the times and the biggest fixes you need.</p><h2 id="evolve-your-old-ways-of-using-chatgpt">Evolve your old ways of using ChatGPT</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="8dcbnFdk2zw7v5KE9VVWcU" name="ChatGPT-shutterstock_2575700163" alt="phone with Chatgpt logo" src="https://cdn.mos.cms.futurecdn.net/8dcbnFdk2zw7v5KE9VVWcU.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>Some obvious and not-so-obvious hints expose just how much your time spent with ChatGPT hasn’t moved past the sort of uses beginners most likely abide by:</p><ul><li><strong>You only ask questions that deliver one answer and nothing more: </strong>You ask simple questions such as “What’s the best way to learn [topic]?”, get your answer and move on from the subject at hand. It’s better to build a conversation derived from more thoughtful prompts instead of isolated ones. A good example of this is telling ChatGPT, "Assess my current skill level, identify the biggest gaps, create a 30-day curriculum, quiz me weekly, and adapt the plan based on my progress."</li><li><strong>You request information instead of asking for methods meant for personal transformation: </strong>Simply asking ChatGPT to give you the information you need about a certain activity meant to improve your life isn’t the way. Instead of telling that chatbot to simply tell you about productivity, it’s better to prompt it to observe your habits and create a productivity routine that caters to you. A strong prompt that can make that happen is "Analyze my schedule, identify where I lose time, redesign my workday, and create a weekly review system."</li><li><strong>You never assign ChatGPT a defined role: </strong>It’s easy to transform the chatbot into anything you desire in connection to your requests. “Find my hidden strengths” is far too simple a prompt. This example works much better to dive deeper into your request: "Act as a strengths coach and behavioral psychologist. Ask me 15 questions, one at a time, about my career, hobbies, relationships, challenges, accomplishments, and moments when I felt most energized. After I've answered all of them, identify 10 strengths that I may be overlooking. For each strength, provide evidence from my answers, explain how it shows up in my life, and suggest practical ways I can use it more intentionally in my career and personal life."</li></ul><h2 id="continue-upgrading-your-prompts">Continue upgrading your prompts</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="ggr4w9sQrzz7NMydLJktgB" name="ChatGPT on phone.jpg" alt="ChatGPT running on phone with laptop in the background" src="https://cdn.mos.cms.futurecdn.net/ggr4w9sQrzz7NMydLJktgB.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>Here’s a slew of other bad habits that are in dire need of fixing if you want to become a better ChatGPT user:</p><ul><li><strong>You don’t make it challenge you: </strong>ChatGPT and other chatbots of its ilk are prone to validating their users when presented with simple prompts like “Here’s my idea. What do you think?” Turning ChatGPT into something that challenges your viewpoints makes for a more helpful experience. This prompt is a great example of that method: "Identify any weaknesses, blind spots, flawed assumptions, competing viewpoints, and reasons this idea might fail."</li><li><strong>You don’t use it like a simulator: </strong>AI tools provide some fascinating insights whenever it's presented with a prompt designed to simulate life coaches, hiring managers and even a future version of yourself. Playing around with the following prompt will show just how ChatGPT can act out simulated situations: "Simulate a roundtable discussion between Simon Sinek, Gary Vaynerchuk, and Lewis Howes debating my career strategy."</li><li><strong>You don’t create reusable prompts: </strong>Using a prompt just one time and moving on from using it ever again just isn’t the way to go when interacting with ChatGPT and other AI tools. Build a library of your go-to prompts that can be plugged into all sorts of situations, such as coming up with a reusable prompt that’s meant to find the most trending news of the day, help you learn a new skill or turn ChatGPT into your personal tutor on a particular topic.</li><li><strong>You never ask it to analyze you: </strong>It’s common to use ChatGPT to simply ask questions about the world at large. But the most curious users tap into the chatbot to ask questions about themselves after making it aware of their habits. Prompts such as "What type of career trajectory would someone with my interests likely enjoy?" and "What recurring blind spots appear in my thinking?" work great in this regard.</li></ul><h2 id="final-thoughts-3">Final thoughts</h2><p>Leave your 2023 ChatGPT usage behaviors behind and bring yourself into the current year by turning into an AI power user who can teach others about your amazing ways. Making great use of OpenAI’s chatbot to help you access knowledge faster, make more informed decisions and build repeatable systems through reusable prompts are just a few of the new routines you can adopt to become a modern-day ChatGPT expert.</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/ai/nvidia-claims-its-new-ai-data-centers-use-almost-no-water-heres-what-that-actually-means" target="_blank">NVIDIA claims its new AI data centers use almost no water — here's what that actually means</a></li><li><a href="https://www.tomsguide.com/ai/is-your-job-ai-resilient-find-your-risk-score-with-our-career-calculator" target="_blank">Is your job 'AI-resilient'? Find your risk score with our career calculator</a></li><li><a href="https://www.tomsguide.com/ai/anthropics-fable-five-ban-exposed-ais-next-big-problem-but-sakanas-fugu-may-have-the-answer" target="_blank">Anthropic's Fable 5 ban exposed AI's next big problem — but Sakana's Fugu may have the answer</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ Forget crunches — this 10-minute core workout fired up my abs more than 100 sit-ups using a surprising piece of equipment ]]></title>
                                                                                                                                                                                                <link>https://www.tomsguide.com/wellness/workouts/forget-crunches-this-10-minute-core-workout-fired-up-my-abs-more-than-100-sit-ups-using-a-surprising-piece-of-equipment</link>
                                                                            <description>
                            <![CDATA[ Grab a soccer ball or similar and give this five-move abs routine a try. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">XkcbpiMardTEBYBqeS8mGe</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/QFbFsGUdC7vySRDKs6TJCW-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Fri, 26 Jun 2026 07:00:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Workouts]]></category>
                                                    <category><![CDATA[Wellness]]></category>
                                                    <category><![CDATA[Fitness]]></category>
                                                                                                <author><![CDATA[ sam.hopes@futurenet.com (Sam Hopes) ]]></author>                    <dc:creator><![CDATA[ Sam Hopes ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/jZ88qJqvjWaCXXv3qvUQPA.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Sam Hopes is a level 3 qualified trainer, a level 2 Reiki practitioner and a fitness editor at Tom&#039;s Guide. She is also currently undertaking her Yoga For Athletes training course. Sam has written for various fitness brands and websites over the years and has experience across brands at Future, such as &lt;a href=&quot;https://www.livescience.com/author/sam-hopes&quot;&gt;Live Science&lt;/a&gt;,&lt;a href=&quot;https://www.fitandwell.com/author/sam-hopes&quot;&gt; Fit&amp;amp;Well&lt;/a&gt;,&lt;a href=&quot;https://www.coachweb.com/author/sam-hopes&quot;&gt; Coach&lt;/a&gt;, and T3. &lt;/p&gt;&lt;p&gt;Having worked with fitness studios like F45 and Virgin Active and trained both group and 1:1, Sam now primarily teaches outdoor bootcamps, bodyweight, and kettlebells. She also coaches mobility and flexibility classes several times a week and believes that true strength comes from a holistic approach to training your body. &lt;/p&gt;&lt;p&gt;Sam has completed two mixed doubles Hyrox competitions in London and the Netherlands and finished her first doubles attempt in 1:11.&lt;/p&gt;&lt;p&gt;In her spare time, she enjoys CrossFit, hot yoga, Pilates and running and can be found perfecting her handstand walks and handstand push-ups in the gym whenever she has the chance to be upside down. At work, she can be found testing the latest in fitness technology and wearables, anything yoga and CrossFit-related and has a keen interest in nutrition, mindfulness, sleep and recovery.&lt;/p&gt; ]]></dc:description>
                                                                                                                                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/QFbFsGUdC7vySRDKs6TJCW-1280-80.jpg">
                                                            <media:credit><![CDATA[Shutterstock]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[a woman doing a bear plank with Pilates ball]]></media:description>                                                            <media:text><![CDATA[a woman doing a bear plank with Pilates ball]]></media:text>
                                <media:title type="plain"><![CDATA[a woman doing a bear plank with Pilates ball]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/QFbFsGUdC7vySRDKs6TJCW-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>I've officially got World Cup fever, and I even bought my dog Mobie a little mini soccer ball to play with outdoors during the warmer weather in the UK. One evening recently, admittedly a little bored, I started playing with the ball and realized it's pretty similar to a Pilates ball.</p><p>Without hesitation, I rolled out one of the <a href="https://www.tomsguide.com/best-picks/best-yoga-mats">best yoga mats</a> and got to work programming a quick 10-minute abs workout using just the ball for equipment. My core is still trembling now. </p><p>Get ready for a humbling core workout with very little equipment, and remember, if you experience any pain during this routine or you're unsure if you should be doing it, please seek advice first.</p><h2 id="watch-10-minute-abs-routine">Watch: 10-minute abs routine</h2><p>Before we get started, building a strong core means more than hitting your abs hard. For that reason, these moves target a range of muscles, including your obliques and deeper core muscles; the former support rotational and lateral movement, whereas the deeper muscles stabilize your torso and act as your body's natural corset.</p><p>You'll be performing these exercises from the side plank and bear plank position, but you can place a supporting knee down at any point if this puts too much strain on your upper body, as they all really fire up the shoulders. </p><p>Throughout, focus on pushing up and away with your shoulder and forearm or hand (whichever is supported on the mat) to help protect your shoulder joints and prevent dumping into the upper body. Think about lifting away from the mat, while actively engaging your core by bracing your stomach and drawing your navel in and up.</p><p>Move with control and focus, not speed, focusing on inhaling and exhaling as you move. Aim for 45 seconds of work, 15 seconds of rest and 2 rounds; if you have time, add more rounds. </p><div class="instagram-embed"><blockquote class="instagram-media"  data-instgrm-version="6" style="width:99.375%; width:-webkit-calc(100% - 2px); width:calc(100% - 2px);"><p><a href="https://www.instagram.com/p/DZ7Plx9CUch/" target="_blank">A post shared by Tom's Guide Fitness (@tomsguidefitness)</a></p><p>A photo posted by  on </p></blockquote></div><ul><li><strong>Side plank crunch combo: </strong>Start in a side plank with your forearm resting on the mat and stacked beneath your shoulder. Hold the ball in your top hand. Brace your stomach, then lift your top leg into the air and touch the ball to your foot. Return to side plank, then extend your leg in front of you and reach with your hand to touch the ball to your foot. Return to center, then repeat.</li><li><strong>Bear plank knee squeeze: </strong>Start on your hands and knees with your shoulders over your wrists. Tuck your toes and brace your stomach, then lift your knees to hover an inch or two off the mat. Step your right foot back slightly, then place the ball between your left forearm and knee. Hold it in position, keep your back flat, then squeeze and release the ball for reps. Switch sides.</li><li><strong>Bear plank kickbacks: </strong>Come back into your bear plank (as above) with the ball positioned between your left forearm and knee. Hold the position with your core braced, then draw your knee inward toward your nose as you push through your hands. Extend your right leg out behind you to hip level, then return to center and repeat. Remember to switch sides.</li><li><strong>Bear plank roll-ups: </strong>Come back to your bear plank (as above) and position the ball between your left forearm and knee. Keep your back flat and core strong as you press the ball into your forearm and roll it up and down with control. Switch sides.</li><li><strong>Standing warrior pulses: </strong>Stand with your left foot forward and right foot back, tucking the toes of your back foot. Lean your weight forward into your left leg. Your feet should be hip-width apart; think train tracks rather than a tightrope with your hips forward. Hinge at the hips while keeping your back flat and gaze forward. Position the ball between one hip and your stomach, then slightly lift and lower your torso to press into the ball and release. Switch sides.</li></ul><h2 id="what-are-the-benefits-3">What are the benefits? </h2><p>I found this routine a lot more versatile and fun to explore than peddling out sit-ups and crunches. Sure, planks are nothing new, but adding the ball and some stability work into the mix tested my balance, fired up my abs and obliques and made me work even harder than usual. </p><p>The ball gives you something to focus on, as you'll need to control the action of it during every move, whether that means gripping it with one hand, pressing it into your thigh or forearm, or rolling it up and down your body. There's plenty to think about, which means you will also notice your muscles working to keep your form in check. That means plenty of core engagement and pressing through your hands to create space beneath you.</p><p>See if you can slow each of the five moves down and aim for the same number of reps per side, move and round. Really press into the ball to activate all those smaller, stabilizer muscles in the body, which will also help you to consciously contract more muscles.</p><p>I also felt this one in my shoulders and hip flexors, which can be a problem area for me as I sit behind a desk for multiple hours during the day. Strong hips and shoulders protect your posture and lower back, so I would try to include shoulder and hip work in any stretching or mobility routine you do.</p><p>Whether you enjoy running, weightlifting, Pilates, or something else entirely, a strong and stable core is crucial for helping you move safely, lift well and avoid injury, so taking the time to include exercises or routines like this will also provide longevity in the gym.</p><p><em><strong>Follow </strong></em><a href="https://www.instagram.com/tomsguidefitness/" target="_blank"><em><strong>Tom's Guide fitness</strong></em></a><em><strong> on Instagram for more workouts, routines, tips, and tricks.</strong></em></p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-ONKRJX"></div>                            </div>                            <script src="https://kwizly.com/embed/ONKRJX.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/wellness/workouts/not-sit-ups-planks-or-crunches-i-do-this-simple-pilates-exercise-every-single-day-to-build-a-strong-and-stable-core-and-work-on-my-hip-flexor-mobility">Not sit-ups, planks, or crunches: I do this simple Pilates exercise every single day to build a strong and stable core and work on my hip flexor mobility</a></li><li><a href="https://www.tomsguide.com/wellness/workouts/not-sit-ups-or-lunges-i-use-this-simple-pilates-exercise-to-sculpt-strong-obliques-inner-thighs-and-hip-stabilizers">Not sit-ups or lunges — I use this simple Pilates exercise to sculpt strong obliques, inner thighs and hip stabilizers</a></li><li><a href="https://www.tomsguide.com/wellness/fitness/im-a-pilates-instructor-and-i-recommend-these-5-core-exercises-to-help-older-clients-build-strength-and-improve-posture">'I’m a Pilates instructor, and I recommend these 5 core exercises to help older clients build strength and improve posture'</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ This 15-minute chair workout helps you strengthen your whole body, and you just need a light set of dumbbells ]]></title>
                                                                                                                                                                                                <link>https://www.tomsguide.com/wellness/workouts/this-15-minute-chair-workout-helps-you-strengthen-your-whole-body-and-you-just-need-a-light-set-of-dumbbells</link>
                                                                            <description>
                            <![CDATA[ If you’re looking for a short and effective way to improve your strength and stability safely, then look no further than this 10-move chair workout. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">apNBBxretDTvKMtcXQGRFn</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/r7SzXSsXxRH4CwvwvnAewM-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Fri, 26 Jun 2026 05:30:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Workouts]]></category>
                                                    <category><![CDATA[Wellness]]></category>
                                                    <category><![CDATA[Fitness]]></category>
                                                                                                                    <dc:creator><![CDATA[ Nick Harris-Fry ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/J5Jjp49GUVjLZEbjEkTex.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Nick has been a journalist since 2012 and has spent most of that time writing about health and fitness for a variety of publications. Nick spent nine years working on the Coach magazine and website before moving to the fitness team at Tom’s Guide in 2024. Nick is a keen runner and also the founder of YouTube channel &lt;a href=&quot;https://www.youtube.com/channel/UCOBM9FasII4dKbyE_HKkbjw&quot;&gt;The Run Testers&lt;/a&gt;, which specialises in reviewing running shoes, watches, headphones and other gear.&lt;/p&gt;&lt;p&gt;Nick has covered all aspects of health and fitness throughout his career, interviewing experts and celebrities, trying fitness classes and running marathons, all in the name of providing readers with the information they need to get the most out of an active lifestyle.&lt;/p&gt;&lt;p&gt;Nick ran his first marathon in 2016 after six weeks of training for a magazine feature and subsequently became obsessed with the sport. He now has PBs of 2hr 25min for the marathon and 15min 30sec for 5K, and has run 16 marathons in total, as well as a 50-mile ultramarathon.&lt;/p&gt;&lt;p&gt;Nick runs 60-90 miles a week and races regularly with his club, which gives him a lot of opportunity to test out running gear: he has tested and reviewed hundreds of pairs of running shoes, as well as fitness trackers, running watches, sports headphones, treadmills, and all manner of other kit. Nick is also a qualified Run Leader in the UK.&lt;/p&gt;&lt;p&gt;Nick is an established expert in the health and fitness area and along with writing for several publications, including &lt;a href=&quot;https://www.livescience.com/author/nick-harris-fry&quot;&gt;Live Science&lt;/a&gt;, &lt;a href=&quot;https://www.expertreviews.co.uk/authors/nick-harris-fry&quot;&gt;Expert Reviews&lt;/a&gt;, &lt;a href=&quot;https://www.wareable.com/author/n.harris-fry&quot;&gt;Wareable&lt;/a&gt;, &lt;a href=&quot;https://www.coachweb.com/author/nick-harris-fry&quot;&gt;Coach&lt;/a&gt; and &lt;a href=&quot;https://www.getsweatgo.com/author/n.harrisfry&quot;&gt;Get Sweat Go&lt;/a&gt;, he has been quoted on &lt;a href=&quot;https://www.theguardian.com/thefilter/2024/oct/20/if-you-pay-more-than-4-youre-being-ripped-off-the-fair-price-for-14-everyday-items-from-cleaning-spray-to-olive-oil&quot;&gt;The Guardian&lt;/a&gt; and &lt;a href=&quot;https://www.independent.co.uk/life-style/health-and-families/london-marathon-2021-date-training-tips-summer-running-a9482486.html&quot;&gt;The Independent&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Nick graduated from the University of York in 2010 with a degree in Politics, Philosophy and Economics and worked in the NHS for three years, during which time he completed his NCTJ Diploma in Journalism at News Associates in London. Before starting on Coach and moving into health and fitness, Nick worked as a football journalist and lived in Kathmandu, Nepal for two years.&lt;/p&gt; ]]></dc:description>
                                                                                                                                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/r7SzXSsXxRH4CwvwvnAewM-1280-80.jpg">
                                                            <media:credit><![CDATA[Getty Images]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[a photo of a woman doing a chair workout]]></media:description>                                                            <media:text><![CDATA[a photo of a woman doing a chair workout]]></media:text>
                                <media:title type="plain"><![CDATA[a photo of a woman doing a chair workout]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/r7SzXSsXxRH4CwvwvnAewM-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>The benefits of chair workouts are that they allow you to train without putting too much pressure on your joints or worrying about your balance, which makes them an accessible option for seniors in particular.</p><p>These benefits do come with a downside, however, in that it can be hard to strengthen all areas of the body when training while seated.</p><p>It’s not impossible, though, as this 10-move chair workout from fitness trainer Lauren of <a href="https://www.youtube.com/@SeniorShapeFitness" target="_blank" rel="nofollow">SeniorShape Fitness</a> shows. It’s a seated session that strengthens the whole body, and all you need is a set of light dumbbells and a chair.</p><p>Lauren is using 5lb dumbbells for the workout, but pick a weight that suits you, or you can use a couple of cans instead if you don’t have dumbbells to hand. </p><p>Whatever weights you end up using, if they feel too heavy during the session, feel free to pop them down and do the exercises without any weight.</p><h3 class="article-body__section" id="section-watch-seniorshape-fitness-10-move-chair-workout"><span>Watch SeniorShape Fitness’ 10-move chair workout</span></h3><div class="youtube-video" data-nosnippet ><div class="video-aspect-box"><iframe data-lazy-priority="low" data-lazy-src="https://www.youtube-nocookie.com/embed/S9ctJJwInv8" allowfullscreen></iframe></div></div><p>In the video, Lauren guides you through a warm-up and cool-down as well as the workout itself, which takes around 15 minutes.</p><p>There are 10 exercises in the workout, and you do each for a minute, then rest for 15 seconds. Lauren demonstrates each upcoming move during the rest period as well, giving technique pointers throughout, so make sure you can see and hear your screen.</p><p>The session is designed to be accessible for all and is especially good if you’re trying to avoid too much impact on your joints during workouts, since you remain seated the whole time.</p><p>It’s also best done at a controlled pace — this isn’t one to rush through. Instead, focus on keeping moving throughout the working sets and engaging the right muscles with each move to challenge the target areas correctly.</p><p>To get the most out of short workouts like this, it's important to do them regularly. If you can do two or three short sessions a week, it will help you build and then maintain your strength and fitness.</p><p>Once you've spent a few weeks training with a chair, you might be able to move on to standing workouts. These are still low-impact and will help you to keep improving your strength and stability.</p><p>You can use your light dumbbell for this<a href="https://www.tomsguide.com/wellness/workouts/this-10-minute-standing-workout-is-perfect-for-improving-your-balance-and-stability-and-you-just-need-a-light-dumbbell-to-do-it"> 10-minute workout</a> if you are ready to try standing sessions. It's another accessible workout that helps to improve stability and balance, along with strengthening muscles all over the body.</p><p><em><strong>Follow </strong></em><a href="https://www.instagram.com/tomsguidefitness/" target="_blank"><em><strong>Tom's Guide fitness</strong></em></a><em><strong> on Instagram for more workouts, routines, tips, and tricks.</strong></em></p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-ONKRJX"></div>                            </div>                            <script src="https://kwizly.com/embed/ONKRJX.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/wellness/workouts/i-teach-people-how-to-be-more-mobile-3-low-impact-back-and-shoulder-moves-that-build-stability-and-strength-after-40" target="_blank">I teach people how to be more mobile: 3 low-impact back and shoulder moves that build stability and strength after 40</a></li><li><a href="https://www.tomsguide.com/wellness/workouts/im-a-personal-trainer-who-works-with-clients-aged-65-daily-here-are-the-2-exercises-i-always-recommend-when-it-comes-to-building-mobility-and-balance" target="_blank">I’m a personal trainer who works with clients aged 65+ daily. Here are the 2 exercises I always recommend when it comes to building mobility and balance</a></li><li><a href="https://www.tomsguide.com/wellness/fitness/sit-all-day-try-these-7-back-exercises-from-a-physical-therapist-right-now" target="_blank">Sit all day? Try these 7 back exercises from a physical therapist right now</a></li></ul><div class="vizualizer-embed"><div class="tg-df-widget-host" data-widget-config="?search=Fitness&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');                    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' ? '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 { background-color: #5DAF08 !important; }              .tg-df-container .hawk-affiliate-link-deal-button: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';          }        }        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.rowsSelect && this.rowsSelect.value) ? parseInt(this.rowsSelect.value, 10) : 12;                    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 airedaleUrl = `https://airedale.futurecdn.net/feeds/feed_1781000519267.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 && this.currentQuery) {             const tagMatch = this.airedaleTags.find(t => t.toLowerCase() === this.currentQuery.toLowerCase());             if (tagMatch) {                this.activeDealTag = tagMatch;             }          }          if (this.activeDealTag) {             const encodedTag = encodeURIComponent(this.activeDealTag.toLowerCase().replace(/\s+/g, '-'));             const url = `https://airedale.futurecdn.net/feeds/feed_1781000519267.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 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');                    if (this.rowsSelect && this.rowsSelect.value) {            url.searchParams.append('rows', this.rowsSelect.value);          } else {             url.searchParams.append('rows', '12'); // default          }          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 = 12;          if (this.rowsSelect && this.rowsSelect.value) {            rowLimit = parseInt(this.rowsSelect.value, 10) || 12;          }          // 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 => {              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}`;                }              }              return `                \x3Ca href="${this.escapeHTML(linkUrl)}" target="_blank" rel="noopener nofollow" class="tg-df-voucher-item">                  ${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);                }              });            });                                  } 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 = `              \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;">` : ''}                            \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;">` : ''}                          \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');            if (!this.processArticleFired) {                  this.processArticleFired = true;                  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 += 12;              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[ Claude Skills changed how I work — 5 ways I use them every day ]]></title>
                                                                                                                                                                                                <link>https://www.tomsguide.com/ai/claude-skills-changed-how-i-work-5-ways-i-use-them-every-day</link>
                                                                            <description>
                            <![CDATA[ I built custom Claude Skills to automate the AI tasks I repeat most often. These five workflows now save me time every single day — and you can make your own in minutes. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">8hvuZRLVgy4u5qy5qeyuNk</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/ViYVUoYbq5yE9sPuwW9h5-1280-80.png" type="image/png" length="0"></enclosure>
                                                                        <pubDate>Fri, 26 Jun 2026 05:00:00 +0000</pubDate>                                                                                                                                <updated>Mon, 29 Jun 2026 21:35:58 +0000</updated>
                                                                                                                                            <category><![CDATA[AI]]></category>
                                                                                                <author><![CDATA[ amanda.caswell@futurenet.com (Amanda Caswell) ]]></author>                    <dc:creator><![CDATA[ Amanda Caswell ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/zYjevim2q7FjQiefqpjZRB.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ null ]]></dc:description>
                                                                                                                                                                                                                                                <media:content type="image/png" url="https://cdn.mos.cms.futurecdn.net/ViYVUoYbq5yE9sPuwW9h5-1280-80.png">
                                                            <media:credit><![CDATA[Future]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[claude]]></media:description>                                                            <media:text><![CDATA[claude]]></media:text>
                                <media:title type="plain"><![CDATA[claude]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/ViYVUoYbq5yE9sPuwW9h5-1280-80.png" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>One of the most underrated AI features is Claude Skills. Rather than copying and pasting your perfect prompt into a new chat every time, a Skill remembers what you need and how to execute it. </p><p>Simply put, a "Skill" is a reusable set of instructions for a particular kind of task. It includes the steps, preferences, templates and reference files (slide decks, documents and spreadsheets) Claude should use whenever that task comes up. </p><p>In other words, instead of re-explaining how I work every time, I write it down once — in a form Claude reaches for on its own — and when I recall the Skill, it saves me hours. Here's how I use Skills every day and why I recommend this often overlooked feature. </p><h2 id="what-makes-skills-different">What makes Skills different </h2><div class="youtube-video" data-nosnippet ><div class="video-aspect-box"><iframe data-lazy-priority="low" data-lazy-src="https://www.youtube-nocookie.com/embed/kS1MJFZWMq4" allowfullscreen></iframe></div></div><p>One thing to be clear about up front, because it trips people up: a Skill is a procedure, not a memory. It doesn't store your data, learn your habits over time or update itself. It does exactly what you wrote into it, every time, until you change it. If you want Claude to actually remember things that keep changing, your calendar, your to-do list, what's in the fridge, that's a different feature (<a href="https://www.tomsguide.com/ai/anthropic-finally-rolls-out-memory-feature-heres-who-can-get-it">Claude's memory</a>, <a href="https://www.tomsguide.com/ai/claude-just-made-two-of-its-best-features-free-heres-how-to-use-projects-and-artifacts">Projects </a>or a <a href="https://www.tomsguide.com/ai/claude-can-now-connect-to-google-drive-canva-slack-and-more-heres-how-to-try-it">Connector</a>), not Skills.</p><p>While Projects load the same background knowledge into every chat inside them, and custom instructions apply to everything, Skills are task-specific. They only switch on when the job in front of Claude actually calls for them. That's the whole idea.</p><p>What's great, is that they are available on every plan, including the free one, as long as you have code execution turned on. (More on setup in a minute). After using them for several weeks, these are the Skills I reach for almost every day.</p><h2 id="1-my-meal-planning-playbook">1. My meal-planning playbook  </h2><p>This is the one most people could use tonight. Planning the week's dinners for my family of five used to mean re-explaining the same things to Claude every time such as who eats what, what we keep stocked, how I want the shopping list laid out and other important instructions. So I wrote that down once, as a Skill.</p><p> The Skill is basically my standing brief for the job. It tells Claude:</p><ul><li>Our dietary preferences</li><li>The staples we always have on hand</li><li>How to build a week of dinners that don't repeat</li><li>How to turn that into a shopping list, grouped by aisle</li></ul><p>Now I just say "plan this week's dinners," and Claude runs the same playbook every time instead of starting from a blank page.</p><p>What it can't do is keep track of my real life. It doesn't know what I bought yesterday or what's already in the pantry. That's <a href="https://www.tomsguide.com/ai/alexa-is-available-to-everyone-now-9-things-to-try-first">something Alexa+ does for me</a>, so I still tell Claude "we've got chicken to use up" or "skip Thursday, we're out." The Skill supplies the method; I supply this week's details.</p><h2 id="2-research-assistant">2. Research assistant  </h2><p>I rely on this one every day as it is so important for my work. Whenever I'm researching a new AI feature, I don't want a wall of text; I want it sorted the "who, what, when, where, how" of reporting.  It creates the bullet points based on the pages of documentation I give it. <br><br>To be clear, the Skill doesn't do the research for me. It can, but that's not what this Skill is for. What Claude does is shape the plethora of research I've found into useable nuggets for reporting.   </p><h2 id="3-my-fact-check-checklist">3. My fact-check checklist  </h2><p>No AI should be trusted blindly. And while Claude is the least <a href="https://www.tomsguide.com/ai/i-tested-chatgpt-vs-gemini-vs-claude-to-see-which-chatbot-is-the-biggest-people-pleaser-one-went-way-too-far">people-pleasing of all the chatbots</a>, it can <a href="https://www.tomsguide.com/ai/45-percent-of-ai-generated-news-is-wrong-new-study-warns-heres-what-happened-when-i-tested-it-myself">get information wrong just as frequently</a>. So I wrote a Skill that runs a checklist over Claude's own drafts before I see them.</p><p>Because the Skill can't independently know what's correct, it forces the checks: flag numbers that need a source, point out where a claim has no evidence behind it and marks statements confident enough to deserve a second look.</p><p>Granted, it's not perfect and I still click links and double check everything myself,  but it catches plenty of things that would otherwise slip past me until later.</p><h2 id="4-family-organizer">4. Family organizer</h2><p>From soccer games to gymnastics practice, birthday parties and events, my after-work schedule is packed with family activities. I even use a Skill to stay organized. <br><br>It's worth noting here, because "organizer" makes it sound like more than it is. The Skill doesn't hold a calendar or remember appointments — it isn't tracking anything between chats. It's a template plus our usual routine, and I feed it this week's changes each time. If I wanted Claude to actually keep my calendar, that's a connector or its memory, not a Skill.</p><p>So the Skill carries the standing version of it: our normal weekly rhythm and the chore rota. When I tell it what's different this week — a dentist appointment Tuesday, swimming moved to Friday — it lays the week out cleanly and divides the chores the way we usually do.</p><h2 id="5-personal-assistant">5. Personal assistant  </h2><p>This is the one I almost left out, because "personal assistant" somewhat oversells what a Skill can do. It can't run errands, watch my inbox or hold my to-do list, but what it can do is take the way I plan and apply it every time so I start with consistency each day.  </p><p>In this case, the Skill is really my planning method, written down. I dump everything on my mind into a chat, and it sorts the pile into a day I'd actually work: top three priorities first, the rest time-boxed, quick wins flagged and the someday-stuff pulled out of the way. Claude lays everything out the way I like to read it.</p><p>The thinking is still mine. The Skill just makes Claude do it my way, every Monday, instead of me re-explaining my system from scratch.</p><h2 id="how-to-make-your-own-it-s-easier-than-it-sounds">How to make your own (it's easier than it sounds)  </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="hivKht7Z68YKgpsSwCs34d" name="Skills-settings-blog-inline_1920x1080" alt="Claude Skills screenshot" src="https://cdn.mos.cms.futurecdn.net/hivKht7Z68YKgpsSwCs34d.png" 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: Anthropic/Claude)</span></figcaption></figure><p>No code is required to create a Skill. Actually, at its simplest, a Skill is a short text file of instructions, wrapped in a folder. Claude reads it the same way a new freelancer would read a one-page brief.</p><p><strong>First, turn it on.</strong> In Claude's settings, make sure <em><strong>Code execution and file creation</strong></em> is enabled, then head to <em><strong>Customize > Skills</strong></em><strong>. </strong>That's where your built-in and custom Skills live, and where you toggle them on or off.</p><p><strong>Then build one.</strong> A Skill is a folder containing a file called <strong>SKILL.md</strong>. The top of that file needs two things: a name and a description. The description is the most important sentence you'll write, because Claude uses it to decide <em>when</em> to reach for the Skill. Vague description, and it won't trigger when you expect; specific description, and it fires at the right moment.</p><p><strong>A bare-bones version of a Skill might look like: </strong></p><p>Name: weekly-meal-plan <br>Description: Plan a week of dinners and build a shopping list. Use when I ask for a meal plan or what to cook this week. When I ask for a meal plan, give me dinners for seven nights.  <br>Our preferences: two vegetarian nights minimum - nothing too spicy for the kids - one slow-cooker meal for busy weeknights - don't repeat the same protein two nights running. Staples we always have: rice, pasta, chicken, shrimp, steak, onions, garlic, fresh veggies. Then turn the plan into a shopping list, grouped by aisle at [grocery store name], leaving out anything from the staples list.</p><p><strong>Then, Save that as SKILL.md, zip the folder, and upload it under </strong><em><strong>Customize > Skills</strong></em><strong>.</strong> That's the whole thing. Everything below the description is just instructions in plain language, the same notes you'd type into a chat, except you only type them once.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-WValye"></div>                            </div>                            <script src="https://kwizly.com/embed/WValye.js" async></script><h2 id="final-take">Final take </h2><p>I learned a few things the hard way, so be patient when you first start out. That said, it will behoove you to keep each Skill fairly narrow. In other words, one job per Skill works far better than a single Skill that tries to do everything. <br><br>Also, you're going to want to spell out the trigger. Write the description as if you're telling Claude exactly when to use it, not just what it does. <br><br>Always test it before you trust it. You'll want to run a few real prompts and check that it switches on when it should. If it doesn't, the description usually needs tightening.</p><p>It's worth noting that the Custom Skills you upload stay private to your account, so there's no risk in experimenting. But unlike prompts that disappear, Skills accumulate. Now, every time I notice myself repeating the same instructions, I create a new Skill. When AI understands you and how you want your answers, the workflow feels unstoppable. <br><br>Have you tried Skills yet? Share your experience by letting me know in the comments how you use them. </p><a href="https://follow.it/articles-by-amanda-caswell-tom-s-guide?leanpub" class="button button--large button--primary">Follow Amanda Caswell and stay ahead of the AI curve</a><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/ai/google-couldnt-give-meta-enough-ai-power-heres-why-running-ai-locally-suddenly-makes-even-more-sense"><strong>Google couldn't give Meta enough AI power — here's why running AI locally suddenly makes even more sense</strong></a></li><li><a href="https://www.tomsguide.com/ai/i-built-five-chatgpt-agents-then-replaced-them-with-one-master-ai"><strong>I built five ChatGPT agents — then replaced them with one 'master' AI</strong></a></li><li><a href="https://www.tomsguide.com/ai/i-used-chatgpt-to-audit-my-subscriptions-these-prompts-helped-me-find-nearly-usd2-000-a-year-in-recurring-charges"><strong>I used ChatGPT to audit my subscriptions — these prompts helped me find nearly $2,000 a year in recurring charges</strong></a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ Why do I have yellow patches in my lawn? Gardening experts share their top tips on how to fix it ]]></title>
                                                                                                                                                                                                <link>https://www.tomsguide.com/home/gardening/why-do-i-have-yellow-patches-in-my-lawn-gardening-experts-share-their-top-tips-on-how-to-fix-it</link>
                                                                            <description>
                            <![CDATA[ Do you have unsightly yellow patches ruining your grass? Gardeners reveal the possible reasons why and how to fix it. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">kAymuRVnGuJ2L9D9NnqARU</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/tyBNke4AjR6gYGGH8NUiDZ-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Fri, 26 Jun 2026 04:30:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Gardening]]></category>
                                                    <category><![CDATA[Home]]></category>
                                                    <category><![CDATA[Outdoors]]></category>
                                                                                                                    <dc:creator><![CDATA[ Cynthia Lawrence ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/CCuSgQpd5NyZ46CgoF9cva.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ null ]]></dc:description>
                                                                                                                                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/tyBNke4AjR6gYGGH8NUiDZ-1280-80.jpg">
                                                            <media:credit><![CDATA[Shutterstock]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Brown patches in grass]]></media:description>                                                            <media:text><![CDATA[Brown patches in grass]]></media:text>
                                <media:title type="plain"><![CDATA[Brown patches in grass]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/tyBNke4AjR6gYGGH8NUiDZ-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Summer is here, and we’re not the only ones who are feeling parched in the heat. If you take pride in your lush and <a href="https://www.tomsguide.com/how-to/how-to-make-grass-greener">green grass</a>, it can be disheartening when you notice yellow patches suddenly appearing that quickly ruin the overall look. </p><p>This is especially the case if you’re hosting those backyard barbecues or gatherings. So if you’ve been watering and maintaining your yard, you’re probably wondering why you have yellow patches in your lawn. </p><p>We’ve called on the gardening and lawn care experts at hand to share their top tips on how to get rid of those discolored spots on your lawn and what causes them in the first place. So, read on if you want to revive and bring your lawn back to life this summer.</p><h2 id="what-causes-the-yellow-patches-in-my-lawn">What causes the yellow patches in my lawn?</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:5390px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="RwnyCYupmo4CsDXuzHHtpJ" name="shutterstock_2249537999.jpg" alt="Brown spots in grass in garden" src="https://cdn.mos.cms.futurecdn.net/RwnyCYupmo4CsDXuzHHtpJ.jpg" mos="" align="middle" fullscreen="" width="5390" height="3032" attribution="" endorsement="" class=""></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="caption-text">Brown patches in grass </span><span class="credit" itemprop="copyrightHolder">(Image credit: Shutterstock)</span></figcaption></figure><p>Essentially, a yellowing lawn is common when the weather switches from heavy rain to a sudden dry spell. Scientifically, this yellowing is known as chlorosis. </p><p>Particularly, when grass undergoes stress, the green chlorophyll breaks down, and this process exposes the underlying yellow carotenoid pigments that are typically concealed during healthier periods.<strong> </strong></p><p>According to experts, there are various causes for your lackluster lawn. One obvious reason could be not watering your lawn adequately during hot spells, which can dry out the soil. Ideally, you should water deeply and infrequently, as this helps the roots grow stronger and penetrate deeper into the soil.</p><p>“If you notice yellow patches in your lawn, it might be a sign that you are overwatering or underwatering your grass,” said Allison Koenig, a lawn and garden expert at <a href="https://www.tractorsupply.com/" target="_blank">Tractor Supply</a>.</p><p>Basically, if your grass looks dry, turns brown, or has a crispy texture to it, you're likely under-watering, and your grass is parched. But if the grass is constantly soggy, has yellowing patches, or shows signs of mold or fungus, it’s a clear sign of overwatering, and you should reduce the amount of water your lawn is getting. </p><p>“The best way to tell what your lawn needs is through a quick soil check," Koenig said. "If it feels compacted and doesn’t absorb water well, you may be overwatering, while a dry, hard soil signals that your lawn needs more moisture.”</p><div><blockquote><p>Pet urine can also cause those yellow or brown spots on your lawn because of the high nitrogen levels, which essentially burn the grass.</p><p>Allison Koenig, lawn and garden expert </p></blockquote></div><p>Another reason could be diseases or pests, in particular chaffer grubs and leatherjackets that are known to feed directly on the grass roots, literally sucking out the water and essential nutrients it needs to thrive.  </p><p>“As they feed directly on the roots of the grass, they sever your lawn’s connection to its water and nutrient supply,” adds Angelika Zaber, Lawn Care Specialist and Gardening Expert working for <a href="https://www.onlineturf.co.uk" target="_blank">Online Turf.</a>  </p><p>“In terms of diseases, Fusarium is a common culprit since it often shows up as small, yellow, circular patches. To treat it, reduce the amount of thatch and loosen the soil by scarifying and aerating your lawn. Additionally, avoid high-nitrogen fertilizers. Instead, use a fertilizer that is low in nitrogen but high in potassium.”</p><p>Furthermore, for those with furry companions, discolored spots frequently stem from animal waste. “Pet urine can also cause those yellow or brown spots on your lawn because of the high nitrogen levels, which essentially burn the grass,” explained Koenig.</p><p>“To prevent these spots, one effective approach is to immediately water the area where your pet has urinated," Koenig said. "This dilutes the nitrogen and prevents it from "burning" the grass, preventing the brown spots from appearing. You can also try training your pet to use a designated area of the yard, such as a gravel or mulch patch, where the urine won’t harm your lawn.” </p><h2 id="how-do-i-fix-any-yellow-patches">How do I fix any yellow patches?</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:4345px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="4obTEfSTnQVSYL2uvtvu8G" name="Main.jpg" alt="A thatching rake removing thatch from the grass" src="https://cdn.mos.cms.futurecdn.net/4obTEfSTnQVSYL2uvtvu8G.jpg" mos="" align="middle" fullscreen="" width="4345" height="2444" attribution="" endorsement="" class=""></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="caption-text">A thatching rake removing thatch from the grass </span><span class="credit" itemprop="copyrightHolder">(Image credit: Shutterstock)</span></figcaption></figure><p>First, it’s advisable to start with a soil test to help you determine the pH levels and what nutrients it’s deficient in. </p><p>"This will help you determine the pH levels of the soil as well as if it has adequate nutrients and organic matter present," said Theresa Smith, the SVP at NaturaLawn of America.</p><p>“If the soil test results show signs of the soil having adequate nutrient content, then you know the yellowing or browning of the grass is being caused by an environmental factor or is under physical stress”.<strong> </strong></p><p>So, once you have established the cause for your discolored grass, how do you fix your unsightly patches? "The best way to fix this is by overseeding,” advises Zaber.</p><p>“Overseeding is a practice of spreading grass seed onto an already existing lawn to thicken it and give it that healthy, green appearance. Start by mowing, then scarifying and aerating the soil. </p><p>“Then, spread the seed at a rate of 25 grams per square meter and add a light layer of topsoil on top. This will improve the seed-to-soil contact, which is critical for good germination rates, and also protect the seeds from being eaten by birds or blown away by wind.”</p><p>Bear in mind that you may need a period of two to four weeks for initial growth, though achieving a fully restored, and lush lawn can take up to six months.“Grass usually takes around 2-4 weeks to germinate, depending on the weather. However, to fully establish, it can take up to 6 months,” added Zaber.</p><p>For more top tips, check out <a href="https://www.tomsguide.com/home/lawn-care/how-to-tell-if-your-lawn-needs-overseeding-3-signs-you-cant-ignore">how to tell if your lawn needs overseeding</a>, especially if you want to maintain healthy grass all year round. Or if you just want a lush lawn, try these <a href="https://www.tomsguide.com/home/lawn-care/11-secrets-to-a-lawn-thats-greener-than-your-neighbors">11 secrets to a lawn that’s greener than your neighbor's.</a></p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-eG0N2W"></div>                            </div>                            <script src="https://kwizly.com/embed/eG0N2W.js" async></script><h3 class="article-body__section" id="section-lawncare-essentials-we-love"><span>Lawncare essentials we love</span></h3>        <div class="featured_product_block featured_block_hero" data-id="908cae43-55fa-4da3-8574-24b29266d738">            <a href="https://www.amazon.com/Garden-Guru-Handheld-Spreader-Shaker/dp/B0F8P8QM3V/ref=sr_1_8?" data-model-name="Garden Guru Handheld Seed Spreader Shaker" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:82.80%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/ezrwVY6BYsgBZtBcNhMTm9.jpg" alt="Garden Guru Handheld Seed Spreader Shaker – Multi Use Grass Seed, Fertilizer, Salt, Ice & Snow Melt Spreader – Adjustable Twist Cap W Multiple Size Openings – Lightweight 1l Capacity Hand Seeder"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Amazon</div>                                        <div class="featured__title">Garden Guru Handheld Seed Spreader Shaker</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="f740eec9-fe02-43b7-b239-5b64bced9d51">            <a href="https://www.amazon.com/dp/B07BD2GZW8" data-model-name="Garden Gloves" 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/YyBJP4YUpLVNV4q2yKFfjS.jpg" alt="Amazing Stuff For You green and gray gardening gloves"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Amazing Stuff</div>                                        <div class="featured__title">Garden Gloves</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="36c3c5ee-d7ff-4592-9d90-3e70c1b065ba">            <a href="https://www.amazon.com/Grampas-Weeder-CW-01-Original-Remover/dp/B001D1FFZA?" data-model-name="Grampa's Weeder" 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/kP7pgu2tpxz8d34HtVQgxC.jpg" alt="Grampa's Weeder The Original Stand Up Weed Puller Tool with Long Handle"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                                                                <div class="featured__title">Grampa's Weeder</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="e9b94b08-caad-456c-b104-34a12eed1cce">            <a href="https://www.amazon.com/Greenworks-G-MAX-Mower-Batteries-Charger/dp/B086K59Q79/ref=sr_1_3?" data-model-name="Greenworks 48v (24v X 2) 17" Cordless (push) Lawn Mower" 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/8LF2UvRs8EXvmebaZefwzA.jpg" alt="Greenworks 48v (24v X 2) 17" Cordless (push) Lawn Mower (200+ Compatible Tools), (2) 4.0ah Batteries and Dual Port Rapid Charger Included"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Amazon</div>                                        <div class="featured__title">Greenworks 48v (24v X 2) 17" Cordless (push) Lawn Mower</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/how-to/7-common-lawn-care-mistakes-you-are-probably-making-right-now"><u>7 common lawn care mistakes you’re probably making right now</u></a></li><li><a href="https://www.tomsguide.com/how-to/9-ways-to-get-the-most-out-of-your-lawn-mower">9 ways to get the most out of your lawn mower</a></li><li><a href="https://www.tomsguide.com/how-to/5-plants-that-will-keep-wasps-out-of-your-yard">5 plants that will keep wasps out of your yard</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ Don't let ISP throttling ruin your USA vs Turkey stream – fix it with our top streaming VPN which has a 60-day money-back guarantee ]]></title>
                                                                                                                                                                                                <link>https://www.tomsguide.com/computing/vpns/dont-let-isp-throttling-ruin-your-usa-vs-turkey-stream-fix-it-with-our-top-streaming-vpn-which-has-a-60-day-money-back-guarantee</link>
                                                                            <description>
                            <![CDATA[ Internet throttling can seriously mess up your streams – if you use too much bandwidth, your ISP may slow you down to keep things fair. However, using a VPN fixes this. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">yNGV2RxVcZU8eBwvqu4fxA</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/dKPHULhwogJnk38dxm4F7m-1280-80.png" type="image/png" length="0"></enclosure>
                                                                        <pubDate>Thu, 25 Jun 2026 23:30:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[VPNs]]></category>
                                                    <category><![CDATA[Streaming]]></category>
                                                    <category><![CDATA[Computing Peripherals]]></category>
                                                    <category><![CDATA[Internet]]></category>
                                                    <category><![CDATA[Entertainment]]></category>
                                                                                                                    <dc:creator><![CDATA[ Aleksandar Stevanović ]]></dc:creator>                                                                                                        <dc:description><![CDATA[ null ]]></dc:description>
                                                                                                                                                                                                                                                <media:content type="image/png" url="https://cdn.mos.cms.futurecdn.net/dKPHULhwogJnk38dxm4F7m-1280-80.png">
                                                            <media:credit><![CDATA[Getty Images]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Christian Pulisic celebrating a goal for the USMNT]]></media:description>                                                            <media:text><![CDATA[Christian Pulisic celebrating a goal for the USMNT]]></media:text>
                                <media:title type="plain"><![CDATA[Christian Pulisic celebrating a goal for the USMNT]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/dKPHULhwogJnk38dxm4F7m-1280-80.png" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>USA vs Turkey is a chance for the USMNT to really flex their muscles, seeing as they're through to the Round of 32 regardless of the result. However, even if you've got a solid broadband connection at home, there's no guarantee of a smooth stream. ISPs routinely throttle bandwidth when they detect heavy streaming activity, and with millions of fans tuning in simultaneously, the risk of a buffering-plagued match is very real.</p><p>The <a href="https://www.tomsguide.com/best-picks/best-vpn">best VPNs</a> tackle this by making your traffic unreadable to your ISP. Without knowing what you're doing, it can't make the decision to slow you down – so instead of throttling your stream mid-match, it simply lets your connection run at full tilt.</p><p>Right now, Norton VPN sits at the top of our <a href="https://www.tomsguide.com/best-picks/streaming-vpn">best streaming VPN</a> rankings, and a compelling World Cup deal makes it particularly well-timed for anyone wanting a buffer-free tournament.</p><div class="product"><a data-dimension112="b3548274-ac8f-4465-8770-518b393dfed5" data-action="Deal Block" data-label="Norton VPN | 60-day money-back guarantee" data-dimension48="Norton VPN | 60-day money-back guarantee" data-dimension25="$" href="https://norton.ow5a.net/c/221109/3913583/4405?sharedid=tg&param1=aff&param2=worldcup26_dealpost&param3=vpn&subid1=Deal_TG" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:280px;"><p class="vanilla-image-block" style="padding-top:56.43%;"><img id="cgidcx9LYVJedVXABk3BpC" name="nortonvpn_graphic_-_affiliates__5_" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/cgidcx9LYVJedVXABk3BpC.png" mos="" align="middle" fullscreen="" width="280" height="158" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><a href="https://norton.ow5a.net/c/221109/3913583/4405?sharedid=tg&param1=aff&param2=worldcup26_dealpost&param3=vpn&subid1=Deal_TG" target="_blank" rel="nofollow" data-dimension112="b3548274-ac8f-4465-8770-518b393dfed5" data-action="Deal Block" data-label="Norton VPN | 60-day money-back guarantee" data-dimension48="Norton VPN | 60-day money-back guarantee" data-dimension25="$"><strong>Norton VPN | 60-day money-back guarantee</strong></a><br>Norton VPN is our top pick for World Cup 2026 streaming, with a 60-day money-back guarantee on annual plans – double the industry standard – covering the entire tournament risk-free.</p><p><strong>What you'll get...</strong></p><p>🔒 Native app for Amazon Fire TV devices<br>⚡️ WireGuard protocol across all Apple platforms<br>📺 Apps for Google TV, Android TV, and Apple TV<br>🌍 Servers in 30+ countries for home-country streaming</p><p>A 12-month Norton VPN plan starts at <a href="https://norton.ow5a.net/c/221109/3913583/4405?sharedid=tg&param1=aff&param2=worldcup26_dealpost&param3=vpn&subid1=Deal_TG" target="_blank" rel="nofollow"><strong>$3.33 per month</strong></a> ($39.99 upfront, pre-tax) and comes with a 60-day money-back guarantee on annual plans.<a class="view-deal button" href="https://norton.ow5a.net/c/221109/3913583/4405?sharedid=tg&param1=aff&param2=worldcup26_dealpost&param3=vpn&subid1=Deal_TG" target="_blank" rel="nofollow" data-dimension112="b3548274-ac8f-4465-8770-518b393dfed5" data-action="Deal Block" data-label="Norton VPN | 60-day money-back guarantee" data-dimension48="Norton VPN | 60-day money-back guarantee" data-dimension25="$">View Deal</a></p></div><h2 id="how-does-norton-vpn-compare-to-other-top-vpns">How does Norton VPN compare to other top VPNs?</h2><p>When it comes to sheer breadth, <a href="https://www.tomsguide.com/reviews/nordvpn-review">NordVPN</a> is hard to beat. Its network spans more than 9,000 servers across 149 countries, and in our speed tests it hit over 1,249 Mbps locally – figures that put it ahead of most of the competition. That firepower does come at a cost, though. NordVPN starts at <a href="http://go.nordvpn.net/aff_c?offer_id=564&aff_id=3013&url_id=10992" target="_blank" rel="nofollow"><strong>$3.49 per month</strong></a>, and that requires you to commit for two years. What's more, it comes with only a 30-day money-back guarantee, compared to Norton's 60-day window.</p><p><a href="https://www.tomsguide.com/reviews/surfshark-vpn-review">Surfshark</a> undercuts both on price, with two-year plans coming in at just <a href="http://get.surfshark.net/aff_c?offer_id=61&aff_id=1691" target="_blank" rel="nofollow"><strong>$1.99 per month</strong></a> – and unlike Norton, it places no cap on device connections, making it an appealing option for households with a lot of hardware. Speed-wise it's no slouch either, ranking among the <a href="https://www.tomsguide.com/best-picks/best-fast-vpn">fastest VPNs</a> we've tested. Where it falls short is consistency: in our streaming tests, it has occasionally failed to unblock certain Netflix regions that Norton handles without issue.</p><p>For throttling specifically, what matters most is that your VPN can reliably access streaming sites and mask your traffic from your ISP – and that's precisely where Norton's streaming credentials count most. Add in the 60-day money-back guarantee, which is double the industry standard and comfortably covers the entire tournament, and the choice is easy. </p><p>NordVPN and Surfshark are both worth considering once the final whistle blows on the group stage, but if a buffer-free World Cup is the goal, Norton is the one to back.</p><p>We test and review VPN services in the context of legal recreational uses. For example:<strong>1.</strong> Accessing a service from another country (subject to the terms and conditions of that service).<strong>2.</strong> Protecting your online security and strengthening your online privacy when abroad.We do not support or condone the illegal or malicious use of VPN services. Consuming pirated content that is paid-for is neither endorsed nor approved by Future Publishing.</p>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ GTA 6's Ultimate Edition is the real full game — and the rumors of it costing $100 were true after all ]]></title>
                                                                                                                                                                                                <link>https://www.tomsguide.com/gaming/gta-6s-ultimate-edition-is-the-real-full-game-and-the-rumors-of-it-costing-usd100-were-true-after-all</link>
                                                                            <description>
                            <![CDATA[ The rumors circulating about GTA 6 being $100 ended up being right after all, as the game’s full content slate is locked behind the Ultimate Edition. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">FnmfskDzuirbNQPVwckYZ6</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/nNYq47owmBv2h9zgLSqhPf-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Thu, 25 Jun 2026 14:42:02 +0000</pubDate>                                                                                                                                <updated>Thu, 25 Jun 2026 14:45:51 +0000</updated>
                                                                                                                                            <category><![CDATA[Gaming]]></category>
                                                                                                                    <dc:creator><![CDATA[ Elton Jones ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/NVtYYXr3tEPUE67jf3HtXM.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ null ]]></dc:description>
                                                                                                                                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/nNYq47owmBv2h9zgLSqhPf-1280-80.jpg">
                                                            <media:credit><![CDATA[Rockstar Games]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[gta 6 ultimate edition]]></media:description>                                                            <media:text><![CDATA[gta 6 ultimate edition]]></media:text>
                                <media:title type="plain"><![CDATA[gta 6 ultimate edition]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/nNYq47owmBv2h9zgLSqhPf-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>It’s safe to say that every time official news of <a href="https://www.tomsguide.com/news/gta-6">GTA 6</a> hits everyone’s timelines, it ends up being the story of the day.</p><p>All Rockstar Games had to do was drop an announcement about when pre-orders were going live, with a seconds-long clip showing off the game’s box art, to send gamers into a frenzy.</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="WvTGFfeAux2frmzFYT3U7M" name="GTA 6 - Vintage Vice 7" alt="GTA 6" src="https://cdn.mos.cms.futurecdn.net/WvTGFfeAux2frmzFYT3U7M.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: Rockstar Games)</span></figcaption></figure><p>And now that those pre-orders have gone live, I’m being treated to my PS5 “Welcome Section” being adorned with promotional material for November 19’s blockbuster gaming release and tweets from friends excitedly explaining how they secured their digital copy.</p><p>The hype surrounding the next mainline installment in one of, if not THE, biggest entertainment properties of all time is hard to ignore. But what’s equally difficult to look past is the anger that’s brewing among gamers for two reasons: GTA 6’s physical copies will only come packaged with a digital code for the game, and the Ultimate Edition comes with a host of content that won’t be available to anyone who gets the Standard Edition.</p><p>And considering the rumors circulating months before that alluded to GTA 6 launching at a standard price of $100, it turns out that it’s technically true once you realize the Ultimate Edition is truly the full experience fans have been eagerly waiting for.</p><h2 id="100-for-the-full-vice-city-experience-yep-time-to-pay-up">$100 for the full Vice City experience? Yep, time to pay up</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="o58Dy5MvAKTH7TMTuBzX9d" name="gta-6-ultimate-edition-screenshot" alt="Screenshot of a white/red sports car in gta 6" src="https://cdn.mos.cms.futurecdn.net/o58Dy5MvAKTH7TMTuBzX9d.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: Rockstar Games)</span></figcaption></figure><p>So here’s a full breakdown of what comes with both the Standard and Ultimate Editions of GTA 6:</p><ul><li><strong>GTA 6 Standard Edition ($79.99): </strong>One free month of GTA+ and the Vintage Vice City Pack (this comes with this ‘55 Vapid Stanier Sedan, a garage located near Ocean Beach, additional outfits & hairstyles for Jason & Lucia and a special firearm pattern set).</li><li><strong>GTA 6 Ultimate Edition ($99.99): </strong>One free month of GTA+, The Vintage Vice City Pack, The ‘95 Grotti Cheetah sports car, the Hawk & Little Morgan Revolver, personalized weapon variants, Vice City Style outfits, hairstyles, tattoos & more, Jason’s Safehouse Vehicles, a Retro Build customization option for Jason’s Vapid Ganado vehicle, the Shitzu Squalo boat, the ‘67 Vapid Dominator Buggy & Garage, the Goodtime Gear capsule collection of additional apparel & accessories, a raid mission that takes players to the PTT Youngin$ Compound, a classic car collection sidequest and special destinations that offer more customization options (Rideout Customs for vehicles, Sara’s Unisex Salon for hair & nails, Stock 305 for streetwear, Electric Fang Tattoo for tattoos and One-Eyed Willie’s for off-road vehicle mods).</li></ul><p>Just by looking at everything that comes with the Ultimate Edition, you’d be hard-pressed to think GTA 6’s Standard Edition is actually worth buying.</p><p>For a gaming franchise so revered for its vast array of customization and overall player expression, locking a whole gamut of those vehicle and character modification options behind a $100 price tag is egregious. What’s even more upsetting is that two missions are also being held off from the game’s Standard Edition and are only being made playable to those who plop down the high entry fee for the Ultimate Edition.</p><p>This isn't the first time Rockstar Games has cut off one of their game's full content slate behind a pricier version, by the way. Red Dead Redemption 2's Ultimate Edition asked gamers to cough up more money to get access to exclusive story content that included a bank robbery mission. So, in other words, we should've seen this GTA 6 Ultimate Edition fiasco coming from a mile away.</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="wbmyQUww4VURhQpwLDfNB5" name="GTA 6 - Vintage Vice 1" alt="GTA 6" src="https://cdn.mos.cms.futurecdn.net/wbmyQUww4VURhQpwLDfNB5.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: Rockstar Games)</span></figcaption></figure><p>As an old head who came up during an age of gaming where Sega Genesis and Super Nintendo cartridges retailed from $50 to $100 (I’ll never forget Phantasy Star IV asking young gamers like me for $99 just to bring it home), I’m sadly become accustomed to paying an arm and a leg for the full experience for my favorite IPs. And as someone who’s addicted to fighting games, I’m used to pouring hundreds of dollars into today’s gamut of fighters as they ask me to pay extra for season passes, costumes, battle passes, in-game currency, etc.</p><p>It’s also become too much to stomach how gaming publishers just want to extract as much money from their consumers as possible. Seeing how GTA 6’s Ultimate Edition is truly the de facto full experience that fans may just be forced to buy is, to put it simply, nasty work. I’m just as disappointed in this news as I was when Capcom forced everyone to pay for DLC just to see the true ending of Asura’s Wrath, since the base game ended on a cliffhanger.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-OLVwKe"></div>                            </div>                            <script src="https://kwizly.com/embed/OLVwKe.js" async></script><h2 id="bottom-line-2">Bottom line</h2><p>I’m confident that GTA 6 will be an amazing game—Rockstar Games' penchant for crafting truly immersive, satisfying open-world experiences, backed by memorable stories and an unforgettable cast of characters, has never wavered. </p><p>But the shocking confirmation that the REAL full GTA 6 experience is locked behind a $100 price tag is definitely a tough pill to swallow. I guess I’ll just have to bite the bullet on the Ultimate Edition since the prospect of trekking around Leonida to discover vintage cars and participating in an explosive raid is all too enticing for me to pass up. Yes, I’m sadly a part of the problem. </p><p>At least the rumor of the disc version of GTA 6 launching in December makes me slightly less upset about this whole deal.</p><p>Fingers crossed that Rockstar makes the next iteration of GTA Online a part of the GTA 6 package rather than an entirely separate digital purchase. They wouldn't go that far...would they?</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/news/live/gta-6-pre-orders-news-and-live-updates" target="_blank">GTA 6 pre-orders live updates: US and UK pre-orders available now! Here’s how to secure your copy of Grand Theft Auto VI today</a></li><li><a href="https://www.tomsguide.com/tvs/these-5-gaming-tvs-are-perfect-for-gta-6-and-theyre-on-sale-for-prime-day" target="_blank">These 5 gaming TVs are perfect for GTA 6 — and they're on sale for Prime Day</a></li><li><a href="https://www.tomsguide.com/gaming/nintendo/star-fox-review" target="_blank">I just finished Star Fox on Switch 2 — and it’s better than the game I imagined I was playing as a kid</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ This thermal camera for my phone gives me instant night vision — and it's $200 off right now ]]></title>
                                                                                                                                                                                                <link>https://www.tomsguide.com/phones/this-thermal-camera-for-my-phone-gives-me-instant-night-vision-and-its-usd200-off-right-now</link>
                                                                            <description>
                            <![CDATA[ I've been testing the Thermal Master P4 and this compact thermal camera blends two lenses to deliver sharp images with heat signature. And it's $200 off for Prime Day. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">PJt7XWSfazchxyVuhKgUbH</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/4JBeib78hsgRSW3G2qBfrm-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Thu, 25 Jun 2026 10:30:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Phones]]></category>
                                                    <category><![CDATA[Cameras &amp; Photography]]></category>
                                                                                                <author><![CDATA[ john.velasco@futurenet.com (John Velasco) ]]></author>                    <dc:creator><![CDATA[ John Velasco ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/TSj224oX8d5ERXaDs8pDGd.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ null ]]></dc:description>
                                                                                                                                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/4JBeib78hsgRSW3G2qBfrm-1280-80.jpg">
                                                            <media:credit><![CDATA[John Velasco / Tom&#039;s Guide]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Thermal Master P4 connected to an Android phone.]]></media:description>                                                            <media:text><![CDATA[Thermal Master P4 connected to an Android phone.]]></media:text>
                                <media:title type="plain"><![CDATA[Thermal Master P4 connected to an Android phone.]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/4JBeib78hsgRSW3G2qBfrm-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>There’s something inherently sci-fi about fastening an accessory to my phone and suddenly getting Predator-vision. In the past couple of years, I’ve tested a bunch of smartphone-connected thermal dongles on the market, including the gear from Thermal Master.</p><p>It started with the <a href="https://www.tomsguide.com/phones/forget-flir-i-tried-this-cheap-thermal-camera-for-my-phone-to-see-in-the-dark">budget-priced P1</a>, followed by the <a href="https://www.tomsguide.com/phones/my-new-favorite-phone-accessory-attaches-to-my-keychain-and-goes-everywhere-i-do-plus-it-lets-me-see-in-the-dark">micro-sized P2</a> that fits on my keychain, and finally the <a href="https://www.tomsguide.com/phones/i-just-gave-my-iphone-night-vision-with-this-usb-c-thermal-camera-and-now-i-can-see-in-the-dark">P3 that introduced thermal vision to my iPhone</a>. With its latest release, the <a href="https://thermalmaster.com/products/thermal-master-p4-thermal-in-one-all-in-one" target="_blank" rel="nofollow">Thermal Master P4</a> steps up as an all-in-one model with dual lenses to deliver outstanding clarity and heat signature performance.</p><p>I’ve been using it around my home for the past few weeks now. From checking out what’s lurking outside while I’m shooting astrophotography, to finding gaps around windows and doors that are letting hot air inside my home, it shows me stuff I simply can’t see with my own eyes. And best of all, it’s <a href="https://www.amazon.com/Thermal-Master-P4-Android-Resolution/dp/B0GL7G2JPL/" target="_blank" rel="nofollow">$200 off right now for Prime Day</a>.</p><div class="product"><a data-dimension112="eb5499d2-dbbf-462b-a24e-f67268941c14" data-action="Deal Block" data-label="Price check: $299 @ Amazon" data-dimension48="Price check: $299 @ Amazon" data-dimension25="$299" href="https://thermalmaster.com/products/thermal-master-p4-thermal-in-one-all-in-one" 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="bdyqRpE3BZSY979hCMLrMh" name="Thermal Master P4 deal block" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/bdyqRpE3BZSY979hCMLrMh.jpg" mos="" align="middle" fullscreen="" width="600" height="600" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>This compact thermal camera fits in your pocket and attaches to an Android phone to provide instant night vision for tracking heat signatures. Its dual-lens system offers impressive performance, making it easy to spot varying temperature differences while seamlessly compositing the two images.<br><strong>Price check: </strong><a href="https://www.amazon.com/Thermal-Master-P4-Android-Resolution/dp/B0GL7G2JPL/" target="_blank" rel="nofollow" data-dimension112="eb5499d2-dbbf-462b-a24e-f67268941c14" data-action="Deal Block" data-label="Price check: $299 @ Amazon" data-dimension48="Price check: $299 @ Amazon" data-dimension25="$299"><strong>$299 @ Amazon</strong></a><a class="view-deal button" href="https://thermalmaster.com/products/thermal-master-p4-thermal-in-one-all-in-one" target="_blank" rel="nofollow" data-dimension112="eb5499d2-dbbf-462b-a24e-f67268941c14" data-action="Deal Block" data-label="Price check: $299 @ Amazon" data-dimension48="Price check: $299 @ Amazon" data-dimension25="$299">View Deal</a></p></div><h2 id="blends-thermal-vision-and-reality-to-undercover-gaps">Blends thermal vision and reality to undercover gaps</h2><figure role="gallery"><figure><img src="https://cdn.mos.cms.futurecdn.net/24xtTUVyR4K32BRFi3y5ih.jpg" alt="Thermal Master P4 sample." /><figcaption><small role="credit">Future</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/NUC9Xo2BG6DUBg7nLDPv8h.jpg" alt="Thermal Master P4 sample." /><figcaption><small role="credit">Future</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/AVrvCgWGiGof5dWm3nUQ5h.jpg" alt="Thermal Master P4 sample." /><figcaption><small role="credit">Future</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/EjZXHT3ByAudaEq5LJDKzg.jpg" alt="Thermal Master P4 sample." /><figcaption><small role="credit">Future</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/PfEKNPTi5UocjjQLyDG9jh.jpg" alt="Thermal Master P4 sample." /><figcaption><small role="credit">Future</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/cBtvwWi2VvS2YLSW39cSNh.jpg" alt="Thermal Master P4 sample." /><figcaption><small role="credit">Future</small></figcaption></figure></figure><p>What really elevates the Thermal Master P4 over previous models I’ve tested is its brilliant dual-lens system. Traditional infrared attachments just show you a blob of heat without distinct edges to add detail to what you’re looking at.</p><p>The Thermal Master P4 solves this by layering a visible light camera over its thermal sensor. This unique, AI-assisted combination of thermal vision and reality allows me to uncover hidden gaps with surgical precision. When I scanned the baseboards and window frames of my home, I wasn't just looking at a generic blue blob of cold air—I could see the exact physical gap in the molding where the draft was coming through. It bridges the gap between digital data and the physical world perfectly.</p><figure role="gallery"><figure><img src="https://cdn.mos.cms.futurecdn.net/EjZXHT3ByAudaEq5LJDKzg.jpg" alt="Thermal Master P4 sample." /><figcaption><small role="credit">Future</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/nHibMh74APLZARNpRNaiJh.jpg" alt="Thermal Master P4 sample." /><figcaption><small role="credit">Future</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/u95sZ9G6uTHTaaSkXet2sg.jpg" alt="Thermal Master P4 sample." /><figcaption><small role="credit">Future</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/Ywo83WusV8FZjeRKnEsoqg.jpg" alt="Thermal Master P4 sample." /><figcaption><small role="credit">Future</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/nhEsAhgNigHwDPj4CGaLog.jpg" alt="Thermal Master P4 sample." /><figcaption><small role="credit">Future</small></figcaption></figure></figure><p>Keep in mind, this feature is most effective when there’s ample light in the scene. While the P4 has no problem showing heat signatures in complete darkness, the real-world physical details fade away without ambient light, making it harder for the AI to blend the two images. You can see the difference with the shots in the gallery above compared to the ones from the previous gallery.</p><h2 id="doesn-t-lag-like-other-infrared-cameras">Doesn’t lag like other infrared cameras</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="zCzKivqHKUchv8woKqRdtm" name="Thermal Master P4" alt="Thermal Master P4 held in the hand." src="https://cdn.mos.cms.futurecdn.net/zCzKivqHKUchv8woKqRdtm.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: John Velasco / Tom's Guide)</span></figcaption></figure><p>Unlike other thermal sensors that painfully stutter and freeze every time you pan across a room, the P4 handles movement like a champ. It doesn’t lag like other infrared cameras. Instead, it delivers a smooth, high-frame-rate feed that tracks shifting temperatures and moving heat signatures in crisp, real-time fluidity. This is probably the biggest reason why I continue to favor Thermal Master's portable cameras over the ones that <a href="https://www.tomsguide.com/us/flir-one-pro-for-ios,review-4511.html">FLIR makes</a>.</p><h2 id="portable-size-lets-me-carry-it-everywhere">Portable size lets me carry it everywhere</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="QH9QcMFSFVFV6MfTDGShzm" name="Thermal Master P4" alt="Thermal Master P4 in its carrying case." src="https://cdn.mos.cms.futurecdn.net/QH9QcMFSFVFV6MfTDGShzm.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: John Velasco / Tom's Guide)</span></figcaption></figure><p>Most professional thermal imagers are bulky, standalone tools that require their own dedicated carrying cases. The P4, by contrast, features a compact design that slides easily into my pocket — and its plug-and-play functionality makes it a breeze to operate.</p><p>Since it’s something I can carry everywhere, I’ve found myself using it in casual situations where I’d never bother hauling a traditional camera — like when I go for walks down by the beach, or bike riding on a path where I know foxes typically roam.</p><p>With the $200 instant discount going on right now for Prime Day, it’s an absolute steal for anyone wanting a high-performing thermal camera without the bulk or the heavy price tag. Its $499 normal cost is right about what you’d pay for a comparable handheld thermal camera from FLIR, but it’s way more valuable at its current $299 price point.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-XpmMGe"></div>                            </div>                            <script src="https://kwizly.com/embed/XpmMGe.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/phones/motorola-phones/motorola-razr-ultra-2026-review">Motorola Razr Ultra 2026 review: Better does come at a premium price</a></li><li><a href="https://www.tomsguide.com/phones/simo-solis-lite-hotspot-review">I tested this puck shaped mobile hotspot — and it’s the simplest way to get online</a></li><li><a href="https://www.tomsguide.com/phones/best-early-prime-day-2026-phone-accessories-deals-magsafe-wallets-power-banks-chargers-and-more">I tested 100+ phone accessories in the last year and these are my favorite early Prime Day deals — MagSafe wallets, power banks, chargers, and more</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ I tried Dua Lipa’s go-to 20-minute mat Pilates routine — and my abs still haven't recovered ]]></title>
                                                                                                                                                                                                <link>https://www.tomsguide.com/wellness/workouts/i-tried-one-of-dua-lipas-20-minute-mat-pilates-classes-and-it-blasted-my-abs-in-just-6-exercises</link>
                                                                            <description>
                            <![CDATA[ Our fitness editor unrolled her exercise mat, grabbed a Pilates ball, and gave this workout a go ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">uxZjqYwhoSdFbWr9QxA2Wd</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/sxbmUtGZMpG4LxUQchNs2g-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Thu, 25 Jun 2026 09:30:00 +0000</pubDate>                                                                                                                                <updated>Thu, 25 Jun 2026 10:54:27 +0000</updated>
                                                                                                                                            <category><![CDATA[Workouts]]></category>
                                                    <category><![CDATA[Wellness]]></category>
                                                    <category><![CDATA[Fitness]]></category>
                                                                                                <author><![CDATA[ jane.mcguire@futurenet.com (Jane McGuire) ]]></author>                    <dc:creator><![CDATA[ Jane McGuire ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/vV4Uj3e5TZvBqmmsjT2EU6.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Jane McGuire is Tom&#039;s Guide&#039;s Fitness Managing Editor, which means she looks after everything fitness-related — from running gear and fitness trackers to yoga mats and sports bras. An avid runner, Jane has tested and reviewed fitness products for the past five years, so she knows what to look for when finding a good running watch or a pair of shorts with pockets big enough for your smartphone, running gels, and house keys. &lt;/p&gt;&lt;p&gt;Jane has run six marathons — the London Marathon five times, and the Berlin Marathon once -and is still on a quest to tick off all of the marathon majors. Her marathon PR is 3:30, which she ran in the New Balance Supercomp Elite V5&#039;s, but she also spends a lot of time talking about her  ‘joy plan’, where she runs for happiness, not for PR’s. &lt;/p&gt;&lt;p&gt;Previous to Tom’s Guide, Jane worked for Runner’s World, where she co-hosted the Runner’s World podcast. She also presents on a YouTube channel called the Run Testers, alongside other running-mad journalists, where they review the latest shoes, kit, and tech. Her work has also appeared in Coach, Get Sweat Go, and Women’s Health. &lt;/p&gt;&lt;p&gt;When she&#039;s not pounding the pavements, you&#039;ll find Jane striding round the Surrey Hills, taking far too many photos of her spaniel, Toby. &lt;/p&gt; ]]></dc:description>
                                                                                                                                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/sxbmUtGZMpG4LxUQchNs2g-1280-80.jpg">
                                                            <media:credit><![CDATA[Instagram/DuaLipa/JaneMcGuire]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[a photo of Dua Lipa ]]></media:description>                                                            <media:text><![CDATA[a photo of Dua Lipa ]]></media:text>
                                <media:title type="plain"><![CDATA[a photo of Dua Lipa ]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/sxbmUtGZMpG4LxUQchNs2g-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>I’ll never be able to sing like Dua Lipa, but getting her abs has become a lifetime goal. The global star frequently posts about her workouts, and luckily for me, they are pretty easy to find, as Dua has co-founded a Pilates-based training platform named <a href="https://www.instagram.com/framereformer/?g=5" target="_blank" rel="nofollow">Frame Fitness</a>, designed to make reformer Pilates more accessible. </p><p>“The one thing that keeps me grounded and keeps me fit is getting on the mat every single day,’ she told <a href="https://www.tiktok.com/@voguemagazine/video/7552283144293059853?lang=en" target="_blank" rel="nofollow"><em>Vogue</em></a>. "That’s doing Pilates, that’s doing yoga – the good thing about the Frame Reformer is that, even when I’m traveling, I can do the mat stuff.”</p><p>Taking a leaf out of Dua’s workout book, I unrolled my mat and gave this 20-minute mat Pilates class a go. Warning: it blasted my core in just six exercises. Read on to find out more. </p><p>As a reminder, if you’re a complete beginner, you’re pregnant or postpartum, or you’re recovering from an injury, this might not be the workout for you. It’s always worth checking in with a qualified professional before trying something new. </p><h2 id="what-is-the-workout-2">What is the workout? </h2><p>The workout is designed by Frame Fitness instructor Melissa Lynn. It’s a full-body workout that only takes 20 minutes to complete. You will need some extra equipment: a Pilates ball, a pair of ankle weights and a pair of wrist weights to add instability and intensity. </p><p>Here are some of the best deals on Pilates equipment to grab this Prime Day: </p><div class="product"><a data-dimension112="5f5d4bc6-fcd6-40fe-a506-13ffa5ce6c5f" data-action="Deal Block" data-label="This Pilates ball is on sale for Prime Day, and will add instability to your workouts, helping really activate those deep core muscles." data-dimension48="This Pilates ball is on sale for Prime Day, and will add instability to your workouts, helping really activate those deep core muscles." data-dimension25="$7" href="https://www.amazon.com/Trideer-Exercise-Training-Stability-Stretching/dp/B0B4C1MZC3" 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:100.15%;"><img id="gsphNrZxripa9FHQuZVQtN" name="71DF0Bq5O7L._AC_SX679_" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/gsphNrZxripa9FHQuZVQtN.jpg" mos="" align="middle" fullscreen="" width="679" height="680" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>This Pilates ball is on sale for Prime Day, and will add instability to your workouts, helping really activate those deep core muscles.<a class="view-deal button" href="https://www.amazon.com/Trideer-Exercise-Training-Stability-Stretching/dp/B0B4C1MZC3" target="_blank" rel="nofollow" data-dimension112="5f5d4bc6-fcd6-40fe-a506-13ffa5ce6c5f" data-action="Deal Block" data-label="This Pilates ball is on sale for Prime Day, and will add instability to your workouts, helping really activate those deep core muscles." data-dimension48="This Pilates ball is on sale for Prime Day, and will add instability to your workouts, helping really activate those deep core muscles." data-dimension25="$7">View Deal</a></p></div><div class="product"><a data-dimension112="1adbbb5a-fe34-42fb-9756-3911cf996e24" data-action="Deal Block" data-label="These beautiful bangles can be worn around the wrist or the ankles to add intensity to your Pilates workouts." data-dimension48="These beautiful bangles can be worn around the wrist or the ankles to add intensity to your Pilates workouts." data-dimension25="$41" href="https://www.amazon.com/Bala-Bangles-Ankle-Weights-Wrist-Workout-Men-Women/dp/B09SNTB8DF/" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1465px;"><p class="vanilla-image-block" style="padding-top:102.39%;"><img id="CnFewGYxQcCh52GEdWxHUW" name="Bala bangles" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/CnFewGYxQcCh52GEdWxHUW.jpg" mos="" align="middle" fullscreen="" width="1465" height="1500" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>These beautiful bangles can be worn around the wrist or the ankles to add intensity to your Pilates workouts.<a class="view-deal button" href="https://www.amazon.com/Bala-Bangles-Ankle-Weights-Wrist-Workout-Men-Women/dp/B09SNTB8DF/" target="_blank" rel="nofollow" data-dimension112="1adbbb5a-fe34-42fb-9756-3911cf996e24" data-action="Deal Block" data-label="These beautiful bangles can be worn around the wrist or the ankles to add intensity to your Pilates workouts." data-dimension48="These beautiful bangles can be worn around the wrist or the ankles to add intensity to your Pilates workouts." data-dimension25="$41">View Deal</a></p></div><p>There are six different exercises in total. Do each exercise for 40 seconds, followed by a 20-second break. Doing a full set (including switching sides) should take you 10 minutes. Repeat the circuit for a bodyweight workout in 20 minutes. </p><p>Here are the exercises: </p><ul><li><strong>Side plank and pulse on ball:</strong> Start in a side plank position, resting on your elbows with your knees stacked, and press your top hand into your Pilates ball. Lift your hips to form a straight line from your head to your knees. As you reach your hips toward the ceiling, press down into the ball, then lower with control. Complete 40 seconds on one side before switching to the other.</li><li><strong>Side plank and pulse on the ball with leg extension: </strong>This exercise follows the same sequence as above, but as you press into the ball and raise your hips, extend your top leg out diagonally towards the ceiling, then bend your knee and bring your legs back together. Lower down into your side plank and repeat.</li><li><strong>Ball ab crunch:</strong> Place the Pilates ball under your bra strap (or mid-back) and brace your core, curling your head, neck and shoulders up off the ball. Keep your arms in line with your shoulders extended out in front of you. Keep your abs braced throughout, sucking your belly button in towards your spine.</li><li><strong>Oblique crunch hold with leg lift:</strong> This exercise works the obliques. To do it, place the Pilates ball against one knee, and raise your head, neck and shoulders to use the opposite elbow to hold the ball in place. Extend the opposite leg away and repeatedly lift and lower your leg. Complete 40 seconds on one side before switching to the other.</li><li><strong>Oblique teaser: </strong>Start by resting on one side, and in one movement, lift your torso and legs into a side V-sit. Holding the Pilates ball in your top hand, extend it overhead and as you crunch, bring your top arm up so the ball meets your feet. Lower with control and repeat. Complete 40 seconds on one side before switching to the other.</li><li><strong>Reverse lunges:</strong> Place the Pilates ball under your front foot, and step the other back into a split stance. Lower into a lunge, making sure your front knee stays over your ankle. Drive through your front heel to return to your starting position. Complete 40 seconds on one side before switching to the other.</li></ul><div class="instagram-embed"><blockquote class="instagram-media"  data-instgrm-version="6" style="width:99.375%; width:-webkit-calc(100% - 2px); width:calc(100% - 2px);"><p><a href="https://www.instagram.com/p/DWZRdDNAP0I/" target="_blank">A post shared by FRAME FITNESS (@framereformer)</a></p><p>A photo posted by  on </p></blockquote></div><h2 id="what-are-the-benefits-4">What are the benefits?</h2><p>This workout is no joke. With the additional instability of the Pilates ball, the deep stabilizer muscles in your core are working hard to stabilize your body as you crunch, lunge, lift and lower your legs. </p><p>As with all Pilates exercises, it’s important to move slowly and with complete control — I had to really think about keeping my core engaged throughout, squeezing my belly button into my spine and keeping my abs zipped up and in. </p><p>All of these exercises target the muscles in your core, including the deep lower abs, lower back stabilizers, glutes and pelvic floor. These deep muscles act as your body’s internal corset, protecting your spine and drastically improving your overall balance and stability. </p><p>Exercises like the reverse lunges and side planks can also help address and correct muscle imbalances, as you’ll be working one side of the body at a time. As a marathon runner who spends most of her day sitting behind a desk, my left side is much weaker than my right, and I could feel this straight away. Pilates places an immense focus on alignment, and workouts like this can help correct imbalances and improve your posture.</p><p>Of course, my abs looked the same after this 20-minute workout, but I really felt it in my core. To get Dua Lipa’s abs, you’d have to pair workouts like this with a balanced diet, enough water and a low-impact form of daily cardio like walking, as visible abs are down to your <a href="https://www.tomsguide.com/wellness/fitness/body-fat-percentage-vs-body-fat-mass-experts-say-this-is-what-you-need-to-know-to-lose-fat">overall body fat percentage</a>, not how many oblique teasers you can do. </p><p>Either way, this is a great workout, and one I’ll be repeating (while listening to Levitating, of course). </p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-ONKRJX"></div>                            </div>                            <script src="https://kwizly.com/embed/ONKRJX.js" async></script><p><em><strong>Follow </strong></em><a href="https://www.instagram.com/tomsguidefitness/" target="_blank"><em><strong>Tom's Guide fitness</strong></em></a><em><strong> on Instagram for more workouts, routines, tips, and tricks.</strong></em></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/wellness/workouts/not-sit-ups-planks-or-crunches-i-do-this-simple-pilates-exercise-every-single-day-to-build-a-strong-and-stable-core-and-work-on-my-hip-flexor-mobility" target="_blank">Not sit-ups, planks, or crunches: I do this simple Pilates exercise every single day to build a strong and stable core and work on my hip flexor mobility</a></li><li><a href="https://www.tomsguide.com/wellness/fitness/im-a-weightlifting-coach-3-exercises-i-prefer-over-lunges-for-building-strong-stable-legs-and-knees-over-40" target="_blank">I'm a weightlifting coach — 3 exercises I prefer over lunges for building strong, stable legs and knees over 40</a></li><li><a href="https://www.tomsguide.com/wellness/workouts/i-tried-a-7-day-standing-core-routine-here-are-the-differences-i-noticed-in-my-strength-and-posture" target="_blank">I tried a 7-day standing core routine. Here are the differences I noticed in my strength and posture</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ I used ChatGPT to audit mysubscriptions —these prompts helped me find nearly $2,000 a year in recurring charges ]]></title>
                                                                                                                                                                                                <link>https://www.tomsguide.com/ai/i-used-chatgpt-to-audit-my-subscriptions-these-prompts-helped-me-find-nearly-usd2-000-a-year-in-recurring-charges</link>
                                                                            <description>
                            <![CDATA[ I used ChatGPT to audit my subscriptions and discovered nearly $2,000 a year in recurring charges. Here's the prompt that helped me save money. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">vEiFFw6RAJxQnLYEagLRCJ</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/iG4a9Jm9PzH75pKNXxpXnf-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Thu, 25 Jun 2026 08:30:00 +0000</pubDate>                                                                                                                                <updated>Sun, 28 Jun 2026 22:55:10 +0000</updated>
                                                                                                                                            <category><![CDATA[AI]]></category>
                                                                                                <author><![CDATA[ amanda.caswell@futurenet.com (Amanda Caswell) ]]></author>                    <dc:creator><![CDATA[ Amanda Caswell ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/zYjevim2q7FjQiefqpjZRB.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ null ]]></dc:description>
                                                                                                                                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/iG4a9Jm9PzH75pKNXxpXnf-1280-80.jpg">
                                                            <media:credit><![CDATA[Shutterstock]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Smartphone with ChatGPT logo on the display]]></media:description>                                                            <media:text><![CDATA[Smartphone with ChatGPT logo on the display]]></media:text>
                                <media:title type="plain"><![CDATA[Smartphone with ChatGPT logo on the display]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/iG4a9Jm9PzH75pKNXxpXnf-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>I'm the type of person who takes advantage of free trials and then forgets to cancel them. Then, with every new charge, I try to figure out how to cancel them and then wonder if I should keep them. It's a vicious cycle that I'm not proud of — most of all, it's a waste of money.<br><br>If you're like me, you know that between streaming services, cloud storage plans, <a href="https://www.tomsguide.com/ai/your-ai-subscription-is-about-to-look-very-different-heres-what-to-expect-in-the-next-year">AI subscriptions</a>, fitness apps and a slew of digital memberships, it's surprisingly easy to lose track of what you're paying for each month.</p><p>I recently decided to audit my own subscriptions and instead of manually sorting through everything,  I used ChatGPT as a personal financial assistant. It was much faster than I anticipated and I finally got a better picture of every subscription. When I added everything together, <strong>I discovered I was spending nearly $166 per month on subscriptions, or almost $2,000 per year.</strong></p><p>Here's exactly how I used ChatGPT to do it.</p><h2 id="step-1-gather-all-of-your-subscriptions">Step 1: Gather all of your subscriptions</h2><p>If you're like me, you have subscriptions connected to Amazon such as <a href="https://www.tomsguide.com/us/amazon-prime-music-unlimited-faq,news-25430.html">Amazon Music </a>and <a href="https://www.tomsguide.com/opinion/i-used-to-hate-audiobooks-and-now-im-a-diehard-audible-user">Audible</a>, as well as <a href="https://www.tomsguide.com/how-to/how-to-cancel-prime-video">Amazon subscriptions</a> like automatic reorder. At the same time, I also have subscriptions tied to Apple such as LinkedIn, Apple+, other streaming services and app subscriptions. Plus, we can't forget about other memberships and subscriptions through Google or that are completely seperate. <br><br>Pulling together all your subscriptions from multiple places is a challenge in itself. I have an iPhone so I started by going to: iPhone: Settings > Apple ID > Subscriptions. From there I checked Google Play subscriptions, Amazon memberships and digital services, credit card statements, PayPal recurring payments and even bank statements.<br><br>I had almost no extra time to gather all these screenshots — which may explain why I'd let these subscriptions continue for so long. By collecting the screenshots over several days and saving them in <a href="https://www.tomsguide.com/ai/chatgpt-projects-just-got-smarter-heres-how-to-use-the-new-tools">ChatGPT Projects</a> until I was ready to act, the process felt much more manageable.<br><br>For every subscription, take screenshots. Mine included: Apple One, Amazon Prime, Audible, Kindle Unlimited, Peacock (just upgraded for the World Cup), Google One, ChatGPT Plus, Claude Pro and Meta. </p><h2 id="step-2-paste-everything-into-chatgpt">Step 2: Paste everything into ChatGPT</h2><p>Once you have a complete list, <strong>use a prompt like this: </strong><em>"I want to reduce my monthly subscription spending. Here is a list of all my subscriptions and their monthly costs: [paste list here]. Calculate my monthly and annual spending by identifying any overlapping services, flag subscriptions I may not be fully using, categorize each as Keep, Investigate or Cancel, estimate how much I could save annually and explain your reasoning for each recommendation"</em></p><p>ChatGPT will quickly organize everything into a readable audit. And, if you have <a href="https://www.tomsguide.com/ai/chatgpts-new-memory-builds-a-profile-of-you-on-its-own-and-openai-admits-you-cant-see-all-of-it">Memory enabled, Dreaming</a> will actually help put the pieces together to determine if those are subscriptions you truly need. </p><h2 id="step-3-look-for-overlaps">Step 3: Look for overlaps</h2><p>This is where the biggest savings often hide. For example, paying for both Apple One and Google One storage or subscribing to Audible plus Kindle Unlimited. Multiple streaming services that aren't being fully utilized or having several AI subscriptions serving similar purposes will all be flagged.</p><p>In my case, ChatGPT immediately flagged a few subscriptions worth investigating because they provided similar benefits.</p><p>That doesn't automatically mean cancel them, but it does reveal where you're possibly paying twice for convenience.</p><h2 id="step-4-ask-chatgpt-tough-questions">Step 4: Ask ChatGPT tough questions</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="mWLFfjW3mM9adLtZuQatGf" name="8 - 2026-06-24T131807.964" alt="subscriptions" src="https://cdn.mos.cms.futurecdn.net/mWLFfjW3mM9adLtZuQatGf.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: Future)</span></figcaption></figure><p>The real value comes from follow-up questions. Try prompts like: </p><p><em>"Which of these subscriptions would I miss the least?"</em></p><p><em>"If I canceled three subscriptions today, which would save the most money while creating the smallest impact?"</em></p><p><em>"Which subscriptions provide the lowest value per dollar?"</em></p><p><em>"Help me build a plan to reduce my spending by $25 per month."</em></p><p>I also took advantage of <a href="https://www.tomsguide.com/ai/chatgpt-tasks-now-feels-like-a-real-assistant-7-ways-im-using-it-including-snagging-the-best-prime-day-deals">ChatGPT Tasks</a> and set a reminder for ChatGPT to cancel trial subscriptions that had already started. </p><h2 id="step-5-check-your-free-trials">Step 5: Check your free trials</h2><p>Speaking of free trials, one surprise from my audit was finding services that had started as trials and quietly became recurring expenses.</p><p><strong>Try this prompt: </strong><em>"Based on my subscription list, which services are most commonly forgotten or underused?"</em></p><p><em>"What questions should I ask myself before renewing each one?"</em></p><p>ChatGPT can help you evaluate whether you're paying out of habit or because you genuinely use the service.</p><h2 id="what-surprised-me-most">What surprised me most </h2><p>Honestly, the total. Individually, most subscriptions felt small. Ten dollars here. Fifteen dollars there. Twenty dollars for an AI service I use every day. But when everything was combined, the total approached $2,000 per year.</p><p>That's enough to fund a vacation, boost retirement contributions or build an emergency fund. Taking the time to have ChatGPT solve my subscription crisis was a game changer. A simple ChatGPT conversation turned into a financial audit for my family by helping me identify recurring charges, spot overlaps and decide what stays and what goes. I should have done it sooner and plan on doing it every few months or so. <br><br>Have you ever used ChatGPT to help manage your finances? Let me know in the comments. </p><a href="https://follow.it/articles-by-amanda-caswell-tom-s-guide?leanpub" class="button button--large button--primary">Follow Amanda Caswell and stay ahead of the AI curve</a><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/ai/claude-skills-changed-how-i-work-5-ways-i-use-them-every-day"><strong>Claude Skills changed how I work — 5 ways I use them every day</strong></a></li><li><a href="https://www.tomsguide.com/ai/i-turned-youtube-into-an-ai-bootcamp-with-notebooklm-heres-my-workflow"><strong>I turned my YouTube watchlist into an AI bootcamp with NotebookLM — here's how</strong></a></li><li><a href="https://www.tomsguide.com/ai/i-built-five-chatgpt-agents-then-replaced-them-with-one-master-ai"><strong>I built five ChatGPT agents — then replaced them with one 'master' AI</strong></a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ I'm seriously allergic to poison ivy — this Gemini feature helps me when I'm weeding ]]></title>
                                                                                                                                                                                                <link>https://www.tomsguide.com/home/gardening/im-seriously-allergic-to-poison-ivy-this-gemini-feature-helps-me-when-im-weeding</link>
                                                                            <description>
                            <![CDATA[ There are a lot of three-leaved plants; this Google Gemini feature helps me know which is poison ivy, and which is safe to touch. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">TE2bCux7zeAW29ffNeW9vE</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/TkaGkaHxBwBACsq4UGKHQh-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Thu, 25 Jun 2026 06:30:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Gardening]]></category>
                                                    <category><![CDATA[Google Gemini]]></category>
                                                    <category><![CDATA[Home]]></category>
                                                    <category><![CDATA[Outdoors]]></category>
                                                    <category><![CDATA[AI]]></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/6ZM8mX4UwccqDJTh9gLPqV.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Michael A. Prospero is the U.S. Editor-in-Chief for Tom’s Guide. He oversees all evergreen content and oversees the Homes, Smart Home, and Fitness/Wearables categories for the site. 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>
                                                                                                                                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/TkaGkaHxBwBACsq4UGKHQh-1280-80.jpg">
                                                            <media:credit><![CDATA[Future]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[An iphone taking a photo of ivy]]></media:description>                                                            <media:text><![CDATA[An iphone taking a photo of ivy]]></media:text>
                                <media:title type="plain"><![CDATA[An iphone taking a photo of ivy]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/TkaGkaHxBwBACsq4UGKHQh-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Every spring, my local gardening Facebook page starts filling up with countless pictures of three-leaved plants, each one framed with the same question: "Is this poison ivy?"</p><p>It's a legitimate concern. Poison ivy is not only invasive, but can cause a severe allergic reaction if you get its oils on your skin. I've had more than enough rashes over the course of my life to look askance at any plant that even remotely resembles poison ivy.</p><p>Rather than post something on my local social network and wait for would-be horticulturists to reply, I've started using a new Google Gemini feature on my phone to find out more quickly if the plant I'm about to grab will leave me itching and scratching. </p><p>Here's how you can use Gemini to identify poison ivy (or any other plant, for that matter), works on both Android and iOS devices, and it takes just seconds.</p><section class="howto-block">                    <h3>Take a picture of the plant in question</h3>                                        <p><p>There's a few ways to go about plant identification. The first is to take a picture of the plant in question on your phone. Make sure that you can isolate its defining features as much as possible, such as a leaf, berries, or some other distinguishing characteristic.</p></p>                </section><section class="howto-block">                    <h3>Open the Google, Google Chrome, or Gemini app on your phone</h3>                    <figure>                            <p class="bordeaux-image-check">                                <img    src="https://cdn.mos.cms.futurecdn.net/bvvHc7zEcLm5DYjHwdxaLo.jpg"                                        alt="Poison ivy identification using Google Lens"                                        onerror="this.parentNode.replaceChild(window.missingImage(),this)"                                        data-pin-media="https://cdn.mos.cms.futurecdn.net/bvvHc7zEcLm5DYjHwdxaLo.jpg"                                        class="expandable van-old-layout-image">                            </p><div class="credit">(Image: © Future)</div></figure>                    <p><p>Google gives you plenty of options here, as this works with the Google app, Chrome, or the Gemini app.</p><p>In the Google or Chrome app, <strong>press the small camera icon on the right side of the search bar</strong>. Make sure to allow Google access to both your camera and your photo library.</p><p>If you've already taken the photo, <strong>select the Album icon to the left of the shutter button</strong>. Then, select the image from your library.</p><p>As soon as the image is loaded, Google Lens will attempt to isolate the plant, and then beneath, will display an AI overview of what it thinks the plant is, along with a description and characteristics.</p></p>                </section><section class="howto-block">                    <h3>Using the Gemini app</h3>                    <figure>                            <p class="bordeaux-image-check">                                <img    src="https://cdn.mos.cms.futurecdn.net/V8K8wGkTzWUtKMVMHjsbZG.jpg"                                        alt="Gemini identifying poison ivy"                                        onerror="this.parentNode.replaceChild(window.missingImage(),this)"                                        data-pin-media="https://cdn.mos.cms.futurecdn.net/V8K8wGkTzWUtKMVMHjsbZG.jpg"                                        class="expandable van-old-layout-image">                            </p><div class="credit">(Image: © Future)</div></figure>                    <p><p>If you're using the Gemini app, the process is fairly similar.<strong> Press the Plus sign on the left of the query bar</strong>, and <strong>select either Photos or Camera.</strong> Take a photo (or upload a picture), and simply ask Gemini "what plant is this"? </p><p>Similar to Google Lens, it will return an AI summary of the plant, tell you about its characteristics, and, in the case of poison ivy, let you know what to do in case you accidentally came in contact with the plant.</p></p>                </section><section class="howto-block">                    <h3>Using Gemini Live</h3>                    <figure>                            <p class="bordeaux-image-check">                                <img    src="https://cdn.mos.cms.futurecdn.net/fk8J7MYeiNGfdTpG5kXLn3.jpg"                                        alt="poison ivy gemini live"                                        onerror="this.parentNode.replaceChild(window.missingImage(),this)"                                        data-pin-media="https://cdn.mos.cms.futurecdn.net/fk8J7MYeiNGfdTpG5kXLn3.jpg"                                        class="expandable van-old-layout-image">                            </p><div class="credit">(Image: © Future)</div></figure>                    <p><p>Within the Gemini app, <strong>press the icon with the three vertical lines</strong> to the right of the text box. Gemini will then enter Gemini Live mode. <strong>Press the Camera icon on the left</strong>. Your phone's screen should then show a view of your camera, and the search bar will shrink. Then simply say "is this poison ivy," and Gemini will attempt to analyze what it's looking at. </p><p>When I tried it, it was a lot less specific than the other methods. "No, that doesn't look like poison ivy. Poison ivy usually has three leaflets, and these leaves look different."</p></p>                </section><p>Using Google Lens to identify plants isn't exactly the newest thing around, but as I've been going around my yard pulling plants, I've found it to be helpful in avoiding poison ivy. I have several other types of ivy and three-leaved plants, so it's been very useful while weeding. It's also come in handy if I'm out for a hike, and come across a new tree or shrub I haven't seen before. </p><p>So, just like <a href="https://www.tomsguide.com/home/outdoors/this-garden-tool-is-a-real-mean-machine-with-weeds-in-my-yard-and-its-under-usd35">Grampa's Weeder</a>, this has become yet another important tool in my gardening kit.</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/gardening/this-stihl-hand-pruner-has-been-so-popular-with-my-neighbors-that-one-of-them-is-buying-it-for-her-husband-for-fathers-day"><strong>This Stihl hand pruner has been so popular with my neighbors that one of them is buying it for her husband for Father’s Day</strong></a></li><li><a href="https://www.tomsguide.com/home/gardening/why-are-my-tomato-plant-leaves-turning-yellow-5-steps-to-save-your-harvest-clone"><strong>How to double your tomato harvest — the 3-step pruning system for massive yields</strong></a></li><li><a href="https://www.tomsguide.com/home/gardening/stop-your-hydrangea-blooms-from-turning-brown-too-early-with-these-3-top-tips"><strong>Stop your hydrangea blooms from turning brown too early with these 3 top tips</strong></a></li></ul><div class="product"><a data-dimension112="2abc3045-cded-4510-bfee-5665a5aaf136" data-action="Deal Block" data-label="This weeding tool isn't cheap, but it saves you from having to bend down to dig up weeds from your yard. The 4-claw design can get rid of weeds easily on soft soil. Our U.S. Editor-in-Chief, Mike Prospero, wrote: "It worked very well in my testing, saving me from unnecessary back pain."" data-dimension48="This weeding tool isn't cheap, but it saves you from having to bend down to dig up weeds from your yard. The 4-claw design can get rid of weeds easily on soft soil. Our U.S. Editor-in-Chief, Mike Prospero, wrote: "It worked very well in my testing, saving me from unnecessary back pain."" data-dimension25="$32" href="https://www.amazon.com/Grampas-Weeder-CW-01-Original-Remover/dp/B001D1FFZA/" 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="airedale-jnRKLfDxcRfxyueVnDCLbH-17" name="Stand Up Weed Puller.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/9qw5MdG27GHCVZsTZWNJac.jpg" mos="" align="middle" fullscreen="" width="1000" height="1000" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>This weeding tool isn't cheap, but it saves you from having to bend down to dig up weeds from your yard. The 4-claw design can get rid of weeds easily on soft soil. Our U.S. Editor-in-Chief, Mike Prospero, wrote: "It worked very well in my testing, saving me from unnecessary back pain."<a class="view-deal button" href="https://www.amazon.com/Grampas-Weeder-CW-01-Original-Remover/dp/B001D1FFZA/" target="_blank" rel="nofollow" data-dimension112="2abc3045-cded-4510-bfee-5665a5aaf136" data-action="Deal Block" data-label="This weeding tool isn't cheap, but it saves you from having to bend down to dig up weeds from your yard. The 4-claw design can get rid of weeds easily on soft soil. Our U.S. Editor-in-Chief, Mike Prospero, wrote: "It worked very well in my testing, saving me from unnecessary back pain."" data-dimension48="This weeding tool isn't cheap, but it saves you from having to bend down to dig up weeds from your yard. The 4-claw design can get rid of weeds easily on soft soil. Our U.S. Editor-in-Chief, Mike Prospero, wrote: "It worked very well in my testing, saving me from unnecessary back pain."" data-dimension25="$32">View Deal</a></p></div><div class="product"><a data-dimension112="273d33a3-8a85-4b9e-896b-7e70af72ea05" data-action="Deal Block" data-label="This handy supplies kit includes gloves, cultivator and weeder for, hand fork, hand rake, trowel and transporter — everything needed to get the job done well. What’s more, these are all organized in a floral, multi-pocketed tote bag making it easy to carry around the garden, and machine-washable." data-dimension48="This handy supplies kit includes gloves, cultivator and weeder for, hand fork, hand rake, trowel and transporter — everything needed to get the job done well. What’s more, these are all organized in a floral, multi-pocketed tote bag making it easy to carry around the garden, and machine-washable." data-dimension25="$23" href="https://www.amazon.com/Grenebo-Gardening-Tool-Set-Rust-Proof/dp/B09F9C3KFS" 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="airedale-jnRKLfDxcRfxyueVnDCLbH-13" name="Gardening Tools 9-Piece.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/LNogvcSma2XUKt52NRpnLf.jpg" mos="" align="middle" fullscreen="" width="1000" height="1000" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>This handy supplies kit includes gloves, cultivator and weeder for, hand fork, hand rake, trowel and transporter — everything needed to get the job done well. What’s more, these are all organized in a floral, multi-pocketed tote bag making it easy to carry around the garden, and machine-washable. <a class="view-deal button" href="https://www.amazon.com/Grenebo-Gardening-Tool-Set-Rust-Proof/dp/B09F9C3KFS" target="_blank" rel="nofollow" data-dimension112="273d33a3-8a85-4b9e-896b-7e70af72ea05" data-action="Deal Block" data-label="This handy supplies kit includes gloves, cultivator and weeder for, hand fork, hand rake, trowel and transporter — everything needed to get the job done well. What’s more, these are all organized in a floral, multi-pocketed tote bag making it easy to carry around the garden, and machine-washable." data-dimension48="This handy supplies kit includes gloves, cultivator and weeder for, hand fork, hand rake, trowel and transporter — everything needed to get the job done well. What’s more, these are all organized in a floral, multi-pocketed tote bag making it easy to carry around the garden, and machine-washable." data-dimension25="$23">View Deal</a></p></div><div class="product"><a data-dimension112="630cd3b2-a944-4d90-b620-4e67099148b2" data-action="Deal Block" data-label="Tools and power equipment: up to 40% off" data-dimension48="Tools and power equipment: up to 40% off" data-dimension25="$0" href="https://www.homedepot.com/b/Tool-Savings/N-5yc1vZ1z1zuqf" 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="airedale-CHZyXBFMgYKYBkGmp4Nt9S-6" name="Tools and power equipment: up to 40% off.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/dpUAvmuGfk45EUpVuzYMyk.png" mos="" align="middle" fullscreen="" width="1000" height="1000" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong>Tools and power equipment: </strong><a href="https://www.homedepot.com/b/Tool-Savings/N-5yc1vZ1z1zuqf" target="_blank" rel="nofollow" data-dimension112="630cd3b2-a944-4d90-b620-4e67099148b2" data-action="Deal Block" data-label="Tools and power equipment: up to 40% off" data-dimension48="Tools and power equipment: up to 40% off" data-dimension25="$0"><strong>up to 40% off</strong></a><br>There's a large range of savings across Home Depot's vast collection of tools right now. These offers include serious savings on everything from power drills to riding mowers.<a class="view-deal button" href="https://www.homedepot.com/b/Tool-Savings/N-5yc1vZ1z1zuqf" target="_blank" rel="nofollow" data-dimension112="630cd3b2-a944-4d90-b620-4e67099148b2" data-action="Deal Block" data-label="Tools and power equipment: up to 40% off" data-dimension48="Tools and power equipment: up to 40% off" data-dimension25="$0">View Deal</a></p></div><div class="product"><a data-dimension112="6584f154-b956-4eea-a8ed-e6e3092059db" data-action="Deal Block" data-label="Add comfortable seating for up to three people to your garden for just $55. The bench is made of durable metal, and the cross-patterned backrest gives it a unique, eye-catching look." data-dimension48="Add comfortable seating for up to three people to your garden for just $55. The bench is made of durable metal, and the cross-patterned backrest gives it a unique, eye-catching look." data-dimension25="$55" href="https://www.homedepot.com/p/SVOPES-46-in-Metal-Outdoor-Garden-Bench-480-lbs-Load-Capacity-with-Backrest-and-Armrests-for-Patio-Park-and-Front-Porch-GYZYJS46YC00W8FDQV0-0819/333288727" 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="airedale-CHZyXBFMgYKYBkGmp4Nt9S-9" name="46 in. Metal Outdoor Garden Bench.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/dNBxkYyGQhMNXHDkGXVgPF.jpg" mos="" align="middle" fullscreen="" width="1000" height="1000" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>Add comfortable seating for up to three people to your garden for just $55. The bench is made of durable metal, and the cross-patterned backrest gives it a unique, eye-catching look.<a class="view-deal button" href="https://www.homedepot.com/p/SVOPES-46-in-Metal-Outdoor-Garden-Bench-480-lbs-Load-Capacity-with-Backrest-and-Armrests-for-Patio-Park-and-Front-Porch-GYZYJS46YC00W8FDQV0-0819/333288727" target="_blank" rel="nofollow" data-dimension112="6584f154-b956-4eea-a8ed-e6e3092059db" data-action="Deal Block" data-label="Add comfortable seating for up to three people to your garden for just $55. The bench is made of durable metal, and the cross-patterned backrest gives it a unique, eye-catching look." data-dimension48="Add comfortable seating for up to three people to your garden for just $55. The bench is made of durable metal, and the cross-patterned backrest gives it a unique, eye-catching look." data-dimension25="$55">View Deal</a></p></div><div class="product"><a data-dimension112="3923c8fa-f89b-40fb-bb42-a1f3b6416564" data-action="Deal Block" data-label="Perfect for a compact space or balcony, this 3-piece set consists of two, high back armchairs with sponge-filled cushions for extra comfort, and a tempered glass tabletop for your drinks and food. With its premium PE rattan design, these are sturdy, weatherproof and easy to clean/maintain. A stylish addition to any backyard." data-dimension48="Perfect for a compact space or balcony, this 3-piece set consists of two, high back armchairs with sponge-filled cushions for extra comfort, and a tempered glass tabletop for your drinks and food. With its premium PE rattan design, these are sturdy, weatherproof and easy to clean/maintain. A stylish addition to any backyard." data-dimension25="$89" href="https://www.amazon.com/Flamaker-Furniture-All-Weather-Outdoor-Tempered/dp/B0CH36DTRL" 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="airedale-KErVJa4TFphiKHRmMtmFeR-14" name="All-Weather Rattan Outdoor Set.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/rbo4eFEx2Qu5fkfDXwLrYT.jpg" mos="" align="middle" fullscreen="" width="1000" height="1000" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>Perfect for a compact space or balcony, this 3-piece set consists of two, high back armchairs with sponge-filled cushions for extra comfort, and a tempered glass tabletop for your drinks and food. With its premium PE rattan design, these are sturdy, weatherproof and easy to clean/maintain. A stylish addition to any backyard.  <a class="view-deal button" href="https://www.amazon.com/Flamaker-Furniture-All-Weather-Outdoor-Tempered/dp/B0CH36DTRL" target="_blank" rel="nofollow" data-dimension112="3923c8fa-f89b-40fb-bb42-a1f3b6416564" data-action="Deal Block" data-label="Perfect for a compact space or balcony, this 3-piece set consists of two, high back armchairs with sponge-filled cushions for extra comfort, and a tempered glass tabletop for your drinks and food. With its premium PE rattan design, these are sturdy, weatherproof and easy to clean/maintain. A stylish addition to any backyard." data-dimension48="Perfect for a compact space or balcony, this 3-piece set consists of two, high back armchairs with sponge-filled cushions for extra comfort, and a tempered glass tabletop for your drinks and food. With its premium PE rattan design, these are sturdy, weatherproof and easy to clean/maintain. A stylish addition to any backyard." data-dimension25="$89">View Deal</a></p></div>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ I connected NotebookLM and Claude — and built the ultimate AI research assistant ]]></title>
                                                                                                                                                                                                <link>https://www.tomsguide.com/ai/i-connected-notebooklm-and-claude-and-built-the-ultimate-ai-research-assistant</link>
                                                                            <description>
                            <![CDATA[ I connected NotebookLM and Claude to create an AI-powered research workflow — and it felt less like using a chatbot and more like having a personal research assistant. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">qZaADDVKmYcTrTaTNsxTMM</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/nWZpFQyEMDHWxRoonprVbX-1280-80.png" type="image/png" length="0"></enclosure>
                                                                        <pubDate>Thu, 25 Jun 2026 06:15:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[AI]]></category>
                                                                                                <author><![CDATA[ amanda.caswell@futurenet.com (Amanda Caswell) ]]></author>                    <dc:creator><![CDATA[ Amanda Caswell ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/zYjevim2q7FjQiefqpjZRB.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ null ]]></dc:description>
                                                                                                                                                                                                                                                <media:content type="image/png" url="https://cdn.mos.cms.futurecdn.net/nWZpFQyEMDHWxRoonprVbX-1280-80.png">
                                                            <media:credit><![CDATA[Future]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[NotebookLM + Claude]]></media:description>                                                            <media:text><![CDATA[NotebookLM + Claude]]></media:text>
                                <media:title type="plain"><![CDATA[NotebookLM + Claude]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/nWZpFQyEMDHWxRoonprVbX-1280-80.png" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>The most interesting thing happening in AI right now isn't that the models are getting smarter — though they are. It's that <a href="https://www.tomsguide.com/ai/reddit-users-arent-picking-one-ai-chatbot-anymore-heres-how-they-stack-their-tools">they're starting to work together</a>. The question is no longer, should you quit ChatGPT and use Claude or Gemini instead, but rather, stacking models for the ultimate AI productivity package. <br><br>Some platforms even <a href="https://www.tomsguide.com/ai/anthropics-fable-five-ban-exposed-ais-next-big-problem-but-sakanas-fugu-may-have-the-answer">use AI to suggest the best AI for the job</a>. But after living inside a workflow that connects <a href="https://www.tomsguide.com/ai/googles-notebooklm-just-got-a-huge-upgrade-heres-why-it-beats-chatgpt-for-team-projects">Google's NotebookLM </a>with <a href="https://www.tomsguide.com/ai/what-is-claude-everything-you-need-to-know-about-anthropics-ai-powerhouse">Anthropic's Claude</a>, I've started to think we've been asking the wrong question entirely.</p><p>I spent the past few weeks testing a setup that lets Claude reach directly into information stored inside NotebookLM, Google's AI-powered research and note-taking tool. Instead of manually shuttling research between two browser tabs, Claude can reference material I've already collected and use it to answer questions, draft content, and connect ideas across sources.</p><p>Here's how it works. </p><h2 id="tl-dr">TL:DR</h2><p>Connecting Claude with NotebookLM is simple. Under the hood, the bridge is something called <a href="https://www.anthropic.com/news/model-context-protocol" target="_blank">MCP — the Model Context Protocol,</a> an open standard for letting AI applications talk to outside systems. </p><p>While it sounds complex, it's essentially a universal adapter that everyday users can already access through the Claude for Desktop app or simple GitHub community plug-ins.</p><h2 id="why-notebooklm-is-different">Why NotebookLM is different  </h2><p>If you haven't used NotebookLM before, the simplest way to describe it is an AI-powered research binder. You upload documents, articles, PDFs, transcripts and notes, and NotebookLM builds a knowledge base around them. It can also pull directly from the internet when prompted. </p><p>NotebookLM has caught on with students, academics, journalists and analysts because it easily ties specific materials together, particularly for research, rather than unsourced generalizations a typical chatbot might produce. In other words, NotebookLM is hyper-specific and focused, delivering citations and sources for deep research. <br><br>On its own, <a href="https://www.tomsguide.com/ai/i-replaced-7-daily-tasks-with-notebooklm-how-the-mobile-app-actually-saves-me-time">NotebookLM is already genuinely useful</a>. I lean on it constantly to organize research, compress hundred-page reports into something readable and surface connections that even <a href="https://www.tomsguide.com/ai/i-asked-notebooklm-to-help-me-think-like-jay-shetty-and-it-nailed-my-biggest-blind-spot">shift my mindset</a>. </p><p>But it has a ceiling. NotebookLM is excellent at retrieval and summary, and noticeably weaker at the things that come after: deep reasoning, structural argument, nuanced drafting, anything that requires holding a problem in mind and turning it over. </p><p> But when Claude is activated with NotebookLM, the tool levels up exponentially. </p><h2 id="claude-brings-the-reasoning-layer">Claude brings the reasoning layer  </h2><p>I was a big fan of<a href="https://www.tomsguide.com/ai/i-pay-usd20-a-month-for-chatgpt-claude-fable-5-made-me-question-why"> Fable Five</a>, even though it was <a href="https://www.tomsguide.com/ai/anthropic-abruptly-disables-fable-5-and-mythos-5-following-us-government-order">short lived</a>. But since putting NotebookLM with Claude, I feel as if I've gotten some of the power back. Connecting the two tools removes the need to go back and forth between the two for a seamless workflow. Now, rather than feeding Claude the same background over and over, I can point it at the research already organized inside NotebookLM and let it build from there.</p><p>Making this happen requires a digital translator called MCP (Model Context Protocol) — an open-source standard designed to help different AI architectures speak the same language. On their own, Claude and NotebookLM operate in total isolation; they have no native way to share data. The workaround relies on a lightweight MCP server acting as a middleman. It intercepts Claude's requests, securely fetches the relevant data from your notebook, and feeds it back to the model, completely automating away the need for the clipboard.</p><p>Worth saying plainly: the connectors that make this possible today are community-built and unofficial. Neither Google nor Anthropic has blessed the setup, and most of these bridges work by automating the NotebookLM interface rather than plugging into a sanctioned API. That puts the whole thing in a gray area you should weigh before pointing it at anything sensitive. You just have to understand that although the experience is remarkably smooth; the plumbing is still a hobbyist project, not a finished product.</p><p>Caveats acknowledged, the workflow itself feels startlingly natural. Instead of assembling context at the start of every conversation, the context is simply already there.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-egZzKX"></div>                            </div>                            <script src="https://kwizly.com/embed/egZzKX.js" async></script><h2 id="the-ultimate-research-assistant">The ultimate research assistant  </h2><p>Most AI conversations begin from nothing. Every new chat is a blank slate that demands you rebuild the situation — re-upload the documents, re-explain the project, re-establish what you already told it yesterday. Even if the AI has memory of your work, you have to enable it to make that happen, then remember to disable it when you want more privacy.  </p><p>With NotebookLM acting as the knowledge layer and Claude acting as the reasoning layer, that overhead mostly disappears. Here are a few concrete examples of what this setup has unlocked for me: </p><p>I have spent a lot of time<a href="https://www.tomsguide.com/ai/i-kept-hearing-that-ai-data-centers-are-draining-towns-dry-so-i-looked-at-the-evidence"> researching data centers</a> lately. With these tools, I could ask follow-up questions about a topic such as e-waste, without re-introducing a single source. I could ask Claude to compare the arguments in three different reports sitting in the same notebook and tell me where they actually disagreed — not where they used different words for the same point. </p><p>I could say, in effect, "draft a section based on what's in here," and get something grounded in my own material rather than the internet's averaged-out consensus. And because the answers traced back to specific sources, I could check the work instead of taking it on faith.</p><p>For the first time, I spent less time loading information into an AI and more time thinking alongside one that already understood it. For me, this subtle shift made a world of difference because I felt like I was really collaborating with AI. </p><h2 id="what-the-setup-actually-takes">What the setup actually takes</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="AHt8WcQ2xxsDLTUaMbdgZS" name="8 - 2026-06-24T143523.413" alt="NotebookLM + Claude setup" src="https://cdn.mos.cms.futurecdn.net/AHt8WcQ2xxsDLTUaMbdgZS.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: Future)</span></figcaption></figure><p>The community setup takes a little patience to install. I'm going to be honest that the setup to get these two tools together might be enough to scare users off. But, it shouldn't. <br><br>The issue is, there's no app store button for this yet, so you really do have to wire it together yourself, mostly through the terminal, and if that sentence made you flinch, know that several non-technical people I've compared notes with got it running in about fifteen minutes. Remember, you're copying and pasting commands, not writing code.</p><p><strong> </strong><u><strong>The setup is roughly this: </strong></u></p><p>First you need <a href="https://nodejs.org/en" target="_blank">Node.js</a> installed on your machine, since the community connectors<a href="https://www.tomsguide.com/ai/claude/getting-started-with-claude-connectors-how-to-control-apps-using-ai-prompts"> </a>are published as small Node packages. Then you add one of those connectors — there are a few floating around GitHub, all doing the same job — by either pasting a single command into your terminal or dropping a few lines into Claude's config file so the app knows the server exists. (If you use <a href="https://www.tomsguide.com/ai/claude-code-vs-openai-codex-i-built-3-real-apps-to-find-the-better-agent-heres-the-verdict">Claude Code</a>, you can hand it the connector's GitHub link and let Claude do most of the installation itself, which is a slightly surreal but very effective shortcut. It's how I did it). </p><p>The step that trips people up is authentication. The first time you run it, a Chrome window pops open on its own and asks you to log in to the Google account tied to your NotebookLM. <strong>The one piece of advice I'll share is: do not close that window! </strong> <br><br>Know that it appears suddenly and looks like a stray pop-up, but it's the whole handshake — shut it by reflex and you'll get a cryptic "authentication failed" error and have to start over. At the same time, if it closes, no biggie, just start over, but nobody wants that. <br><br>Finally, log in, let it finish, and the connection persists from then on. After a restart, Claude shows the NotebookLM connector as active. The way to confirm it's really talking is to just ask by having Claude list your notebooks and the number of sources in each. If it reads back your actual notebook names, you're connected.  </p><h2 id="a-few-honest-caveats-before-you-dive-in">A few honest caveats before you dive in</h2><p>These connectors are unofficial, so they can break when the underlying tools update, and you may occasionally need to re-authenticate when a session goes stale. Most of them work by quietly driving a real browser in the background rather than plugging into a sanctioned API, which is smooth in practice but is exactly why I'd think twice before pointing this at genuinely sensitive material. It's a clever community hack, not a supported product — and it's good to know which one you're relying on.</p><p>And the oldest rule still holds: the output is only as good as how you've organized your sources going in. Dump everything into one giant notebook and you get mush. But, if you take the time to keep focused notebooks (one per project, research questions seperated, etc.) you'll notice everything feels sharper. When Claude can reason against a clean, well-scoped body of material, there's a big difference. </p><h2 id="final-thoughts-4">Final thoughts </h2><p>Pair-programming your AI tools is one of my favorite ways to get more out of them. Until recently, we’ve treated these models as standalone islands. But when you wire them together, you get the best of both worlds — they push past their individual ceilings to create something entirely new.</p><p>And it's not just me doing this. Increasingly, power users are building interconnected systems. One tool stores and grounds the data, while another reasons over it to produce the actual work. (I often even throw in a third model to validate the output or format it into a presentation deck).</p><p>To be clear, this setup isn't going to replace human researchers or analysts anytime soon. The judgment of what to ask, what to keep, and what is flat-out wrong still sits entirely with the person at the keyboard. But changing the workflow from a single chatbot to an ecosystem has completely rewritten how I view the future of productivity. </p><p>Give this setup a try and let me know what you think in the comments. </p><a href="https://follow.it/articles-by-amanda-caswell-tom-s-guide?leanpub" class="button button--large button--primary">Follow Amanda Caswell and stay ahead of the AI curve</a><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/ai/anthropic-will-pay-workers-usd85-000-to-learn-ai-and-it-reveals-the-next-big-ai-job-trend">Anthropic will pay workers $85,000 to learn AI — and it reveals the next big AI job trend</a></li><li><a href="https://www.tomsguide.com/ai/chatgpt-tasks-now-feels-like-a-real-assistant-7-ways-im-using-it-including-snagging-the-best-prime-day-deals">ChatGPT Tasks now feels like a real assistant — 7 ways I'm using it, including snagging the best Prime Day deals</a></li><li><a href="https://www.tomsguide.com/ai/is-your-job-ai-resilient-find-your-risk-score-with-our-career-calculator">Is your job 'AI-resilient'? Find your risk score with our career calculator</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ 'It’s going to be that shift from phones to glasses': Snap Specs chief on design, target audience and that $2,200 price tag ]]></title>
                                                                                                                                                                                                <link>https://www.tomsguide.com/computing/smart-glasses/really-pushing-the-frontier-of-what-technology-can-deliver-snap-specs-product-head-reveals-the-challenges-in-designing-the-new-ar-glasses</link>
                                                                            <description>
                            <![CDATA[ I interviewed Snap Specs Product Manager Russell Patton. He breaks down the custom engineering behind the $2,195 standalone AR glasses, and how it sets Snap up for a post-phone world. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">Uf5GjWNh3taeNAWmeukaKn</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/BR5qJseLxE3fwAfDXh8vCg-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Thu, 25 Jun 2026 06:01:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Smart Glasses]]></category>
                                                    <category><![CDATA[Computing Peripherals]]></category>
                                                    <category><![CDATA[VR &amp; AR]]></category>
                                                                                                                    <dc:creator><![CDATA[ Jason England ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/v4fSq5U4uZUEtGY2BwNuJ6.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Jason brings a decade of tech and gaming journalism experience to his role as a Managing Editor of Computing at Tom&#039;s Guide. He has previously written for Laptop Mag, Tom&#039;s Hardware, Kotaku, Stuff and BBC Science Focus. In his spare time, you&#039;ll find Jason looking for good dogs to pet or thinking about eating pizza if he isn&#039;t already.&lt;/p&gt; ]]></dc:description>
                                                                                                                                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/BR5qJseLxE3fwAfDXh8vCg-1280-80.jpg">
                                                            <media:credit><![CDATA[Future]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Snap Specs]]></media:description>                                                            <media:text><![CDATA[Snap Specs]]></media:text>
                                <media:title type="plain"><![CDATA[Snap Specs]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/BR5qJseLxE3fwAfDXh8vCg-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p><a href="https://www.tomsguide.com/computing/smart-glasses/i-just-went-eyes-on-with-snap-specs-theyre-a-lot-more-stylish-than-i-feared-at-first">Snap Specs</a> are a <em>very </em>ambitious pair of AR glasses. They transcend that idea of AI glasses like the <a href="https://www.tomsguide.com/computing/smart-glasses/ray-ban-meta-gen-2-review">Ray-Ban Metas</a>, and actually give you an <a href="https://www.tomsguide.com/computing/augmented-reality/apple-vision-pro-m5-2025-review">Apple Vision Pro</a>-esque experience in something much more wearable than a bulky headset with a battery pack wired to it.</p><p>But I could only imagine how much of a challenge designing something like this actually is, given the fact it’s got 2x Snapdragon chips, a battery and a ton of sensors built in (and no compute puck to offload that). </p><p>It’s a massive undertaking, so I got to chat to Russell Patton, product manager for Specs at Snap, about the past decade that has led to this moment — the challenges faced, what the Specs are, and how he sees these as a new paradigm of computing.</p>                    <div class= "tiktok-wrapper" style="min-height: 750px;"><blockquote class="tiktok-embed" cite="https://www.tiktok.com/@tomsguide/video/7652415879581289758" data-video-id="7652415879581289758" 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="♬ original sound - Tom’s Guide" href="https://www.tiktok.com/music/original-sound-7652415855426325279">♬ original sound - Tom’s Guide</a></section>                    </blockquote></div>                <h2 id="who-are-the-snap-specs-for">Who are the Snap Specs for?</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="ZYVS3zhj5gsa6Uqf5CS8zh" name="Snap Specs worn by Kaia Gerber" alt="Snap Specs worn by Kaia Gerber" src="https://cdn.mos.cms.futurecdn.net/ZYVS3zhj5gsa6Uqf5CS8zh.png" 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: Snap)</span></figcaption></figure><p>So as I watched Evan’s keynote at <a href="https://www.tomsguide.com/computing/augmented-reality/best-of-awe-2026-the-top-gadgets-that-show-us-the-future-of-xr">AWE 2026</a>, it’s clear he’s a fan of the Steve Jobs showmanship, and aimed for this to be Snap’s own personal iPhone moment — defining a new category of product and doing so with flair. I spoke to Russell about the idea of glasses as the next category and he provided a little more detail.</p><p>“We’ve seen these different shifts in computing happen, and we see a shift is coming,” Patton stated. “Going forward, it’s going to be that shift from phones to glasses, and I think it’s not just taking the apps that are on our phones and putting them into glasses.” </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="mdqF65aji8AbY3sph9M4bd" name="Snap Specs" alt="Snap Specs" src="https://cdn.mos.cms.futurecdn.net/mdqF65aji8AbY3sph9M4bd.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: Future)</span></figcaption></figure><p>Instead, he theorizes a new computing generation that works around “truly spatial content,” which I’ve been able to sample a bit of over the past year in Specs’ development — AR-infused AI that’s able to not just guide you to fix a car with text, but actually label all the key components in an AR space to better aid you.</p><p>That’s one of the huge parts of Snap OS from all my experiences testing it. Visual AI from things like Gemini on Android XR products like <a href="https://www.tomsguide.com/computing/smart-glasses/youve-got-questions-about-xreals-android-xr-glasses-and-ive-got-answers-3-things-you-need-to-know-about-project-aura">Xreal Aura</a> is all well and good — looking at what you’re showing and verbalizing an answer. Instead, Snap Specs and the many lenses built for it by the over 450k developers on Snap’s platform, use this in a much more visual mode, and it’s a real difference maker in spatial computing.</p><h2 id="on-designing-the-glasses">On designing the glasses</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:3840px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="bgk3JYKAvMvGJBXJPxXupf" name="Snap Specs" alt="Snap Specs" src="https://cdn.mos.cms.futurecdn.net/bgk3JYKAvMvGJBXJPxXupf.jpg" mos="" align="middle" fullscreen="" width="3840" height="2160" 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 also talked to Russell about getting to this point and designing the glasses around the huge amount of tech going into them. After <a href="https://www.tomsguide.com/computing/smart-glasses/exclusive-i-asked-snaps-hardware-chief-about-the-companys-next-gen-specs-heres-what-i-found-out">speaking to Snap’s former hardware VP last year</a>, it was clear that the mission was to make them “substantially smaller,” and Snap’s done this by working the aesthetic around the size demands of the internal hardware.</p><p>“You need to look at how we can make things efficient. How can we really take optical displays, really push down the size but at the same time deliver the capability to do true spatial computing?” Russell commented. </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:3840px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="VmzEQJu4TN65AThSJ7yKmf" name="Snap Specs" alt="Snap Specs" src="https://cdn.mos.cms.futurecdn.net/VmzEQJu4TN65AThSJ7yKmf.jpg" mos="" align="middle" fullscreen="" width="3840" height="2160" 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>Asking more about the design, it became clear that the display optics became one of the real challenges in making these a reality. For those uninitiated, these use Waveguide display tech — tiny projectors that refract an image through millions of grooves imprinted directly onto the lenses themselves (rather than a prism like you see on other AR glasses). </p><p>“You need it to be efficient so that you can make the battery a reasonable size, and you need it to be compact so the projector is not driving the size of the glasses to be large. A huge amount of work on the optics and the entire mechanical design happened to just do a really thoughtful integration,” Russell added. </p><h2 id="about-that-2-200-price">About that $2,200 price</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:3840px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="AStxUqZoTX9GTJyXyDxysf" name="Snap Specs" alt="Snap Specs" src="https://cdn.mos.cms.futurecdn.net/AStxUqZoTX9GTJyXyDxysf.jpg" mos="" align="middle" fullscreen="" width="3840" height="2160" 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><a href="https://www.specs.com/smart-glasses/specs-27" target="_blank" rel="nofollow">Snap Specs are available to pre-order now</a> for $2,195 (£1,995 for my fellow Brits), and they’re coming out this fall. It’s fair to assume that a lot of you reading this may see a massive price here, and that’s understandable. </p><p>Of course it's worth noting that this is defining a whole new category of wearable computing in a way your standard display glasses like the Ray-Ban Display can’t come close too. But it’s still a tough pill to swallow, so I asked Russell what the big pitch is.</p><p>“It’s about unlocking multiple categories of really exciting value,” Patton said. “So utilities, whether that’s AI assistance, measurement, listening to audio, having that large virtual display, browsing the web, or streaming video from your other device.”</p><p>A lot of AR glasses already do these things, but Russell expanded: “Using this very large external manager can create a really engaging, rich spatial AR experience. I think it’s really for someone who is excited to be experiencing a new computing platform and engage with those capabilities.”</p><h2 id="outlook-2">Outlook</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:3840px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="Rci5HX2DHn5SnEE8DVQonf" name="Snap Specs" alt="Snap Specs" src="https://cdn.mos.cms.futurecdn.net/Rci5HX2DHn5SnEE8DVQonf.jpg" mos="" align="middle" fullscreen="" width="3840" height="2160" 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>So I’ll be real — it’s clear these are for the (very rich) early adopters. But from my time talking to Russell, trying Snap OS for myself and seeing the glasses, those early adopters are in for a treat.</p><p>It’s the first true realization of my vision for smart glasses when I tested my first pair years ago: taking the computational capabilities of a bulky VR headset and squashing them down into glasses. Not only that, but taking advantage of that compression to give you some real-world killer apps.</p><p>I’m excited to try these out more as we close in on a fall launch.</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/computing/smart-glasses/im-just-going-to-wear-this-for-30-minutes-for-fun-even-realities-cto-shares-his-thoughts-on-snap-specs-and-gives-details-on-upcoming-g3-smart-glasses">'136 grams is not for all-day wearing' — Even Realities CTO sounds off on Snap Specs, and gives details on the future roadmap</a></li><li><a href="https://www.tomsguide.com/computing/smart-glasses/snap-wont-confirm-the-chip-but-qualcomm-claims-its-new-specs-are-in-the-ar-family-will-that-be-enough">Snap won't confirm the chip but Qualcomm claims its new Specs are in the 'AR family' — will that be enough?</a></li><li><a href="https://www.tomsguide.com/computing/smart-glasses/i-went-hands-on-with-all-of-metas-new-usd299-smart-glasses-to-see-if-theyre-actually-better-without-the-logos">I went hands-on with all of Meta’s new $299 smart glasses to see if they’re actually better without the logos</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ I've been lifting weights for years, but this 3-move ab workout completely humbled me ]]></title>
                                                                                                                                                                                                <link>https://www.tomsguide.com/wellness/workouts/im-a-personal-trainer-and-these-3-moves-torch-your-abs-and-build-muscle-using-one-dumbbell</link>
                                                                            <description>
                            <![CDATA[ You just need these three moves and a dumbbell to build your deep core and abs. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">TBbMNTBMwjrh9wY3NEwFDb</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/KbU4pxgWsiCFDkEGYupQFa-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Thu, 25 Jun 2026 05:00:00 +0000</pubDate>                                                                                                                                <updated>Thu, 25 Jun 2026 13:40:02 +0000</updated>
                                                                                                                                            <category><![CDATA[Workouts]]></category>
                                                    <category><![CDATA[Wellness]]></category>
                                                    <category><![CDATA[Fitness]]></category>
                                                                                                <author><![CDATA[ sam.hopes@futurenet.com (Sam Hopes) ]]></author>                    <dc:creator><![CDATA[ Sam Hopes ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/jZ88qJqvjWaCXXv3qvUQPA.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Sam Hopes is a level 3 qualified trainer, a level 2 Reiki practitioner and a fitness editor at Tom&#039;s Guide. She is also currently undertaking her Yoga For Athletes training course. Sam has written for various fitness brands and websites over the years and has experience across brands at Future, such as &lt;a href=&quot;https://www.livescience.com/author/sam-hopes&quot;&gt;Live Science&lt;/a&gt;,&lt;a href=&quot;https://www.fitandwell.com/author/sam-hopes&quot;&gt; Fit&amp;amp;Well&lt;/a&gt;,&lt;a href=&quot;https://www.coachweb.com/author/sam-hopes&quot;&gt; Coach&lt;/a&gt;, and T3. &lt;/p&gt;&lt;p&gt;Having worked with fitness studios like F45 and Virgin Active and trained both group and 1:1, Sam now primarily teaches outdoor bootcamps, bodyweight, and kettlebells. She also coaches mobility and flexibility classes several times a week and believes that true strength comes from a holistic approach to training your body. &lt;/p&gt;&lt;p&gt;Sam has completed two mixed doubles Hyrox competitions in London and the Netherlands and finished her first doubles attempt in 1:11.&lt;/p&gt;&lt;p&gt;In her spare time, she enjoys CrossFit, hot yoga, Pilates and running and can be found perfecting her handstand walks and handstand push-ups in the gym whenever she has the chance to be upside down. At work, she can be found testing the latest in fitness technology and wearables, anything yoga and CrossFit-related and has a keen interest in nutrition, mindfulness, sleep and recovery.&lt;/p&gt; ]]></dc:description>
                                                                                                                                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/KbU4pxgWsiCFDkEGYupQFa-1280-80.jpg">
                                                            <media:credit><![CDATA[Shutterstock]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Woman with toned abs punching to camera in gym with dumbbells in hands]]></media:description>                                                            <media:text><![CDATA[Woman with toned abs punching to camera in gym with dumbbells in hands]]></media:text>
                                <media:title type="plain"><![CDATA[Woman with toned abs punching to camera in gym with dumbbells in hands]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/KbU4pxgWsiCFDkEGYupQFa-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>We're all pretty time-poor these days, so saving a trip to the gym to roll out your mat at home is a great solution, but it's not always easy to find ab workouts you can depend on if you want to build a strong core with minimal equipment.</p><p>Before you turn to the pretty boring bank of sit-ups, crunches, or <a href="https://www.tomsguide.com/how-to/do-a-russian-twist-exercise">Russian twists</a>, I strongly recommend giving my three-move core workout a try instead. You only need a dumbbell (the <a href="https://www.tomsguide.com/best-picks/best-adjustable-dumbbells">best adjustable dumbbells </a>will give you more wiggle room) and roughly 15 minutes. It fits nicely onto the end of any leg or upper-body workout as a neat finisher to round off your hard work, plus it torches your abs and deep core.</p><p>Watch how to do this dumbbell abs workout step-by-step. </p><h2 id="watch-3-move-dumbbell-workout-for-home">Watch: 3-move dumbbell workout for home</h2><div class="instagram-embed"><blockquote class="instagram-media"  data-instgrm-version="6" style="width:99.375%; width:-webkit-calc(100% - 2px); width:calc(100% - 2px);"><p><a href="https://www.instagram.com/p/DZ9vxk7FaDF/" target="_blank">A post shared by Tom's Guide Fitness (@tomsguidefitness)</a></p><p>A photo posted by  on </p></blockquote></div><p>Complete two reps of each combination movement (there are three combos), then increase to four on the next round and so on. For beginners, aim to reach 10 reps per combo, then go back down the ladder again. For experienced exercisers, aim for 20. </p><p>Your core muscles help stabilize your trunk and pelvis, which means your body becomes better able to deal with balance, coordination, movement and injury. Always engage your core by drawing your navel up and in toward your spine while bracing down and directing your breath down and out. This encourages belly breathing, which engages the diaphragm, rather than reducing your breath to your chest, which is limiting.</p><div><blockquote><p>Your core muscles help stabilize your trunk and pelvis, which means your body becomes better able to deal with balance, coordination, movement and injury. </p></blockquote></div><p>During this workout, you'll focus on engaging and strengthening multiple core muscles, including your abs, obliques and other deeper stabilizing muscles like the transverse abdominis, as you hold, crunch and rotate your way through. </p><p>Your abs are commonly referred to as the six-pack muscles, which run along the front of your stomach and give people muscle definition. Typically they're targeted during exercises like sit-ups, but we don't want to limit the body to only targeting these muscles.</p><p>That's why we add twisting or lateral movement to focus on the lesser-known obliques — a group of superficial (external) and deeper (internal) muscles along the waist that aid rotation and lateral movement, plus the deeper stabilizing muscles responsible for protecting your spine and pelvis.</p><h3 class="article-body__section" id="section-why-does-this-workout-work"><span>Why does this workout work?</span></h3><p>If you constantly bang out 100s of sit-ups and crunches, you're really only strengthening a particular group of muscles, which means creating potential imbalances or weaknesses elsewhere.</p><p>I like to program workouts to work in all <a href="https://www.tomsguide.com/wellness/fitness/what-are-the-3-planes-of-motion-for-exercise-and-why-do-they-matter">planes of motion</a>, which means I have clients sitting, kneeling, standing, lying, rotating, crawling, holding, moving, not moving and everything in between. </p><p>That's how you target as many different muscle groups as possible to build true strength, endurance, posture and stability.</p><p>That said, growing muscle comes from stimulus and consistency, so remember to increase the intensity or volume of training as your body adapts. Either repeat this workout several times per week or mix the exercises into any existing routine that you follow.</p><div><blockquote><p> Growing muscle comes from stimulus and consistency.</p></blockquote></div><p>Lastly, remember that control and range of motion are everything; try not to rush reps, even when it feels super spicy and challenging. Come back to your breath and focus on the quality of your reps over quantity. That might mean you even reduce your working sets or increase rest breaks at first, which is better than losing form and hurting yourself. Listen to your body, and stop if necessary. </p><p><em><strong>Follow </strong></em><a href="https://www.instagram.com/tomsguidefitness/" target="_blank"><em><strong>Tom's Guide fitness</strong></em></a><em><strong> on Instagram for more workouts, routines, tips, and tricks.</strong></em></p><div class="instagram-embed"><blockquote class="instagram-media"  data-instgrm-version="6" style="width:99.375%; width:-webkit-calc(100% - 2px); width:calc(100% - 2px);"><p><a href="https://www.instagram.com/p/DWvhgVoEaf5/" target="_blank">A post shared by Tom's Guide Fitness (@tomsguidefitness)</a></p><p>A photo posted by  on </p></blockquote></div><h3 class="article-body__section" id="section-more-from-toms-s-guide"><span>More from Toms's Guide</span></h3><ul><li><a href="https://www.tomsguide.com/news/5-best-kettlebell-exercises-for-beginners-to-build-muscle-and-strength" target="_blank">5 best kettlebell exercises for beginners to build muscle and strength</a></li><li><a href="https://www.tomsguide.com/wellness/workouts/stop-doing-100s-of-sit-ups-im-a-personal-trainer-and-i-use-shoot-throughs-to-build-strong-abs-and-obliques-instead" target="_blank">Stop doing 100s of sit-ups: I'm a personal trainer, and I use 'shoot-throughs' to build strong abs and obliques instead</a></li><li><a href="https://www.tomsguide.com/wellness/fitness/you-dont-need-the-gym-to-build-strength-try-this-10-minute-kettlebell-workout-instead" target="_blank">You don’t need the gym to build strength, try this 10-minute kettlebell workout instead</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ I used ChatGPT to find the best Prime Day deals — and some of them are even better than Amazon’s discounts ]]></title>
                                                                                                                                                                                                <link>https://www.tomsguide.com/ai/i-used-chatgpt-to-find-the-best-anti-prime-day-deals-and-some-of-them-are-better-than-amazons-discounts</link>
                                                                            <description>
                            <![CDATA[ I used ChatGPT to find the best methods and deals for online retailers participating in Anti-Prime Day — these are the best discounts I found. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">CGMek75NaZAJYy9AhAW97L</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/oBzxuDzSjcxxokuLx6ZdR9-1280-80.png" type="image/png" length="0"></enclosure>
                                                                        <pubDate>Thu, 25 Jun 2026 04:30:00 +0000</pubDate>                                                                                                                                <updated>Thu, 25 Jun 2026 17:22:50 +0000</updated>
                                                                                                                                            <category><![CDATA[AI]]></category>
                                                                                                                    <dc:creator><![CDATA[ Elton Jones ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/NVtYYXr3tEPUE67jf3HtXM.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ null ]]></dc:description>
                                                                                                                                                                                                                                                <media:content type="image/png" url="https://cdn.mos.cms.futurecdn.net/oBzxuDzSjcxxokuLx6ZdR9-1280-80.png">
                                                            <media:credit><![CDATA[Future/Amanda Caswell]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[ChatGPT Image]]></media:description>                                                            <media:text><![CDATA[ChatGPT Image]]></media:text>
                                <media:title type="plain"><![CDATA[ChatGPT Image]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/oBzxuDzSjcxxokuLx6ZdR9-1280-80.png" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Forgive me for being extra late to the movement, but I was today years old when I learned about the “Anti-Prime Day” trend.</p><p>Simply put, it’s a period where non-Amazon retailers <a href="https://www.tomsguide.com/deals/live/walmart-rollback-sale-live-blog-apple-watch-8-for-dollar349-55-4k-tv-for-dollar198-and-more">launch competing sales </a>events with attractive discounts for all manner of items. Now that we’re smack dab in the middle of this year’s installment of <a href="https://www.tomsguide.com/uk/news/best-prime-day-deals-and-sales">Prime Day sales</a>, I’m keen on checking out the abundance of sweet deals I can find. </p><p>As a fan of wearable devices, video games, action flicks, trading card games and books, I had a feeling that some of the retailers I frequent inside and outside my home could hook me up with the appropriate items.</p><p>So I made a beeline to ChatGPT and asked it what methods I should adopt to cash in on the most appealing Anti-Prime Day sales. Not only did it show me the best price history tools to use, but it also sent me to one of my favorite retailers to discover discounts that are better than some Prime Day sales.</p><h2 id="adopting-the-best-anti-prime-day-discount-searching-methods">Adopting the best Anti-Prime Day discount searching methods</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="4BhtyJM26FZkmy8jKGheKV" name="online shopping" alt="Young woman making payment with credit card while doing subscription shopping via laptop" src="https://cdn.mos.cms.futurecdn.net/4BhtyJM26FZkmy8jKGheKV.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: Getty Images)</span></figcaption></figure><p>After asking ChatGPT how to come out at the end of Anti-Prime Day sales with the best deals imaginable, it responded with this statement to put me on the right path: </p><p><em>If you're trying to find the best Anti-Prime Day sales, the goal isn't just to avoid shopping on Prime Day—it's to take advantage of the fact that almost every major retailer launches competing discounts during the same period.</em></p><p>Then it went on to list a bunch of competing online retailers that currently have a long list of amazing products being sold at good to great prices:</p><ul><li><em>Best Buy (Tech Fest Sale; Ends on Sunday, June 28)</em></li><li><em>Kohl’s (Deal Days; Ends on Sunday, June 28)</em></li><li><em>Cozy Earth (Cozy Day Deals: Ends on Saturday, June 27)</em></li><li><em>Bugaboo (Summer Sale; Ends on Tuesday, July 7)</em></li><li><em>Athleta (Semi-Annual Sale; Ends on Sunday, June 28)</em></li><li><em>Walmart (Walmart Deals; Ends on Sunday, June 28)</em></li></ul><p>The chatbot also made mention of what items tend to get discounted to their lowest possible prices during Anti-Prime Day sales. The ones that stood out to me from that list included physical video games, gaming accessories, headphones, anime box sets, graphic novel omnibuses, manga box sets, LEGO sets and 4K Blu-rays.</p><p>ChatGPT also recommended the perfect Anti-Prime Day setup to rely on, which primarily focused on using a bunch of efficient price history tools:</p><ul><li><em>Keepa for deep Amazon price history.</em></li><li><em>CamelCamelCamel for quick verification.</em></li><li><em>Slickdeals alerts for deal discovery.</em></li><li><em>Honey for cross-retailer coupon and price tracking.</em></li><li><em>Compare prices at Target, Walmart, Best Buy, and Barnes & Noble before buying.</em></li><li><em>One useful rule: if a Prime Day deal isn't at or near the lowest price shown in Keepa or </em><a href="https://www.tomsguide.com/deals/i-cover-deals-for-a-living-and-this-is-the-one-prime-day-trick-you-need-to-know"><em>CamelCamelCamel, </em></a><em>it's usually worth waiting for a better sale later in the year. Multiple deal experts and experienced shoppers use that exact approach to avoid fake discounts and inflated "was" prices.</em></li></ul><h2 id="the-six-best-buy-goodies-i-came-across">The six Best Buy goodies I came across</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="KSNAKC4xcsGqeYkfWz3zBf" name="Best Buy logo.jpg" alt="Best Buy store logo" src="https://cdn.mos.cms.futurecdn.net/KSNAKC4xcsGqeYkfWz3zBf.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>Since my main focus during all those Anti-Prime Day sales was getting the best prices for a new smartwatch, a couple of video games, a collection of films starring an iconic spy and a set of trading cards I had been eyeing for a long time, I ended up on Best Buy’s digital storefront and found exactly what I wanted.</p><p>And what’s even better about these finds is how their discounts ended up being better than the ones seen on Amazon:</p><ul><li><strong>Garmin - Forerunner 165 GPS Smartwatch: </strong><a href="https://www.bestbuy.com/product/garmin-forerunner-165-gps-smartwatch-43-mm-fiber-reinforced-polymer-black-slate-gray-2024/JXF9YF456W?irclickid=QqOUGl34pxyZUpP1Ii3fPRo2UkuQzzU%3AO1lU3M0&irgwc=1&afsrc=1&ref=198&loc=Skimbit%20Ltd.&acampID=&mpid=10078&affgroup=%22Sub%20Affiliate%22" target="_blank" rel="nofollow"><strong>was $249.99 now $199.99</strong></a><strong> </strong>($249.98 on Amazon)</li><li><strong>BRAVELY DEFAULT FLYING FAIRY HD Remaster - Nintendo Switch 2: </strong><a href="https://www.bestbuy.com/product/bravely-default-flying-fairy-hd-remaster-nintendo-switch-2/J7GSL5JF46" target="_blank" rel="nofollow"><strong>was $39.99 now $19.99</strong></a><strong> </strong>($49.99 on Amazon)</li><li><strong>STREET FIGHTER 6 Year 1-2 Fighters Edition - Nintendo Switch 2: </strong><a href="https://www.bestbuy.com/product/street-fighter-6-year-1-2-fighters-edition-nintendo-switch-2/J7GSL5JFKH" target="_blank" rel="nofollow"><strong>was $59.99 now $29.99</strong></a><strong> </strong>($49.95 on Amazon)</li><li><strong>Gothic 1 Remake - PlayStation 5: </strong><a href="https://www.bestbuy.com/product/gothic-1-remake-playstation-5/J3L7FXT9WG" target="_blank" rel="nofollow"><strong>was $59.99 now $23.99</strong></a><strong> </strong>($59.88 on Amazon)</li><li><strong>The James Bond Collection (24 Films) - Blu-ray: </strong><a href="https://www.bestbuy.com/product/the-james-bond-collection-24-films-blu-ray/J3KZSZ2XWQ" target="_blank" rel="nofollow"><strong>was $68.06 now $61.26</strong></a><strong> </strong>($98.99 on Amazon)</li><li><strong>Wizards of The Coast - Magic: The Gathering Final Fantasy Starter Kit: </strong><a href="https://www.bestbuy.com/product/wizards-of-the-coast-magic-the-gathering-final-fantasy-starter-kit/JJ8VP7HL59/sku/12644248" target="_blank" rel="nofollow"><strong>was $19.99 now $14.99</strong></a><strong> </strong>($19.99 on Amazon)</li></ul><h2 id="the-takeaway-3">The takeaway</h2><p>I owe it to my living under a cave at some point and not even knowing about Anti-Prime Day before this little ChatGPT experiment I conducted. Better late than never, I say! </p><p>My go-to chatbot helped me set up a winning game plan for this week’s digital sales from a variety of online retailers, use price history tools to compare all the items I had sitting on my Amazon wish list and find much better prices for those same items through Best Buy. </p><p>What started this year as a money-saving experiment has now morphed into an annual tradition for me and my wallet.</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/ai/i-asked-chatgpt-to-help-me-score-big-on-prime-day-these-5-money-saving-tips-are-better-than-i-expected" target="_blank">I asked ChatGPT to help me score big on Prime Day — these 5 money-saving tips are better than I expected</a></li><li><a href="https://www.tomsguide.com/ai/i-just-found-alexas-hidden-prime-day-trick-use-it-now-so-you-dont-miss-the-best-deals" target="_blank">I just found Alexa's hidden Prime Day trick — use it now so you don't miss the best deals</a></li><li><a href="https://www.tomsguide.com/ai/that-viral-jeff-bezos-quote-about-ai-and-water-isnt-real-heres-what-actually-happened" target="_blank">That viral Jeff Bezos quote about AI and water isn't real — here's what actually happened</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ I use these 3 ChatGPT prompts to turn AI into my personal tutor — and learning became much more engaging ]]></title>
                                                                                                                                                                                                <link>https://www.tomsguide.com/ai/i-use-these-3-chatgpt-prompts-to-turn-chatgpt-into-my-personal-tutor-and-learning-became-much-more-engaging</link>
                                                                            <description>
                            <![CDATA[ With these three prompts, I turn ChatGPT into my personal tutor and make the simple activity of learning and acquiring new skills that much more engaging. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">5KTVMwNdSG3e3kmMZKMJ9m</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/QMpcTdTaBjXqox6aSgfujZ-1280-80.png" type="image/png" length="0"></enclosure>
                                                                        <pubDate>Wed, 24 Jun 2026 10:00:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[AI]]></category>
                                                                                                                    <dc:creator><![CDATA[ Elton Jones ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/NVtYYXr3tEPUE67jf3HtXM.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ null ]]></dc:description>
                                                                                                                                                                                                                                                <media:content type="image/png" url="https://cdn.mos.cms.futurecdn.net/QMpcTdTaBjXqox6aSgfujZ-1280-80.png">
                                                            <media:credit><![CDATA[Future]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[ChatGPT learning]]></media:description>                                                            <media:text><![CDATA[ChatGPT learning]]></media:text>
                                <media:title type="plain"><![CDATA[ChatGPT learning]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/QMpcTdTaBjXqox6aSgfujZ-1280-80.png" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>I’m in my late 30s, but I never stop looking for ways to learn something new. Until recently, I didn't even know what ChatGPT was—that is, until a friend gave me a crash course in AI. Fascinated by its potential, I started testing how it could enhance my daily learning.</p><p>Since then, I've used ChatGPT as a personal fitness coach, music curator, travel adviser, and custom tutor. It completely transformed how I acquire new skills. Here are the three prompts I used to upgrade my learning experience, and how you can use them to master whatever you're curious about.</p><h2 id="prompting-to-increase-my-know-how">Prompting to increase my know-how</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="YHzpzc3Qbe4NQ3a6YDMGk8" name="A teenager studying at school." alt="A teenage girl sits at a desk at school studying." src="https://cdn.mos.cms.futurecdn.net/YHzpzc3Qbe4NQ3a6YDMGk8.png" 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: Getty Images)</span></figcaption></figure><p>Let’s state the obvious: learning a new language is tough. I got a C in high school Spanish, and usually rely on translation apps just to order drinks on vacation. While I’m not bilingual yet, I’ve had a blast learning the basics of Spanish and Japanese using this roadmap prompt:</p><p><strong>Prompt 1: The Language Roadmap</strong> <em>"I want to learn [language] from scratch. Act as an expert instructor and curriculum designer. Assess what a beginner needs to know, identify the 20% of concepts that produce 80% of the results, and create a step-by-step learning roadmap. Break the roadmap into: Beginner, Intermediate, and Advanced. For each stage, include: Key concepts, Recommended practice exercises, Common mistakes, Milestones that prove mastery and Estimated time investment."</em></p><p>Even if you're smart, some topics are just too complex to wrap your head around. Back in college, a professor introduced me to the "Feynman Technique"—a method where you master a subject by forcing yourself to explain it in simple, jargon-free terms.</p><p>Whenever I need ChatGPT to break down complex issues—like how AI data centers impact the environment or why the cost of living keeps rising—I use this prompt to flatten the learning curve:</p><p><strong>Prompt 2: The Feynman Technique</strong> <em>"Teach me about [subject] using the Feynman Technique. Explain it as if I'm 12 years old. Then gradually increase the complexity. After each section, ask me a question to test my understanding before moving on."</em></p><p>I’m no handyman. When something breaks in my apartment, I usually give up and call maintenance. Lately, I've been trying to change that by using ChatGPT as a skill tutor (while double-checking its advice against legitimate sources, of course).</p><p>Whether I'm deep-cleaning my PS5, attempting to build a gaming PC, or trying to code, this interactive tutor prompt keeps me on track:</p><p><strong>Prompt 3: The Socratic Tutor</strong><em> "Act as my personal tutor for [skill]. Your job is not to lecture me but to guide me. Ask me questions, identify gaps in my understanding, challenge my assumptions, and adapt lessons based on my responses. Do not move on until I've demonstrated understanding."</em></p><h2 id="bottom-line-3">Bottom line</h2><p><strong>Bonus Prompt: The Masterclass Deep-Dive</strong><em> "I want to develop an expert-level understanding of [topic]. Don't just teach me facts. Teach me about what experts think about the topic, common misconceptions, contrarian viewpoints, important debates, first principles, mental models, historical context and future trends. Help me move from knowledge to wisdom by challenging my assumptions and encouraging critical thinking throughout the learning process."</em></p><p>The more you use AI, the better it adapts to your habits. By pairing ChatGPT with reliable outside sources, my learning sessions have become genuinely engaging instead of a chore. With these three prompts in my digital back pocket, picking up new skills and researching random topics has never been easier.</p><p>Put these prompts to work for yourself and see how much they change your workflow. </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/ai/these-5-chatgpt-prompts-ended-my-dinner-planning-problems-and-introduced-me-to-amazing-new-recipes" target="_blank">These 5 ChatGPT prompts ended my dinner planning problems — and introduced me to amazing new recipes</a></li><li><a href="https://www.tomsguide.com/ai/turns-out-ai-was-destroying-my-phones-battery-here-is-the-setting-i-changed-to-stop-it" target="_blank">Turns out AI was destroying my phone’s battery — here is the setting I changed to stop it</a></li><li><a href="https://www.tomsguide.com/ai/i-asked-chatgpt-and-claude-to-plan-my-next-dream-trip-to-japan-with-viator-one-delivered-much-better-destinations" target="_blank">I asked ChatGPT and Claude to plan my next dream trip to Japan with Viator — one delivered much better destinations</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ 3 DIY jobs you should strictly leave to the professionals ]]></title>
                                                                                                                                                                                                <link>https://www.tomsguide.com/home/3-diy-jobs-you-should-strictly-leave-to-the-professionals</link>
                                                                            <description>
                            <![CDATA[ Planning to refresh your living space this summer? While a DIY project is tempting, it turns out some tasks require a professional touch. Read our expert advice before picking up any tools. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">gGENi66NE4KpdARyJCoFaK</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/Vkh7ZDktGTsjNWDnD3mrCR-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Wed, 24 Jun 2026 09:00:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Home]]></category>
                                                                                                                    <dc:creator><![CDATA[ Cynthia Lawrence ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/CCuSgQpd5NyZ46CgoF9cva.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ null ]]></dc:description>
                                                                                                                                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/Vkh7ZDktGTsjNWDnD3mrCR-1280-80.jpg">
                                                            <media:credit><![CDATA[Shutterstock]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Man drilling a blue wall]]></media:description>                                                            <media:text><![CDATA[Man drilling a blue wall]]></media:text>
                                <media:title type="plain"><![CDATA[Man drilling a blue wall]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/Vkh7ZDktGTsjNWDnD3mrCR-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>As Homes Editor, I find great joy in refreshing my living and outdoor spaces, especially for the warmer months — often scouring social media for the latest DIY trends and expert-led renovation tips.</p><p>But while there are plenty of home reno jobs you can do yourself (and save a grand fortune), there are some jobs best left to the skilled professionals.</p><p>If not done properly (and safely), you could easily end up causing more damage to your home or, worse, injure yourself and others. What’s more, you’ll be wasting money on materials and costly repairs — when you need to call in a professional to fix your mistakes. </p><p>I’ve called on an expert to determine which home renovation tasks are safe for a DIY enthusiast and which ones require the specialized skills of an expert. So before you start your summer renovation project, read this first. </p><h3 class="article-body__section" id="section-knocking-down-a-wall"><span>Knocking down a wall</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:5938px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="FdtHkq5F3LshtZxns36BxH" name="shutterstock_editorial_16847678kt" alt="demolished wall in bathroom" src="https://cdn.mos.cms.futurecdn.net/FdtHkq5F3LshtZxns36BxH.jpg" mos="" align="middle" fullscreen="" width="5938" height="3340" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="caption-text">demolished wall in bathroom </span><span class="credit" itemprop="copyrightHolder">(Image credit: Shutterstock)</span></figcaption></figure><p>As an avid viewer of home improvement shows, I’ve often seen homeowners knock through interior walls to open up their living areas. And while it might seem tempting to do it yourself, experts warn against this idea.</p><p>“Knocking down an internal wall is also something homeowners are urged to think twice about,” states Danielle Croce, director at <a href="https://www.intasite.com/" target="_blank" rel="nofollow">Intasite</a>. “While it can be tempting to open up space, there are several important factors to consider before picking up a hammer.</p><p> Some walls are load-bearing, meaning they support the structure of the property, and removing them without proper assessment could cause serious structural damage. In certain cases, permission from your local council may also be required.”</p><p>So while it may look simple to do on television, it’s always safer to call in the qualified professionals to tackle this job. Not only will they have the expertise, but the specialist equipment needed to reduce the risk of any further structural damage.</p><h3 class="article-body__section" id="section-electrical-rewiring"><span>Electrical rewiring</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:4104px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="9yGvWj83eLKceLVQZeVANo" name="shutterstock_editorial_1426008e" alt="Man fixing electrical wires" src="https://cdn.mos.cms.futurecdn.net/9yGvWj83eLKceLVQZeVANo.jpg" mos="" align="middle" fullscreen="" width="4104" height="2309" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="caption-text">Man fixing electrical wires </span><span class="credit" itemprop="copyrightHolder">(Image credit: Shutterstock)</span></figcaption></figure><p>Now, I’ve known plenty of people who’ve attempted to tackle electrical rewiring themselves, but experts strictly warn against this dangerous job. If you're planning on adding fresh circuits or dealing with high-risk areas like the bathroom or backyard, these projects require a certified electrician. </p><p>The safest DIY tasks we can do are minor fixes like swapping out fuses or bulbs without assistance. In fact, why not invest in some<a href="https://www.tomsguide.com/home/smart-home/brighten-up-your-home-with-smart-lighting-solutions"> smart lighting</a> solutions to save you the hassle? </p><h3 class="article-body__section" id="section-fitting-a-new-bath"><span>Fitting a new bath</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:7836px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="xE4fAqoCwfaVyH2EauUWxA" name="shutterstock_2631104293" alt="Running tap filling bathtub with water" src="https://cdn.mos.cms.futurecdn.net/xE4fAqoCwfaVyH2EauUWxA.jpg" mos="" align="middle" fullscreen="" width="7836" height="4408" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="caption-text">Running tap filling bathtub with water </span><span class="credit" itemprop="copyrightHolder">(Image credit: Shutterstock)</span></figcaption></figure><p>I’ve lost count of the number of social media posts I’ve scrolled past featuring stunning bathtub installations as part of a high-end bathroom transformation. Again, while it seems to be a simple task, you should never take on any form of plumbing job yourself.</p><p>“Fitting a new bath is another job that may seem straightforward but can quickly lead to complications,” explains Croce. “Installing a bath incorrectly could mean breaking water regulations, which may result in fines or further costly work to fix the issue.”</p><p> “There are specific approved fittings that must be used, and in some cases, homeowners may even need to consult their water supplier before making changes. Getting it wrong could lead to leaks, water damage, or compliance issues further down the line.”</p><p>So if you don't want to risk causing a leak, broken pipe or any further damage, stay far away from plumbing works. </p><div class="product"><a data-dimension112="f69c3d1e-2247-4a07-8be0-2bbafbf6578a" data-action="Deal Block" data-label="Paint sprayers are a perfect tool for painting your home, fast. With adjustable flow control, you can dictate how wide or narrow it sprays. Plus, you can change the nozzles with this paint sprayer coming with four different sizes, depending on the job you want to get done. It's easily disassembled after use, making cleaning quick and easy." data-dimension48="Paint sprayers are a perfect tool for painting your home, fast. With adjustable flow control, you can dictate how wide or narrow it sprays. Plus, you can change the nozzles with this paint sprayer coming with four different sizes, depending on the job you want to get done. It's easily disassembled after use, making cleaning quick and easy." data-dimension25="$78" href="https://www.amazon.com/Sprayer-Electric-Furniture-Cabinets-Garden/dp/B0D5WKHFD7" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1426px;"><p class="vanilla-image-block" style="padding-top:99.93%;"><img id="Z3tX6HWR7hhvNpWSUNza8C" name="Paint-Sprayer-1000W-High-Power-Electric-Spray-Paint-Gun" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/Z3tX6HWR7hhvNpWSUNza8C.jpg" mos="" align="middle" fullscreen="" width="1426" height="1425" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>Paint sprayers are a perfect tool for painting your home, fast. With adjustable flow control, you can dictate how wide or narrow it sprays. Plus, you can change the nozzles with this paint sprayer coming with four different sizes, depending on the job you want to get done. It's easily disassembled after use, making cleaning quick and easy.<a class="view-deal button" href="https://www.amazon.com/Sprayer-Electric-Furniture-Cabinets-Garden/dp/B0D5WKHFD7" target="_blank" rel="nofollow" data-dimension112="f69c3d1e-2247-4a07-8be0-2bbafbf6578a" data-action="Deal Block" data-label="Paint sprayers are a perfect tool for painting your home, fast. With adjustable flow control, you can dictate how wide or narrow it sprays. Plus, you can change the nozzles with this paint sprayer coming with four different sizes, depending on the job you want to get done. It's easily disassembled after use, making cleaning quick and easy." data-dimension48="Paint sprayers are a perfect tool for painting your home, fast. With adjustable flow control, you can dictate how wide or narrow it sprays. Plus, you can change the nozzles with this paint sprayer coming with four different sizes, depending on the job you want to get done. It's easily disassembled after use, making cleaning quick and easy." data-dimension25="$78">View Deal</a></p></div><h3 class="article-body__section" id="section-and-jobs-that-are-safe-to-diy"><span>...and jobs that are safe to DIY</span></h3><ul><li>Painting and wallpapering</li><li>Tiling</li><li>Replacing cabinets, doors and fixtures</li><li>Cleaning gutters</li></ul><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/how-to/7-clever-painting-hacks-that-you-wish-you-knew-sooner">7 clever painting hacks that you wish you knew sooner</a></li><li><a href="https://www.tomsguide.com/how-to/how-to-paint-a-ceiling">How to paint a ceiling</a></li><li><a href="https://www.tomsguide.com/how-to/how-to-remove-wallpaper">how to remove wallpaper </a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ ChatGPT Tasks now feels like a real assistant — 7 ways I'm using it, including snagging the best Prime Day deals ]]></title>
                                                                                                                                                                                                <link>https://www.tomsguide.com/ai/chatgpt-tasks-now-feels-like-a-real-assistant-7-ways-im-using-it-including-snagging-the-best-prime-day-deals</link>
                                                                            <description>
                            <![CDATA[ ChatGPT Tasks can now monitor the web, track changes and send useful alerts. Here are 7 practical ways I'm using the upgraded feature to save time every week. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">GWGgEwwrgCuNkUtJyBHh3T</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/jN3EBZbAaLRko8gjF6Uj9h-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Wed, 24 Jun 2026 07:30:00 +0000</pubDate>                                                                                                                                <updated>Wed, 24 Jun 2026 14:30:39 +0000</updated>
                                                                                                                                            <category><![CDATA[AI]]></category>
                                                                                                <author><![CDATA[ amanda.caswell@futurenet.com (Amanda Caswell) ]]></author>                    <dc:creator><![CDATA[ Amanda Caswell ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/zYjevim2q7FjQiefqpjZRB.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ null ]]></dc:description>
                                                                                                                                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/jN3EBZbAaLRko8gjF6Uj9h-1280-80.jpg">
                                                            <media:credit><![CDATA[Shutterstock]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[ChatGPT app on iPhone ]]></media:description>                                                            <media:text><![CDATA[ChatGPT app on iPhone ]]></media:text>
                                <media:title type="plain"><![CDATA[ChatGPT app on iPhone ]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/jN3EBZbAaLRko8gjF6Uj9h-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>OpenAI has upgraded ChatGPT Tasks, finally giving the AI chatbot the ability to  keep working after you've closed the app.</p><p>If you tried Tasks when it first rolled out, you may still think of it as more of a reminder feature. I'll admit, when I first tried it, <a href="https://www.tomsguide.com/ai/i-let-chatgpt-task-schedule-a-me-time-hour-and-it-booked-me-for-a-dentist-appointment">I wasn't sure how useful it would be for me. </a>You can ask ChatGPT to remind you about appointments, recurring chores or upcoming events. Useful enough, but I always felt as if my phone or Alexa was enough, not to mention, both have been doing that for years. <br><br>But the recent upgrade caught my attention because now ChatGPT can monitor the web and connected apps for changes, then notify you only when something worth rnoting happens. For someone who spends way too many hours glued to her computer, this update fundamentally changes the way I can use AI. </p><p>Instead of constantly checking websites, searching for updates or refreshing pages, you can hand the monitoring over to ChatGPT and let it do the waiting for you.</p><h2 id="getting-started-with-chatgpt-tasks">Getting started with ChatGPT Tasks </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="caJ5gS5bT8dmtyvb2kno38" name="Tasks" alt="ChatGPT Tasks" src="https://cdn.mos.cms.futurecdn.net/caJ5gS5bT8dmtyvb2kno38.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: Future)</span></figcaption></figure><p>OpenAI says the new Scheduled Tasks feature is rolling out to paid users on <a href="https://www.tomsguide.com/news/chatgpt-plus-is-getting-a-massive-upgrade-heres-whats-coming">Plus</a>, Pro, Business and Enterprise plans. It's not available via the free tier yet. If you have access to the upgraded Tasks feature, you can create a task by describing what you want ChatGPT to do and when you want it to happen. In other words, you do not need to do anything else but simply type a prompt. </p><p>For those who would prefer a reminder option, OpenAI has also added a dedicated Scheduled page, available from the ChatGPT sidebar. From there, you can view all active tasks, see when they'll run next, edit task details, pause tasks temporarily or delete them altogether.</p><p>The most useful Tasks tend to be specific. Instead of asking ChatGPT to "watch Prime Day deals," tell it exactly what products, price thresholds or categories you care about. The more precise your instructions, the more helpful the notifications are likely to be.  </p><p>Here are seven ways I'm already using it.</p><h2 id="1-monitoring-prime-day-deals">1. Monitoring Prime Day Deals </h2><p><strong>Prompt: </strong><em>During Prime Day, monitor deals on AirPods Pro, Kindle Paperwhite, Fitbit smartwatches and robot vacuums. Notify me only when a discount exceeds 25% or when a deal appears unusually good compared to typical sale prices.</em></p><p>Who am I kidding, it's <a href="https://www.tomsguide.com/news/best-prime-day-deals-and-sales">Prime Day</a> and I'm not just using one prompt. I'm also using this one: <em>During Prime Day, monitor deals on LEGO sets, educational toys, noise-canceling headphones, tablets and school supplies. Notify me only when discounts reach 30% or more.</em></p><p>With these prompts or prompts like it, you're essentially telling ChatGPT Tasks, "I"m interested in this category. Don't bother me unless something genuinely good appears." That's why ChatGPT Tasks feels like an assistant. </p><h2 id="2-monitoring-airfare-without-checking-every-day">2. Monitoring airfare without checking every day</h2><p>One of the most annoying parts of planning a trip is repeatedly checking whether prices have dropped. If you're thinking about <a href="https://www.tomsguide.com/ai/i-asked-chatgpt-and-claude-to-plan-my-next-dream-trip-to-japan-with-viator-one-delivered-much-better-destinations">traveling to Japan</a> or elsewhere this summer, this update is a real time-saver. </p><p>Instead, you can tell ChatGPT: <em>Watch airfare from Newark to Orlando and notify me if round-trip prices fall below $250.</em></p><p>Rather than remembering to search every few days, the AI can keep an eye on things and alert you when it's worth paying attention. The alert comes in as an email. ChatGPT uses whatever email you have associated with your account, so be sure you're logged into your <a href="https://www.tomsguide.com/ai/ever-wonder-why-chatgpt-is-free-the-answer-is-far-more-calculated-than-you-might-think">ChatGPT account</a> when creating a Task. </p><h2 id="3-following-major-news-or-announcements">3. Following major news or announcements</h2><p>If you're following a major news story or want World Cup updates without constantly refreshing apps and social media, ChatGPT Tasks can notify you when something important happens. Instead of scrolling through endless headlines hoping not to miss an update, you can ask:  </p><p><em>"Notify me when there are major developments in the Israel-Iran conflict."</em></p><p><em>"Alert me when the U.S. team advances to the next round of the World Cup."</em></p><p><em>"Let me know when breaking news occurs involving severe weather in my area."</em></p><p>This turns ChatGPT into a personalized news watcher. I use it all the time! </p><h2 id="4-keeping-an-eye-on-school-and-weather-disruptions">4. Keeping an eye on school and weather disruptions</h2><p>Parents know how quickly schedules can change. One practical use for Tasks is:</p><p><em>"Alert me if local schools announce closures, delayed openings or emergency schedule changes."</em></p><p>You could also set up weather-related monitoring to stay informed about severe storms, snow days or other disruptions that affect your daily routine.</p><h2 id="5-catching-important-emails-i-may-have-missed">5. Catching important emails I may have missed</h2><p>Email overload is real. If I'm expecting an important email, I always set up a Task such as<em> "notify me when X sends me an email."</em> I also use the prompt: <em>"At the end of each workday, summarize important emails that have not received a response."</em></p><p>Instead of scanning through dozens of messages before bed, you get a quick summary of what might actually need your attention.</p><h2 id="6-planning-weekends-automatically">6. Planning weekends automatically</h2><p>I love the idea of using AI to eliminate the mental effort of figuring out what to do with the family.</p><p>A simple prompt like:<em> "Every Thursday afternoon, suggest family-friendly events happening nearby this weekend."</em></p><p>It can create a personalized list of activities without requiring any research on your part. And while it may seem small, once you use it, you realize it's a total game-changer to already have activities picked out by the time the weekend hits. </p><h2 id="7-creating-a-personalized-morning-briefing">7. Creating a personalized morning briefing</h2><p>One of the most practical uses for ChatGPT Tasks is building a custom daily briefing around the topics that matter most to you.</p><p>For example, you could ask: "Every morning, send me a briefing covering the latest technology news, weather, major headlines and anything important happening in my area."</p><p> Or: <em>"Every weekday at 7 a.m., summarize the top news stories, stock market updates and sports headlines."</em></p><p>Instead of jumping between news apps, weather forecasts and social media feeds, you can start the day with a single summary tailored to your interests and then click on the stories that interest you. </p><h2 id="this-was-a-major-update">This was a major update</h2><p>ChatGPT Tasks was useful before this update, but the ability to monitor information on your behalf is what makes it feel like a real assistant. Instead of waiting for your next prompt, ChatGPT can now keep watch over the things you care about and notify you when something important changes.</p><p>It's not replacing your calendar or becoming a fully autonomous AI agent overnight. But it's one of the clearest signs yet that ChatGPT is evolving beyond a chatbot and into something far more useful for everyday life. Give it a try and let me know in the comments how you're using it — I may feature your suggestion in a story. </p><a href="https://follow.it/articles-by-amanda-caswell-tom-s-guide?leanpub" class="button button--large button--primary">Follow Amanda Caswell and stay ahead of the AI curve</a><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/ai/anthropic-will-pay-workers-usd85-000-to-learn-ai-and-it-reveals-the-next-big-ai-job-trend">Anthropic will pay workers $85,000 to learn AI — and it reveals the next big AI job trend</a></li><li><a href="https://www.tomsguide.com/ai/that-viral-jeff-bezos-quote-about-ai-and-water-isnt-real-heres-what-actually-happened">That viral Jeff Bezos quote about AI and water isn't real — here's what actually happened</a></li><li><a href="https://www.tomsguide.com/ai/is-your-job-ai-resilient-find-your-risk-score-with-our-career-calculator">Is your job 'AI-resilient'? Find your risk score with our career calculator</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ According to a personal trainer, this exercise is 100 times more effective than crunches. I tried it and was humbled ]]></title>
                                                                                                                                                                                                <link>https://www.tomsguide.com/wellness/workouts/according-to-a-personal-trainer-this-exercise-is-100-times-more-effective-than-crunches-i-tried-it-and-was-humbled</link>
                                                                            <description>
                            <![CDATA[ This move builds functional strength in your core: here's how to do it. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">LeN8qaQRsetjwQC3XVCEGW</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/E2U8RmmcP9wVUbiUXkk8V3-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Wed, 24 Jun 2026 07:00:00 +0000</pubDate>                                                                                                                                <updated>Wed, 24 Jun 2026 16:17:57 +0000</updated>
                                                                                                                                            <category><![CDATA[Workouts]]></category>
                                                    <category><![CDATA[Wellness]]></category>
                                                    <category><![CDATA[Fitness]]></category>
                                                                                                <author><![CDATA[ jane.mcguire@futurenet.com (Jane McGuire) ]]></author>                    <dc:creator><![CDATA[ Jane McGuire ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/vV4Uj3e5TZvBqmmsjT2EU6.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Jane McGuire is Tom&#039;s Guide&#039;s Fitness Managing Editor, which means she looks after everything fitness-related — from running gear and fitness trackers to yoga mats and sports bras. An avid runner, Jane has tested and reviewed fitness products for the past five years, so she knows what to look for when finding a good running watch or a pair of shorts with pockets big enough for your smartphone, running gels, and house keys. &lt;/p&gt;&lt;p&gt;Jane has run six marathons — the London Marathon five times, and the Berlin Marathon once -and is still on a quest to tick off all of the marathon majors. Her marathon PR is 3:30, which she ran in the New Balance Supercomp Elite V5&#039;s, but she also spends a lot of time talking about her  ‘joy plan’, where she runs for happiness, not for PR’s. &lt;/p&gt;&lt;p&gt;Previous to Tom’s Guide, Jane worked for Runner’s World, where she co-hosted the Runner’s World podcast. She also presents on a YouTube channel called the Run Testers, alongside other running-mad journalists, where they review the latest shoes, kit, and tech. Her work has also appeared in Coach, Get Sweat Go, and Women’s Health. &lt;/p&gt;&lt;p&gt;When she&#039;s not pounding the pavements, you&#039;ll find Jane striding round the Surrey Hills, taking far too many photos of her spaniel, Toby. &lt;/p&gt; ]]></dc:description>
                                                                                                                                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/E2U8RmmcP9wVUbiUXkk8V3-1280-80.jpg">
                                                            <media:credit><![CDATA[Shutterstock/Future]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[a photo of a woman doing a bear plank and fitness editor Jane McGuire ]]></media:description>                                                            <media:text><![CDATA[a photo of a woman doing a bear plank and fitness editor Jane McGuire ]]></media:text>
                                <media:title type="plain"><![CDATA[a photo of a woman doing a bear plank and fitness editor Jane McGuire ]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/E2U8RmmcP9wVUbiUXkk8V3-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>When you think about ab workouts, chances are your brain will immediately think of endless sit-ups and crunches, lying prone on your exercise mat. While both exercises do a great job of working the six-pack muscles along the front of your core, they aren’t the best at building <a href="https://www.tomsguide.com/features/what-is-functional-training">functional fitness</a>, as you probably don’t find yourself lying on your back and crunching much in your day-to-day life.</p><p>This is why strength and run coach Melissa Kendter wants you to swap the exercise for the bear plank pull-through. “Reminding women this exercise is 100x more effective than crunches,” she writes on <a href="https://www.instagram.com/reels/DYpNBaCOgAC/" target="_blank" rel="nofollow">Instagram</a>. </p><p>“Crunches train your abs in isolation. Bear plank pull-throughs train your core the way we actually use it,” she adds. As a female runner myself, I added this powerhouse ab exercise to my strength training routine for a month — read on to find out what happened next. </p><p><em>As a reminder, if you’re a complete beginner, you’re recovering from an injury, or you’re pregnant or postpartum, it’s always best to seek personalized advice from a qualified professional. </em></p><h2 id="how-to-do-a-bear-plank-pull-through">How to do a bear plank pull-through </h2><p>All you’ll need for this exercise is a weight of some kind. You can check out the <a href="https://www.tomsguide.com/wellness/fitness/best-adjustable-dumbbells">best adjustable dumbbells</a> for your home workouts here, or you can use anything heavy, like a book or a milk carton. </p><p>In her video demonstration, Kendter is using a kettlebell. Remember, the right weight for you will feel challenging, but not impossible, by the final few reps.</p><p><strong>Here’s how to do the bear plank pull-through with good form: </strong></p><ul><li>Place a heavy dumbbell or kettlebell to one side of you, and start on all fours. Make sure your wrists are stacked underneath your shoulders, and your knees are in line with your hips.</li><li>Squeeze your core, thinking about sucking your belly button into your spine, and push through your hands to raise into a bear plank, hovering your knees a few inches from the floor.</li><li>Check your form: your hips should be completely still, and your back should be straight. Imagine you have a drink balanced on the small of your back — it shouldn’t spill.</li><li>Reach under and across your body with the opposite hand to grab the weight and drag it underneath your body while staying lifted in the bear plank. Repeat on the opposite side.</li><li>Keep switching sides until you have completed the same number of reps on each side.</li></ul><div class="instagram-embed"><blockquote class="instagram-media"  data-instgrm-version="6" style="width:99.375%; width:-webkit-calc(100% - 2px); width:calc(100% - 2px);"><p><a href="https://www.instagram.com/p/DYpNBaCOgAC/" target="_blank">A post shared by MELISSA KENDTER (@melissa_kendter)</a></p><p>A photo posted by  on </p></blockquote></div><h2 id="what-are-the-benefits-5">What are the benefits? </h2><p>You’re getting a lot of bang for your buck with this move. “As a runner (and honestly for women in general), this move is 100x more functional because it builds deep core stability, hip and shoulder strength, anti-rotation control, balance and coordination, better posture when fatigued, and pelvic/core connection without endless crunches,” says Kendter. </p><div><blockquote><p>I’ve run six marathons, and I do Pilates a few times a week, so I thought this move would be easy. I was wrong. </p></blockquote></div><p>If you think about your posture as you run and walk, you aren’t in a crunch. Instead, your core has to work to stabilize your pelvis and resist rotation as you move, helping you stay balanced and run more efficiently. </p><p>This is an elite anti-rotation exercise that challenges your core by firing up your obliques and deep transverse abdominis to keep your body stable as you move. You’ll also be challenging your glutes and shoulders, as well as your quads, to keep you stable in the isometric hold.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-Xp4dAX"></div>                            </div>                            <script src="https://kwizly.com/embed/Xp4dAX.js" async></script><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2120px;"><p class="vanilla-image-block" style="padding-top:56.27%;"><img id="bSQGDiwoLcXZP86D9LmkaD" name="bear plank getty.jpg" alt="a photo of a woman doing a bear plank" src="https://cdn.mos.cms.futurecdn.net/bSQGDiwoLcXZP86D9LmkaD.jpg" mos="" align="middle" fullscreen="" width="2120" height="1193" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Getty/Luca Sage)</span></figcaption></figure><h2 id="i-added-this-move-to-my-routine-for-a-month-and-was-humbled">I added this move to my routine for a month, and was humbled  </h2><p>I was humbled by this exercise. I’ve run six marathons, and I do Pilates a few times a week, so I thought this move would be easy. I was wrong. I had to really focus on keeping my hips steady as I dragged my dumbbell underneath my torso while holding the bear plank. I found I had to do five reps on each side before stopping to drop my knees down to the floor and reset to ensure I was moving with good form.</p><p>I spend a lot of time sitting down behind my desk, and have sciatica, so a tight lower back is a common occurrence. I often struggle to keep my hips level in traditional planks, but the bent-knee setup of the bear plank made it easier for me to ensure my back was flat. </p><p>Over the course of this challenge, the deep core shake I got throughout this exercise didn’t subside, although I definitely improved my form. Of course, my abs look the same — visible abs are the result of a low body fat percentage, not endless bear planks, but my deep core feels stronger, and I found I could really think about engaging my abs on the run. Give this one a go. You won’t regret it. </p><p><em><strong>Follow </strong></em><a href="https://www.instagram.com/tomsguidefitness/" target="_blank"><em><strong>Tom's Guide fitness</strong></em></a><em><strong> on Instagram for more workouts, routines, tips, and tricks.</strong></em></p><div class="instagram-embed"><blockquote class="instagram-media"  data-instgrm-version="6" style="width:99.375%; width:-webkit-calc(100% - 2px); width:calc(100% - 2px);"><p><a href="https://www.instagram.com/p/DZ5LtHionbs/" target="_blank">A post shared by Tom's Guide Fitness (@tomsguidefitness)</a></p><p>A photo posted by  on </p></blockquote></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/workouts/not-sit-ups-planks-or-crunches-i-do-this-simple-pilates-exercise-every-single-day-to-build-a-strong-and-stable-core-and-work-on-my-hip-flexor-mobility" target="_blank">Not sit-ups, planks, or crunches: I do this simple Pilates exercise every single day to build a strong and stable core and work on my hip flexor mobility</a></li><li><a href="https://www.tomsguide.com/wellness/fitness/im-a-weightlifting-coach-3-exercises-i-prefer-over-lunges-for-building-strong-stable-legs-and-knees-over-40" target="_blank">I'm a weightlifting coach — 3 exercises I prefer over lunges for building strong, stable legs and knees over 40</a></li><li><a href="https://www.tomsguide.com/wellness/workouts/i-tried-a-7-day-standing-core-routine-here-are-the-differences-i-noticed-in-my-strength-and-posture" target="_blank">I tried a 7-day standing core routine. Here are the differences I noticed in my strength and posture</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ 9 tips to keep your phone cool during a heatwave — and prevent damage ]]></title>
                                                                                                                                                                                                <link>https://www.tomsguide.com/phones/9-tips-to-keep-your-phone-cool-during-a-heatwave-and-prevent-damage</link>
                                                                            <description>
                            <![CDATA[ Summer heat can wreck your phone, but these 9 tips can help keep things running along without it overheating. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">HA7LWA6s36EHFX8KrPXTeA</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/YFqZwwwCWTdYA2KdbC42dM-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Wed, 24 Jun 2026 06:00:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Phones]]></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>
                                                                                                                                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/YFqZwwwCWTdYA2KdbC42dM-1280-80.jpg">
                                                            <media:credit><![CDATA[Shutterstock]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[hot phone]]></media:description>                                                            <media:text><![CDATA[hot phone]]></media:text>
                                <media:title type="plain"><![CDATA[hot phone]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/YFqZwwwCWTdYA2KdbC42dM-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>I'm currently sitting here in the U.K., which is <a href="https://www.tomsguide.com/tech/who-needs-a-c-anyway-heatwave-essentials-im-relying-on-right-now">currently undergoing a monster heat wave</a> with temperatures expected to exceed 100-degrees Fahrenheit later in the week. Needless to say, staying cool has been a priority, not just for me but for my phone as well. </p><p>Just like people, the <a href="https://www.tomsguide.com/best-picks/best-phones">best phones</a> don't do so well in extreme temperatures. Batteries, in particular, are more prone to degradation when things get too hot, but temperatures like this can cause all sorts of problems, from overheating to damaged screens.</p><p>So, to help keep your phone safe from the heat, here are 9 things you should do to help keep your phone cool during a heatwave.</p><h2 id="avoid-the-fridge-or-freezer">Avoid the fridge or freezer</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:6687px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="7LdprFCzb79MDKTWWkqr5F" name="Defrost main image.jpg" alt="Freezer with Ice" src="https://cdn.mos.cms.futurecdn.net/7LdprFCzb79MDKTWWkqr5F.jpg" mos="" align="middle" fullscreen="" width="6687" height="3761" 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>The absolute last thing you want to do is put your phone in the fridge or freezer, especially if it's already heating up. The first issue is that putting a hot phone into a cool environment runs the risk of causing thermal shock, the process by which rapid changes in temperature cause objects to break.</p><p>The main problem is the environment of the fridges and freezers themselves. Cold temperatures are just as bad for phones as hot ones, especially in the battery department. Fridges are also rather humid, which may eventually cause condensation to form in or around your phone. Water and electronics don't mix, so make sure to keep your phone out of the fridge.</p><h2 id="stick-to-cooler-rooms">Stick to cooler rooms</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:899px;"><p class="vanilla-image-block" style="padding-top:56.28%;"><img id="ycjeBLiNu8T4eA9tU8MFvK" name="Air conditioner on wall - crop.jpg" alt="Air conditioner unit on wall" src="https://cdn.mos.cms.futurecdn.net/ycjeBLiNu8T4eA9tU8MFvK.jpg" mos="" align="middle" fullscreen="" width="899" height="506" 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>The most obvious way to keep your phone cool is to keep it in a cool room. Whether that means relying on air conditioning, blocking the sun by covering the windows in aluminum foil, or simply using a fan to create some kind of breeze. You should also make sure not to leave your phone in places you know will heat up rapidly, like your car.</p><p>It doesn't really matter <a href="https://www.tomsguide.com/news/beat-the-heat-wave-10-essential-tips-and-tricks-to-stay-cool-this-summer">how you keep the room cool</a>, the important thing here is to ensure your phone is in a cool environment. That way you don't need to worry about it overheating, or things going wrong, because it's not getting the opportunity to heat in the first place.</p><h2 id="stay-out-of-the-sun">Stay out of the sun</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="TCcg5Zk5WqmfhkUFS5Ty97" name="GettyImages-923237808" alt="Bright sunlight" src="https://cdn.mos.cms.futurecdn.net/TCcg5Zk5WqmfhkUFS5Ty97.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: Getty Images)</span></figcaption></figure><p>If you aren't able to stay in a cool room for the duration of the heatwave, then it's especially important to avoid spending too much time in direct sunlight. Direct exposure causes things to heat up quite rapidly. </p><p>That includes you and your phone, which is why you should avoid as much sun as possible. Stick to the shady areas where you can, and keep your phone inside a bag of some kind so that it has some insulation around it. Avoid pockets, because such close contact to you stops any of the built-up heat from escaping and makes the problem worse.</p><h2 id="don-t-cover-your-phone">Don't cover your phone</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:3840px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="koRnLna2RmU9XgJXnhg3YV" name="iPhone 17 Pro Max-20" alt="iPhone 17 Pro Max" src="https://cdn.mos.cms.futurecdn.net/koRnLna2RmU9XgJXnhg3YV.jpg" mos="" align="middle" fullscreen="" width="3840" height="2160" 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>Heat build-up is only part of the equation, since you need to ensure that the heat surrounding your phone is able to escape off into the ether as well. For that reason, you should make sure your phone stays uncovered and has adequate ventilation. </p><p>That's a little ironic considering I just said to keep your phone in a bag if you're going out into the sun. But different circumstances have different needs. Whether you're inside or out, you should not be covering your phone with anything that would block airflow and prevent heat from escaping. Because, if it can't escape, the heat is just going to keep building up until it starts causing problems.</p><h2 id="remove-accessories">Remove accessories</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="tHYMPnpouL9jyX6ivSmrNn" name="google pixel 9 pro magsafe case" alt="google pixel 9 pro with a case that allows magsafe compatibility" src="https://cdn.mos.cms.futurecdn.net/tHYMPnpouL9jyX6ivSmrNn.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>Similarly, this is also a good reason to strip your phone down to its essentials by removing cases or other accessories that are stopping your phone from cooling down. I generally don't recommend keeping a naked phone, because even the most durable phone in the world needs some extra protection.</p><p>Still, all that extra protection can trap heat, and that's the last thing we want when the temperatures are this high.</p><h2 id="avoid-fast-and-wireless-charging">Avoid fast and wireless charging</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:3890px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="jLZsYi4ZT2SsMypA3BhvR7" name="ESR 3-in-1 MagSafe Travel Charger Stand-1.jpg" alt="ESR 3-in-1 MagSafe Travel Charger Stand" src="https://cdn.mos.cms.futurecdn.net/jLZsYi4ZT2SsMypA3BhvR7.jpg" mos="" align="middle" fullscreen="" width="3890" height="2188" 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>You can't avoid recharging your phone for days at a time, not unless you're still rocking a Nokia 3310 or some other late '90s handset. The problem is that recharging is not a perfect energy distribution system, and there is always some heat generation involved in the process. However, there are still ways to minimize the risk — and that means charging as slowly as possible.</p><p>Fast charging and wireless charging are both great, and very convenient features to have on hand. But they aren't very efficient, and they have a habit of producing a lot of excess heat during the charging process. For that reason, you can help protect your phone by avoiding both and using the slowest charging brick you have on hand. You should also avoid recharging in hot environments, especially direct sunlight. </p><h2 id="avoid-performance-heavy-features">Avoid performance heavy features</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:3840px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="2p68W9mHAAZd9qESYGbtvV" name="iPhone 17 Pro Max-22" alt="iPhone 17 Pro Max" src="https://cdn.mos.cms.futurecdn.net/2p68W9mHAAZd9qESYGbtvV.jpg" mos="" align="middle" fullscreen="" width="3840" height="2160" 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>Charging may be one of the more common ways people heat up their phone without realizing it, but there's more to consider when the temperatures are on the rise. Your phone is very good at producing its own heat, particularly when it's involved in any high-performance features. </p><p>We're talking things like on-device AI, gaming, editing and even something as simple as streaming a movie or recording video. They can all cause your phone to work harder, which generates more heat in the process. That's why so many flagships have been adding larger vapor chambers, to help dissipate that heat more effectively and protect key components from excess heat build-up.</p><h2 id="invest-in-a-cooling-device">Invest in a cooling device</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:1500px;"><p class="vanilla-image-block" style="padding-top:66.67%;"><img id="pcs32ob7deuBJ5FURcfFU6" name="Razer Cooler Chroma.jpg" alt="Razer Cooler Chroma image" src="https://cdn.mos.cms.futurecdn.net/pcs32ob7deuBJ5FURcfFU6.jpg" mos="" align="middle" fullscreen="" width="1500" height="1000" attribution="" endorsement="" class=""></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Razer)</span></figcaption></figure><p>A fairly simple way to keep your phone cool in high temperatures is to invest in a <a href="https://www.amazon.com/s?k=phone+cooler&crid=1JXNUKXMT7WOQ&sprefix=phone+cooler+razer%2Caps%2C268&ref=nb_sb_noss_1" target="_blank" rel="nofollow">specialized phone cooling device</a>. These attach to the back of your phone, and use a system of high-powered fans to direct heat away from your phone and blow it away. This can lead to a noticeable decrease in your phone's temperature — which is what you want.</p><p>The only question is deciding which cooler is the right one for you. Some coolers have attached magnetically and are compatible with both MagSafe and Qi2, while others use grips or cases to stay in place. Similarly, some have their own reserve of battery power, while others need to stay plugged into an external power source.</p><h2 id="change-some-settings">Change some settings</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="kNFEjP9owutZkLmdJpqXZK" name="iOS 18 Control Center editing B-2.jpg" alt="iOS 18 Control Center" src="https://cdn.mos.cms.futurecdn.net/kNFEjP9owutZkLmdJpqXZK.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 help reduce the amount of heat that your phone produces by tinkering with some settings. </p><p>First up, you should turn your brightness down as much as you can. Not to the point where you can't see, but enough to dim the screen by a noticeable amount. Switch off adaptive brightness while you're at it too; otherwise, your phone may crank up the brightness again. Likewise, consider switching off mobile data or using Airplane mode if you don't plan on connecting to cell towers.</p><p>Both of these features can use up more power than you need them to, which in turn increases the temperature of your phone. Switching them off when you don't need them helps preserve that power, keeping your phone a tiny bit cooler and extending your battery life. If possible you should also switch off features like Bluetooth, GPS and anything else that you don't need right away — for much the same reason.</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/phones/motorola-phones/motorola-razr-ultra-2026-review">Motorola Razr Ultra 2026 review: Better does come at a premium price</a></li><li><a href="https://www.tomsguide.com/phones/simo-solis-lite-hotspot-review">I tested this puck shaped mobile hotspot — and it’s the simplest way to get online</a></li><li><a href="https://www.tomsguide.com/phones/best-early-prime-day-2026-phone-accessories-deals-magsafe-wallets-power-banks-chargers-and-more">I tested 100+ phone accessories in the last year and these are my favorite early Prime Day deals — MagSafe wallets, power banks, chargers, and more</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ Is your career actually safe from AI? This 1-minute test reveals your risk score ]]></title>
                                                                                                                                                                                                <link>https://www.tomsguide.com/ai/is-your-job-ai-resilient-find-your-risk-score-with-our-career-calculator</link>
                                                                            <description>
                            <![CDATA[ Is your career safe from automation? Find your "AI-resilient" score with our custom career calculator and see how your industry ranks. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">fBT7vKWTfurfomVGFXxTzW</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/XvpximPesvHhzTNvq3dtm4-1280-80.png" type="image/png" length="0"></enclosure>
                                                                        <pubDate>Wed, 24 Jun 2026 05:04:00 +0000</pubDate>                                                                                                                                <updated>Wed, 24 Jun 2026 20:24:34 +0000</updated>
                                                                                                                                            <category><![CDATA[AI]]></category>
                                                                                                <author><![CDATA[ amanda.caswell@futurenet.com (Amanda Caswell) ]]></author>                    <dc:creator><![CDATA[ Amanda Caswell ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/zYjevim2q7FjQiefqpjZRB.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ null ]]></dc:description>
                                                                                                                                                                                                                                                <media:content type="image/png" url="https://cdn.mos.cms.futurecdn.net/XvpximPesvHhzTNvq3dtm4-1280-80.png">
                                                            <media:credit><![CDATA[Future]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[AI readiness]]></media:description>                                                            <media:text><![CDATA[AI readiness]]></media:text>
                                <media:title type="plain"><![CDATA[AI readiness]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/XvpximPesvHhzTNvq3dtm4-1280-80.png" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>The headline-grabbing news that <a href="https://www.tomsguide.com/ai/anthropic-will-pay-workers-usd85-000-to-learn-ai-and-it-reveals-the-next-big-ai-job-trend">Anthropic is launching a $150 million “Claude Corps” fellowship to pay early-career workers $85,000 to learn AI </a>highlights a massive shift in the labor market. It proves that the biggest hurdle facing tech giants right now is getting real-world organizations to understand how to actually use AI. </p><p>But beneath the surface of this massive hiring push is something worth noting: you don’t need a computer science degree to survive the ongoing AI transition. But what you do need is to understand how vulnerable your current career track is to wage stagnation.  </p><p>The future belongs to "domain experts," otherwise known as people with deep knowledge of specific industries like education, healthcare or finance and who know how to work alongside large language models. If you refuse to adapt, your job might not disappear overnight, but your <a href="https://www.tomsguide.com/ai/ai-might-not-take-your-job-but-it-could-quietly-shrink-what-your-paycheck-is-worth">earning potential could quietly shrink </a>as AI-literate peers optimize their output.  </p><h2 id="test-your-career-s-ai-resilience-right-now">Test your career's AI resilience right now</h2><a href="https://aijobcalculator.netlify.app/" class="button button--medium button--primary">AI Career Resilience Calculator</a><p>Your long-term career security depends on a vital mix of your industry experience, your human-centric "soft" skills and your willingness to<a href="https://www.tomsguide.com/ai/employees-using-ai-earn-40-percent-more-9-prompts-to-upskill-your-resume-and-future-proof-your-career"> </a>build basic AI fluency as <a href="https://www.tomsguide.com/ai/employees-using-ai-earn-40-percent-more-9-prompts-to-upskill-your-resume-and-future-proof-your-career"><strong>studies show employees who use AI can make up to 40% more.</strong></a> </p><p>To see where your current role falls on the safety spectrum, enter your field and experience into our <strong>AI Career Resilience Calculator.</strong></p><h2 id="how-to-boost-your-score-for-free">How to boost your score for free</h2><p>If your calculator results show you have high exposure to automation, you do not need to panic, and you don't need to drop thousands of dollars returning to school for a technical degree. The absolute fastest way to build career resilience is to learn how to manage the AI tools disrupting your sector before someone else does.  </p><p>For a closer look at the training programs tech companies expect applicants to know, you can check out this <a href="https://www.youtube.com/shorts/KFfIw0WW1rk" target="_blank">Anthropic Paid AI Fellowship Prep Stack Video</a> which details the free prompt engineering resources and certifications you can use right now.  </p><p>You can also build competitive AI literacy right now with tools like <a href="https://www.tomsguide.com/ai/this-masterclass-ai-course-made-me-rethink-how-i-use-chatgpt-at-work-and-its-up-to-50-percent-off-for-memorial-day">Masterclass</a> and other free resources that I think are exceptional:</p><ul><li><strong>Anthropic Academy:</strong> You can access<a href="https://www.anthropic.com/learn" target="_blank"> 17 free courses</a> and step-by-step prompt engineering interactive tutorials hosted directly on GitHub to learn how to structure instructions like a pro.</li><li><strong>Official AI Fluency Courses:</strong> Platforms like <a href="https://www.coursera.org/learn/ai-for-everyone" target="_blank">Coursera</a> host official, beginner-friendly AI literacy certifications designed specifically for non-technical workers looking to upskill quickly.</li><li><strong>Build a "Human-in-the-Loop" Project:</strong> Look at the most repetitive task in your current daily routine —whether it's sorting spreadsheets, drafting emails or scheduling workflows, <a href="https://www.tomsguide.com/ai/i-reclaimed-15-hours-this-week-with-ai-agents-here-is-the-exact-setup-i-used-to-automate-my-workflow">then and use a free LLM to automate it.</a></li></ul><h2 id="bottom-line-4">Bottom line</h2><p>Anyone can say they've used ChatGPT. Far fewer people can point to a specific workflow they improved, a task they automated or time they saved. That's the kind of experience that stands out in interviews.</p><p>As AI becomes a standard part of the workplace, employers are increasingly looking for people who can use these tools thoughtfully rather than simply experiment with them. </p><p>Even a small project that saves time, improves accuracy or reduces repetitive work can demonstrate initiative, problem-solving skills and a practical understanding of how AI fits into real-world business processes.  </p><a href="https://follow.it/articles-by-amanda-caswell-tom-s-guide?leanpub" class="button button--large button--primary">Follow Amanda Caswell and stay ahead of the AI curve</a><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/ai/anthropic-will-pay-workers-usd85-000-to-learn-ai-and-it-reveals-the-next-big-ai-job-trend">Anthropic will pay workers $85,000 to learn AI — and it reveals the next big AI job trend</a></li><li><a href="https://www.tomsguide.com/ai/that-viral-jeff-bezos-quote-about-ai-and-water-isnt-real-heres-what-actually-happened">That viral Jeff Bezos quote about AI and water isn't real — here's what actually happened</a></li><li><a href="https://www.tomsguide.com/ai/turns-out-ai-was-destroying-my-phones-battery-here-is-the-setting-i-changed-to-stop-it">Turns out AI was destroying my phone’s battery — here is the setting I changed to stop it</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ I tried this 3-move mobility routine using my dog instead of dumbbells. Here's what happened ]]></title>
                                                                                                                                                                                                <link>https://www.tomsguide.com/wellness/workouts/i-tried-this-3-move-mobility-routine-using-my-dog-instead-of-dumbbells-heres-what-happened</link>
                                                                            <description>
                            <![CDATA[ These three mobility exercises can be done with any equipment to improve balance, strength and stability, so I tested them with my dog. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">Pg5CWReZGAUWifR7sCLB8A</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/5jz2QKXd8Pg9W9dEWkhAUQ-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Wed, 24 Jun 2026 04:30:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Workouts]]></category>
                                                    <category><![CDATA[Wellness]]></category>
                                                    <category><![CDATA[Fitness]]></category>
                                                                                                <author><![CDATA[ sam.hopes@futurenet.com (Sam Hopes) ]]></author>                    <dc:creator><![CDATA[ Sam Hopes ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/jZ88qJqvjWaCXXv3qvUQPA.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Sam Hopes is a level 3 qualified trainer, a level 2 Reiki practitioner and a fitness editor at Tom&#039;s Guide. She is also currently undertaking her Yoga For Athletes training course. Sam has written for various fitness brands and websites over the years and has experience across brands at Future, such as &lt;a href=&quot;https://www.livescience.com/author/sam-hopes&quot;&gt;Live Science&lt;/a&gt;,&lt;a href=&quot;https://www.fitandwell.com/author/sam-hopes&quot;&gt; Fit&amp;amp;Well&lt;/a&gt;,&lt;a href=&quot;https://www.coachweb.com/author/sam-hopes&quot;&gt; Coach&lt;/a&gt;, and T3. &lt;/p&gt;&lt;p&gt;Having worked with fitness studios like F45 and Virgin Active and trained both group and 1:1, Sam now primarily teaches outdoor bootcamps, bodyweight, and kettlebells. She also coaches mobility and flexibility classes several times a week and believes that true strength comes from a holistic approach to training your body. &lt;/p&gt;&lt;p&gt;Sam has completed two mixed doubles Hyrox competitions in London and the Netherlands and finished her first doubles attempt in 1:11.&lt;/p&gt;&lt;p&gt;In her spare time, she enjoys CrossFit, hot yoga, Pilates and running and can be found perfecting her handstand walks and handstand push-ups in the gym whenever she has the chance to be upside down. At work, she can be found testing the latest in fitness technology and wearables, anything yoga and CrossFit-related and has a keen interest in nutrition, mindfulness, sleep and recovery.&lt;/p&gt; ]]></dc:description>
                                                                                                                                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/5jz2QKXd8Pg9W9dEWkhAUQ-1280-80.jpg">
                                                            <media:credit><![CDATA[Shutterstock]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Woman sitting on an exercise mat with her dog during workout]]></media:description>                                                            <media:text><![CDATA[Woman sitting on an exercise mat with her dog during workout]]></media:text>
                                <media:title type="plain"><![CDATA[Woman sitting on an exercise mat with her dog during workout]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/5jz2QKXd8Pg9W9dEWkhAUQ-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Recently, I had a random thought: what if I swapped dumbbells for my dog during workouts? So, ever curious to try new things with my training, I gave it a try.</p><p>I didn't think Mobie (that's my dog) would appreciate anything high-intensity, but a three-move mobility routine felt like a great place to start, as mobility combines strength and control (with or without load) to improve balance, stability, and range of motion in the body.</p><p>Mobie weighs 5kg (roughly 11lbs), so I knew I'd be able to perform some of the <a href="https://www.tomsguide.com/wellness/fitness/forget-tight-hips-try-these-5-mobility-moves-to-unlock-stiff-hips-and-build-stronger-glutes">best mobility exercises</a> I know using her safely. I like to perform mobility routines at least twice per week, as this helps me not only build but maintain results, so I repeated this several times, keeping the sets and reps consistent each time.</p><p>If you're keen to find out what happened, I documented it below and show you how to try it for yourself.</p><p><em>If you experience pain at any time, stop and rest. If you're working with an injury or health condition, or you're currently pregnant or postnatal, I recommend seeking advice before starting these exercises.</em></p><h2 id="watch-3-move-mobility-routine">Watch: 3-move mobility routine</h2><div class="instagram-embed"><blockquote class="instagram-media"  data-instgrm-version="6" style="width:99.375%; width:-webkit-calc(100% - 2px); width:calc(100% - 2px);"><p><a href="https://www.instagram.com/p/DZ5LtHionbs/" target="_blank">A post shared by Tom's Guide Fitness (@tomsguidefitness)</a></p><p>A photo posted by  on </p></blockquote></div><p>The goal with any mobility routine is to protect the body against injury and the natural decline in strength, balance, and stability that comes with aging. Call it a longevity routine, if you will. </p><p>This is also important for maintaining healthy fascia, a web of connective tissue that helps hold everything together, like your bones, muscles, and organs. Tight fascia increases friction, and mobility work helps reduce this using movement.</p><p><strong>The routine:</strong> You'll need one of the <a href="https://www.tomsguide.com/best-picks/best-yoga-mats">best yoga mats </a>and time<a href="https://www.tomsguide.com/best-picks/best-yoga-mats"> </a>to complete 3-4 sets and 8-10 reps.</p><ul><li><strong>Wide-leg lifts: </strong>Sit upright with your legs wide apart until you feel a stretch down the inner thighs. Sit tall with your spine long and core braced, shoulders relaxed. Place something (or someone!) inside of your right foot at a challenging height setting. With control, lift your foot up and over to the other side, then back again. Complete reps on one side, then swap to the other leg.</li><li><strong>Cossack squats: </strong>Stand with your feet hip-width apart, core engaged, and hold a weight to your chest. Take a big step to the right side with your right leg, toes pointed forward, and bend the knee to lower into a lunge. Keep your back straight and chest lifted, lowering as far as you can. Pause, then drive up through your legs and step to standing. Repeat on the other side.</li><li><strong>Windshield wiper hip extensions: </strong>Sit with your legs bent at 90 degrees, similar to a <a href="https://www.tomsguide.com/wellness/fitness/i-did-the-90-90-hip-stretch-for-a-week-and-my-mobility-improved-in-a-way-i-didnt-expect">90-90 stretch position</a>, and hold a weight to your chest. Keep your spine long and core engaged. Sweep your knees over to the opposite side, then lift your hips and butt into the air and squeeze your glutes. Pause, then carefully lower to the ground and sweep your knees in the opposite direction. Continue alternating.</li></ul><h2 id="what-are-the-benefits-6">What are the benefits?</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="fiSCshiuHD6XQyfoQ7V6hR" name="90-90" alt="90-90 hip stretch performed on a yoga mat" src="https://cdn.mos.cms.futurecdn.net/fiSCshiuHD6XQyfoQ7V6hR.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: Future)</span></figcaption></figure><p>Each of these exercises is beneficial for lower-body mobility, core stability and healthy hips.</p><p><strong>Wide-leg lifts:</strong> This is an effective hip flexor strengthener, as you must lift and lower your leg with control. You don't need to place anything there to begin with, but using a dumbbell, yoga block, or similar as a target is useful to ensure you lift far enough each time and creates a challenge as you progress.</p><p><strong>Cossack squats: </strong>These are killer for the legs, glutes, hips, core and even the upper body, as you sit your butt low while lifting your chest, balancing and stretching the inner thighs. Your entire lower body will feel this one, and not only does it increase mobility, but also strength and power in the legs, especially when loading the move.</p><p><strong>Windshield hip extensions: </strong>Building space and strength around your hips is crucial for proper movement mechanics, and the 90-degree position of your legs does this while also activating the gluteal muscles. The added benefit is that you'll lift your hips and squeeze your glutes at the top, adding hip extension and further glute work to the movement.</p><div><blockquote><p>Each of these exercises is beneficial for lower-body mobility, core stability and healthy hips.</p></blockquote></div><p>Give yourself enough time to really work through and control these movements, rather than rushing. </p><p>Combined into one routine, you'll build stronger hips, groin, adductors and glutes while challenging your range of motion and ability to control strength-based movements.</p><p>Adjust the reps and sets as necessary, and play around as I did, with weights and equipment. You can stick to using your bodyweight, but if the moves feel too easy, adjust, even if that means testing a few out with your pooch.</p><p>It's important to keep your core active and spine long throughout, so try to avoid any hunching over, especially in seated positions, where posture is lost very quickly.</p><p>I had great fun getting Mobie involved in this one, and she offered the perfect amount of weight (and cuddles) to make these already challenging moves more so. Not only did I focus on controlling the exercises and moving slowly, but I also contended with keeping her safely steady at my chest, meaning I was actually really focusing on these moves. </p><p>Besides, any excuse to give my dog an extra cuddle, right?</p><p>Give these a try, and let us know how you get on in the comments.</p><p><em><strong>Follow </strong></em><a href="https://www.instagram.com/tomsguidefitness/" target="_blank"><em><strong>Tom's Guide fitness</strong></em></a><em><strong> on Instagram for more workouts, routines, tips, and tricks.</strong></em></p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-ONKRJX"></div>                            </div>                            <script src="https://kwizly.com/embed/ONKRJX.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/wellness/workouts/i-teach-people-how-to-be-more-mobile-3-low-impact-back-and-shoulder-moves-that-build-stability-and-strength-after-40" target="_blank">I teach people how to be more mobile: 3 low-impact back and shoulder moves that build stability and strength after 40</a></li><li><a href="https://www.tomsguide.com/wellness/workouts/stop-doing-100s-of-sit-ups-im-a-personal-trainer-and-i-use-shoot-throughs-to-build-strong-abs-and-obliques-instead" target="_blank">Stop doing 100s of sit-ups: I'm a personal trainer, and I use 'shoot-throughs' to build strong abs and obliques instead</a></li><li><a href="https://www.tomsguide.com/wellness/workouts/i-teach-people-over-50-to-be-mobile-3-low-impact-moves-that-build-more-stability-than-a-30-minute-walk" target="_blank">I teach people over 50 to be mobile: 3 low-impact moves that build more stability than a 30-minute walk</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ From the 'caveman method' to the 'frozen salt water fan trick' — 7 expert-approved ways to cool your bedroom and sleep well in a heatwave ]]></title>
                                                                                                                                                                                                <link>https://www.tomsguide.com/wellness/sleep/from-the-caveman-method-to-the-frozen-salt-water-fan-trick-7-expert-approved-ways-to-cool-your-bedroom-and-sleep-well-in-a-heatwave</link>
                                                                            <description>
                            <![CDATA[ Don't let a heatwave ruin your sleep. We've tested 7 ways to stay cool in bed and these were our winners. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">kUfMoyyFArPaDodjGM8t3c</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/AwARxXNSYVCLqCLXtabQx9-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Tue, 23 Jun 2026 18:00:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Sleep]]></category>
                                                    <category><![CDATA[Wellness]]></category>
                                                                                                <author><![CDATA[ ruth.jones@futurenet.com (Ruth Jones) ]]></author>                    <dc:creator><![CDATA[ Ruth Jones ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/Cqbswyyro7aBYnvMKaoS6W.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ null ]]></dc:description>
                                                                                                                                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/AwARxXNSYVCLqCLXtabQx9-1280-80.jpg">
                                                            <media:credit><![CDATA[Future]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[TG Sleep Senior Writer Ruth Jones sleeps on her stomach on a comfy mattress]]></media:description>                                                            <media:text><![CDATA[TG Sleep Senior Writer Ruth Jones sleeps on her stomach on a comfy mattress]]></media:text>
                                <media:title type="plain"><![CDATA[TG Sleep Senior Writer Ruth Jones sleeps on her stomach on a comfy mattress]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/AwARxXNSYVCLqCLXtabQx9-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Temperatures are soaring, the <a href="https://www.almanac.com/summer-weather-forecast" target="_blank">Old Farmer's Almanac</a> is predicting a "hotter-than-usual" summer for much of the US, and the UK is experiencing <a href="https://www.metoffice.gov.uk/" target="_blank">record-breaking heat</a>. How are you meant to sleep with all that going on?</p><p>Here at Tom's Guide, we know a thing or two about struggling to <a href="https://www.tomsguide.com/wellness/sleep-problems/how-to-sleep-cool-in-summer-without-aircon">sleep in the heat</a>. In last year's heatwaves we were left restless, <a href="https://www.tomsguide.com/wellness/sleep/why-do-i-keep-waking-up-at-3am">awake at 3 a.m.</a> and trying every <a href="https://www.tomsguide.com/wellness/sleep/5-steps-heatwave-sleep-experts-take-to-drop-off-fast-and-avoid-sweaty-3-a-m-wake-ups">cooling sleep hack</a> that drifted across our algorithm. This year, we're putting that pain to good use by curating the sleep tips that actually work and enjoying good rest even during the hottest nights of the year.</p><p>Below are the best of the best tips for sleeping in hot weather, tried, tested and approved by our sleep team. (Including hacks you can try out tonight, no purchase necessary.) So close your curtains, fill your ice cube maker, and enjoy sweet dreams of the Arctic Circle...</p><h2 id="key-takeaways">Key takeaways</h2><ul><li><strong>Use the caveman method: </strong>close the windows and curtains during the day to keep warm air out and open them up overnight to let cool air in.</li><li><strong>Feel cozy while sleeping cool:</strong> Dress your bed in a breathable top sheet to create a feeling of security without stuffiness.</li><li><strong>Go natural:</strong> Check the labels on your bedding and pajamas, then swap out synthetic fibers for natural fabrics such as cotton and bamboo.</li><li><strong>Harness any and all breezes:</strong> Place your fans facing an open window to create a cross breeze, or freeze a bottle of salt water and place it in the path of a desk fan to supercharge the cooling.</li><li><strong>Try the inverse hot water bottle hack: </strong>Half-fill your hot water bottle with water and freeze it. Place the frozen bottle by your feet for quick and effective cooling.</li></ul><h3 class="article-body__section" id="section-how-to-keep-your-bedroom-cool-in-a-heatwave-expert-tips"><span>How to keep your bedroom cool in a heatwave: Expert tips</span></h3><h3 class="article-body__section" id="section-1-try-the-caveman-method"><span>1. Try the 'caveman method'</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:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="LBUawXiJ6WsR3F5dupLWfa" name="Caveman method for cooler sleep" alt="The image shows the back of a woman silhouetted against the bedroom curtains she is closing" src="https://cdn.mos.cms.futurecdn.net/LBUawXiJ6WsR3F5dupLWfa.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: Getty Images)</span></figcaption></figure><p>"Having spent seven swelteringly hot summers in Sydney, my number one sleep tip is to close your bedroom window, blinds and doors during the day.," says <a href="https://www.tomsguide.com/author/nicola-appleton">Nicola Appleton, Sleep Editor</a>.</p><p>This is known as the <a href="https://www.tomsguide.com/wellness/sleep/caveman-method">caveman method</a> (because caves are cold and dark — get it?) and while it might seem counterintuitive, it's one of the best ways to <a href="https://www.tomsguide.com/how-to/how-to-cool-down-a-room">cool your house during a heatwave</a>.</p><p>On a hot, still day an open window simply lets more unwelcome warmth into the house. Closing your windows and your curtains keeps any lingering coolness from the night inside the house, for you to soak up, while blocking out sweltering air.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-Xk3LJX"></div>                            </div>                            <script src="https://kwizly.com/embed/Xk3LJX.js" async></script><div class="product"><a data-dimension112="206827b6-fd22-4bce-b7f9-2305d313b857" data-action="Deal Block" data-label="Rabbitgoo Blackout Window Film: from $6.64 Amazon US" data-dimension48="Rabbitgoo Blackout Window Film: from $6.64 Amazon US" 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="7bEWPU8PBGXPHqWXFMQ8j5" name="rabbitgoo blackout film deal" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/7bEWPU8PBGXPHqWXFMQ8j5.jpg" mos="" align="middle" fullscreen="" width="1500" height="1500" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong>Rabbitgoo Blackout Window Film: </strong><a href="https://www.amazon.com/rabbitgoo-Blackout-Blocking-Removable-Darkening/dp/B0FPQ6Y2TD/?th=1" target="_blank" data-dimension112="206827b6-fd22-4bce-b7f9-2305d313b857" data-action="Deal Block" data-label="Rabbitgoo Blackout Window Film: from $6.64 Amazon US" data-dimension48="Rabbitgoo Blackout Window Film: from $6.64 Amazon US" data-dimension25="">from $6.64 Amazon US</a> | <a href="https://www.amazon.co.uk/rabbitgoo-Blackout-Privacy-Blocking-Protection/dp/B0CKMRMJYR/" target="_blank">£10.99 Amazon UK</a><br>Don't have <a href="https://www.tomsguide.com/features/blackout-curtains-5-reasons-to-buy-and-4-to-skip">blackout blinds or curtains</a>? This blackout film simply sticks to your window to block out harsh sunlight. And with no glue, it's easy to take down (and reapply when the next heatwave hits.)<a class="view-deal button" href="" target="_blank" rel="nofollow" data-dimension112="206827b6-fd22-4bce-b7f9-2305d313b857" data-action="Deal Block" data-label="Rabbitgoo Blackout Window Film: from $6.64 Amazon US" data-dimension48="Rabbitgoo Blackout Window Film: from $6.64 Amazon US" data-dimension25="">View Deal</a></p></div><h3 class="article-body__section" id="section-2-open-your-windows-and-curtains-at-night"><span>2. Open your windows and curtains at night</span></h3><p>There's an important step two to the caveman method...</p><p>"When the outside temperatures drop lower than the indoor temperatures, open the window wide and allow the cool air to flow through," says Nicola. "And not just the window in your bedroom. Open windows on the opposite side of the house to <a href="https://www.tomsguide.com/home/experts-recommend-the-wind-tunnel-method-to-keep-your-house-cool-in-a-heatwave-and-it-wont-cost-you-a-dime">create cross ventilation</a>."</p><p>"I hate any light in my room when I'm sleeping but in a heatwave, I'll fling my curtains open at night to ensure lots of cool air can flow through," says <a href="https://www.tomsguide.com/author/ruth-jones">Ruth Jones, Senior Sleep Writer</a>. "I use an eye mask made of breathable materials to block out most of the light, so I get a comfortable balance of cool and dark."</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="2Pt9XMeXKy88tgHvTGEke7" name="woman closes the curtains in her bedroom GettyImages-1084105542" alt="A woman stands in front of a window in her bedroom during time, with her hands on the curtains preparing to pull them closed" src="https://cdn.mos.cms.futurecdn.net/2Pt9XMeXKy88tgHvTGEke7.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: Getty Images)</span></figcaption></figure><p><strong>Use your dual sash windows (if you have them)</strong><br>“I used to live in a beautiful Victorian apartment with no AC but I did have dual-sash windows, and they were excellent for keeping my bedroom cool in summer," adds <a href="https://www.tomsguide.com/author/claire-davies">Claire Davies, Managing Editor of Sleep and Certified Sleep Science Coach</a>.</p><p>“With these, you can open the window equally at the top and the bottom. Rising hot air gets sucked out the top of the window, and crisp, cooler air comes in the bottom, creating a natural convection current.”</p><h3 class="article-body__section" id="section-3-the-inverse-hot-water-bottle-rapid-cooling-hack"><span>3. The inverse hot water bottle rapid cooling hack</span></h3><p>“I have a major issue with people putting their <a href="https://www.tomsguide.com/wellness/sleep/frozen-bed-sheets-and-cold-spoons-weird-tips-for-how-to-sleep-cool-during-a-heatwave">bed sheets in the freezer</a> – mold on my mattress is just not worth it, thanks. But I do like the <a href="https://www.tomsguide.com/wellness/sleep/hot-water-bottle-cooling-sleep-hack">frozen hot water bottle trick</a> when done correctly," says Claire.</p><p>“Here you fill a rubber hot water bottle with cold water to around halfway (if you fill it completely, the ice will expand and burst the hot water bottle), then lay it flat in the freezer for a few hours."</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="5tQVopfbEAR3YqvcRRQjZj" name="Filling a hot water bottle with cold water" alt="A close up of a hand holding the lip of a hot water bottle under a faucet as the water bottle is filled with cold water" src="https://cdn.mos.cms.futurecdn.net/5tQVopfbEAR3YqvcRRQjZj.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: Future)</span></figcaption></figure><p>“Before heading up to bed, put the cold water bottle in a towel," she advises. "Place another thick towel at the foot of your mattress, where your feet will lie. Slide the bottle into its cover (or a thin pillowcase) just before you get into bed, then rest your feet on it once you’re in bed.</p><p>“This cools the blood in the vessels in your feet, <a href="https://pubmed.ncbi.nlm.nih.gov/7661832/" target="_blank">helping to lower your body temperature</a> so that you can fall asleep faster during the heatwave," she explains. For another way to cool your feet quickly, try keeping your socks in the freezer (put them in a bag first, to keep them away from your food.)</p><p>Freezing a hot water bottle can weaken the materials so avoid using it for hot water at a later date.</p><div class="product"><a data-dimension112="d165e9cf-c055-47d4-ba2a-702f867f24ca" data-action="Deal Block" data-label="From $8.49 Amazon US" data-dimension48="From $8.49 Amazon US" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1550px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="kvufXvkpPiMaNfdCYuJHjh" name="samply hot water bottle" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/kvufXvkpPiMaNfdCYuJHjh.jpg" mos="" align="middle" fullscreen="" width="1550" height="1550" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong>Samply Hot Water Bottle:</strong> <a href="https://www.amazon.com/Samply-Bottle-Knitted-Transparent-Purple/dp/B08JCNZX25?th=1" target="_blank" data-dimension112="d165e9cf-c055-47d4-ba2a-702f867f24ca" data-action="Deal Block" data-label="From $8.49 Amazon US" data-dimension48="From $8.49 Amazon US" data-dimension25="">From $8.49 Amazon US</a> | <a href="https://www.amazon.co.uk/Samply-Transparents-Water-Bottle-Knited/dp/B07ZLQVYWC/" target="_blank">£7.26 Amazon UK</a><br>Hot water bottles can be bought for cheap online and from big-box retailers. If you can pick up a two-pack, even better: one for the summer months and one to stash away until winter.<a class="view-deal button" href="" target="_blank" rel="nofollow" data-dimension112="d165e9cf-c055-47d4-ba2a-702f867f24ca" data-action="Deal Block" data-label="From $8.49 Amazon US" data-dimension48="From $8.49 Amazon US" data-dimension25="">View Deal</a></p></div><h3 class="article-body__section" id="section-4-turn-your-fan-toward-the-window"><span>4. Turn your fan toward the window</span></h3><p><a href="https://www.tomsguide.com/home/3-ways-to-create-a-diy-cool-room-for-instant-relief-no-ac-required">No AC</a>? A fan is the next best solution to quickly cool a room. But don't just point your fan at the bed. We've tried a better solution: <a href="https://www.tomsguide.com/home/this-cooling-fan-hack-has-gone-viral-and-its-not-as-strange-as-you-think">direct your fan toward an open window</a>. This pushes the hot air from your room out while helping cold air be drawn in. </p><p>For the most effective set up, try the two fan method. Open two windows: one in your bedroom and one on the opposite side of the house. Place one fan facing out towards an open window, and the other fan facing in towards the room by the second window. Turn both fans on to create cross ventilation and a consistent cooling breeze.</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="485nxtq9KpSfJVdGL6wL9P" name="Fan step 1.jpg" alt="Cooling fan cross breeze" src="https://cdn.mos.cms.futurecdn.net/485nxtq9KpSfJVdGL6wL9P.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><strong>OR direct your fan at the wall or ceiling</strong><br>If you don't have the windows (or fans) to make the above method work, try Frances's trick and <a href="https://www.tomsguide.com/wellness/sleep/waking-up-with-zero-energy-this-summer-youre-probably-making-this-common-sleep-mistake-heres-how-to-fix-it">turn your fan toward the ceiling or wall</a>.</p><p>While having the fan facing your bed will give you the quickest stream of cool air, it also directs a blast of dust and other allergens directly at your face. This can lead to itchy eyes and sneezing. </p><p>By allowing the air to move around the room, you won't get the same concentration of allergens, for cooler sleep without the coughing.</p><div class="product"><a data-dimension112="834bf0de-3500-4a04-8985-441ee1550f77" data-action="Deal Block" data-label="From $199 Amazon US" data-dimension48="From $199 Amazon US" data-dimension25="$" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:448px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="hUDB5w7g84sqnBQBr9ehK8" name="Shark FlexBreeze fan" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/hUDB5w7g84sqnBQBr9ehK8.jpg" mos="" align="middle" fullscreen="" width="448" height="448" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong>Shark FlexBreeze Fan:</strong> <a href="https://www.amazon.com/Shark-FlexBreeze-Oscillating-Attachment-FA222/dp/B0CSDS34CQ" target="_blank" data-dimension112="834bf0de-3500-4a04-8985-441ee1550f77" data-action="Deal Block" data-label="From $199 Amazon US" data-dimension48="From $199 Amazon US" data-dimension25="$">From $199 Amazon US</a> | <a href="https://www.amazon.co.uk/Shark-FlexBreeze-High-Velocity-Water-Resistant-FA220UK/dp/B0CSSZ5SJF/" target="_blank">£199 Amazon UK</a><br>With an adjustable base, corded and cordless functionality, plus a remote control the FlexBreeze Fan from Shark can adapt to almost any room. Frances bought this fan in last year's heatwaves when she couldn't cope with the warmth any longer and it's now her go-to on hot nights (and days.)<a class="view-deal button" href="" target="_blank" rel="nofollow" data-dimension112="834bf0de-3500-4a04-8985-441ee1550f77" data-action="Deal Block" data-label="From $199 Amazon US" data-dimension48="From $199 Amazon US" data-dimension25="$">View Deal</a></p></div><h3 class="article-body__section" id="section-5-small-fan-try-the-ice-water-bottle-trick"><span>5. Small fan? Try the ice water bottle trick</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:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="XQuhbxM6M2f76dkyM48Xjd" name="Mini cooling fan" alt="A small green mini fan balanced in an upright position on a white bedside table" src="https://cdn.mos.cms.futurecdn.net/XQuhbxM6M2f76dkyM48Xjd.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: Future)</span></figcaption></figure><p>“One my mum taught me: freeze a few small bottles of water, and put a generous helping of salt inside each one before sealing them. Once the bottles are fully frozen, wrap them in a damp, thin cloth and stand them in front of your fan," says Claire.</p><p>“<a href="https://sciencenotes.org/why-salt-makes-ice-colder-how-cold-ice-gets/" target="_blank">Salt lowers the freezing point of water</a>, so these bottles will get significantly colder than ice cubes – and they will stay frozen for longer," she adds. "So you’ll feel the benefit of them for hours instead of minutes."</p><p>"I only have a small fan so unless it's point directly at my face, it can't keep me cool in the night," says Ruth. "Placing frozen bottles, or even a handful of ice cubes in a bowl, in front of it really ramps up the cooling power. </p><p>Why the damp cloth? "It catches condensation so you don't end up with a puddle on your nightstand come morning," explains Claire.</p><div class="product"><a data-dimension112="291e4074-9935-4eff-b2ac-8137f884c810" data-action="Deal Block" data-label="From $22.55 Amazon US" data-dimension48="From $22.55 Amazon US" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1390px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="ASqjXvtfC54envkzfLZq6G" name="Jisulife fan life7" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/ASqjXvtfC54envkzfLZq6G.jpg" mos="" align="middle" fullscreen="" width="1390" height="1390" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong>Jisulife Handheld Fan Life7:</strong> <a href="https://www.amazon.com/JISULIFE-Handheld-Powerful-150%C2%B0Folded-Essentials/dp/B0CRDT715R/" target="_blank" data-dimension112="291e4074-9935-4eff-b2ac-8137f884c810" data-action="Deal Block" data-label="From $22.55 Amazon US" data-dimension48="From $22.55 Amazon US" data-dimension25="">From $22.55 Amazon US</a> | <a href="https://www.amazon.co.uk/JISULIFE-Handheld-Powerful-150%C2%B0Folded-Essentials/dp/B0CRDT715R/" target="_blank">£23.19 Amazon UK</a><br>Handheld and desk fans might lack the power of their larger brethren but they're typically cheaper, highly portable and can deliver reliably cool comfort.<a class="view-deal button" href="" target="_blank" rel="nofollow" data-dimension112="291e4074-9935-4eff-b2ac-8137f884c810" data-action="Deal Block" data-label="From $22.55 Amazon US" data-dimension48="From $22.55 Amazon US" data-dimension25="">View Deal</a></p></div><h3 class="article-body__section" id="section-6-ditch-heavy-bedding-and-sleep-under-a-breathable-top-sheet"><span>6. Ditch heavy bedding and sleep under a breathable top sheet</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:1536px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="LXQbFNhYXEuGMacbozzFg3" name="Quince Bed Sheets" alt="A woman stands by the side of a mattress in our sleep studio as she arranges a set of Quince Sheets on the bed" src="https://cdn.mos.cms.futurecdn.net/LXQbFNhYXEuGMacbozzFg3.jpg" mos="" align="middle" fullscreen="" width="1536" height="864" 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>"Another tip I swear by is ditching the duvet and comforter in favor of a cooling and <a href="https://www.tomsguide.com/mattresses/pillows-bedding/flat-sheet-summer-sleep">breathable flat sheet</a>, like the DOZ Bamboo Flat Sheet," says Nicola. </p><p>"I don't really feel safe at night unless I have something covering me but a cooling sheet feels feather-light against my skin, allowing me to drop off quickly," she explains.</p><div class="product"><a data-dimension112="29f24fb5-edc0-4bf0-8f89-6c8216bd8983" data-action="Deal Block" data-label="From $21.25 Amazon US" data-dimension48="From $21.25 Amazon US" 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="KrcMsvnsCrfkXZ6fcJLGsP" name="doz bamboo flat sheet" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/KrcMsvnsCrfkXZ6fcJLGsP.jpg" mos="" align="middle" fullscreen="" width="1500" height="1500" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong>DOZ Bamboo Flat Sheet:</strong> <a href="https://www.amazon.com/DOZ-Viscose-derived-Organically-Buttery/dp/B0C5NYD6BS/" target="_blank" data-dimension112="29f24fb5-edc0-4bf0-8f89-6c8216bd8983" data-action="Deal Block" data-label="From $21.25 Amazon US" data-dimension48="From $21.25 Amazon US" data-dimension25="">From $21.25 Amazon US</a> | <a href="https://www.amazon.co.uk/DOZ-SIJO-Bamboo-Sleepers-Breathable/dp/B0C5NT5K3T/" target="_blank">£42.54 Amazon UK</a><br>Wrapping yourself in a breathable flat sheet gives you the security of coverage without the clammy, sweaty heat build-up of heavier bedding. For the best air circulation and a cooler feel, consider natural materials such as cotton and bamboo (we'll explain why below.)<a class="view-deal button" href="" target="_blank" rel="nofollow" data-dimension112="29f24fb5-edc0-4bf0-8f89-6c8216bd8983" data-action="Deal Block" data-label="From $21.25 Amazon US" data-dimension48="From $21.25 Amazon US" data-dimension25="">View Deal</a></p></div><h3 class="article-body__section" id="section-7-upgrade-your-bedding-to-natural-materials"><span>7. Upgrade your bedding to natural materials</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:7712px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="FFf6QpxHumCt8VCjM2EMZV" name="Cozy Earth bamboo sheet set" alt="Cozy Earth bamboo sheet set, a close-up look of the OEKO certification" src="https://cdn.mos.cms.futurecdn.net/FFf6QpxHumCt8VCjM2EMZV.jpg" mos="" align="middle" fullscreen="" width="7712" height="4337" 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>"Check the material composition of your bedding, including bed sheets, pillowcases, mattress protectors, and eye masks," advises <a href="https://www.tomsguide.com/author/frances-daniels">Frances Daniels, Senior Sleep Writer</a>. "I used to use satin pillowcases and eye masks, plus polyester bed sheets and pjs, during heatwaves until I realized they were causing me to feel uncomfortably warm." </p><p>While you might be tempted to <a href="https://www.tomsguide.com/wellness/sleep/dont-sleep-naked-7-top-tips-for-sleeping-better-in-a-heatwave">ditch the pajamas altogether</a>, the fabric helps sweat dissipate so you cool down faster. When you're naked, sweat instead sits on the skin causing that uncomfortably clammy sensation.</p><p>"I now use natural materials like cotton, silk, linen, and bamboo-viscose," says Frances. "These have built-in breathability, allowing hot air to circulate and cool."</p><p>And this doesn't have to mean an expensive shopping trip: check the labels on the sheet sets and pajamas forgotten in the back of your cupboard.</p><div class="product"><a data-dimension112="d3d2be72-e4ed-4dea-9edb-e3b25e1d4636" data-action="Deal Block" data-label="From $86.40 Cozy Earth US" data-dimension48="From $86.40 Cozy Earth US" 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="iXdcQjMjbXuYtur9iD5Mzd" name="Cozy Earth Bamboo pajamas man" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/iXdcQjMjbXuYtur9iD5Mzd.jpg" mos="" align="middle" fullscreen="" width="1500" height="1500" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong>Cozy Earth Bamboo Stretch-Knit Lounge Set:</strong> <a href="https://cozyearth.com/products/mens-bamboo-stretch-knit-short-sleeve-pajama-set?variant=43730516246708" target="_blank" data-dimension112="d3d2be72-e4ed-4dea-9edb-e3b25e1d4636" data-action="Deal Block" data-label="From $86.40 Cozy Earth US" data-dimension48="From $86.40 Cozy Earth US" data-dimension25="">From $86.40 Cozy Earth US</a> | <a href="https://cozyearth.com/products/mens-bamboo-stretch-knit-short-sleeve-pajama-set?variant=43730516246708" target="_blank">£94.40 Cozy Earth UK</a><br>Bamboo is a naturally derived material that wicks away sweat for faster cooling. Sleep writer Ruth is currently testing a set of Cozy Earth pajamas: "I love how light they are against the skin, so even in a top and long pants I stay cool during the night." This Cozy Earth set is available in men's and women's styles.<a class="view-deal button" href="" target="_blank" rel="nofollow" data-dimension112="d3d2be72-e4ed-4dea-9edb-e3b25e1d4636" data-action="Deal Block" data-label="From $86.40 Cozy Earth US" data-dimension48="From $86.40 Cozy Earth US" data-dimension25="">View Deal</a></p></div><h3 class="article-body__section" id="section-why-is-it-so-hard-to-sleep-in-a-heatwave"><span>Why is it so hard to sleep in a heatwave?</span></h3><p>You're sweaty, you're frustrated, and your pillow feels like it's fresh out of the oven — no wonder it's so hard to sleep in a heatwave.</p><p>But hot weather impacts your sleep beyond discomfort. It's also a fly in the ointment of the internal processes that control our sleep-wake cycle.</p><p>In the evening, your body naturally starts to lower in temperature by roughly 2°F / 1°C. This mimics the natural temperature drop between day and night while indicating to your <a href="https://www.tomsguide.com/wellness/sleep/circadian-rhythm">circadian rhythm</a> (your internal body clock) that it's time to sleep.</p><p>During a heatwave, however, your body can't successfully lose that heat. An increased ambient temperature keeps you warm and disrupts your body clock's wind-down process.</p><p>High overnight temperatures have also shown a decrease in <a href="https://pubmed.ncbi.nlm.nih.gov/10341381/" target="_blank">sleep efficiency</a>. In other words, when you do fall asleep, you're more likely to <a href="https://www.tomsguide.com/wellness/sleep/waking-up-in-the-middle-of-the-night">wake up in the night</a>.</p>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ Stay private while streaming Scotland vs Brazil – use our top streaming VPN which has a 60-day money-back guarantee ]]></title>
                                                                                                                                                                                                <link>https://www.tomsguide.com/computing/vpns/stay-private-while-streaming-england-vs-ghana-use-our-top-streaming-vpn-which-has-a-60-day-money-back-guarantee</link>
                                                                            <description>
                            <![CDATA[ If you're out and about or abroad and trying to stream, a VPN is the perfect companion. It hides your IP, and stops any dodgy sites recording your IP address. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">d5a7TT39CVKoybUvgvFh4R</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/iwVtzsLdhsxtR5TqhDPrzL-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Tue, 23 Jun 2026 17:30:00 +0000</pubDate>                                                                                                                                <updated>Wed, 24 Jun 2026 15:22:23 +0000</updated>
                                                                                                                                            <category><![CDATA[VPNs]]></category>
                                                    <category><![CDATA[Streaming]]></category>
                                                    <category><![CDATA[Computing Peripherals]]></category>
                                                    <category><![CDATA[Internet]]></category>
                                                    <category><![CDATA[Entertainment]]></category>
                                                                                                                    <dc:creator><![CDATA[ Aleksandar Stevanović ]]></dc:creator>                                                                                                        <dc:description><![CDATA[ null ]]></dc:description>
                                                                                                                                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/iwVtzsLdhsxtR5TqhDPrzL-1280-80.jpg">
                                                            <media:credit><![CDATA[Getty Images / Visionhaus]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Ryan Christie of Scotland receives the ball in the FIFA World Cup 2026]]></media:description>                                                            <media:text><![CDATA[Ryan Christie of Scotland receives the ball in the FIFA World Cup 2026]]></media:text>
                                <media:title type="plain"><![CDATA[Ryan Christie of Scotland receives the ball in the FIFA World Cup 2026]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/iwVtzsLdhsxtR5TqhDPrzL-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Scotland vs Brazil is one of the most anticipated matches of the FIFA World Cup 2026's group stage – and whether you're watching from a bar, a hotel, or any other network that isn't your own, your connection may be more exposed than you think. Plus, if you accidentally end up on websites that aren't trustworthy, exposing your IP address to them can spell danger.</p><p>Using one of the <a href="https://www.tomsguide.com/best-picks/best-vpn">best VPNs</a> closes that window by encrypting your traffic and masking your IP address, so nobody on the same network can see what you're doing. It also means your ISP can't monitor your streaming habits, and websites can't see your real IP – useful if you'd rather keep your viewing activity to yourself.</p><p>We currently rate Norton VPN as the <a href="https://www.tomsguide.com/best-picks/streaming-vpn">best VPN for streaming</a>, and there's a sensational deal running right now that makes it an easy choice for World Cup coverage.</p><div class="product"><a data-dimension112="b3548274-ac8f-4465-8770-518b393dfed5" data-action="Deal Block" data-label="Norton VPN | 60-day money-back guarantee" data-dimension48="Norton VPN | 60-day money-back guarantee" data-dimension25="$" href="https://norton.ow5a.net/c/221109/3913583/4405?sharedid=tg&param1=aff&param2=worldcup26_dealpost&param3=vpn&subid1=Deal_TG" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:280px;"><p class="vanilla-image-block" style="padding-top:56.43%;"><img id="cgidcx9LYVJedVXABk3BpC" name="nortonvpn_graphic_-_affiliates__5_" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/cgidcx9LYVJedVXABk3BpC.png" mos="" align="middle" fullscreen="" width="280" height="158" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><a href="https://norton.ow5a.net/c/221109/3913583/4405?sharedid=tg&param1=aff&param2=worldcup26_dealpost&param3=vpn&subid1=Deal_TG" target="_blank" rel="nofollow" data-dimension112="b3548274-ac8f-4465-8770-518b393dfed5" data-action="Deal Block" data-label="Norton VPN | 60-day money-back guarantee" data-dimension48="Norton VPN | 60-day money-back guarantee" data-dimension25="$"><strong>Norton VPN | 60-day money-back guarantee</strong></a><br>Norton VPN is our top pick for World Cup 2026 streaming, with a 60-day money-back guarantee on annual plans – double the industry standard – covering the entire tournament risk-free.</p><p><strong>What you'll get...</strong></p><p>🔒 Native app for Amazon Fire TV devices<br>⚡️ WireGuard protocol across all Apple platforms<br>📺 Apps for Google TV, Android TV, and Apple TV<br>🌍 Servers in 30+ countries for home-country streaming</p><p>A 12-month Norton VPN plan starts at <a href="https://norton.ow5a.net/c/221109/3913583/4405?sharedid=tg&param1=aff&param2=worldcup26_dealpost&param3=vpn&subid1=Deal_TG" target="_blank" rel="nofollow"><strong>$3.33 per month</strong></a> ($39.99 upfront, pre-tax) and comes with a 60-day money-back guarantee on annual plans.<a class="view-deal button" href="https://norton.ow5a.net/c/221109/3913583/4405?sharedid=tg&param1=aff&param2=worldcup26_dealpost&param3=vpn&subid1=Deal_TG" target="_blank" rel="nofollow" data-dimension112="b3548274-ac8f-4465-8770-518b393dfed5" data-action="Deal Block" data-label="Norton VPN | 60-day money-back guarantee" data-dimension48="Norton VPN | 60-day money-back guarantee" data-dimension25="$">View Deal</a></p></div><h2 id="how-does-norton-vpn-compare-to-other-top-vpns-2">How does Norton VPN compare to other top VPNs?</h2><p><a href="https://www.tomsguide.com/reviews/nordvpn-review">NordVPN</a> continues to outperform Norton VPN in our overall VPN rankings, and its testing record backs that up: speeds of over 1,249 Mbps locally, a server network spanning more than 8,000 servers across 135 countries, and a near-flawless streaming unblocking record. In comparison, Norton VPN only offers servers in 65+ countries – meaning potentially less choice when it comes to streaming services.</p><p>The catch is price – even on the discounted two-year plan, NordVPN works out at around <a href="http://go.nordvpn.net/aff_c?offer_id=564&aff_id=3013&url_id=10992" target="_blank" rel="nofollow"><strong>$3.49 per month</strong></a>, which is a little more than Norton. What's more, it only comes with a 30-day money-back guarantee. Norton also has the edge when it comes to raw streaming performance, unblocking every major streaming platform in our latest round of testing, despite its smaller network.</p><p><a href="https://www.tomsguide.com/reviews/surfshark-vpn-review">Surfshark</a> is a budget alternative, with plans starting at a very reasonable <a href="http://get.surfshark.net/aff_c?offer_id=61&aff_id=1691" target="_blank" rel="nofollow"><strong>$1.99 per month</strong></a> and the bonus of unlimited device connections. This is a contrast to Norton VPN, which has strict limits on how many devices you can install the VPN on. Surfshark's a capable all-rounder, too, and one of the <a href="https://www.tomsguide.com/best-picks/best-fast-vpn">fastest VPNs</a> we've tested. However, its streaming unblocking has been less consistent than Norton's in our reviews, occasionally struggling with certain Netflix regions.</p><p>If your main priority is keeping your streaming activity private without interruption, Norton VPN is the clear choice. What's more, that performance currently comes with competitive pricing against NordVPN and a 60-day guarantee which is double what most competitors offer, giving you the entire tournament to decide if it's right for you.</p><p>NordVPN and Surfshark remain solid options for general use once the World Cup wraps up, but for streaming this tournament privately and securely, Norton's combination of unblocking power and excellent pricing is hard to beat.</p><p>We test and review VPN services in the context of legal recreational uses. For example:<strong>1.</strong> Accessing a service from another country (subject to the terms and conditions of that service).<strong>2.</strong> Protecting your online security and strengthening your online privacy when abroad.We do not support or condone the illegal or malicious use of VPN services. Consuming pirated content that is paid-for is neither endorsed nor approved by Future Publishing.</p>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ This new Chinese AI Is outperforming ChatGPT — and it runs locally ]]></title>
                                                                                                                                                                                                <link>https://www.tomsguide.com/ai/this-new-chinese-ai-is-outperforming-chatgpt-and-it-runs-locally</link>
                                                                            <description>
                            <![CDATA[ China’s new GLM 5.2 model is convincing developers to ditch expensive AI subscriptions for a powerful, free alternative. Here’s why it’s a threat. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">9jJR2R6yXmmYwfHEtouf9E</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/YsxBpeimxPkqswGNmFFkjc-1280-80.png" type="image/png" length="0"></enclosure>
                                                                        <pubDate>Tue, 23 Jun 2026 09:00:00 +0000</pubDate>                                                                                                                                <updated>Tue, 23 Jun 2026 21:10:45 +0000</updated>
                                                                                                                                            <category><![CDATA[AI]]></category>
                                                                                                <author><![CDATA[ amanda.caswell@futurenet.com (Amanda Caswell) ]]></author>                    <dc:creator><![CDATA[ Amanda Caswell ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/zYjevim2q7FjQiefqpjZRB.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ null ]]></dc:description>
                                                                                                                                                                                                                                                <media:content type="image/png" url="https://cdn.mos.cms.futurecdn.net/YsxBpeimxPkqswGNmFFkjc-1280-80.png">
                                                            <media:credit><![CDATA[Future]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[quitgpt]]></media:description>                                                            <media:text><![CDATA[quitgpt]]></media:text>
                                <media:title type="plain"><![CDATA[quitgpt]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/YsxBpeimxPkqswGNmFFkjc-1280-80.png" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Developers are flocking to a new open weight AI model that can be downloaded, customized and run entirely on local hardware.  <strong>Released by Z.ai (formerly Zhipu AI), GLM 5.2</strong> is turning heads by challenging a major industry assumption: that you always have to pay <a href="https://www.tomsguide.com/ai/i-was-paying-for-too-many-ai-tools-here-are-the-4-i-kept-and-3-i-cancelled">premium subscription prices</a> to a tech giant to get frontier-level performance.  </p><p>Unlike completely closed systems like ChatGPT or Claude, GLM 5.2 gives developers direct access to the model itself. This is important in an industry increasingly dominated by gated, corporate servers because it gives users much more control. </p><h2 id="the-ai-industry-is-splitting-into-two-worlds">The AI industry is splitting into two worlds</h2><p>Simply put, Open Weights = You get the model's brain. Open Source = You get everything (Model weights, training code, data processing pipeline, evaluation framework and often the training dataset). For years, open-source and open-weight AI models lived in the shadow of proprietary giants. They were highly flexible and much cheaper, but they invariably lagged behind the raw capabilities of OpenAI and Google.</p><p>Now, that gap is shrinking fast. With powerful models like Meta’s Llama family, Mistral, and now GLM 5.2, enterprises are highlighting that we may not need the most expensive AI model for every single task. Many businesses don't need a model that can solve world-class theoretical logic; they just need a system that can accurately summarize massive internal document libraries, autonomously write and debug code.  </p><p>If an open model can complete 90% to 95% of those jobs at a fraction of the cost, then this type of model is impossible to ignore. </p><h2 id="why-local-ai-is-a-game-changer">Why Local AI is a game-changer</h2><p>The buzz surrounding GLM 5.2 spiked when developers successfully demonstrated the model running locally on high-end <a href="https://www.tomsguide.com/reviews/mac-mini-m1">Apple hardware like the mac mini. </a></p><p>While the average person isn't buying multiple Mac Studios for their living room, the demonstration proved that capable AI can now be owned rather than "rented" with a subscription. </p><p>When you rely on a subscription, a third party controls the pricing, privacy policies and feature roadmap. Open-weight models flip the script. For industries handling sensitive financial data, medical records, or proprietary corporate research, keeping data completely in-house on private hardware is a massive security win.  </p><p>Instead of relying on a single, expensive subscription, the future of business tech will likely look like a "mix-and-match" AI stack:</p><ul><li><strong>A flagship closed model</strong> handles the absolute toughest reasoning problems.</li><li><strong>An open-weight model</strong> powers high-volume, routine workflows.</li><li><strong>A locally hosted model</strong> safely manages top-secret internal data.</li></ul><h2 id="the-brutal-reality-check-of-local-ai">The brutal reality check of local AI</h2><p>If running a frontier-level AI on your own desk sounds like a dream, the physical requirements are where reality hits hard. GLM 5.2 is a massive <strong>744-billion to 753-billion parameter Mixture-of-Experts (MoE)</strong> model. In its uncompressed form, its weights consume a staggering <strong>1.51 terabytes</strong> of storage and memory.  <br><br>For perspective: </p><ul><li>Standard High-End PC > Maxes out at 24GB VRAM > Hits a "VRAM Wall"</li><li>Maxed Mac Studio > 256GB Unified Memory  > Can run heavily compressed versions</li></ul><p>To run GLM 5.2 locally, developers must aggressively compress it using a technique called quantization. Yet, even when heavily compressed, it requires roughly 240GB of memory just to load.  </p><p>Furthermore, GLM 5.2 boasts a massive <a href="https://www.tomsguide.com/ai/claude-just-upgraded-its-ai-and-it-can-now-process-entire-projects-at-once"><strong>1-million-token context window like Claude</strong></a>, meaning it can digest entire codebases or small libraries of books in one go. However, tracking that much data requires its own dedicated memory allocation. Push the model to its limits, and even the most powerful consumer desktop will start to sweat.  </p><h2 id="the-takeaway-for-everyday-users">The takeaway for everyday users </h2><p>If you aren't a programmer, this news remains relevant to the way AI fundamentally changes the software we use every day. While GLM 5.2 isn't going to replace the apps on your phone tomorrow, it does highlight that open models are becoming cheaper and fiercely competitive. </p><p>As software companies gain options and no longer have to pay massive fees to a single provider to add AI features to their apps, this shift could mean the next generation of digital tools will likely be cheaper, highly specialized and significantly more private.</p><a href="https://follow.it/articles-by-amanda-caswell-tom-s-guide?leanpub" class="button button--large button--primary">Follow Amanda Caswell and stay ahead of the AI curve</a><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/ai/anthropic-will-pay-workers-usd85-000-to-learn-ai-and-it-reveals-the-next-big-ai-job-trend">Anthropic will pay workers $85,000 to learn AI — and it reveals the next big AI job trend</a></li><li><a href="https://www.tomsguide.com/ai/i-asked-gemini-what-was-slowing-down-my-windows-pc-heres-what-it-found">I asked Gemini what was slowing down my Windows PC — here’s what it found</a></li><li><a href="https://www.tomsguide.com/ai/anthropics-fable-five-ban-exposed-ais-next-big-problem-but-sakanas-fugu-may-have-the-answer">Anthropic's Fable 5 ban exposed AI's next big problem — but Sakana's Fugu may have the answer</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ This Garmin app is helping me avoid sunburn during the heatwave, and it’s completely free ]]></title>
                                                                                                                                                                                                <link>https://www.tomsguide.com/wellness/smartwatches/this-smart-garmin-app-is-helping-me-avoid-sunburn-during-the-heatwave-and-its-completely-free</link>
                                                                            <description>
                            <![CDATA[ The SunAlert Connect IQ app can help you avoid spending too long in the sun by using the UV index from your Garmin’s weather forecast. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">LiajZVhFTektoEGDa3F52P</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/hEKJeoVj7csDraxZzVtnQe-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Tue, 23 Jun 2026 08:00:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Smartwatches]]></category>
                                                    <category><![CDATA[Wellness]]></category>
                                                                                                                    <dc:creator><![CDATA[ Nick Harris-Fry ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/J5Jjp49GUVjLZEbjEkTex.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Nick has been a journalist since 2012 and has spent most of that time writing about health and fitness for a variety of publications. Nick spent nine years working on the Coach magazine and website before moving to the fitness team at Tom’s Guide in 2024. Nick is a keen runner and also the founder of YouTube channel &lt;a href=&quot;https://www.youtube.com/channel/UCOBM9FasII4dKbyE_HKkbjw&quot;&gt;The Run Testers&lt;/a&gt;, which specialises in reviewing running shoes, watches, headphones and other gear.&lt;/p&gt;&lt;p&gt;Nick has covered all aspects of health and fitness throughout his career, interviewing experts and celebrities, trying fitness classes and running marathons, all in the name of providing readers with the information they need to get the most out of an active lifestyle.&lt;/p&gt;&lt;p&gt;Nick ran his first marathon in 2016 after six weeks of training for a magazine feature and subsequently became obsessed with the sport. He now has PBs of 2hr 25min for the marathon and 15min 30sec for 5K, and has run 16 marathons in total, as well as a 50-mile ultramarathon.&lt;/p&gt;&lt;p&gt;Nick runs 60-90 miles a week and races regularly with his club, which gives him a lot of opportunity to test out running gear: he has tested and reviewed hundreds of pairs of running shoes, as well as fitness trackers, running watches, sports headphones, treadmills, and all manner of other kit. Nick is also a qualified Run Leader in the UK.&lt;/p&gt;&lt;p&gt;Nick is an established expert in the health and fitness area and along with writing for several publications, including &lt;a href=&quot;https://www.livescience.com/author/nick-harris-fry&quot;&gt;Live Science&lt;/a&gt;, &lt;a href=&quot;https://www.expertreviews.co.uk/authors/nick-harris-fry&quot;&gt;Expert Reviews&lt;/a&gt;, &lt;a href=&quot;https://www.wareable.com/author/n.harris-fry&quot;&gt;Wareable&lt;/a&gt;, &lt;a href=&quot;https://www.coachweb.com/author/nick-harris-fry&quot;&gt;Coach&lt;/a&gt; and &lt;a href=&quot;https://www.getsweatgo.com/author/n.harrisfry&quot;&gt;Get Sweat Go&lt;/a&gt;, he has been quoted on &lt;a href=&quot;https://www.theguardian.com/thefilter/2024/oct/20/if-you-pay-more-than-4-youre-being-ripped-off-the-fair-price-for-14-everyday-items-from-cleaning-spray-to-olive-oil&quot;&gt;The Guardian&lt;/a&gt; and &lt;a href=&quot;https://www.independent.co.uk/life-style/health-and-families/london-marathon-2021-date-training-tips-summer-running-a9482486.html&quot;&gt;The Independent&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Nick graduated from the University of York in 2010 with a degree in Politics, Philosophy and Economics and worked in the NHS for three years, during which time he completed his NCTJ Diploma in Journalism at News Associates in London. Before starting on Coach and moving into health and fitness, Nick worked as a football journalist and lived in Kathmandu, Nepal for two years.&lt;/p&gt; ]]></dc:description>
                                                                                                                                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/hEKJeoVj7csDraxZzVtnQe-1280-80.jpg">
                                                            <media:credit><![CDATA[Future]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[SunAlert app on Garmin Forerunner 970]]></media:description>                                                            <media:text><![CDATA[SunAlert app on Garmin Forerunner 970]]></media:text>
                                <media:title type="plain"><![CDATA[SunAlert app on Garmin Forerunner 970]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/hEKJeoVj7csDraxZzVtnQe-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>As someone who lives in the UK, it’s true to say I don’t often have to worry that much about sunburn, at least when I’m not on holiday.</p><p>However, heatwaves do occur — the UK is currently melting thanks to 100+℉ temperatures, and as a keen runner I spend a lot of time outdoors all year round, so I do keep an eye out for risky conditions.</p><p>Recently I came across the free ConnectIQ <a href="https://apps.garmin.com/apps/33a60aac-8f33-4ca5-9e94-7fd0a61cac0d?tid=1" target="_blank" rel="nofollow">SunAlert app,</a> which gives very precise advice about your risk of sunburn at any time, based on the current UV index, the activity you have planned and the strength of sunscreen you’re using.</p><p>I downloaded it to my <a href="https://www.tomsguide.com/wellness/smartwatches/ive-been-wearing-the-garmin-forerunner-970-for-six-months-here-are-my-long-term-pros-and-cons">Garmin Forerunner 970</a> to use during the UK heatwave, and the SunAlert app is available on almost all of the <a href="https://www.tomsguide.com/best-picks/best-garmin-watch">best Garmin watches</a>.</p><h2 id="helpful-advice-based-on-conditions-and-your-skin-type">Helpful advice based on conditions and your skin type</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:4127px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="YXTNyxJnvLvT2a754ZXrDe" name="SunAlert app on Garmin Forerunner 970" alt="SunAlert app on Garmin Forerunner 970" src="https://cdn.mos.cms.futurecdn.net/YXTNyxJnvLvT2a754ZXrDe.jpg" mos="" align="middle" fullscreen="" width="4127" height="2321" 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 app is naturally only to be used for advice — it’s not definitive guidance and doesn't claim to be — but it does give a set amount of time you can spend in the sun before you risk burning.</p><p>This advice is based on the UV index, as reported by the weather forecast on your Garmin watch, as well as the skin type you have set in the SunAlert app, which is based on the six Fitzpatrick skin types.</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:4111px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="Mi5fiaGNPmNVqXvYfXaBAe" name="SunAlert app on Garmin Forerunner 970" alt="SunAlert app on Garmin Forerunner 970" src="https://cdn.mos.cms.futurecdn.net/Mi5fiaGNPmNVqXvYfXaBAe.jpg" mos="" align="middle" fullscreen="" width="4111" height="2313" 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 app shows how long it will take before you burn, along with an estimate of how long it will take before you start tanning, for those in the sun for that purpose.</p><p>If you’re outside for a certain activity, like swimming or snow sports, you can set this in the app, along with the SPF of your sunscreen from 15-100, and this will then adjust the estimated time to burn.</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:4298px;"><p class="vanilla-image-block" style="padding-top:56.28%;"><img id="NtRQkBkkxDvoaxvDXSniFe" name="SunAlert app on Garmin Forerunner 970" alt="SunAlert app on Garmin Forerunner 970" src="https://cdn.mos.cms.futurecdn.net/NtRQkBkkxDvoaxvDXSniFe.jpg" mos="" align="middle" fullscreen="" width="4298" height="2419" 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>Once you’ve got everything set up, you can start your session in the sun and then get notified when you’ve hit the predicted time that you will start burning.</p><p>The app also logs how much vitamin D it thinks you have taken in while outside and gives a target to work towards each day, which will be a useful tool for the long UK winter.</p><h2 id="sunburn-comes-on-faster-than-you-think">Sunburn comes on faster than you think</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:4220px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="24LjmNNiJ7VSfJQFicZeBe" name="SunAlert app on Garmin Forerunner 970" alt="SunAlert app on Garmin Forerunner 970" src="https://cdn.mos.cms.futurecdn.net/24LjmNNiJ7VSfJQFicZeBe.jpg" mos="" align="middle" fullscreen="" width="4220" height="2374" 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>Perhaps the most useful aspect of the app for me has been that it shows how little time you actually need to spend in the sun to risk burning, especially if you have a fairer skin type like mine.</p><p>If I’m only going out for a 45-minute run and it’s late morning, I’ll usually not bother with sunscreen, but the app shows that even with a moderate UV index of 5, I’d risk sunburn during that run if I was exposed the whole time.</p><p>Once the UV index gets into the high or very high range, even half an hour outdoors is risky without sunscreen, so the app has pushed me to be more diligent in applying it before all my runs.</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:4241px;"><p class="vanilla-image-block" style="padding-top:56.28%;"><img id="aX3vwyjmf7jQfnXCudd45e" name="SunAlert app on Garmin Forerunner 970" alt="SunAlert app on Garmin Forerunner 970" src="https://cdn.mos.cms.futurecdn.net/aX3vwyjmf7jQfnXCudd45e.jpg" mos="" align="middle" fullscreen="" width="4241" height="2387" 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 find it just helps to have the numbers so plainly laid out, even if they are estimates, and you can set the Sun Alert app up as a widget on your watch to get info on the risk of sunburn quickly.</p><p>It’s a completely free app and works with most Garmin watches — there are a couple of new models it’s not on yet, like the <a href="https://www.tomsguide.com/wellness/smartwatches/garmin-forerunner-170-review-an-affordable-and-accurate-running-watch">Garmin Forerunner 170 </a>— so it’s definitely one I think is worth adding even just to survive the current UK heatwave, or to use all the time if you live in sunnier climates.</p><h3 class="article-body__section" id="section-we-re-tracking-all-the-best-prime-day-smartwatch-deals"><span>We're tracking all the best Prime Day smartwatch deals</span></h3><div class="vizualizer-embed"><div class="tg-df-widget-host" data-widget-config="?search=Wearables+%26+Fitness+Tech&price=60_&min_discount_ratio=0.95&offer_type=all&rows=4&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.&show_countdown=true&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 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-right {      position: absolute;      right: 8px;      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-right:hover {      background-color: #f8fafc;      border-color: #cbd5e1;    }    .tg-df-carousel-roundels-wrapper .tg-df-carousel-scroll-right {      right: 0;      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-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">          \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.previousElementSibling.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-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>\n        \x3C/div>\n      \x3C/div>\n    \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">      \x3Cdiv class="tg-df-grid" id="tg-df-grid">        \x3C!-- Content populated by JavaScript --\x3E      \x3C/div>    \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';             }          }                    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')}`                });              }            });          }        }        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';          }        }        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.rowsSelect && this.rowsSelect.value) ? parseInt(this.rowsSelect.value, 10) : 12;          } else {             this.displayLimit += (this.rowsSelect && this.rowsSelect.value) ? parseInt(this.rowsSelect.value, 10) : 12;          }                    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 encodedTag = encodeURIComponent(this.activeDealTag.toLowerCase().replace(/\s+/g, '-'));             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');                    if (this.rowsSelect && this.rowsSelect.value) {            url.searchParams.append('rows', this.rowsSelect.value);          } else {             url.searchParams.append('rows', '12'); // default          }          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 = 12;          if (this.rowsSelect && this.rowsSelect.value) {            rowLimit = parseInt(this.rowsSelect.value, 10) || 12;          }          // 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 => {              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}`;                }              }              return `                \x3Ca href="${this.escapeHTML(linkUrl)}" target="_blank" rel="noopener nofollow" class="tg-df-voucher-item">                  ${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);                }              });            });                                  } 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 = `              \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;                    let gridWrapper = this.grid.parentElement;          if (gridWrapper && gridWrapper.classList.contains('tg-df-grid-wrapper')) {             let existingChevron = gridWrapper.querySelector('.tg-df-carousel-scroll-right');             if (this.getViewMode() === 'carousel') {                 if (!existingChevron) {                     gridWrapper.insertAdjacentHTML('beforeend', '\n                 \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" onclick="this.previousElementSibling.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>');                 }             } else {                 if (existingChevron) {                     existingChevron.remove();                 }             }          }                    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.rowsSelect && this.rowsSelect.value) ? parseInt(this.rowsSelect.value, 10) : 12);                 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');            if (!this.processArticleFired) {                  this.processArticleFired = true;                  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[ I asked ChatGPT to help me score big on Prime Day — these 5 money-saving tips are better than I expected ]]></title>
                                                                                                                                                                                                <link>https://www.tomsguide.com/ai/i-asked-chatgpt-to-help-me-score-big-on-prime-day-these-5-money-saving-tips-are-better-than-i-expected</link>
                                                                            <description>
                            <![CDATA[ I asked ChatGPT to help me discover the best ways to find the best Prime Day deals — and it gave me a bunch of useful money-saving tips. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">3CrBQDnoCzQSEiWQvCzgra</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/CazrfECG9STYnXWWdabvjd-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Tue, 23 Jun 2026 06:30:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[AI]]></category>
                                                                                                                    <dc:creator><![CDATA[ Elton Jones ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/NVtYYXr3tEPUE67jf3HtXM.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ null ]]></dc:description>
                                                                                                                                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/CazrfECG9STYnXWWdabvjd-1280-80.jpg">
                                                            <media:credit><![CDATA[Amazon]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Amazon Prime Day stock image]]></media:description>                                                            <media:text><![CDATA[Amazon Prime Day stock image]]></media:text>
                                <media:title type="plain"><![CDATA[Amazon Prime Day stock image]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/CazrfECG9STYnXWWdabvjd-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Amazon Prime Day prep has become an annual tradition for me.</p><p>Every year, I spend the weekend before the big sale scouting early discounts and building a wish list of items I hope to snag at the lowest possible prices. Over the years, Prime Day has helped me amass a sizable collection of video games, anime Blu-rays and Marvel and DC graphic novels — and this year is no different.</p><p>But this time, I decided to bring ChatGPT along for the hunt.</p><p>With AI tools becoming increasingly useful for shopping and research, I wanted to see whether ChatGPT could uncover deals I might have overlooked or point me toward products I didn't even know were on sale.</p><p>The results surprised me. Not only did the chatbot offer practical strategies for finding the best Prime Day bargains, but it also surfaced several deeply discounted items that made their way into my shopping cart almost immediately.</p><h2 id="prepping-for-prime-day-sales-with-this-essential-advice">Prepping for Prime Day sales with this essential advice</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="zVXmup3WZAZQTPVh9GeTK7" name="Prime Day 2026" alt="Prime Day 2026 ad" src="https://cdn.mos.cms.futurecdn.net/zVXmup3WZAZQTPVh9GeTK7.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: Amazon)</span></figcaption></figure><p>To get this money-saving mission underway, I presented this prompt to ChatGPT to see how it could assist me:</p><p>“I'm into video games, anime on Blu-ray, and graphic novels from Marvel Comics & DC Comics. What are the best ways to prepare for Amazon Prime Day and find the best sales for those types of items during that sale period?”</p><p>The chatbot initially responded with a piece of advice that set me up nicely: <em>For the categories you're interested in—video games, anime Blu-rays, and Marvel/DC graphic novels—Prime Day rewards preparation more than impulse buying. The biggest savings often go to people who build watchlists weeks in advance and know the "normal" prices before the sale starts.</em></p><p>After taking note of its suggestion to build a watchlist of all the items I’m looking to buy before and during Amazon Prime Day, I also jotted down ChatGPT’s five tips on how to locate the best prices imaginable:</p><ul><li><strong>Track Historical Prices: </strong><em>One of the biggest Prime Day mistakes is assuming every "deal" is actually a deal. Use sites/tools like camelcamelcamel and Keepa. These tools show Amazon price history.</em></li><li><strong>Follow Deal Communities: </strong><em>Prime Day moves fast, and some of the best deals disappear within minutes. Stay updated on them by following sources such as Wario64 on X, Cheap A** Gamer, Slickdeals and IGN Deals. For your interests specifically, these sources are often faster than Amazon's own deal pages.</em></li><li><strong>Set a Budget by Category: </strong><em>A collector's trap is buying too many "good deals." Try something like a $150 budget for video games, a $100 budget for anime Blu-rays, and an $80 budget for graphic novels, for example. Then rank your purchases for each category under must-have, nice-to-have and only-if-heavily-discounted. This prevents regret purchases.</em></li><li><strong>Focus on the First 12 Hours: </strong><em>The strongest deals are often midnight launch deals, Lightning Deals and limited inventory offers. If there's a specific omnibus, collector's edition or anime box set you've been waiting for, check as soon as Prime Day starts.</em></li><li><strong>Set Up Prime Day Alerts Through Alexa:</strong><em><strong> </strong></em><em>Alexa can notify you about discounts on items in your Wish List, Cart or Buy Later collection up to 24 hours in advance or track target prices for specific products. Open the Alexa app, go to More, select Settings, tap on Notifications, proceed to Amazon Shopping and turn on Deal Recommendations.</em></li></ul><h2 id="putting-those-tips-into-action">Putting those tips into action</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="cnCyefvhMdEkyVQQttapdM" name="Prime Day deals" alt="Smartphone displaying Prime Day on its screen with $100 dollar bills as the backdrop" src="https://cdn.mos.cms.futurecdn.net/cnCyefvhMdEkyVQQttapdM.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>With all of those money-saving tips in the back of my mind, my search for the best Amazon Prime Day sales I could find became a much more streamlined process. Plus, I came upon a bunch of amazing deals that went live before the Amazon Prime Day madness officially kicked in:</p><ul><li><strong>Borderlands 4 - PS5: </strong><a href="https://www.amazon.com/Borderlands-4-PlayStation-5/dp/B0FDBL8L41/ref=sr_1_1?crid=2U5DYAQLRFVTI&dib=eyJ2IjoiMSJ9.xL7GGcMGJfKE784YOTdwtq-2BF4oXgNVriZ6lb79Qp4urCQbxB3QP1PBNUXeQ6EV6xuuwg9RLWkzlXWtp5LW9uHHUIVFTwjTFwmfiqrBwM-hl6cZYQsnw7zt4HPThDflruzfdO52TzT7ZQDqUGmuSAVQCp_J9kH2MI4_kyEht-xVuTPD4x2i5NzOiX8X8VJr_Il383mT5LvaA5H0PNbQazoP1bom0BCRWfyIIsI6lAo.birlPKUKaEctabctKHyQcdY17j1eSpdvmRitWmbmTrk&dib_tag=se&keywords=borderlands%2B4%2Bxbox%2Bseries%2Bx&qid=1782152292&sprefix=borderlands%2B4%2Bxbox%2Caps%2C131&sr=8-1&th=1" target="_blank" rel="nofollow">was $49.99 now $34.99</a></li><li><strong>Cyberpunk 2077: Ultimate Edition - Nintendo Switch 2: </strong><a href="https://www.amazon.com/Cyberpunk-2077-Nintendo-Switch-2/dp/B0F64Q8C97/ref=sr_1_1?crid=2BV7BPXGOTV6&dib=eyJ2IjoiMSJ9.AyV7ji6BuhWYp6ObHXbI8vmSmWkhg5GmqB7Lgu4hgy8Ma7R-C_4QTdoj1nvcTwwBskG4_Hjr5GruMGufg_s7DdOZid4fi55wmdPE52T3H2RC__R_1wTCxIaLHdLrVQVAD-JGO038l8bxCbjaw7jxy-K6QxBvNMDjGplg2RbZ8Q6eUqjJk1eT66oKHR5XxZlEFO5ZAh4Ms0Lb9Qs7GYGbWqS4Nj8QGLf67Dcx1WUPd-0.6g0GnTR3rmXe87thxnUXd4zMKb4zbYnIhc96N2cIEwY&dib_tag=se&keywords=cyberpunk%2B2077%2Bswitch%2B2&qid=1782152381&sprefix=cyberpunk%2B2077%2Caps%2C132&sr=8-1&th=1" target="_blank" rel="nofollow">was $69.99 now $57.99</a></li><li><strong>Akira - 4K & Blu-ray [4K UHD]: </strong><a href="https://www.amazon.com/Akira-Movie-4K-UHD/dp/B09JXWP8N1/ref=sr_1_1?crid=1ST3TR27THSG9&dib=eyJ2IjoiMSJ9.nfCSjcRtAJfhMeZpBGGrf9BCbZaqdHTLVUq0qLT-_BSOShYURIKZ6VZVNp0C8utVL3TrDU7onWVFAZrUXUORp3pepMQQgDK-o0BpytmHkUqpEhqRfApnxGLv5SJBfQLVxHSlwgWO5OcV3mBxaLwdIY8GRlzjdtrj4YK8k4DhvJkX1pzqj2fJv8Xs-rKoBWHt_49M77UMFR_MQw2XdI6zZpuZRhwUBfjlLypsQf4VwjQ.n38LspVgED7RNjahB3WQiaZ5O32Apz6e8RBJNKs0bZs&dib_tag=se&keywords=akira+4k&qid=1782143562&sprefix=akira%2Caps%2C124&sr=8-1" target="_blank" rel="nofollow">was $29.98 now $11.99</a></li><li><strong>Bayonetta [Blu-ray & DVD]: </strong><a href="https://www.amazon.com/Bayonetta-Bloody-Anime-Movie-Blu-ray/dp/B00LXGL7EI/ref=sr_1_1?crid=HGT04EGDGXS7&dib=eyJ2IjoiMSJ9.1qh0EDqYEHvdF2PwMb2QuEaaxjWgfF1cwxnBNhAhy_3ChJsemo2fXZSEa2kxBc-H-iXi2RVr0ubD8YnmXiJ7Wg.XQbgs_Pky5cr0bp5nMks8XVFkWFkIyJoXWmTM-TtA9M&dib_tag=se&keywords=bayonetta+blu+ray&qid=1782152096&sprefix=%2Caps%2C93&sr=8-1" target="_blank" rel="nofollow">was $19.98 now $12.82</a></li><li><strong>Samurai 7: The Complete Series [Blu-ray]: </strong><a href="https://www.amazon.com/Samurai-Complete-Blu-ray-Colleen-Clinkenbeard/dp/B07KLFLYHM/ref=sr_1_1?crid=2TJXDMABF5UTS&dib=eyJ2IjoiMSJ9.nqalIS7-3HeH4Nov8Z-xKRjzpWkTTzYqLy631mECvSBTYuXNl99gF2BI0cicxuUWnUqk5Yw5NJPIO3_BcJ9lvO83LbRVnVkDIi-764YWvCMzCE3ENVqLs28NNkkK3KCeZ8r6znQRMJ-HlbuSKvO-4TFJTr86aSAgFmiiB5oKTAGtmTaNQ4pwm4jQhd_84x_IKvMpbcxZ8LJuP-JGAMCgNua8-l1ALgcVuM6PDPScUvQ.JNey3ibKztwngE7Aitqv4KQk4JdvYhUSEjODcNPdhfw&dib_tag=se&keywords=samurai+7+complete+series&qid=1782152171&sprefix=samurai+7+the+c%2Caps%2C128&sr=8-1" target="_blank" rel="nofollow">was $49.98 now $34.99</a></li><li><strong>Daredevil: Born Again [Marvel Premier Collection]: </strong><a href="https://www.amazon.com/Daredevil-Again-Marvel-Premier-Collection/dp/1302965980/ref=sr_1_1?crid=3GXSUQWA8ND72&dib=eyJ2IjoiMSJ9.ee0FPTGjFEJ3Xyx-mGj6B-xWrDbYdnLzXxm4qYYFPbWs_s5MNDsdURg_2p7Wz3wCq3-UWbGDbLYuE4OxgJkXNwr2vvK97-5z3asT2xb5jfdlW7nzVvTdLXv5ek2SmmCen_xu3WcDgjKup0zZgwkpMyuYUVZWowqLqc7BHg0oCLAwLX32zRyv9Sg2VcmdEvTKwAgG2ultWx3R6xW-jd89UwkNpLe-KcjYf12D2zlH2sA.ksb0PWDUZBIOc325h2AzycZkFf9OtvLzamDEXlAML3I&dib_tag=se&keywords=daredevil+born+again+marvel+premier+collection&qid=1782152477&sprefix=daredevil+born+again+marvel+pr%2Caps%2C140&sr=8-1" target="_blank" rel="nofollow">was $14.99 now $11.27</a><strong> </strong>(with Amazon Prime)</li><li><strong>Wolverine: Old Man Logan [Marvel Premier Collection]: </strong><a href="https://www.amazon.com/Wolverine-Logan-Marvel-Premier-Collection/dp/1302965581/ref=sr_1_1?crid=398PJ7O9Y2Q38&dib=eyJ2IjoiMSJ9.AeMXqtqAxZQNqDeGIhaKeWE-CMZVcJE97kmh_PfVWyw4x9KVBcyFah1KWO2MVpgtZ4JQvfqhks9cHFyT-zmjMzzXsdpoIsP9aa9N8n8YMUAA0L8_ec6YC64wWZU7VXFSkfjs6MrrQBgvlTqTYsXHnUf47rzWH6qvtGE0CiiwbQxFxryXfHGelDeSKdnBzStt2ePuVHRUqzdcpxZhonuLiqGs6rFNGyEdqvUXHGICPsM.N40GQ9dkmAr8T0ZkElHJ3rLrn73q-5pHe5eSEMoJW_A&dib_tag=se&keywords=wolverine+old+man+logan+marvel+premier+collection&qid=1782152559&sprefix=wolverine+old+man+logan+marvel+premier+collection%2Caps%2C109&sr=8-1" target="_blank" rel="nofollow">was $14.99 now $12.82</a><strong> </strong>(with Amazon Prime)</li></ul><h2 id="the-takeaway-4">The takeaway</h2><p>Patience isn’t one of my best traits—the act of impulse buying has a hold over me that’s just too hard to ignore. </p><p>But for this year’s Amazon Prime Day routine, I didn’t rush to buy everything I saw for sale, kept ChatGPT’s money-saving advice close to mind and followed every step it laid out to discover the best deals imaginable. </p><p>That plan worked to perfection and made two video games, three anime Blu-rays and graphic novels a part of my growing collection of physical goods I’ll be cherishing forever.</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/ai/that-viral-jeff-bezos-quote-about-ai-and-water-isnt-real-heres-what-actually-happened" target="_blank">That viral Jeff Bezos quote about AI and water isn't real — here's what actually happened</a></li><li><a href="https://www.tomsguide.com/ai/tiktoks-ai-slop-problem-is-spiraling-out-of-control-and-kids-are-getting-the-worst-of-it" target="_blank">TikTok’s AI slop problem is spiraling out of control — and kids are getting the worst of it</a></li><li><a href="https://www.tomsguide.com/ai/i-used-chatgpt-to-discover-my-hidden-strengths-and-it-changed-my-perspective-on-work" target="_blank">I used ChatGPT to discover my hidden strengths — and it changed my perspective on work</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
            </channel>
</rss>